Created
November 29, 2017 21:47
-
-
Save lmorchard/d4a8159d9cab44e7c56556c0158d1f82 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const path = require('path'); | |
const util = require('util'); | |
const globby = require('globby'); | |
const readFile = util.promisify(fs.readFile); | |
// const YAML = require('yamljs'); | |
// const ContentTransformerPlugin = require('./frontend/lib/content-transformer-plugin'); | |
// | |
// new ContentTransformerPlugin({ | |
// inputs: { | |
// experiments: 'content-src/experiments/**/*.yaml', | |
// news_updates: 'content-src/news_updates.yaml' | |
// }, | |
// parser: ({ file }) => YAML.parse(file.content.toString('utf8')), | |
// transforms: [ | |
// ({ inputs }) => [['TESTING 1', 'moooo ' + Date.now()]], | |
// ({ inputs }) => [['TESTING 2', 'foooo ' + Date.now()]], | |
// async ({ inputs }) => | |
// inputs.experiments | |
// .filter(file => file.modified) | |
// .map(async ({ filename, parsed }) => { | |
// return [filename + '.txt', 'foooo ' + Date.now()]; | |
// }) | |
// ] | |
// }) | |
class ContentTransformerPlugin { | |
constructor(options = {}) { | |
// Assemble options with defaults. | |
this.options = { | |
inputs: {}, | |
parser: () => {}, | |
transforms: [], | |
...options | |
}; | |
// Resolve configured input globs into file tracking records | |
this.inputs = {}; | |
Object.entries(this.options.inputs).forEach(([key, patterns]) => { | |
this.inputs[key] = globby.sync(patterns).map(filename => ({ | |
filename, | |
content: null, | |
parsed: null, | |
lastModified: null, | |
modified: true | |
})); | |
}); | |
} | |
apply(compiler) { | |
compiler.plugin('emit', (compilation, callback) => { | |
const result = (async () => { | |
const inputs = await this.updateInputs(compiler, compilation); | |
const result = await this.runTransforms(compiler, compilation); | |
return result; | |
})(); | |
result.then(() => callback(), err => callback(err)); | |
}); | |
} | |
updateInputs(compiler, compilation) { | |
const updateFile = async (file, key) => { | |
// Update full file path from current compiler. | |
file.path = path.join(compiler.context, file.filename); | |
// Add the file to the dependency watch list | |
compilation.fileDependencies.push(file.path); | |
// Work out whether this file has been modified. | |
const currentModified = compilation.fileTimestamps[file.path]; | |
file.modified = !file.lastModified || file.lastModified < currentModified; | |
file.lastModified = currentModified; | |
if (file.modified) { | |
// If modified, load & parse the file. | |
file.content = await readFile(file.filename); | |
file.parsed = await this.options.parser({ | |
key, | |
file, | |
compiler, | |
compilation | |
}); | |
} | |
}; | |
// Return a promise with a flat set of all pending file updates. | |
return Promise.all( | |
Object.entries(this.inputs).reduce( | |
(pending, [key, files]) => | |
pending.concat(files.map(file => updateFile(file, key))), | |
[] | |
) | |
); | |
} | |
runTransforms(compiler, compilation) { | |
const runTransform = async transform => { | |
// Transform can be async, so await. | |
const pending = await transform({ | |
inputs: this.inputs, | |
compiler, | |
compilation | |
}); | |
// Each array item from transform can be async, so await those too. | |
const result = await Promise.all(pending); | |
// Finally, add the generated assets to the compilation. | |
result.forEach(([name, content]) => { | |
compilation.assets[name] = { | |
source: () => content, | |
size: () => content.length | |
}; | |
}); | |
}; | |
// Return a promise to run all the transforms. | |
return Promise.all(this.options.transforms.map(runTransform)); | |
} | |
} | |
module.exports = ContentTransformerPlugin; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment