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