UNPKG

makestatic-core

Version:

Generic file processing library

264 lines (234 loc) 5.77 kB
const File = require('makestatic-filewrap') /** * Encapsulates the output file lists. * * The `files` list is an array of file objects whilst * the `assets` list is a map of relative file paths to file objects. * * @class FileList */ class FileList { /** * Create a FileList. * * @constructor FileList * @param {Object} context the processing context. * @param {Array} sources list of file names. */ constructor (context, sources = []) { this._context = context this._assets = {} this.propagate(sources) } /** * The processing context. * * @property {Object} context * @readonly */ get context () { return this._context } /** * The root directory for input files. * * @property {String} root * @readonly */ get root () { return this._context.options.root } /** * Raw list of input file names. * * @property {Array} sources * @readonly */ get sources () { return this._sources } /** * List of current output files. * * @property {Array} files * @readonly */ get files () { return this._files } /** * Map of current output files. * * @property {Object} assets list of output assets. */ get assets () { return this._assets } set assets (val) { this._assets = val if (val) { this._files = [] for (let k in val) { this._files.push(val[k]) } } } /** * Add a file to the list by name or pointer. * * The file is not added if it already exists in the `files` list. * * @function add * @member FileList * @param {String|Object} options source file name or file properties. * * @returns the file on success otherwise undefined. */ add (options) { const file = this.getFile(options) const key = file.path const index = this._files.findIndex((file) => { return file.path === key }) if (index === -1) { this._assets[key] = file this._files.push(file) } return index === -1 ? file : undefined } /** * Remove a file from the list by name or pointer. * * @function remove * @member FileList * @param {String|Object} options source file name or file properties. * * @returns the file on success otherwise undefined. */ remove (options) { const file = this.getFile(options) const key = file.path if (!this._assets[key]) { throw new Error(`cannot remove non-existent file ${file.path}`) } delete this._assets[key] const index = this._files.findIndex((file) => { return file.path === key }) if (index > -1) { this._files.splice(index, 1) } return index > -1 ? file : undefined } /** * Rewrite the output path for an existing file. * * @function rewrite * @member FileList * @param {String|Object} options source file name or file properties. * @param {String} dest the new output path for the file. * * @throw Error if the file does not exist. * * @returns the file on success otherwise undefined. */ rewrite (options, dest) { const file = this.get(options) if (!file) { throw new Error(`cannot rewrite non-existent file`) } this.remove(file) file.output = dest this.add(file) return file } /** * Rename the output file name for an existing file. * * @function rename * @member FileList * @param {String|Object} options source file name or file properties. * @param {String} name the new output name for the file. * * @throw Error if the file does not exist. * * @returns the file on success otherwise undefined. */ rename (options, name) { const file = this.get(options) if (!file) { throw new Error(`cannot rename non-existent file`) } const path = require('path') const dest = path.join( file.output ? path.dirname(file.output) : this.dir || '', name) return this.rewrite(file, dest) } /** * Get a file from the list by name or pointer. * * @function get * @member FileList * @param {String|Object} options source file name or file properties. * * @returns a file object or undefined. */ get (options) { let key if (typeof options === 'string') { key = options } else { key = this.getFile(options).path } return this._assets[key] } /** * Get a File pointer. * * Accepts an input file path which becomes the file `name` or a map of * properties for the new file. * * If a `File` is passed it is returned. * * @function getFile * @member FileList * @param {String|Object} options source file name or file properties. * * @returns a file object. */ getFile (options) { if (options instanceof File) { return options } else if (typeof options === 'string') { options = {name: options} } if (!options.root) { options.root = this.root } if (!options.dir) { options.dir = this.context.options.output } // assume object file options return new File(options) } /** * Propagates the file lists converting file path strings to * complex `filewrap` objects. * * @function propagate * @member FileList * * @param {Array} sources list of input file names. */ propagate (sources) { this._sources = sources.slice() // set up linked list this._files = this._sources.map((name) => { const file = new File( {name: name, root: this.root, dir: this.context.options.output}) this._assets[file.path] = file return file }) } } module.exports = FileList