| 'use strict'; |
| /* |
| Copyright 2012-2015, Yahoo Inc. |
| Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. |
| */ |
| const path = require('path'); |
| const fs = require('fs'); |
| const mkdirp = require('make-dir'); |
| const supportsColor = require('supports-color'); |
| |
| /** |
| * Base class for writing content |
| * @class ContentWriter |
| * @constructor |
| */ |
| class ContentWriter { |
| /** |
| * 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 |
| */ |
| colorize(str /*, clazz*/) { |
| return str; |
| } |
| |
| /** |
| * writes a string appended with a newline to the destination |
| * @param {String} str the string to write |
| */ |
| println(str) { |
| this.write(`${str}\n`); |
| } |
| |
| /** |
| * closes this content writer. Should be called after all writes are complete. |
| */ |
| close() {} |
| } |
| |
| /** |
| * a content writer that writes to a file |
| * @param {Number} fd - the file descriptor |
| * @extends ContentWriter |
| * @constructor |
| */ |
| class FileContentWriter extends ContentWriter { |
| constructor(fd) { |
| super(); |
| |
| this.fd = fd; |
| } |
| |
| write(str) { |
| fs.writeSync(this.fd, str); |
| } |
| |
| close() { |
| fs.closeSync(this.fd); |
| } |
| } |
| |
| // allow stdout to be captured for tests. |
| let capture = false; |
| let output = ''; |
| |
| /** |
| * a content writer that writes to the console |
| * @extends ContentWriter |
| * @constructor |
| */ |
| class ConsoleWriter extends ContentWriter { |
| write(str) { |
| if (capture) { |
| output += str; |
| } else { |
| process.stdout.write(str); |
| } |
| } |
| |
| colorize(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 |
| */ |
| class FileWriter { |
| constructor(baseDir) { |
| if (!baseDir) { |
| throw new Error('baseDir must be specified'); |
| } |
| this.baseDir = baseDir; |
| } |
| |
| /** |
| * static helpers for capturing stdout report output; |
| * super useful for tests! |
| */ |
| static startCapture() { |
| capture = true; |
| } |
| |
| static stopCapture() { |
| capture = false; |
| } |
| |
| static getOutput() { |
| return output; |
| } |
| |
| static resetOutput() { |
| 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} |
| */ |
| writerForDir(subdir) { |
| if (path.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.) |
| */ |
| copyFile(source, dest, header) { |
| if (path.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} |
| */ |
| writeFile(file) { |
| if (file === null || file === '-') { |
| return new ConsoleWriter(); |
| } |
| if (path.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; |