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