@gram-data/gram-parse
Version:
parse text into gram data graphs
1,814 lines (1,495 loc) • 111 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = global || self, factory((global.gram = global.gram || {}, global.gram.parse = {})));
}(this, (function (exports) { 'use strict';
var bail_1 = bail;
function bail(err) {
if (err) {
throw err
}
}
/*!
* Determine if an object is a Buffer
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
var isBuffer = function isBuffer (obj) {
return obj != null && obj.constructor != null &&
typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
};
var hasOwn = Object.prototype.hasOwnProperty;
var toStr = Object.prototype.toString;
var defineProperty = Object.defineProperty;
var gOPD = Object.getOwnPropertyDescriptor;
var isArray = function isArray(arr) {
if (typeof Array.isArray === 'function') {
return Array.isArray(arr);
}
return toStr.call(arr) === '[object Array]';
};
var isPlainObject = function isPlainObject(obj) {
if (!obj || toStr.call(obj) !== '[object Object]') {
return false;
}
var hasOwnConstructor = hasOwn.call(obj, 'constructor');
var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');
// Not own constructor property must be Object
if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
return false;
}
// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
var key;
for (key in obj) { /**/ }
return typeof key === 'undefined' || hasOwn.call(obj, key);
};
// If name is '__proto__', and Object.defineProperty is available, define __proto__ as an own property on target
var setProperty = function setProperty(target, options) {
if (defineProperty && options.name === '__proto__') {
defineProperty(target, options.name, {
enumerable: true,
configurable: true,
value: options.newValue,
writable: true
});
} else {
target[options.name] = options.newValue;
}
};
// Return undefined instead of __proto__ if '__proto__' is not an own property
var getProperty = function getProperty(obj, name) {
if (name === '__proto__') {
if (!hasOwn.call(obj, name)) {
return void 0;
} else if (gOPD) {
// In early versions of node, obj['__proto__'] is buggy when obj has
// __proto__ as an own property. Object.getOwnPropertyDescriptor() works.
return gOPD(obj, name).value;
}
}
return obj[name];
};
var extend = function extend() {
var options, name, src, copy, copyIsArray, clone;
var target = arguments[0];
var i = 1;
var length = arguments.length;
var deep = false;
// Handle a deep copy situation
if (typeof target === 'boolean') {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}
if (target == null || (typeof target !== 'object' && typeof target !== 'function')) {
target = {};
}
for (; i < length; ++i) {
options = arguments[i];
// Only deal with non-null/undefined values
if (options != null) {
// Extend the base object
for (name in options) {
src = getProperty(target, name);
copy = getProperty(options, name);
// Prevent never-ending loop
if (target !== copy) {
// Recurse if we're merging plain objects or arrays
if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
if (copyIsArray) {
copyIsArray = false;
clone = src && isArray(src) ? src : [];
} else {
clone = src && isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
setProperty(target, { name: name, newValue: extend(deep, clone, copy) });
// Don't bring in undefined values
} else if (typeof copy !== 'undefined') {
setProperty(target, { name: name, newValue: copy });
}
}
}
}
}
// Return the modified object
return target;
};
var isPlainObj = value => {
if (Object.prototype.toString.call(value) !== '[object Object]') {
return false;
}
const prototype = Object.getPrototypeOf(value);
return prototype === null || prototype === Object.prototype;
};
var slice = [].slice;
var wrap_1 = wrap;
// Wrap `fn`.
// Can be sync or async; return a promise, receive a completion handler, return
// new values and errors.
function wrap(fn, callback) {
var invoked;
return wrapped
function wrapped() {
var params = slice.call(arguments, 0);
var callback = fn.length > params.length;
var result;
if (callback) {
params.push(done);
}
try {
result = fn.apply(null, params);
} catch (error) {
// Well, this is quite the pickle.
// `fn` received a callback and invoked it (thus continuing the pipeline),
// but later also threw an error.
// We’re not about to restart the pipeline again, so the only thing left
// to do is to throw the thing instead.
if (callback && invoked) {
throw error
}
return done(error)
}
if (!callback) {
if (result && typeof result.then === 'function') {
result.then(then, done);
} else if (result instanceof Error) {
done(result);
} else {
then(result);
}
}
}
// Invoke `next`, only once.
function done() {
if (!invoked) {
invoked = true;
callback.apply(null, arguments);
}
}
// Invoke `done` with one value.
// Tracks if an error is passed, too.
function then(value) {
done(null, value);
}
}
var trough_1 = trough;
trough.wrap = wrap_1;
var slice$1 = [].slice;
// Create new middleware.
function trough() {
var fns = [];
var middleware = {};
middleware.run = run;
middleware.use = use;
return middleware
// Run `fns`. Last argument must be a completion handler.
function run() {
var index = -1;
var input = slice$1.call(arguments, 0, -1);
var done = arguments[arguments.length - 1];
if (typeof done !== 'function') {
throw new Error('Expected function as last argument, not ' + done)
}
next.apply(null, [null].concat(input));
// Run the next `fn`, if any.
function next(err) {
var fn = fns[++index];
var params = slice$1.call(arguments, 0);
var values = params.slice(1);
var length = input.length;
var pos = -1;
if (err) {
done(err);
return
}
// Copy non-nully input into values.
while (++pos < length) {
if (values[pos] === null || values[pos] === undefined) {
values[pos] = input[pos];
}
}
input = values;
// Next or done.
if (fn) {
wrap_1(fn, next).apply(null, input);
} else {
done.apply(null, [null].concat(input));
}
}
}
// Add `fn` to the list.
function use(fn) {
if (typeof fn !== 'function') {
throw new Error('Expected `fn` to be a function, not ' + fn)
}
fns.push(fn);
return middleware
}
}
var own = {}.hasOwnProperty;
var unistUtilStringifyPosition = stringify;
function stringify(value) {
// Nothing.
if (!value || typeof value !== 'object') {
return ''
}
// Node.
if (own.call(value, 'position') || own.call(value, 'type')) {
return position(value.position)
}
// Position.
if (own.call(value, 'start') || own.call(value, 'end')) {
return position(value)
}
// Point.
if (own.call(value, 'line') || own.call(value, 'column')) {
return point(value)
}
// ?
return ''
}
function point(point) {
if (!point || typeof point !== 'object') {
point = {};
}
return index(point.line) + ':' + index(point.column)
}
function position(pos) {
if (!pos || typeof pos !== 'object') {
pos = {};
}
return point(pos.start) + '-' + point(pos.end)
}
function index(value) {
return value && typeof value === 'number' ? value : 1
}
var vfileMessage = VMessage;
// Inherit from `Error#`.
function VMessagePrototype() {}
VMessagePrototype.prototype = Error.prototype;
VMessage.prototype = new VMessagePrototype();
// Message properties.
var proto = VMessage.prototype;
proto.file = '';
proto.name = '';
proto.reason = '';
proto.message = '';
proto.stack = '';
proto.fatal = null;
proto.column = null;
proto.line = null;
// Construct a new VMessage.
//
// Note: We cannot invoke `Error` on the created context, as that adds readonly
// `line` and `column` attributes on Safari 9, thus throwing and failing the
// data.
function VMessage(reason, position, origin) {
var parts;
var range;
var location;
if (typeof position === 'string') {
origin = position;
position = null;
}
parts = parseOrigin(origin);
range = unistUtilStringifyPosition(position) || '1:1';
location = {
start: {line: null, column: null},
end: {line: null, column: null}
};
// Node.
if (position && position.position) {
position = position.position;
}
if (position) {
// Position.
if (position.start) {
location = position;
position = position.start;
} else {
// Point.
location.start = position;
}
}
if (reason.stack) {
this.stack = reason.stack;
reason = reason.message;
}
this.message = reason;
this.name = range;
this.reason = reason;
this.line = position ? position.line : null;
this.column = position ? position.column : null;
this.location = location;
this.source = parts[0];
this.ruleId = parts[1];
}
function parseOrigin(origin) {
var result = [null, null];
var index;
if (typeof origin === 'string') {
index = origin.indexOf(':');
if (index === -1) {
result[1] = origin;
} else {
result[0] = origin.slice(0, index);
result[1] = origin.slice(index + 1);
}
}
return result
}
// A derivative work based on:
// <https://github.com/browserify/path-browserify>.
// Which is licensed:
//
// MIT License
//
// Copyright (c) 2013 James Halliday
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// A derivative work based on:
//
// Parts of that are extracted from Node’s internal `path` module:
// <https://github.com/nodejs/node/blob/master/lib/path.js>.
// Which is licensed:
//
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var basename_1 = basename;
var dirname_1 = dirname;
var extname_1 = extname;
var join_1 = join;
var sep = '/';
function basename(path, ext) {
var start = 0;
var end = -1;
var index;
var firstNonSlashEnd;
var seenNonSlash;
var extIndex;
if (ext !== undefined && typeof ext !== 'string') {
throw new TypeError('"ext" argument must be a string')
}
assertPath(path);
index = path.length;
if (ext === undefined || !ext.length || ext.length > path.length) {
while (index--) {
if (path.charCodeAt(index) === 47 /* `/` */) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now.
if (seenNonSlash) {
start = index + 1;
break
}
} else if (end < 0) {
// We saw the first non-path separator, mark this as the end of our
// path component.
seenNonSlash = true;
end = index + 1;
}
}
return end < 0 ? '' : path.slice(start, end)
}
if (ext === path) {
return ''
}
firstNonSlashEnd = -1;
extIndex = ext.length - 1;
while (index--) {
if (path.charCodeAt(index) === 47 /* `/` */) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now.
if (seenNonSlash) {
start = index + 1;
break
}
} else {
if (firstNonSlashEnd < 0) {
// We saw the first non-path separator, remember this index in case
// we need it if the extension ends up not matching.
seenNonSlash = true;
firstNonSlashEnd = index + 1;
}
if (extIndex > -1) {
// Try to match the explicit extension.
if (path.charCodeAt(index) === ext.charCodeAt(extIndex--)) {
if (extIndex < 0) {
// We matched the extension, so mark this as the end of our path
// component
end = index;
}
} else {
// Extension does not match, so our result is the entire path
// component
extIndex = -1;
end = firstNonSlashEnd;
}
}
}
}
if (start === end) {
end = firstNonSlashEnd;
} else if (end < 0) {
end = path.length;
}
return path.slice(start, end)
}
function dirname(path) {
var end;
var unmatchedSlash;
var index;
assertPath(path);
if (!path.length) {
return '.'
}
end = -1;
index = path.length;
// Prefix `--` is important to not run on `0`.
while (--index) {
if (path.charCodeAt(index) === 47 /* `/` */) {
if (unmatchedSlash) {
end = index;
break
}
} else if (!unmatchedSlash) {
// We saw the first non-path separator
unmatchedSlash = true;
}
}
return end < 0
? path.charCodeAt(0) === 47 /* `/` */
? '/'
: '.'
: end === 1 && path.charCodeAt(0) === 47 /* `/` */
? '//'
: path.slice(0, end)
}
function extname(path) {
var startDot = -1;
var startPart = 0;
var end = -1;
// Track the state of characters (if any) we see before our first dot and
// after any path separator we find.
var preDotState = 0;
var unmatchedSlash;
var code;
var index;
assertPath(path);
index = path.length;
while (index--) {
code = path.charCodeAt(index);
if (code === 47 /* `/` */) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now.
if (unmatchedSlash) {
startPart = index + 1;
break
}
continue
}
if (end < 0) {
// We saw the first non-path separator, mark this as the end of our
// extension.
unmatchedSlash = true;
end = index + 1;
}
if (code === 46 /* `.` */) {
// If this is our first dot, mark it as the start of our extension.
if (startDot < 0) {
startDot = index;
} else if (preDotState !== 1) {
preDotState = 1;
}
} else if (startDot > -1) {
// We saw a non-dot and non-path separator before our dot, so we should
// have a good chance at having a non-empty extension.
preDotState = -1;
}
}
if (
startDot < 0 ||
end < 0 ||
// We saw a non-dot character immediately before the dot.
preDotState === 0 ||
// The (right-most) trimmed path component is exactly `..`.
(preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)
) {
return ''
}
return path.slice(startDot, end)
}
function join() {
var index = -1;
var joined;
while (++index < arguments.length) {
assertPath(arguments[index]);
if (arguments[index]) {
joined =
joined === undefined
? arguments[index]
: joined + '/' + arguments[index];
}
}
return joined === undefined ? '.' : normalize(joined)
}
// Note: `normalize` is not exposed as `path.normalize`, so some code is
// manually removed from it.
function normalize(path) {
var absolute;
var value;
assertPath(path);
absolute = path.charCodeAt(0) === 47; /* `/` */
// Normalize the path according to POSIX rules.
value = normalizeString(path, !absolute);
if (!value.length && !absolute) {
value = '.';
}
if (value.length && path.charCodeAt(path.length - 1) === 47 /* / */) {
value += '/';
}
return absolute ? '/' + value : value
}
// Resolve `.` and `..` elements in a path with directory names.
function normalizeString(path, allowAboveRoot) {
var result = '';
var lastSegmentLength = 0;
var lastSlash = -1;
var dots = 0;
var index = -1;
var code;
var lastSlashIndex;
while (++index <= path.length) {
if (index < path.length) {
code = path.charCodeAt(index);
} else if (code === 47 /* `/` */) {
break
} else {
code = 47; /* `/` */
}
if (code === 47 /* `/` */) {
if (lastSlash === index - 1 || dots === 1) ; else if (lastSlash !== index - 1 && dots === 2) {
if (
result.length < 2 ||
lastSegmentLength !== 2 ||
result.charCodeAt(result.length - 1) !== 46 /* `.` */ ||
result.charCodeAt(result.length - 2) !== 46 /* `.` */
) {
if (result.length > 2) {
lastSlashIndex = result.lastIndexOf('/');
/* istanbul ignore else - No clue how to cover it. */
if (lastSlashIndex !== result.length - 1) {
if (lastSlashIndex < 0) {
result = '';
lastSegmentLength = 0;
} else {
result = result.slice(0, lastSlashIndex);
lastSegmentLength = result.length - 1 - result.lastIndexOf('/');
}
lastSlash = index;
dots = 0;
continue
}
} else if (result.length) {
result = '';
lastSegmentLength = 0;
lastSlash = index;
dots = 0;
continue
}
}
if (allowAboveRoot) {
result = result.length ? result + '/..' : '..';
lastSegmentLength = 2;
}
} else {
if (result.length) {
result += '/' + path.slice(lastSlash + 1, index);
} else {
result = path.slice(lastSlash + 1, index);
}
lastSegmentLength = index - lastSlash - 1;
}
lastSlash = index;
dots = 0;
} else if (code === 46 /* `.` */ && dots > -1) {
dots++;
} else {
dots = -1;
}
}
return result
}
function assertPath(path) {
if (typeof path !== 'string') {
throw new TypeError(
'Path must be a string. Received ' + JSON.stringify(path)
)
}
}
var minpath_browser = {
basename: basename_1,
dirname: dirname_1,
extname: extname_1,
join: join_1,
sep: sep
};
// Somewhat based on:
// <https://github.com/defunctzombie/node-process/blob/master/browser.js>.
// But I don’t think one tiny line of code can be copyrighted. 😅
var cwd_1 = cwd;
function cwd() {
return '/'
}
var minproc_browser = {
cwd: cwd_1
};
var core = VFile;
var own$1 = {}.hasOwnProperty;
// Order of setting (least specific to most), we need this because otherwise
// `{stem: 'a', path: '~/b.js'}` would throw, as a path is needed before a
// stem can be set.
var order = ['history', 'path', 'basename', 'stem', 'extname', 'dirname'];
VFile.prototype.toString = toString;
// Access full path (`~/index.min.js`).
Object.defineProperty(VFile.prototype, 'path', {get: getPath, set: setPath});
// Access parent path (`~`).
Object.defineProperty(VFile.prototype, 'dirname', {
get: getDirname,
set: setDirname
});
// Access basename (`index.min.js`).
Object.defineProperty(VFile.prototype, 'basename', {
get: getBasename,
set: setBasename
});
// Access extname (`.js`).
Object.defineProperty(VFile.prototype, 'extname', {
get: getExtname,
set: setExtname
});
// Access stem (`index.min`).
Object.defineProperty(VFile.prototype, 'stem', {get: getStem, set: setStem});
// Construct a new file.
function VFile(options) {
var prop;
var index;
if (!options) {
options = {};
} else if (typeof options === 'string' || isBuffer(options)) {
options = {contents: options};
} else if ('message' in options && 'messages' in options) {
return options
}
if (!(this instanceof VFile)) {
return new VFile(options)
}
this.data = {};
this.messages = [];
this.history = [];
this.cwd = minproc_browser.cwd();
// Set path related properties in the correct order.
index = -1;
while (++index < order.length) {
prop = order[index];
if (own$1.call(options, prop)) {
this[prop] = options[prop];
}
}
// Set non-path related properties.
for (prop in options) {
if (order.indexOf(prop) < 0) {
this[prop] = options[prop];
}
}
}
function getPath() {
return this.history[this.history.length - 1]
}
function setPath(path) {
assertNonEmpty(path, 'path');
if (this.path !== path) {
this.history.push(path);
}
}
function getDirname() {
return typeof this.path === 'string' ? minpath_browser.dirname(this.path) : undefined
}
function setDirname(dirname) {
assertPath$1(this.path, 'dirname');
this.path = minpath_browser.join(dirname || '', this.basename);
}
function getBasename() {
return typeof this.path === 'string' ? minpath_browser.basename(this.path) : undefined
}
function setBasename(basename) {
assertNonEmpty(basename, 'basename');
assertPart(basename, 'basename');
this.path = minpath_browser.join(this.dirname || '', basename);
}
function getExtname() {
return typeof this.path === 'string' ? minpath_browser.extname(this.path) : undefined
}
function setExtname(extname) {
assertPart(extname, 'extname');
assertPath$1(this.path, 'extname');
if (extname) {
if (extname.charCodeAt(0) !== 46 /* `.` */) {
throw new Error('`extname` must start with `.`')
}
if (extname.indexOf('.', 1) > -1) {
throw new Error('`extname` cannot contain multiple dots')
}
}
this.path = minpath_browser.join(this.dirname, this.stem + (extname || ''));
}
function getStem() {
return typeof this.path === 'string'
? minpath_browser.basename(this.path, this.extname)
: undefined
}
function setStem(stem) {
assertNonEmpty(stem, 'stem');
assertPart(stem, 'stem');
this.path = minpath_browser.join(this.dirname || '', stem + (this.extname || ''));
}
// Get the value of the file.
function toString(encoding) {
return (this.contents || '').toString(encoding)
}
// Assert that `part` is not a path (i.e., does not contain `p.sep`).
function assertPart(part, name) {
if (part && part.indexOf(minpath_browser.sep) > -1) {
throw new Error(
'`' + name + '` cannot be a path: did not expect `' + minpath_browser.sep + '`'
)
}
}
// Assert that `part` is not empty.
function assertNonEmpty(part, name) {
if (!part) {
throw new Error('`' + name + '` cannot be empty')
}
}
// Assert `path` exists.
function assertPath$1(path, name) {
if (!path) {
throw new Error('Setting `' + name + '` requires `path` to be set too')
}
}
var lib = core;
core.prototype.message = message;
core.prototype.info = info;
core.prototype.fail = fail;
// Create a message with `reason` at `position`.
// When an error is passed in as `reason`, copies the stack.
function message(reason, position, origin) {
var message = new vfileMessage(reason, position, origin);
if (this.path) {
message.name = this.path + ':' + message.name;
message.file = this.path;
}
message.fatal = false;
this.messages.push(message);
return message
}
// Fail: creates a vmessage, associates it with the file, and throws it.
function fail() {
var message = this.message.apply(this, arguments);
message.fatal = true;
throw message
}
// Info: creates a vmessage, associates it with the file, and marks the fatality
// as null.
function info() {
var message = this.message.apply(this, arguments);
message.fatal = null;
return message
}
var vfile = lib;
// Expose a frozen processor.
var unified_1 = unified().freeze();
var slice$2 = [].slice;
var own$2 = {}.hasOwnProperty;
// Process pipeline.
var pipeline = trough_1()
.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(err, tree, file) {
if (err) {
next(err);
} else {
ctx.tree = tree;
ctx.file = file;
next();
}
}
}
function pipelineStringify(p, ctx) {
var result = p.stringify(ctx.tree, ctx.file);
var file = ctx.file;
if (result === undefined || result === null) ; else if (typeof result === 'string' || isBuffer(result)) {
file.contents = result;
} else {
file.result = result;
}
}
// Function to create the first processor.
function unified() {
var attachers = [];
var transformers = trough_1();
var namespace = {};
var frozen = false;
var freezeIndex = -1;
// 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 length = attachers.length;
var index = -1;
while (++index < 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: it’s 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 plugin;
var options;
var transformer;
if (frozen) {
return processor
}
while (++freezeIndex < attachers.length) {
values = attachers[freezeIndex];
plugin = values[0];
options = values[1];
transformer = null;
if (options === false) {
continue
}
if (options === true) {
values[1] = undefined;
}
transformer = plugin.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$2.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) ; 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 length;
var index;
if (plugins === null || plugins === undefined) ; else if (typeof plugins === 'object' && 'length' in plugins) {
length = plugins.length;
index = -1;
while (++index < 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 (isPlainObj(entry[1]) && isPlainObj(value)) {
value = extend(entry[1], value);
}
entry[1] = value;
} else {
attachers.push(slice$2.call(arguments));
}
}
}
function find(plugin) {
var length = attachers.length;
var index = -1;
var entry;
while (++index < length) {
entry = attachers[index];
if (entry[0] === plugin) {
return entry
}
}
}
// 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(err, tree, file) {
tree = tree || node;
if (err) {
reject(err);
} 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 complete = false;
var result;
run(node, file, done);
assertDone('runSync', 'run', complete);
return result
function done(err, tree) {
complete = true;
bail_1(err);
result = tree;
}
}
// 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(err) {
if (err) {
reject(err);
} else if (resolve) {
resolve(file);
} else {
cb(null, file);
}
}
}
}
// Process the given document (in string or vfile representation), sync.
function processSync(doc) {
var complete = false;
var file;
freeze();
assertParser('processSync', processor.Parser);
assertCompiler('processSync', processor.Compiler);
file = vfile(doc);
process(file, done);
assertDone('processSync', 'process', complete);
return file
function done(err) {
complete = true;
bail_1(err);
}
}
}
// 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'
)
}
}
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var nearley = createCommonjsModule(function (module) {
(function(root, factory) {
if ( module.exports) {
module.exports = factory();
} else {
root.nearley = factory();
}
}(commonjsGlobal, function() {
function Rule(name, symbols, postprocess) {
this.id = ++Rule.highestId;
this.name = name;
this.symbols = symbols; // a list of literal | regex class | nonterminal
this.postprocess = postprocess;
return this;
}
Rule.highestId = 0;
Rule.prototype.toString = function(withCursorAt) {
var symbolSequence = (typeof withCursorAt === "undefined")
? this.symbols.map(getSymbolShortDisplay).join(' ')
: ( this.symbols.slice(0, withCursorAt).map(getSymbolShortDisplay).join(' ')
+ " ● "
+ this.symbols.slice(withCursorAt).map(getSymbolShortDisplay).join(' ') );
return this.name + " → " + symbolSequence;
};
// a State is a rule at a position from a given starting point in the input stream (reference)
function State(rule, dot, reference, wantedBy) {
this.rule = rule;
this.dot = dot;
this.reference = reference;
this.data = [];
this.wantedBy = wantedBy;
this.isComplete = this.dot === rule.symbols.length;
}
State.prototype.toString = function() {
return "{" + this.rule.toString(this.dot) + "}, from: " + (this.reference || 0);
};
State.prototype.nextState = function(child) {
var state = new State(this.rule, this.dot + 1, this.reference, this.wantedBy);
state.left = this;
state.right = child;
if (state.isComplete) {
state.data = state.build();
// Having right set here will prevent the right state and its children
// form being garbage collected
state.right = undefined;
}
return state;
};
State.prototype.build = function() {
var children = [];
var node = this;
do {
children.push(node.right.data);
node = node.left;
} while (node.left);
children.reverse();
return children;
};
State.prototype.finish = function() {
if (this.rule.postprocess) {
this.data = this.rule.postprocess(this.data, this.reference, Parser.fail);
}
};
function Column(grammar, index) {
this.grammar = grammar;
this.index = index;
this.states = [];
this.wants = {}; // states indexed by the non-terminal they expect
this.scannable = []; // list of states that expect a token
this.completed = {}; // states that are nullable
}
Column.prototype.process = function(nextColumn) {
var states = this.states;
var wants = this.wants;
var completed = this.completed;
for (var w = 0; w < states.length; w++) { // nb. we push() during iteration
var state = states[w];
if (state.isComplete) {
state.finish();
if (state.data !== Parser.fail) {
// complete
var wantedBy = state.wantedBy;
for (var i = wantedBy.length; i--; ) { // this line is hot
var left = wantedBy[i];
this.complete(left, state);
}
// special-case nullables
if (state.reference === this.index) {
// make sure future predictors of this rule get completed.
var exp = state.rule.name;
(this.completed[exp] = this.completed[exp] || []).push(state);
}
}
} else {
// queue scannable states
var exp = state.rule.symbols[state.dot];
if (typeof exp !== 'string') {
this.scannable.push(state);
continue;
}
// predict
if (wants[exp]) {
wants[exp].push(state);
if (completed.hasOwnProperty(exp)) {
var nulls = completed[exp];
for (var i = 0; i < nulls.length; i++) {
var right = nulls[i];
this.complete(state, right);
}
}
} else {
wants[exp] = [state];
this.predict(exp);
}
}
}
};
Column.prototype.predict = function(exp) {
var rules = this.grammar.byName[exp] || [];
for (var i = 0; i < rules.length; i++) {
var r = rules[i];
var wantedBy = this.wants[exp];
var s = new State(r, 0, this.index, wantedBy);
this.states.push(s);
}
};
Column.prototype.complete = function(left, right) {
var copy = left.nextState(right);
this.states.push(copy);
};
function Grammar(rules, start) {
this.rules = rules;
this.start = start || this.rules[0].name;
var byName = this.byName = {};
this.rules.forEach(function(rule) {
if (!byName.hasOwnProperty(rule.name)) {
byName[rule.name] = [];
}
byName[rule.name].push(rule);
});
}
// So we can allow passing (rules, start) directly to Parser for backwards compatibility
Grammar.fromCompiled = function(rules, start) {
var lexer = rules.Lexer;
if (rules.ParserStart) {
start = rules.ParserStart;
rules = rules.ParserRules;
}
var rules = rules.map(function (r) { return (new Rule(r.name, r.symbols, r.postprocess)); });
var g = new Grammar(rules, start);
g.lexer = lexer; // nb. storing lexer on Grammar is iffy, but unavoidable
return g;
};
function StreamLexer() {
this.reset("");
}
StreamLexer.prototype.reset = function(data, state) {
this.buffer = data;
this.index = 0;
this.line = state ? state.line : 1;
this.lastLineBreak = state ? -state.col : 0;
};
StreamLexer.prototype.next = function() {
if (this.index < this.buffer.length) {
var ch = this.buffer[this.index++];
if (ch === '\n') {
this.line += 1;
this.lastLineBreak = this.index;
}
return {value: ch};
}
};
StreamLexer.prototype.save = function() {
return {
line: this.line,
col: this.index - this.lastLineBreak,
}
};
StreamLexer.prototype.formatError = function(token, message) {
// nb. this gets called after consuming the offending token,
// so the culprit is index-1
var buffer = this.buffer;
if (typeof buffer === 'string') {
var lines = buffer
.split("\n")
.slice(
Math.max(0, this.line - 5),
this.line
);
var nextLineBreak = buffer.indexOf('\n', this.index);
if (nextLineBreak === -1) nextLineBreak = buffer.length;
var col = this.index - this.lastLineBreak;
var lastLineDigits = String(this.line).length;
message += " at line " + this.line + " col " + col + ":\n\n";
message += lines
.map(function(line, i) {
return pad(this.line - lines.length + i + 1, lastLineDigits) + " " + line;
}, this)
.join("\n");
message += "\n" + pad("", lastLineDigits + col) + "^\n";
return message;
} else {
return message + " at index " + (this.index - 1);
}
function pad(n, length) {
var s = String(n);
return Array(length - s.length + 1).join(" ") + s;
}
};
function Parser(rules, start, options) {
if (rules instanceof Grammar) {
var grammar = rules;
var options = start;
} else {
var grammar = Grammar.fromCompiled(rules, start);
}
this.grammar = grammar;
// Read options
this.options = {
keepHistory: false,
lexer: grammar.lexer || new StreamLexer,
};
for (var key in (options || {})) {
this.options[key] = options[key];
}
// Setup lexer
this.lexer = this.options.lexer;
this.lexerState = undefined;
// Setup a table
var column = new Column(grammar, 0);
var table = this.table = [column];
// I could be expecting anything.
column.wants[grammar.start] = [];
column.predict(grammar.start);
// TODO what if start rule is nullable?
column.process();
this.current = 0; // token index
}
// create a reserved token for indicating a parse fail
Parser.fail = {};
Parser.prototype.feed = function(chunk) {
var lexer = this.lexer;
lexer.reset(chunk, this.lexerState);
var token;
while (true) {
try {
token = lexer.next();
if (!token) {
break;
}
} catch (e) {
// Create the next column so that the error reporter
// can display the correctly predicted states.
var nextColumn = new Column(this.grammar, this.current + 1);
this.table.push(nextColumn);
var err = new Error(this.reportLexerError(e));
err.offset = this.current;
err.token = e.token;
throw err;
}
// We add new states to table[current+1]
var column = this.table[this.current];
// GC unused states
if (!this.options.keepHistory) {
delete this.table[this.current - 1];
}
var n = this.current + 1;
var nextColumn = new Column(this.grammar, n);
this.table.push(nextColumn);
// Advance all tokens that expect the symbol
var literal = token.text !== undefined ? token.text : token.value;
var value = lexer.constructor === StreamLexer ? token.value : token;
var scannable = column.scannable;
for (var w = scannable.length; w--; ) {
var state = scannable[w];
var expect = state.rule.symbols[state.dot];