UNPKG

4.99 kBJavaScriptView Raw
1/*
2 Copyright 2012-2015, Yahoo Inc.
3 Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
4 */
5var util = require('util'),
6 path = require('path'),
7 fs = require('fs'),
8 mkdirp = require('make-dir'),
9 supportsColor = require('supports-color'),
10 isAbsolute = path.isAbsolute || /* istanbul ignore next */ function (p) {
11 return path.resolve(p) === path.normalize(p);
12 };
13
14/**
15 * abstract interface for writing content
16 * @class ContentWriter
17 * @constructor
18 */
19/* istanbul ignore next: abstract class */
20function ContentWriter() {
21}
22
23/**
24 * writes a string as-is to the destination
25 * @param {String} str the string to write
26 */
27/* istanbul ignore next: abstract class */
28ContentWriter.prototype.write = function () {
29 throw new Error('write: must be overridden');
30};
31
32/**
33 * returns the colorized version of a string. Typically,
34 * content writers that write to files will return the
35 * same string and ones writing to a tty will wrap it in
36 * appropriate escape sequences.
37 * @param {String} str the string to colorize
38 * @param {String} clazz one of `high`, `medium` or `low`
39 * @returns {String} the colorized form of the string
40 */
41ContentWriter.prototype.colorize = function (str /*, clazz*/) {
42 return str;
43};
44
45/**
46 * writes a string appended with a newline to the destination
47 * @param {String} str the string to write
48 */
49ContentWriter.prototype.println = function (str) {
50 this.write(str + '\n');
51};
52
53/**
54 * closes this content writer. Should be called after all writes are complete.
55 */
56ContentWriter.prototype.close = function () {
57};
58
59/**
60 * a content writer that writes to a file
61 * @param {Number} fd - the file descriptor
62 * @extends ContentWriter
63 * @constructor
64 */
65function FileContentWriter(fd) {
66 this.fd = fd;
67}
68util.inherits(FileContentWriter, ContentWriter);
69
70FileContentWriter.prototype.write = function (str) {
71 fs.writeSync(this.fd, str);
72};
73
74FileContentWriter.prototype.close = function () {
75 fs.closeSync(this.fd);
76};
77
78/**
79 * a content writer that writes to the console
80 * @extends ContentWriter
81 * @constructor
82 */
83function ConsoleWriter() {
84}
85util.inherits(ConsoleWriter, ContentWriter);
86
87// allow stdout to be captured for tests.
88var capture = false;
89var output = '';
90ConsoleWriter.prototype.write = function (str) {
91 if (capture) {
92 output += str;
93 } else {
94 process.stdout.write(str);
95 }
96};
97
98ConsoleWriter.prototype.colorize = function (str, clazz) {
99 var colors = {
100 low: '31;1',
101 medium: '33;1',
102 high: '32;1'
103 };
104
105 /* istanbul ignore next: different modes for CI and local */
106 if (supportsColor.stdout && colors[clazz]) {
107 return '\u001b[' + colors[clazz] + 'm' + str + '\u001b[0m';
108 }
109 return str;
110};
111
112/**
113 * utility for writing files under a specific directory
114 * @class FileWriter
115 * @param {String} baseDir the base directory under which files should be written
116 * @constructor
117 */
118function FileWriter(baseDir) {
119 if (!baseDir) {
120 throw new Error('baseDir must be specified');
121 }
122 this.baseDir = baseDir;
123}
124
125/**
126* static helpers for capturing stdout report output;
127* super useful for tests!
128*/
129FileWriter.startCapture = function () {
130 capture = true;
131};
132FileWriter.stopCapture = function () {
133 capture = false;
134};
135FileWriter.getOutput = function () {
136 return output;
137};
138FileWriter.resetOutput = function () {
139 output = '';
140};
141
142/**
143 * returns a FileWriter that is rooted at the supplied subdirectory
144 * @param {String} subdir the subdirectory under which to root the
145 * returned FileWriter
146 * @returns {FileWriter}
147 */
148FileWriter.prototype.writerForDir = function (subdir) {
149 if (isAbsolute(subdir)) {
150 throw new Error('Cannot create subdir writer for absolute path: ' + subdir);
151 }
152 return new FileWriter(this.baseDir + '/' + subdir);
153};
154/**
155 * copies a file from a source directory to a destination name
156 * @param {String} source path to source file
157 * @param {String} dest relative path to destination file
158 */
159FileWriter.prototype.copyFile = function (source, dest) {
160 if (isAbsolute(dest)) {
161 throw new Error('Cannot write to absolute path: ' + dest);
162 }
163 dest = path.resolve(this.baseDir, dest);
164 mkdirp.sync(path.dirname(dest));
165 fs.writeFileSync(dest, fs.readFileSync(source));
166};
167/**
168 * returns a content writer for writing content to the supplied file.
169 * @param {String|null} file the relative path to the file or the special
170 * values `"-"` or `null` for writing to the console
171 * @returns {ContentWriter}
172 */
173FileWriter.prototype.writeFile = function (file) {
174 if (file === null || file === '-') {
175 return new ConsoleWriter();
176 }
177 if (isAbsolute(file)) {
178 throw new Error('Cannot write to absolute path: ' + file);
179 }
180 file = path.resolve(this.baseDir, file);
181 mkdirp.sync(path.dirname(file));
182 return new FileContentWriter(fs.openSync(file, 'w'));
183};
184
185module.exports = FileWriter;