| /* |
| 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; |