let fs = require('fs'); let md5 = require('md5'); let chokidar = require('chokidar'); let mkdirp = require('mkdirp'); let options = require('./Options'); let uglify = require('uglify-js'); let UglifyCss = require('clean-css'); class File { /** * Create a new File instance. * * @param {string} file */ constructor(file) { this.file = file; this.fileType = path.extname(file); } /** * Static constructor. * * @param {string} file */ static find(file) { return new File(file); } /** * Make all nested directories in the current file path. */ makeDirectories() { mkdirp.sync(this.parsePath().base); return this; } /** * Minify the file, if it is CSS or JS. */ minify() { if (this.fileType === '.js') { this.write(uglify.minify(this.file, options.uglify).code); } if (this.fileType === '.css') { this.write( new UglifyCss(options.cleanCss).minify(this.read()).styles ); } } /** * Determine if the given file exists. * * @param {string} file */ static exists(file) { return fs.existsSync(file); } /** * Read the file. */ read() { return fs.readFileSync(this.file, { encoding: 'utf-8' }); } /** * Write the given contents to the file. * * @param {string} body */ write(body) { if (typeof body === 'object') { body = JSON.stringify(body, null, 2); } fs.writeFileSync(this.file, body); return this; } /** * Delete/Unlink the current file. */ delete() { if (fs.existsSync(this.file)) { fs.unlinkSync(this.file); } } /** * Watch the current file for changes. * * @param {Function} callback */ watch(callback) { return chokidar.watch( this.path(), { persistent: true } ).on('change', () => callback(this)); } /** * Fetch the full path to the file. * * @return {string} */ path() { return path.resolve(this.file); } /** * Version the current file. */ version() { let contents = this.read(); let versionedPath = this.versionedPath(md5(contents)); return new File(versionedPath).write(contents); } /** * Fetch a full, versioned path to the file. * * @param {string} hash */ versionedPath(hash) { if (! hash) hash = md5(this.read()); return this.parsePath().hashedPath.replace('[hash]', hash); } /** * Parse the file path into segments. */ parsePath() { let outputSegments = path.parse(this.file); return { path: this.file, pathWithoutExt: path.join(outputSegments.dir, `${outputSegments.name}`), hashedPath: path.join(outputSegments.dir, `${outputSegments.name}.[hash]${outputSegments.ext}`), base: outputSegments.dir, file: outputSegments.base, hashedFile: `${outputSegments.name}.[hash]${outputSegments.ext}`, name: outputSegments.name, isFile: !! outputSegments.ext, isDir: ! outputSegments.ext, ext: outputSegments.ext }; } /** * Rename the file. * * @param {string} to */ rename(to) { fs.renameSync(this.file, to); this.file = to; return this; } } module.exports = File;