UNPKG

mako-tree

Version:

The build tree structure used internally by mako

241 lines (218 loc) 5.41 kB
'use strict' let clone = require('clone') let debug = require('debug')('mako-file') let extension = require('file-extension') let uuid = require('uuid') let relative = require('relative') let Vinyl = require('vinyl') const builtins = [ // vinyl 'cwd', 'base', 'path', 'history', 'stat', '_contents', // mako 'tree' ] /** * Represents a file within a build tree. * * @class */ class File extends Vinyl { /** * Sets up the instance. * * @param {Object} params The vinyl params for this file. * @param {Tree} tree The parent build tree. */ constructor (params, tree) { debug('initialize with %s', params) if (typeof params === 'string') { super({ path: params }) this.id = uuid.v4() } else { super(params) // pick up custom properties Object.keys(params || {}).forEach(key => { if (builtins.indexOf(key) === -1 || key === 'history' || key === '_contents') { this[key] = clone(params[key]) } }) this.id = this.id || uuid.v4() } this.tree = tree } /** * Check to see if this file has the given path currently. (or did at some * point in it's history) * * @param {String} path The absolute path to search for. * @return {Boolean} */ hasPath (path) { return this.history.indexOf(path) > -1 } /** * Check to see if the `child` file is a dependency of this file. * * @see Tree#hasDependency() * @param {String} child The file ID of the dependency. * @return {Boolean} */ hasDependency (child) { return this.tree.hasDependency(this.id, child) } /** * Adds the `child` as a dependency of this file. Returns the new `File` * instance. * * @see Tree#addDependency() * @param {String} child The file ID of the dependency. */ addDependency (child) { this.tree.addDependency(this.id, child) } /** * Removes the `child` as a dependency of this file. * * @see Tree#removeDependency() * @param {String} child The file ID of the dependency. */ removeDependency (child) { this.tree.removeDependency(this.id, child) } /** * Find the dependencies of this file. * * @see Tree#dependencies() * @param {Object} [options] The search criteria. * @return {Array} */ dependencies (options) { return this.tree.dependenciesOf(this.id, options) } /** * Check to see if the `parent` file is a dependant of this file. * * @see Tree#hasDependant() * @param {String} parent The file ID of the dependant. * @return {Boolean} */ hasDependant (parent) { return this.tree.hasDependant(this.id, parent) } /** * Adds the `parent` as a dependant of this file. Returns the new `File` * instance. * * @see Tree#addDependant() * @param {String} parent The file ID of the dependant. */ addDependant (parent) { this.tree.addDependant(this.id, parent) } /** * Removes the `parent` as a dependant of this file. * * @see Tree#removeDependant() * @param {String} parent The file ID of the dependant. */ removeDependant (parent) { this.tree.removeDependant(this.id, parent) } /** * Find the dependants of this file. * * @see Tree#dependants() * @param {Object} [options] The search criteria. * @return {Array} */ dependants (options) { return this.tree.dependantsOf(this.id, options) } /** * Used to reset a file prior to re-running the analyze phase. */ reset () { this.history.splice(1) // remove all but original path this.contents = null } /** * Retrieves the current type for the file. * * @return {String} */ get type () { return extension(this.path) } /** * Set the type/extension for this file. * * @param {String} type The type (without the leading dot) */ set type (type) { this.extname = `.${type}` } /** * Gets the initial path for this file. * * @return {String} */ get initialPath () { return this.history[0] } /** * Determine the original file type for this file (as if no transformations * have been run) * * @return {String} */ get initialType () { return extension(this.initialPath) } /** * Creates a clone of this file. * * @param {Tree} tree The tree to attach the clone to. * @return {File} */ clone (tree) { debug('cloning %s', relative(this.path)) return new File(this, tree || this.tree) } /** * Returns a trimmed object that can be serialized as JSON. It strips the tree * link and includes all other properties, including the custom ones. * * @return {File} */ toJSON () { let clone = this.clone(null) delete clone.tree return clone } /** * Allow for easier logging. * * @return {String} */ toString () { return this.inspect() } /** * Used to parse a string value into a usable file. * * @static * @param {String} input The raw JSON string to parse. * @param {Tree} tree The tree to associate this file with. * @return {File} */ static fromObject (input, tree) { debug('creating file instance from a plain object') let file = new File(input.path) Object.assign(file, input) file.tree = tree debug('done creating file instance') return file } } // single export module.exports = File