UNPKG

5.2 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 =
11 path.isAbsolute ||
12 /* istanbul ignore next */ function(p) {
13 return path.resolve(p) === path.normalize(p);
14 };
15
16/**
17 * abstract interface for writing content
18 * @class ContentWriter
19 * @constructor
20 */
21/* istanbul ignore next: abstract class */
22function ContentWriter() {}
23
24/**
25 * writes a string as-is to the destination
26 * @param {String} str the string to write
27 */
28/* istanbul ignore next: abstract class */
29ContentWriter.prototype.write = function() {
30 throw new Error('write: must be overridden');
31};
32
33/**
34 * returns the colorized version of a string. Typically,
35 * content writers that write to files will return the
36 * same string and ones writing to a tty will wrap it in
37 * appropriate escape sequences.
38 * @param {String} str the string to colorize
39 * @param {String} clazz one of `high`, `medium` or `low`
40 * @returns {String} the colorized form of the string
41 */
42ContentWriter.prototype.colorize = function(str /*, clazz*/) {
43 return str;
44};
45
46/**
47 * writes a string appended with a newline to the destination
48 * @param {String} str the string to write
49 */
50ContentWriter.prototype.println = function(str) {
51 this.write(str + '\n');
52};
53
54/**
55 * closes this content writer. Should be called after all writes are complete.
56 */
57ContentWriter.prototype.close = function() {};
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() {}
84util.inherits(ConsoleWriter, ContentWriter);
85
86// allow stdout to be captured for tests.
87var capture = false;
88var output = '';
89ConsoleWriter.prototype.write = function(str) {
90 if (capture) {
91 output += str;
92 } else {
93 process.stdout.write(str);
94 }
95};
96
97ConsoleWriter.prototype.colorize = function(str, clazz) {
98 var colors = {
99 low: '31;1',
100 medium: '33;1',
101 high: '32;1'
102 };
103
104 /* istanbul ignore next: different modes for CI and local */
105 if (supportsColor.stdout && colors[clazz]) {
106 return '\u001b[' + colors[clazz] + 'm' + str + '\u001b[0m';
107 }
108 return str;
109};
110
111/**
112 * utility for writing files under a specific directory
113 * @class FileWriter
114 * @param {String} baseDir the base directory under which files should be written
115 * @constructor
116 */
117function FileWriter(baseDir) {
118 if (!baseDir) {
119 throw new Error('baseDir must be specified');
120 }
121 this.baseDir = baseDir;
122}
123
124/**
125 * static helpers for capturing stdout report output;
126 * super useful for tests!
127 */
128FileWriter.startCapture = function() {
129 capture = true;
130};
131FileWriter.stopCapture = function() {
132 capture = false;
133};
134FileWriter.getOutput = function() {
135 return output;
136};
137FileWriter.resetOutput = function() {
138 output = '';
139};
140
141/**
142 * returns a FileWriter that is rooted at the supplied subdirectory
143 * @param {String} subdir the subdirectory under which to root the
144 * returned FileWriter
145 * @returns {FileWriter}
146 */
147FileWriter.prototype.writerForDir = function(subdir) {
148 if (isAbsolute(subdir)) {
149 throw new Error(
150 'Cannot create subdir writer for absolute path: ' + subdir
151 );
152 }
153 return new FileWriter(this.baseDir + '/' + subdir);
154};
155/**
156 * copies a file from a source directory to a destination name
157 * @param {String} source path to source file
158 * @param {String} dest relative path to destination file
159 * @param {String} [header=undefined] optional text to prepend to destination
160 * (e.g., an "this file is autogenerated" comment, copyright notice, etc.)
161 */
162FileWriter.prototype.copyFile = function(source, dest, header) {
163 if (isAbsolute(dest)) {
164 throw new Error('Cannot write to absolute path: ' + dest);
165 }
166 dest = path.resolve(this.baseDir, dest);
167 mkdirp.sync(path.dirname(dest));
168 fs.writeFileSync(dest, (header || '') + fs.readFileSync(source));
169};
170/**
171 * returns a content writer for writing content to the supplied file.
172 * @param {String|null} file the relative path to the file or the special
173 * values `"-"` or `null` for writing to the console
174 * @returns {ContentWriter}
175 */
176FileWriter.prototype.writeFile = function(file) {
177 if (file === null || file === '-') {
178 return new ConsoleWriter();
179 }
180 if (isAbsolute(file)) {
181 throw new Error('Cannot write to absolute path: ' + file);
182 }
183 file = path.resolve(this.baseDir, file);
184 mkdirp.sync(path.dirname(file));
185 return new FileContentWriter(fs.openSync(file, 'w'));
186};
187
188module.exports = FileWriter;