makestatic-sources-loader
Version:
Loads source files from disc
126 lines (111 loc) • 3.55 kB
JavaScript
const when = require('when')
const fs = require('fs')
const path = require('path')
const globule = require('globule')
/**
* Initializes the source files that will be processed.
*
* @class SourcesLoader
*/
class SourcesLoader {
/**
* Propagates the list of files to process.
*
* If the configuration option `files` is an array it is used otherwise all
* files in the `input` directory are added to the list of files to process.
*
* @function before
* @member SourcesLoader
* @param {Object} context the processing context.
*/
before (context) {
let files = Array.isArray(context.options.files) ? context.options.files
: globule.find(path.join(context.options.input, '**/**'))
context.list.propagate(files)
}
/**
* Reads a file from disc.
*
* If the file name matches a pattern in the `matchers` configuration option
* if is assigned the corresponding file extension so that it will be
* renamed when the file output path is set.
*
* If the file name matches a pattern in the `ignore` configuration option
* it is removed from the list of files to process.
*
* If the file points to a directory it is removed from the list of files to
* process.
*
* By default this implementation will read the file content and assign the
* buffer to the `file.buffer` and set the initial `file.content` unless the
* `buffer` option is disabled.
*
* If the `buffer` option is disabled the file will still be assigned
* a `stat` object.
*
* @function sources
* @member SourcesLoader
* @param {Object} file the current file.
* @param {Object} context the processing context.
* @param {Object} [options] plugin options.
*
* @option {Boolean=true} load the file buffer.
*
* @throws Error if the stat fails.
* @throws Error if the file read fails.
*
* @returns a promise that resolves when the file has been read.
*/
sources (file, context, options = {}) {
const ignores = context.options.ignore
const matchers = context.options.matchers
if (matchers) {
for (let ext in matchers) {
if (matchers[ext].test(file.name)) {
file.extension = ext
break
}
}
}
return when.promise((resolve, reject) => {
if (Array.isArray(ignores)) {
for (let i = 0; i < ignores.length; i++) {
// this file is being ignored
if (ignores[i].test(file.name)) {
context.list.remove(file)
return resolve()
}
}
}
fs.stat(file.name, (e, stat) => {
if (e) {
return reject(e)
}
// ignore directories
if (stat.isDirectory()) {
context.list.remove(file)
return resolve()
}
file.stat = stat
// if we are not buffering we don't read the file content
// to prevent reading the file from disc twice
// typically this will be the case when webpack is compiling
if (options.buffer === false) {
return resolve()
}
fs.readFile(file.name, (e, content) => {
/* istanbul ignore next: not going to mock fs error */
if (e) {
return reject(e)
}
// NOTE: `buffer` is raw untouched input
// NOTE: `content` is mutable output
file.buffer = content
file.content = content
resolve()
})
})
})
}
}
module.exports = SourcesLoader