makestatic-manifest
Version:
Generates a JSON manifest of the output files
138 lines (115 loc) • 3.13 kB
JavaScript
const path = require('path')
/**
* Generates a JSON manifest of the output files that is written to
* `manifest.json` in the output directory.
*
* @class Manifest
*
* @see /docs/api/core-standard/ Core Standard
*/
class Manifest {
/**
* Creates a Manifest plugin.
*
* The structure of the generated document is:
*
* ```json
* {
* "algorithm": "sha512",
* "files": {}
* }
* ```
*
* Each key in the `files` map is the path of the file relative to the output
* directory. Each file entry contains the fields:
*
* + `source` the original source file.
* + `hash` object containing checksums.
* + `size` the size of the file in bytes.
*
* Transient files are not included in the manifest.
*
* @constructor Manifest
* @param {Object} context the processing context.
* @param {Object} [options] the plugin options.
*
* @option {String=sha512} algorithm checksum generation algorithm.
*/
constructor (context, options = {}) {
this.data = {}
this.algorithm = options.algorithm || 'sha512'
}
/**
* Adds files to the manifest data.
*
* If the `manifest` context option is not set this function call is a noop.
*
* @function sources
* @member Manifest
* @param {Object} file the current file.
* @param {Object} context the processing context.
*/
sources (file, context) {
if (!context.options.manifest) {
return
}
const log = context.log
// can be configured with no resolve phase
// in which case we skip the file
if (file.transient || !file.output) {
return
}
// relative to output directory
let key = file.output
key = key.replace(context.options.output, '')
key = key.replace(/^\//, '')
let name = file.name
if (path.isAbsolute(name)) {
name = file.relative(context.options.input)
}
const item = {
source: name,
hash: file.hash
}
if (file.content) {
if (!item.hash.content) {
item.hash.content = file.checksum(file.content, this.algorithm)
}
item.size = Buffer.byteLength(file.content)
}
log.debug('[manifest] %s', key)
this.data[key] = item
}
/**
* Adds the manifest file to the pipeline.
*
* If the `manifest` context option is not set this function call is a noop.
*
* @function after
* @member Manifest
* @param {Object} context the processing context.
*/
after (context) {
const log = context.log
const manifest = context.options.manifest
if (!manifest) {
return
}
let output = path.join(context.options.output, manifest)
const content = {
algorithm: this.algorithm,
files: this.data
}
context.manifest = content
const out = context.getFile({
name: manifest,
output: output,
content: JSON.stringify(content, undefined, 2)
})
log.debug(
`[manifest] ${out.path} (${Object.keys(this.data).length} files)`)
// add file to the list
context.list.add(out)
}
}
module.exports = Manifest