lix-website/themes/lix/assets/bootstrap/node_modules/unified/index.js
2024-04-26 22:49:34 -06:00

461 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict'
var bail = require('bail')
var buffer = require('is-buffer')
var extend = require('extend')
var plain = require('is-plain-obj')
var trough = require('trough')
var vfile = require('vfile')
// Expose a frozen processor.
module.exports = unified().freeze()
var slice = [].slice
var own = {}.hasOwnProperty
// Process pipeline.
var pipeline = trough()
.use(pipelineParse)
.use(pipelineRun)
.use(pipelineStringify)
function pipelineParse(p, ctx) {
ctx.tree = p.parse(ctx.file)
}
function pipelineRun(p, ctx, next) {
p.run(ctx.tree, ctx.file, done)
function done(error, tree, file) {
if (error) {
next(error)
} else {
ctx.tree = tree
ctx.file = file
next()
}
}
}
function pipelineStringify(p, ctx) {
var result = p.stringify(ctx.tree, ctx.file)
if (result === undefined || result === null) {
// Empty.
} else if (typeof result === 'string' || buffer(result)) {
if ('value' in ctx.file) {
ctx.file.value = result
}
ctx.file.contents = result
} else {
ctx.file.result = result
}
}
// Function to create the first processor.
function unified() {
var attachers = []
var transformers = trough()
var namespace = {}
var freezeIndex = -1
var frozen
// Data management.
processor.data = data
// Lock.
processor.freeze = freeze
// Plugins.
processor.attachers = attachers
processor.use = use
// API.
processor.parse = parse
processor.stringify = stringify
processor.run = run
processor.runSync = runSync
processor.process = process
processor.processSync = processSync
// Expose.
return processor
// Create a new processor based on the processor in the current scope.
function processor() {
var destination = unified()
var index = -1
while (++index < attachers.length) {
destination.use.apply(null, attachers[index])
}
destination.data(extend(true, {}, namespace))
return destination
}
// Freeze: used to signal a processor that has finished configuration.
//
// For example, take unified itself: its frozen.
// Plugins should not be added to it.
// Rather, it should be extended, by invoking it, before modifying it.
//
// In essence, always invoke this when exporting a processor.
function freeze() {
var values
var transformer
if (frozen) {
return processor
}
while (++freezeIndex < attachers.length) {
values = attachers[freezeIndex]
if (values[1] === false) {
continue
}
if (values[1] === true) {
values[1] = undefined
}
transformer = values[0].apply(processor, values.slice(1))
if (typeof transformer === 'function') {
transformers.use(transformer)
}
}
frozen = true
freezeIndex = Infinity
return processor
}
// Data management.
// Getter / setter for processor-specific informtion.
function data(key, value) {
if (typeof key === 'string') {
// Set `key`.
if (arguments.length === 2) {
assertUnfrozen('data', frozen)
namespace[key] = value
return processor
}
// Get `key`.
return (own.call(namespace, key) && namespace[key]) || null
}
// Set space.
if (key) {
assertUnfrozen('data', frozen)
namespace = key
return processor
}
// Get space.
return namespace
}
// Plugin management.
//
// Pass it:
// * an attacher and options,
// * a preset,
// * a list of presets, attachers, and arguments (list of attachers and
// options).
function use(value) {
var settings
assertUnfrozen('use', frozen)
if (value === null || value === undefined) {
// Empty.
} else if (typeof value === 'function') {
addPlugin.apply(null, arguments)
} else if (typeof value === 'object') {
if ('length' in value) {
addList(value)
} else {
addPreset(value)
}
} else {
throw new Error('Expected usable value, not `' + value + '`')
}
if (settings) {
namespace.settings = extend(namespace.settings || {}, settings)
}
return processor
function addPreset(result) {
addList(result.plugins)
if (result.settings) {
settings = extend(settings || {}, result.settings)
}
}
function add(value) {
if (typeof value === 'function') {
addPlugin(value)
} else if (typeof value === 'object') {
if ('length' in value) {
addPlugin.apply(null, value)
} else {
addPreset(value)
}
} else {
throw new Error('Expected usable value, not `' + value + '`')
}
}
function addList(plugins) {
var index = -1
if (plugins === null || plugins === undefined) {
// Empty.
} else if (typeof plugins === 'object' && 'length' in plugins) {
while (++index < plugins.length) {
add(plugins[index])
}
} else {
throw new Error('Expected a list of plugins, not `' + plugins + '`')
}
}
function addPlugin(plugin, value) {
var entry = find(plugin)
if (entry) {
if (plain(entry[1]) && plain(value)) {
value = extend(true, entry[1], value)
}
entry[1] = value
} else {
attachers.push(slice.call(arguments))
}
}
}
function find(plugin) {
var index = -1
while (++index < attachers.length) {
if (attachers[index][0] === plugin) {
return attachers[index]
}
}
}
// Parse a file (in string or vfile representation) into a unist node using
// the `Parser` on the processor.
function parse(doc) {
var file = vfile(doc)
var Parser
freeze()
Parser = processor.Parser
assertParser('parse', Parser)
if (newable(Parser, 'parse')) {
return new Parser(String(file), file).parse()
}
return Parser(String(file), file) // eslint-disable-line new-cap
}
// Run transforms on a unist node representation of a file (in string or
// vfile representation), async.
function run(node, file, cb) {
assertNode(node)
freeze()
if (!cb && typeof file === 'function') {
cb = file
file = null
}
if (!cb) {
return new Promise(executor)
}
executor(null, cb)
function executor(resolve, reject) {
transformers.run(node, vfile(file), done)
function done(error, tree, file) {
tree = tree || node
if (error) {
reject(error)
} else if (resolve) {
resolve(tree)
} else {
cb(null, tree, file)
}
}
}
}
// Run transforms on a unist node representation of a file (in string or
// vfile representation), sync.
function runSync(node, file) {
var result
var complete
run(node, file, done)
assertDone('runSync', 'run', complete)
return result
function done(error, tree) {
complete = true
result = tree
bail(error)
}
}
// Stringify a unist node representation of a file (in string or vfile
// representation) into a string using the `Compiler` on the processor.
function stringify(node, doc) {
var file = vfile(doc)
var Compiler
freeze()
Compiler = processor.Compiler
assertCompiler('stringify', Compiler)
assertNode(node)
if (newable(Compiler, 'compile')) {
return new Compiler(node, file).compile()
}
return Compiler(node, file) // eslint-disable-line new-cap
}
// Parse a file (in string or vfile representation) into a unist node using
// the `Parser` on the processor, then run transforms on that node, and
// compile the resulting node using the `Compiler` on the processor, and
// store that result on the vfile.
function process(doc, cb) {
freeze()
assertParser('process', processor.Parser)
assertCompiler('process', processor.Compiler)
if (!cb) {
return new Promise(executor)
}
executor(null, cb)
function executor(resolve, reject) {
var file = vfile(doc)
pipeline.run(processor, {file: file}, done)
function done(error) {
if (error) {
reject(error)
} else if (resolve) {
resolve(file)
} else {
cb(null, file)
}
}
}
}
// Process the given document (in string or vfile representation), sync.
function processSync(doc) {
var file
var complete
freeze()
assertParser('processSync', processor.Parser)
assertCompiler('processSync', processor.Compiler)
file = vfile(doc)
process(file, done)
assertDone('processSync', 'process', complete)
return file
function done(error) {
complete = true
bail(error)
}
}
}
// Check if `value` is a constructor.
function newable(value, name) {
return (
typeof value === 'function' &&
value.prototype &&
// A function with keys in its prototype is probably a constructor.
// Classes prototype methods are not enumerable, so we check if some value
// exists in the prototype.
(keys(value.prototype) || name in value.prototype)
)
}
// Check if `value` is an object with keys.
function keys(value) {
var key
for (key in value) {
return true
}
return false
}
// Assert a parser is available.
function assertParser(name, Parser) {
if (typeof Parser !== 'function') {
throw new Error('Cannot `' + name + '` without `Parser`')
}
}
// Assert a compiler is available.
function assertCompiler(name, Compiler) {
if (typeof Compiler !== 'function') {
throw new Error('Cannot `' + name + '` without `Compiler`')
}
}
// Assert the processor is not frozen.
function assertUnfrozen(name, frozen) {
if (frozen) {
throw new Error(
'Cannot invoke `' +
name +
'` on a frozen processor.\nCreate a new processor first, by invoking it: use `processor()` instead of `processor`.'
)
}
}
// Assert `node` is a unist node.
function assertNode(node) {
if (!node || typeof node.type !== 'string') {
throw new Error('Expected node, got `' + node + '`')
}
}
// Assert that `complete` is `true`.
function assertDone(name, asyncName, complete) {
if (!complete) {
throw new Error(
'`' + name + '` finished async. Use `' + asyncName + '` instead'
)
}
}