mirror of
https://github.com/imezx/Warp.git
synced 2025-06-20 21:49:17 +00:00
63726 lines
1.7 MiB
63726 lines
1.7 MiB
import { createHash } from 'crypto';
|
||
import { createRequire } from 'module';
|
||
import path$q, { win32, posix as posix$1, resolve as resolve$1, parse as parse$d, basename, join, dirname, normalize as normalize$3 } from 'path';
|
||
import path$r from 'node:path';
|
||
import process$2, { stdin, stdout } from 'node:process';
|
||
import 'node:fs/promises';
|
||
import { fileURLToPath } from 'node:url';
|
||
import fs$u from 'node:fs';
|
||
import require$$3, { fileURLToPath as fileURLToPath$1, URL as URL$1, pathToFileURL } from 'url';
|
||
import * as fs$t from 'fs';
|
||
import fs__default, { realpathSync as realpathSync$1, lstatSync, readdir as readdir$4, readdirSync as readdirSync$1, readlinkSync, unlinkSync, rmdirSync, chmodSync, statSync as statSync$1, renameSync, rmSync } from 'fs';
|
||
import { lstat as lstat$4, readdir as readdir$5, readlink, realpath } from 'fs/promises';
|
||
import require$$0$7, { EventEmitter } from 'events';
|
||
import require$$0$3 from 'stream';
|
||
import require$$1, { StringDecoder } from 'string_decoder';
|
||
import require$$0$4, { inspect } from 'util';
|
||
import require$$0$6, { tmpdir } from 'os';
|
||
import require$$5 from 'assert';
|
||
import { normalizePath, loadConfigFromFile, createLogger, mergeConfig as mergeConfig$1, searchForWorkspaceRoot, build as build$1, transformWithEsbuild, createServer as createServer$1 } from 'vite';
|
||
import require$$2$1 from 'readline';
|
||
import require$$0$8 from 'child_process';
|
||
import require$$1$1 from 'zlib';
|
||
import f$1 from 'node:readline';
|
||
import { WriteStream } from 'node:tty';
|
||
import require$$0$9 from 'buffer';
|
||
import require$$0$5 from 'tty';
|
||
import require$$4 from 'net';
|
||
import http from 'http';
|
||
import * as qs from 'querystring';
|
||
import require$$0$2 from 'constants';
|
||
import { webcrypto } from 'node:crypto';
|
||
import { getHighlighter, bundledLanguages, addClassToHast, isPlaintext, isSpecialLang } from 'shikiji';
|
||
import { transformerNotationDiff, transformerNotationFocus, transformerNotationHighlight, transformerNotationErrorLevel, transformerCompactLineOptions } from 'shikiji-transformers';
|
||
import MiniSearch from 'minisearch';
|
||
|
||
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
||
|
||
function getDefaultExportFromCjs (x) {
|
||
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
||
}
|
||
|
||
function getAugmentedNamespace(n) {
|
||
if (n.__esModule) return n;
|
||
var f = n.default;
|
||
if (typeof f == "function") {
|
||
var a = function a () {
|
||
if (this instanceof a) {
|
||
return Reflect.construct(f, arguments, this.constructor);
|
||
}
|
||
return f.apply(this, arguments);
|
||
};
|
||
a.prototype = f.prototype;
|
||
} else a = {};
|
||
Object.defineProperty(a, '__esModule', {value: true});
|
||
Object.keys(n).forEach(function (k) {
|
||
var d = Object.getOwnPropertyDescriptor(n, k);
|
||
Object.defineProperty(a, k, d.get ? d : {
|
||
enumerable: true,
|
||
get: function () {
|
||
return n[k];
|
||
}
|
||
});
|
||
});
|
||
return a;
|
||
}
|
||
|
||
var fs$s = {};
|
||
|
||
var universalify$1 = {};
|
||
|
||
universalify$1.fromCallback = function (fn) {
|
||
return Object.defineProperty(function (...args) {
|
||
if (typeof args[args.length - 1] === 'function') fn.apply(this, args);
|
||
else {
|
||
return new Promise((resolve, reject) => {
|
||
args.push((err, res) => (err != null) ? reject(err) : resolve(res));
|
||
fn.apply(this, args);
|
||
})
|
||
}
|
||
}, 'name', { value: fn.name })
|
||
};
|
||
|
||
universalify$1.fromPromise = function (fn) {
|
||
return Object.defineProperty(function (...args) {
|
||
const cb = args[args.length - 1];
|
||
if (typeof cb !== 'function') return fn.apply(this, args)
|
||
else {
|
||
args.pop();
|
||
fn.apply(this, args).then(r => cb(null, r), cb);
|
||
}
|
||
}, 'name', { value: fn.name })
|
||
};
|
||
|
||
var constants$5 = require$$0$2;
|
||
|
||
var origCwd = process.cwd;
|
||
var cwd = null;
|
||
|
||
var platform$1 = process.env.GRACEFUL_FS_PLATFORM || process.platform;
|
||
|
||
process.cwd = function() {
|
||
if (!cwd)
|
||
cwd = origCwd.call(process);
|
||
return cwd
|
||
};
|
||
try {
|
||
process.cwd();
|
||
} catch (er) {}
|
||
|
||
// This check is needed until node.js 12 is required
|
||
if (typeof process.chdir === 'function') {
|
||
var chdir = process.chdir;
|
||
process.chdir = function (d) {
|
||
cwd = null;
|
||
chdir.call(process, d);
|
||
};
|
||
if (Object.setPrototypeOf) Object.setPrototypeOf(process.chdir, chdir);
|
||
}
|
||
|
||
var polyfills$1 = patch$1;
|
||
|
||
function patch$1 (fs) {
|
||
// (re-)implement some things that are known busted or missing.
|
||
|
||
// lchmod, broken prior to 0.6.2
|
||
// back-port the fix here.
|
||
if (constants$5.hasOwnProperty('O_SYMLINK') &&
|
||
process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
|
||
patchLchmod(fs);
|
||
}
|
||
|
||
// lutimes implementation, or no-op
|
||
if (!fs.lutimes) {
|
||
patchLutimes(fs);
|
||
}
|
||
|
||
// https://github.com/isaacs/node-graceful-fs/issues/4
|
||
// Chown should not fail on einval or eperm if non-root.
|
||
// It should not fail on enosys ever, as this just indicates
|
||
// that a fs doesn't support the intended operation.
|
||
|
||
fs.chown = chownFix(fs.chown);
|
||
fs.fchown = chownFix(fs.fchown);
|
||
fs.lchown = chownFix(fs.lchown);
|
||
|
||
fs.chmod = chmodFix(fs.chmod);
|
||
fs.fchmod = chmodFix(fs.fchmod);
|
||
fs.lchmod = chmodFix(fs.lchmod);
|
||
|
||
fs.chownSync = chownFixSync(fs.chownSync);
|
||
fs.fchownSync = chownFixSync(fs.fchownSync);
|
||
fs.lchownSync = chownFixSync(fs.lchownSync);
|
||
|
||
fs.chmodSync = chmodFixSync(fs.chmodSync);
|
||
fs.fchmodSync = chmodFixSync(fs.fchmodSync);
|
||
fs.lchmodSync = chmodFixSync(fs.lchmodSync);
|
||
|
||
fs.stat = statFix(fs.stat);
|
||
fs.fstat = statFix(fs.fstat);
|
||
fs.lstat = statFix(fs.lstat);
|
||
|
||
fs.statSync = statFixSync(fs.statSync);
|
||
fs.fstatSync = statFixSync(fs.fstatSync);
|
||
fs.lstatSync = statFixSync(fs.lstatSync);
|
||
|
||
// if lchmod/lchown do not exist, then make them no-ops
|
||
if (fs.chmod && !fs.lchmod) {
|
||
fs.lchmod = function (path, mode, cb) {
|
||
if (cb) process.nextTick(cb);
|
||
};
|
||
fs.lchmodSync = function () {};
|
||
}
|
||
if (fs.chown && !fs.lchown) {
|
||
fs.lchown = function (path, uid, gid, cb) {
|
||
if (cb) process.nextTick(cb);
|
||
};
|
||
fs.lchownSync = function () {};
|
||
}
|
||
|
||
// on Windows, A/V software can lock the directory, causing this
|
||
// to fail with an EACCES or EPERM if the directory contains newly
|
||
// created files. Try again on failure, for up to 60 seconds.
|
||
|
||
// Set the timeout this long because some Windows Anti-Virus, such as Parity
|
||
// bit9, may lock files for up to a minute, causing npm package install
|
||
// failures. Also, take care to yield the scheduler. Windows scheduling gives
|
||
// CPU to a busy looping process, which can cause the program causing the lock
|
||
// contention to be starved of CPU by node, so the contention doesn't resolve.
|
||
if (platform$1 === "win32") {
|
||
fs.rename = typeof fs.rename !== 'function' ? fs.rename
|
||
: (function (fs$rename) {
|
||
function rename (from, to, cb) {
|
||
var start = Date.now();
|
||
var backoff = 0;
|
||
fs$rename(from, to, function CB (er) {
|
||
if (er
|
||
&& (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY")
|
||
&& Date.now() - start < 60000) {
|
||
setTimeout(function() {
|
||
fs.stat(to, function (stater, st) {
|
||
if (stater && stater.code === "ENOENT")
|
||
fs$rename(from, to, CB);
|
||
else
|
||
cb(er);
|
||
});
|
||
}, backoff);
|
||
if (backoff < 100)
|
||
backoff += 10;
|
||
return;
|
||
}
|
||
if (cb) cb(er);
|
||
});
|
||
}
|
||
if (Object.setPrototypeOf) Object.setPrototypeOf(rename, fs$rename);
|
||
return rename
|
||
})(fs.rename);
|
||
}
|
||
|
||
// if read() returns EAGAIN, then just try it again.
|
||
fs.read = typeof fs.read !== 'function' ? fs.read
|
||
: (function (fs$read) {
|
||
function read (fd, buffer, offset, length, position, callback_) {
|
||
var callback;
|
||
if (callback_ && typeof callback_ === 'function') {
|
||
var eagCounter = 0;
|
||
callback = function (er, _, __) {
|
||
if (er && er.code === 'EAGAIN' && eagCounter < 10) {
|
||
eagCounter ++;
|
||
return fs$read.call(fs, fd, buffer, offset, length, position, callback)
|
||
}
|
||
callback_.apply(this, arguments);
|
||
};
|
||
}
|
||
return fs$read.call(fs, fd, buffer, offset, length, position, callback)
|
||
}
|
||
|
||
// This ensures `util.promisify` works as it does for native `fs.read`.
|
||
if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read);
|
||
return read
|
||
})(fs.read);
|
||
|
||
fs.readSync = typeof fs.readSync !== 'function' ? fs.readSync
|
||
: (function (fs$readSync) { return function (fd, buffer, offset, length, position) {
|
||
var eagCounter = 0;
|
||
while (true) {
|
||
try {
|
||
return fs$readSync.call(fs, fd, buffer, offset, length, position)
|
||
} catch (er) {
|
||
if (er.code === 'EAGAIN' && eagCounter < 10) {
|
||
eagCounter ++;
|
||
continue
|
||
}
|
||
throw er
|
||
}
|
||
}
|
||
}})(fs.readSync);
|
||
|
||
function patchLchmod (fs) {
|
||
fs.lchmod = function (path, mode, callback) {
|
||
fs.open( path
|
||
, constants$5.O_WRONLY | constants$5.O_SYMLINK
|
||
, mode
|
||
, function (err, fd) {
|
||
if (err) {
|
||
if (callback) callback(err);
|
||
return
|
||
}
|
||
// prefer to return the chmod error, if one occurs,
|
||
// but still try to close, and report closing errors if they occur.
|
||
fs.fchmod(fd, mode, function (err) {
|
||
fs.close(fd, function(err2) {
|
||
if (callback) callback(err || err2);
|
||
});
|
||
});
|
||
});
|
||
};
|
||
|
||
fs.lchmodSync = function (path, mode) {
|
||
var fd = fs.openSync(path, constants$5.O_WRONLY | constants$5.O_SYMLINK, mode);
|
||
|
||
// prefer to return the chmod error, if one occurs,
|
||
// but still try to close, and report closing errors if they occur.
|
||
var threw = true;
|
||
var ret;
|
||
try {
|
||
ret = fs.fchmodSync(fd, mode);
|
||
threw = false;
|
||
} finally {
|
||
if (threw) {
|
||
try {
|
||
fs.closeSync(fd);
|
||
} catch (er) {}
|
||
} else {
|
||
fs.closeSync(fd);
|
||
}
|
||
}
|
||
return ret
|
||
};
|
||
}
|
||
|
||
function patchLutimes (fs) {
|
||
if (constants$5.hasOwnProperty("O_SYMLINK") && fs.futimes) {
|
||
fs.lutimes = function (path, at, mt, cb) {
|
||
fs.open(path, constants$5.O_SYMLINK, function (er, fd) {
|
||
if (er) {
|
||
if (cb) cb(er);
|
||
return
|
||
}
|
||
fs.futimes(fd, at, mt, function (er) {
|
||
fs.close(fd, function (er2) {
|
||
if (cb) cb(er || er2);
|
||
});
|
||
});
|
||
});
|
||
};
|
||
|
||
fs.lutimesSync = function (path, at, mt) {
|
||
var fd = fs.openSync(path, constants$5.O_SYMLINK);
|
||
var ret;
|
||
var threw = true;
|
||
try {
|
||
ret = fs.futimesSync(fd, at, mt);
|
||
threw = false;
|
||
} finally {
|
||
if (threw) {
|
||
try {
|
||
fs.closeSync(fd);
|
||
} catch (er) {}
|
||
} else {
|
||
fs.closeSync(fd);
|
||
}
|
||
}
|
||
return ret
|
||
};
|
||
|
||
} else if (fs.futimes) {
|
||
fs.lutimes = function (_a, _b, _c, cb) { if (cb) process.nextTick(cb); };
|
||
fs.lutimesSync = function () {};
|
||
}
|
||
}
|
||
|
||
function chmodFix (orig) {
|
||
if (!orig) return orig
|
||
return function (target, mode, cb) {
|
||
return orig.call(fs, target, mode, function (er) {
|
||
if (chownErOk(er)) er = null;
|
||
if (cb) cb.apply(this, arguments);
|
||
})
|
||
}
|
||
}
|
||
|
||
function chmodFixSync (orig) {
|
||
if (!orig) return orig
|
||
return function (target, mode) {
|
||
try {
|
||
return orig.call(fs, target, mode)
|
||
} catch (er) {
|
||
if (!chownErOk(er)) throw er
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
function chownFix (orig) {
|
||
if (!orig) return orig
|
||
return function (target, uid, gid, cb) {
|
||
return orig.call(fs, target, uid, gid, function (er) {
|
||
if (chownErOk(er)) er = null;
|
||
if (cb) cb.apply(this, arguments);
|
||
})
|
||
}
|
||
}
|
||
|
||
function chownFixSync (orig) {
|
||
if (!orig) return orig
|
||
return function (target, uid, gid) {
|
||
try {
|
||
return orig.call(fs, target, uid, gid)
|
||
} catch (er) {
|
||
if (!chownErOk(er)) throw er
|
||
}
|
||
}
|
||
}
|
||
|
||
function statFix (orig) {
|
||
if (!orig) return orig
|
||
// Older versions of Node erroneously returned signed integers for
|
||
// uid + gid.
|
||
return function (target, options, cb) {
|
||
if (typeof options === 'function') {
|
||
cb = options;
|
||
options = null;
|
||
}
|
||
function callback (er, stats) {
|
||
if (stats) {
|
||
if (stats.uid < 0) stats.uid += 0x100000000;
|
||
if (stats.gid < 0) stats.gid += 0x100000000;
|
||
}
|
||
if (cb) cb.apply(this, arguments);
|
||
}
|
||
return options ? orig.call(fs, target, options, callback)
|
||
: orig.call(fs, target, callback)
|
||
}
|
||
}
|
||
|
||
function statFixSync (orig) {
|
||
if (!orig) return orig
|
||
// Older versions of Node erroneously returned signed integers for
|
||
// uid + gid.
|
||
return function (target, options) {
|
||
var stats = options ? orig.call(fs, target, options)
|
||
: orig.call(fs, target);
|
||
if (stats) {
|
||
if (stats.uid < 0) stats.uid += 0x100000000;
|
||
if (stats.gid < 0) stats.gid += 0x100000000;
|
||
}
|
||
return stats;
|
||
}
|
||
}
|
||
|
||
// ENOSYS means that the fs doesn't support the op. Just ignore
|
||
// that, because it doesn't matter.
|
||
//
|
||
// if there's no getuid, or if getuid() is something other
|
||
// than 0, and the error is EINVAL or EPERM, then just ignore
|
||
// it.
|
||
//
|
||
// This specific case is a silent failure in cp, install, tar,
|
||
// and most other unix tools that manage permissions.
|
||
//
|
||
// When running as root, or if other types of errors are
|
||
// encountered, then it's strict.
|
||
function chownErOk (er) {
|
||
if (!er)
|
||
return true
|
||
|
||
if (er.code === "ENOSYS")
|
||
return true
|
||
|
||
var nonroot = !process.getuid || process.getuid() !== 0;
|
||
if (nonroot) {
|
||
if (er.code === "EINVAL" || er.code === "EPERM")
|
||
return true
|
||
}
|
||
|
||
return false
|
||
}
|
||
}
|
||
|
||
var Stream$1 = require$$0$3.Stream;
|
||
|
||
var legacyStreams = legacy$1;
|
||
|
||
function legacy$1 (fs) {
|
||
return {
|
||
ReadStream: ReadStream,
|
||
WriteStream: WriteStream
|
||
}
|
||
|
||
function ReadStream (path, options) {
|
||
if (!(this instanceof ReadStream)) return new ReadStream(path, options);
|
||
|
||
Stream$1.call(this);
|
||
|
||
var self = this;
|
||
|
||
this.path = path;
|
||
this.fd = null;
|
||
this.readable = true;
|
||
this.paused = false;
|
||
|
||
this.flags = 'r';
|
||
this.mode = 438; /*=0666*/
|
||
this.bufferSize = 64 * 1024;
|
||
|
||
options = options || {};
|
||
|
||
// Mixin options into this
|
||
var keys = Object.keys(options);
|
||
for (var index = 0, length = keys.length; index < length; index++) {
|
||
var key = keys[index];
|
||
this[key] = options[key];
|
||
}
|
||
|
||
if (this.encoding) this.setEncoding(this.encoding);
|
||
|
||
if (this.start !== undefined) {
|
||
if ('number' !== typeof this.start) {
|
||
throw TypeError('start must be a Number');
|
||
}
|
||
if (this.end === undefined) {
|
||
this.end = Infinity;
|
||
} else if ('number' !== typeof this.end) {
|
||
throw TypeError('end must be a Number');
|
||
}
|
||
|
||
if (this.start > this.end) {
|
||
throw new Error('start must be <= end');
|
||
}
|
||
|
||
this.pos = this.start;
|
||
}
|
||
|
||
if (this.fd !== null) {
|
||
process.nextTick(function() {
|
||
self._read();
|
||
});
|
||
return;
|
||
}
|
||
|
||
fs.open(this.path, this.flags, this.mode, function (err, fd) {
|
||
if (err) {
|
||
self.emit('error', err);
|
||
self.readable = false;
|
||
return;
|
||
}
|
||
|
||
self.fd = fd;
|
||
self.emit('open', fd);
|
||
self._read();
|
||
});
|
||
}
|
||
|
||
function WriteStream (path, options) {
|
||
if (!(this instanceof WriteStream)) return new WriteStream(path, options);
|
||
|
||
Stream$1.call(this);
|
||
|
||
this.path = path;
|
||
this.fd = null;
|
||
this.writable = true;
|
||
|
||
this.flags = 'w';
|
||
this.encoding = 'binary';
|
||
this.mode = 438; /*=0666*/
|
||
this.bytesWritten = 0;
|
||
|
||
options = options || {};
|
||
|
||
// Mixin options into this
|
||
var keys = Object.keys(options);
|
||
for (var index = 0, length = keys.length; index < length; index++) {
|
||
var key = keys[index];
|
||
this[key] = options[key];
|
||
}
|
||
|
||
if (this.start !== undefined) {
|
||
if ('number' !== typeof this.start) {
|
||
throw TypeError('start must be a Number');
|
||
}
|
||
if (this.start < 0) {
|
||
throw new Error('start must be >= zero');
|
||
}
|
||
|
||
this.pos = this.start;
|
||
}
|
||
|
||
this.busy = false;
|
||
this._queue = [];
|
||
|
||
if (this.fd === null) {
|
||
this._open = fs.open;
|
||
this._queue.push([this._open, this.path, this.flags, this.mode, undefined]);
|
||
this.flush();
|
||
}
|
||
}
|
||
}
|
||
|
||
var clone_1 = clone$1;
|
||
|
||
var getPrototypeOf = Object.getPrototypeOf || function (obj) {
|
||
return obj.__proto__
|
||
};
|
||
|
||
function clone$1 (obj) {
|
||
if (obj === null || typeof obj !== 'object')
|
||
return obj
|
||
|
||
if (obj instanceof Object)
|
||
var copy = { __proto__: getPrototypeOf(obj) };
|
||
else
|
||
var copy = Object.create(null);
|
||
|
||
Object.getOwnPropertyNames(obj).forEach(function (key) {
|
||
Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key));
|
||
});
|
||
|
||
return copy
|
||
}
|
||
|
||
var fs$r = fs__default;
|
||
var polyfills = polyfills$1;
|
||
var legacy = legacyStreams;
|
||
var clone = clone_1;
|
||
|
||
var util$2 = require$$0$4;
|
||
|
||
/* istanbul ignore next - node 0.x polyfill */
|
||
var gracefulQueue;
|
||
var previousSymbol;
|
||
|
||
/* istanbul ignore else - node 0.x polyfill */
|
||
if (typeof Symbol === 'function' && typeof Symbol.for === 'function') {
|
||
gracefulQueue = Symbol.for('graceful-fs.queue');
|
||
// This is used in testing by future versions
|
||
previousSymbol = Symbol.for('graceful-fs.previous');
|
||
} else {
|
||
gracefulQueue = '___graceful-fs.queue';
|
||
previousSymbol = '___graceful-fs.previous';
|
||
}
|
||
|
||
function noop$2 () {}
|
||
|
||
function publishQueue(context, queue) {
|
||
Object.defineProperty(context, gracefulQueue, {
|
||
get: function() {
|
||
return queue
|
||
}
|
||
});
|
||
}
|
||
|
||
var debug$5 = noop$2;
|
||
if (util$2.debuglog)
|
||
debug$5 = util$2.debuglog('gfs4');
|
||
else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || ''))
|
||
debug$5 = function() {
|
||
var m = util$2.format.apply(util$2, arguments);
|
||
m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ');
|
||
console.error(m);
|
||
};
|
||
|
||
// Once time initialization
|
||
if (!fs$r[gracefulQueue]) {
|
||
// This queue can be shared by multiple loaded instances
|
||
var queue$1 = commonjsGlobal[gracefulQueue] || [];
|
||
publishQueue(fs$r, queue$1);
|
||
|
||
// Patch fs.close/closeSync to shared queue version, because we need
|
||
// to retry() whenever a close happens *anywhere* in the program.
|
||
// This is essential when multiple graceful-fs instances are
|
||
// in play at the same time.
|
||
fs$r.close = (function (fs$close) {
|
||
function close (fd, cb) {
|
||
return fs$close.call(fs$r, fd, function (err) {
|
||
// This function uses the graceful-fs shared queue
|
||
if (!err) {
|
||
resetQueue();
|
||
}
|
||
|
||
if (typeof cb === 'function')
|
||
cb.apply(this, arguments);
|
||
})
|
||
}
|
||
|
||
Object.defineProperty(close, previousSymbol, {
|
||
value: fs$close
|
||
});
|
||
return close
|
||
})(fs$r.close);
|
||
|
||
fs$r.closeSync = (function (fs$closeSync) {
|
||
function closeSync (fd) {
|
||
// This function uses the graceful-fs shared queue
|
||
fs$closeSync.apply(fs$r, arguments);
|
||
resetQueue();
|
||
}
|
||
|
||
Object.defineProperty(closeSync, previousSymbol, {
|
||
value: fs$closeSync
|
||
});
|
||
return closeSync
|
||
})(fs$r.closeSync);
|
||
|
||
if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) {
|
||
process.on('exit', function() {
|
||
debug$5(fs$r[gracefulQueue]);
|
||
require$$5.equal(fs$r[gracefulQueue].length, 0);
|
||
});
|
||
}
|
||
}
|
||
|
||
if (!commonjsGlobal[gracefulQueue]) {
|
||
publishQueue(commonjsGlobal, fs$r[gracefulQueue]);
|
||
}
|
||
|
||
var gracefulFs = patch(clone(fs$r));
|
||
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs$r.__patched) {
|
||
gracefulFs = patch(fs$r);
|
||
fs$r.__patched = true;
|
||
}
|
||
|
||
function patch (fs) {
|
||
// Everything that references the open() function needs to be in here
|
||
polyfills(fs);
|
||
fs.gracefulify = patch;
|
||
|
||
fs.createReadStream = createReadStream;
|
||
fs.createWriteStream = createWriteStream;
|
||
var fs$readFile = fs.readFile;
|
||
fs.readFile = readFile;
|
||
function readFile (path, options, cb) {
|
||
if (typeof options === 'function')
|
||
cb = options, options = null;
|
||
|
||
return go$readFile(path, options, cb)
|
||
|
||
function go$readFile (path, options, cb, startTime) {
|
||
return fs$readFile(path, options, function (err) {
|
||
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
||
enqueue([go$readFile, [path, options, cb], err, startTime || Date.now(), Date.now()]);
|
||
else {
|
||
if (typeof cb === 'function')
|
||
cb.apply(this, arguments);
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
var fs$writeFile = fs.writeFile;
|
||
fs.writeFile = writeFile;
|
||
function writeFile (path, data, options, cb) {
|
||
if (typeof options === 'function')
|
||
cb = options, options = null;
|
||
|
||
return go$writeFile(path, data, options, cb)
|
||
|
||
function go$writeFile (path, data, options, cb, startTime) {
|
||
return fs$writeFile(path, data, options, function (err) {
|
||
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
||
enqueue([go$writeFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()]);
|
||
else {
|
||
if (typeof cb === 'function')
|
||
cb.apply(this, arguments);
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
var fs$appendFile = fs.appendFile;
|
||
if (fs$appendFile)
|
||
fs.appendFile = appendFile;
|
||
function appendFile (path, data, options, cb) {
|
||
if (typeof options === 'function')
|
||
cb = options, options = null;
|
||
|
||
return go$appendFile(path, data, options, cb)
|
||
|
||
function go$appendFile (path, data, options, cb, startTime) {
|
||
return fs$appendFile(path, data, options, function (err) {
|
||
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
||
enqueue([go$appendFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()]);
|
||
else {
|
||
if (typeof cb === 'function')
|
||
cb.apply(this, arguments);
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
var fs$copyFile = fs.copyFile;
|
||
if (fs$copyFile)
|
||
fs.copyFile = copyFile;
|
||
function copyFile (src, dest, flags, cb) {
|
||
if (typeof flags === 'function') {
|
||
cb = flags;
|
||
flags = 0;
|
||
}
|
||
return go$copyFile(src, dest, flags, cb)
|
||
|
||
function go$copyFile (src, dest, flags, cb, startTime) {
|
||
return fs$copyFile(src, dest, flags, function (err) {
|
||
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
||
enqueue([go$copyFile, [src, dest, flags, cb], err, startTime || Date.now(), Date.now()]);
|
||
else {
|
||
if (typeof cb === 'function')
|
||
cb.apply(this, arguments);
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
var fs$readdir = fs.readdir;
|
||
fs.readdir = readdir;
|
||
var noReaddirOptionVersions = /^v[0-5]\./;
|
||
function readdir (path, options, cb) {
|
||
if (typeof options === 'function')
|
||
cb = options, options = null;
|
||
|
||
var go$readdir = noReaddirOptionVersions.test(process.version)
|
||
? function go$readdir (path, options, cb, startTime) {
|
||
return fs$readdir(path, fs$readdirCallback(
|
||
path, options, cb, startTime
|
||
))
|
||
}
|
||
: function go$readdir (path, options, cb, startTime) {
|
||
return fs$readdir(path, options, fs$readdirCallback(
|
||
path, options, cb, startTime
|
||
))
|
||
};
|
||
|
||
return go$readdir(path, options, cb)
|
||
|
||
function fs$readdirCallback (path, options, cb, startTime) {
|
||
return function (err, files) {
|
||
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
||
enqueue([
|
||
go$readdir,
|
||
[path, options, cb],
|
||
err,
|
||
startTime || Date.now(),
|
||
Date.now()
|
||
]);
|
||
else {
|
||
if (files && files.sort)
|
||
files.sort();
|
||
|
||
if (typeof cb === 'function')
|
||
cb.call(this, err, files);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (process.version.substr(0, 4) === 'v0.8') {
|
||
var legStreams = legacy(fs);
|
||
ReadStream = legStreams.ReadStream;
|
||
WriteStream = legStreams.WriteStream;
|
||
}
|
||
|
||
var fs$ReadStream = fs.ReadStream;
|
||
if (fs$ReadStream) {
|
||
ReadStream.prototype = Object.create(fs$ReadStream.prototype);
|
||
ReadStream.prototype.open = ReadStream$open;
|
||
}
|
||
|
||
var fs$WriteStream = fs.WriteStream;
|
||
if (fs$WriteStream) {
|
||
WriteStream.prototype = Object.create(fs$WriteStream.prototype);
|
||
WriteStream.prototype.open = WriteStream$open;
|
||
}
|
||
|
||
Object.defineProperty(fs, 'ReadStream', {
|
||
get: function () {
|
||
return ReadStream
|
||
},
|
||
set: function (val) {
|
||
ReadStream = val;
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(fs, 'WriteStream', {
|
||
get: function () {
|
||
return WriteStream
|
||
},
|
||
set: function (val) {
|
||
WriteStream = val;
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
|
||
// legacy names
|
||
var FileReadStream = ReadStream;
|
||
Object.defineProperty(fs, 'FileReadStream', {
|
||
get: function () {
|
||
return FileReadStream
|
||
},
|
||
set: function (val) {
|
||
FileReadStream = val;
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
var FileWriteStream = WriteStream;
|
||
Object.defineProperty(fs, 'FileWriteStream', {
|
||
get: function () {
|
||
return FileWriteStream
|
||
},
|
||
set: function (val) {
|
||
FileWriteStream = val;
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
|
||
function ReadStream (path, options) {
|
||
if (this instanceof ReadStream)
|
||
return fs$ReadStream.apply(this, arguments), this
|
||
else
|
||
return ReadStream.apply(Object.create(ReadStream.prototype), arguments)
|
||
}
|
||
|
||
function ReadStream$open () {
|
||
var that = this;
|
||
open(that.path, that.flags, that.mode, function (err, fd) {
|
||
if (err) {
|
||
if (that.autoClose)
|
||
that.destroy();
|
||
|
||
that.emit('error', err);
|
||
} else {
|
||
that.fd = fd;
|
||
that.emit('open', fd);
|
||
that.read();
|
||
}
|
||
});
|
||
}
|
||
|
||
function WriteStream (path, options) {
|
||
if (this instanceof WriteStream)
|
||
return fs$WriteStream.apply(this, arguments), this
|
||
else
|
||
return WriteStream.apply(Object.create(WriteStream.prototype), arguments)
|
||
}
|
||
|
||
function WriteStream$open () {
|
||
var that = this;
|
||
open(that.path, that.flags, that.mode, function (err, fd) {
|
||
if (err) {
|
||
that.destroy();
|
||
that.emit('error', err);
|
||
} else {
|
||
that.fd = fd;
|
||
that.emit('open', fd);
|
||
}
|
||
});
|
||
}
|
||
|
||
function createReadStream (path, options) {
|
||
return new fs.ReadStream(path, options)
|
||
}
|
||
|
||
function createWriteStream (path, options) {
|
||
return new fs.WriteStream(path, options)
|
||
}
|
||
|
||
var fs$open = fs.open;
|
||
fs.open = open;
|
||
function open (path, flags, mode, cb) {
|
||
if (typeof mode === 'function')
|
||
cb = mode, mode = null;
|
||
|
||
return go$open(path, flags, mode, cb)
|
||
|
||
function go$open (path, flags, mode, cb, startTime) {
|
||
return fs$open(path, flags, mode, function (err, fd) {
|
||
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
|
||
enqueue([go$open, [path, flags, mode, cb], err, startTime || Date.now(), Date.now()]);
|
||
else {
|
||
if (typeof cb === 'function')
|
||
cb.apply(this, arguments);
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
return fs
|
||
}
|
||
|
||
function enqueue (elem) {
|
||
debug$5('ENQUEUE', elem[0].name, elem[1]);
|
||
fs$r[gracefulQueue].push(elem);
|
||
retry();
|
||
}
|
||
|
||
// keep track of the timeout between retry() calls
|
||
var retryTimer;
|
||
|
||
// reset the startTime and lastTime to now
|
||
// this resets the start of the 60 second overall timeout as well as the
|
||
// delay between attempts so that we'll retry these jobs sooner
|
||
function resetQueue () {
|
||
var now = Date.now();
|
||
for (var i = 0; i < fs$r[gracefulQueue].length; ++i) {
|
||
// entries that are only a length of 2 are from an older version, don't
|
||
// bother modifying those since they'll be retried anyway.
|
||
if (fs$r[gracefulQueue][i].length > 2) {
|
||
fs$r[gracefulQueue][i][3] = now; // startTime
|
||
fs$r[gracefulQueue][i][4] = now; // lastTime
|
||
}
|
||
}
|
||
// call retry to make sure we're actively processing the queue
|
||
retry();
|
||
}
|
||
|
||
function retry () {
|
||
// clear the timer and remove it to help prevent unintended concurrency
|
||
clearTimeout(retryTimer);
|
||
retryTimer = undefined;
|
||
|
||
if (fs$r[gracefulQueue].length === 0)
|
||
return
|
||
|
||
var elem = fs$r[gracefulQueue].shift();
|
||
var fn = elem[0];
|
||
var args = elem[1];
|
||
// these items may be unset if they were added by an older graceful-fs
|
||
var err = elem[2];
|
||
var startTime = elem[3];
|
||
var lastTime = elem[4];
|
||
|
||
// if we don't have a startTime we have no way of knowing if we've waited
|
||
// long enough, so go ahead and retry this item now
|
||
if (startTime === undefined) {
|
||
debug$5('RETRY', fn.name, args);
|
||
fn.apply(null, args);
|
||
} else if (Date.now() - startTime >= 60000) {
|
||
// it's been more than 60 seconds total, bail now
|
||
debug$5('TIMEOUT', fn.name, args);
|
||
var cb = args.pop();
|
||
if (typeof cb === 'function')
|
||
cb.call(null, err);
|
||
} else {
|
||
// the amount of time between the last attempt and right now
|
||
var sinceAttempt = Date.now() - lastTime;
|
||
// the amount of time between when we first tried, and when we last tried
|
||
// rounded up to at least 1
|
||
var sinceStart = Math.max(lastTime - startTime, 1);
|
||
// backoff. wait longer than the total time we've been retrying, but only
|
||
// up to a maximum of 100ms
|
||
var desiredDelay = Math.min(sinceStart * 1.2, 100);
|
||
// it's been long enough since the last retry, do it again
|
||
if (sinceAttempt >= desiredDelay) {
|
||
debug$5('RETRY', fn.name, args);
|
||
fn.apply(null, args.concat([startTime]));
|
||
} else {
|
||
// if we can't do this job yet, push it to the end of the queue
|
||
// and let the next iteration check again
|
||
fs$r[gracefulQueue].push(elem);
|
||
}
|
||
}
|
||
|
||
// schedule our next run if one isn't already scheduled
|
||
if (retryTimer === undefined) {
|
||
retryTimer = setTimeout(retry, 0);
|
||
}
|
||
}
|
||
|
||
(function (exports) {
|
||
// This is adapted from https://github.com/normalize/mz
|
||
// Copyright (c) 2014-2016 Jonathan Ong me@jongleberry.com and Contributors
|
||
const u = universalify$1.fromCallback;
|
||
const fs = gracefulFs;
|
||
|
||
const api = [
|
||
'access',
|
||
'appendFile',
|
||
'chmod',
|
||
'chown',
|
||
'close',
|
||
'copyFile',
|
||
'fchmod',
|
||
'fchown',
|
||
'fdatasync',
|
||
'fstat',
|
||
'fsync',
|
||
'ftruncate',
|
||
'futimes',
|
||
'lchmod',
|
||
'lchown',
|
||
'link',
|
||
'lstat',
|
||
'mkdir',
|
||
'mkdtemp',
|
||
'open',
|
||
'opendir',
|
||
'readdir',
|
||
'readFile',
|
||
'readlink',
|
||
'realpath',
|
||
'rename',
|
||
'rm',
|
||
'rmdir',
|
||
'stat',
|
||
'symlink',
|
||
'truncate',
|
||
'unlink',
|
||
'utimes',
|
||
'writeFile'
|
||
].filter(key => {
|
||
// Some commands are not available on some systems. Ex:
|
||
// fs.cp was added in Node.js v16.7.0
|
||
// fs.lchown is not available on at least some Linux
|
||
return typeof fs[key] === 'function'
|
||
});
|
||
|
||
// Export cloned fs:
|
||
Object.assign(exports, fs);
|
||
|
||
// Universalify async methods:
|
||
api.forEach(method => {
|
||
exports[method] = u(fs[method]);
|
||
});
|
||
|
||
// We differ from mz/fs in that we still ship the old, broken, fs.exists()
|
||
// since we are a drop-in replacement for the native module
|
||
exports.exists = function (filename, callback) {
|
||
if (typeof callback === 'function') {
|
||
return fs.exists(filename, callback)
|
||
}
|
||
return new Promise(resolve => {
|
||
return fs.exists(filename, resolve)
|
||
})
|
||
};
|
||
|
||
// fs.read(), fs.write(), fs.readv(), & fs.writev() need special treatment due to multiple callback args
|
||
|
||
exports.read = function (fd, buffer, offset, length, position, callback) {
|
||
if (typeof callback === 'function') {
|
||
return fs.read(fd, buffer, offset, length, position, callback)
|
||
}
|
||
return new Promise((resolve, reject) => {
|
||
fs.read(fd, buffer, offset, length, position, (err, bytesRead, buffer) => {
|
||
if (err) return reject(err)
|
||
resolve({ bytesRead, buffer });
|
||
});
|
||
})
|
||
};
|
||
|
||
// Function signature can be
|
||
// fs.write(fd, buffer[, offset[, length[, position]]], callback)
|
||
// OR
|
||
// fs.write(fd, string[, position[, encoding]], callback)
|
||
// We need to handle both cases, so we use ...args
|
||
exports.write = function (fd, buffer, ...args) {
|
||
if (typeof args[args.length - 1] === 'function') {
|
||
return fs.write(fd, buffer, ...args)
|
||
}
|
||
|
||
return new Promise((resolve, reject) => {
|
||
fs.write(fd, buffer, ...args, (err, bytesWritten, buffer) => {
|
||
if (err) return reject(err)
|
||
resolve({ bytesWritten, buffer });
|
||
});
|
||
})
|
||
};
|
||
|
||
// Function signature is
|
||
// s.readv(fd, buffers[, position], callback)
|
||
// We need to handle the optional arg, so we use ...args
|
||
exports.readv = function (fd, buffers, ...args) {
|
||
if (typeof args[args.length - 1] === 'function') {
|
||
return fs.readv(fd, buffers, ...args)
|
||
}
|
||
|
||
return new Promise((resolve, reject) => {
|
||
fs.readv(fd, buffers, ...args, (err, bytesRead, buffers) => {
|
||
if (err) return reject(err)
|
||
resolve({ bytesRead, buffers });
|
||
});
|
||
})
|
||
};
|
||
|
||
// Function signature is
|
||
// s.writev(fd, buffers[, position], callback)
|
||
// We need to handle the optional arg, so we use ...args
|
||
exports.writev = function (fd, buffers, ...args) {
|
||
if (typeof args[args.length - 1] === 'function') {
|
||
return fs.writev(fd, buffers, ...args)
|
||
}
|
||
|
||
return new Promise((resolve, reject) => {
|
||
fs.writev(fd, buffers, ...args, (err, bytesWritten, buffers) => {
|
||
if (err) return reject(err)
|
||
resolve({ bytesWritten, buffers });
|
||
});
|
||
})
|
||
};
|
||
|
||
// fs.realpath.native sometimes not available if fs is monkey-patched
|
||
if (typeof fs.realpath.native === 'function') {
|
||
exports.realpath.native = u(fs.realpath.native);
|
||
} else {
|
||
process.emitWarning(
|
||
'fs.realpath.native is not a function. Is fs being monkey-patched?',
|
||
'Warning', 'fs-extra-WARN0003'
|
||
);
|
||
}
|
||
} (fs$s));
|
||
|
||
var makeDir$1 = {};
|
||
|
||
var utils$u = {};
|
||
|
||
const path$p = path$q;
|
||
|
||
// https://github.com/nodejs/node/issues/8987
|
||
// https://github.com/libuv/libuv/pull/1088
|
||
utils$u.checkPath = function checkPath (pth) {
|
||
if (process.platform === 'win32') {
|
||
const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path$p.parse(pth).root, ''));
|
||
|
||
if (pathHasInvalidWinCharacters) {
|
||
const error = new Error(`Path contains invalid characters: ${pth}`);
|
||
error.code = 'EINVAL';
|
||
throw error
|
||
}
|
||
}
|
||
};
|
||
|
||
const fs$q = fs$s;
|
||
const { checkPath } = utils$u;
|
||
|
||
const getMode = options => {
|
||
const defaults = { mode: 0o777 };
|
||
if (typeof options === 'number') return options
|
||
return ({ ...defaults, ...options }).mode
|
||
};
|
||
|
||
makeDir$1.makeDir = async (dir, options) => {
|
||
checkPath(dir);
|
||
|
||
return fs$q.mkdir(dir, {
|
||
mode: getMode(options),
|
||
recursive: true
|
||
})
|
||
};
|
||
|
||
makeDir$1.makeDirSync = (dir, options) => {
|
||
checkPath(dir);
|
||
|
||
return fs$q.mkdirSync(dir, {
|
||
mode: getMode(options),
|
||
recursive: true
|
||
})
|
||
};
|
||
|
||
const u$f = universalify$1.fromPromise;
|
||
const { makeDir: _makeDir, makeDirSync } = makeDir$1;
|
||
const makeDir = u$f(_makeDir);
|
||
|
||
var mkdirs$2 = {
|
||
mkdirs: makeDir,
|
||
mkdirsSync: makeDirSync,
|
||
// alias
|
||
mkdirp: makeDir,
|
||
mkdirpSync: makeDirSync,
|
||
ensureDir: makeDir,
|
||
ensureDirSync: makeDirSync
|
||
};
|
||
|
||
const u$e = universalify$1.fromPromise;
|
||
const fs$p = fs$s;
|
||
|
||
function pathExists$6 (path) {
|
||
return fs$p.access(path).then(() => true).catch(() => false)
|
||
}
|
||
|
||
var pathExists_1 = {
|
||
pathExists: u$e(pathExists$6),
|
||
pathExistsSync: fs$p.existsSync
|
||
};
|
||
|
||
const fs$o = fs$s;
|
||
const u$d = universalify$1.fromPromise;
|
||
|
||
async function utimesMillis$1 (path, atime, mtime) {
|
||
// if (!HAS_MILLIS_RES) return fs.utimes(path, atime, mtime, callback)
|
||
const fd = await fs$o.open(path, 'r+');
|
||
|
||
let closeErr = null;
|
||
|
||
try {
|
||
await fs$o.futimes(fd, atime, mtime);
|
||
} finally {
|
||
try {
|
||
await fs$o.close(fd);
|
||
} catch (e) {
|
||
closeErr = e;
|
||
}
|
||
}
|
||
|
||
if (closeErr) {
|
||
throw closeErr
|
||
}
|
||
}
|
||
|
||
function utimesMillisSync$1 (path, atime, mtime) {
|
||
const fd = fs$o.openSync(path, 'r+');
|
||
fs$o.futimesSync(fd, atime, mtime);
|
||
return fs$o.closeSync(fd)
|
||
}
|
||
|
||
var utimes = {
|
||
utimesMillis: u$d(utimesMillis$1),
|
||
utimesMillisSync: utimesMillisSync$1
|
||
};
|
||
|
||
const fs$n = fs$s;
|
||
const path$o = path$q;
|
||
const u$c = universalify$1.fromPromise;
|
||
|
||
function getStats$1 (src, dest, opts) {
|
||
const statFunc = opts.dereference
|
||
? (file) => fs$n.stat(file, { bigint: true })
|
||
: (file) => fs$n.lstat(file, { bigint: true });
|
||
return Promise.all([
|
||
statFunc(src),
|
||
statFunc(dest).catch(err => {
|
||
if (err.code === 'ENOENT') return null
|
||
throw err
|
||
})
|
||
]).then(([srcStat, destStat]) => ({ srcStat, destStat }))
|
||
}
|
||
|
||
function getStatsSync (src, dest, opts) {
|
||
let destStat;
|
||
const statFunc = opts.dereference
|
||
? (file) => fs$n.statSync(file, { bigint: true })
|
||
: (file) => fs$n.lstatSync(file, { bigint: true });
|
||
const srcStat = statFunc(src);
|
||
try {
|
||
destStat = statFunc(dest);
|
||
} catch (err) {
|
||
if (err.code === 'ENOENT') return { srcStat, destStat: null }
|
||
throw err
|
||
}
|
||
return { srcStat, destStat }
|
||
}
|
||
|
||
async function checkPaths (src, dest, funcName, opts) {
|
||
const { srcStat, destStat } = await getStats$1(src, dest, opts);
|
||
if (destStat) {
|
||
if (areIdentical$2(srcStat, destStat)) {
|
||
const srcBaseName = path$o.basename(src);
|
||
const destBaseName = path$o.basename(dest);
|
||
if (funcName === 'move' &&
|
||
srcBaseName !== destBaseName &&
|
||
srcBaseName.toLowerCase() === destBaseName.toLowerCase()) {
|
||
return { srcStat, destStat, isChangingCase: true }
|
||
}
|
||
throw new Error('Source and destination must not be the same.')
|
||
}
|
||
if (srcStat.isDirectory() && !destStat.isDirectory()) {
|
||
throw new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`)
|
||
}
|
||
if (!srcStat.isDirectory() && destStat.isDirectory()) {
|
||
throw new Error(`Cannot overwrite directory '${dest}' with non-directory '${src}'.`)
|
||
}
|
||
}
|
||
|
||
if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
|
||
throw new Error(errMsg(src, dest, funcName))
|
||
}
|
||
|
||
return { srcStat, destStat }
|
||
}
|
||
|
||
function checkPathsSync (src, dest, funcName, opts) {
|
||
const { srcStat, destStat } = getStatsSync(src, dest, opts);
|
||
|
||
if (destStat) {
|
||
if (areIdentical$2(srcStat, destStat)) {
|
||
const srcBaseName = path$o.basename(src);
|
||
const destBaseName = path$o.basename(dest);
|
||
if (funcName === 'move' &&
|
||
srcBaseName !== destBaseName &&
|
||
srcBaseName.toLowerCase() === destBaseName.toLowerCase()) {
|
||
return { srcStat, destStat, isChangingCase: true }
|
||
}
|
||
throw new Error('Source and destination must not be the same.')
|
||
}
|
||
if (srcStat.isDirectory() && !destStat.isDirectory()) {
|
||
throw new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`)
|
||
}
|
||
if (!srcStat.isDirectory() && destStat.isDirectory()) {
|
||
throw new Error(`Cannot overwrite directory '${dest}' with non-directory '${src}'.`)
|
||
}
|
||
}
|
||
|
||
if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
|
||
throw new Error(errMsg(src, dest, funcName))
|
||
}
|
||
return { srcStat, destStat }
|
||
}
|
||
|
||
// recursively check if dest parent is a subdirectory of src.
|
||
// It works for all file types including symlinks since it
|
||
// checks the src and dest inodes. It starts from the deepest
|
||
// parent and stops once it reaches the src parent or the root path.
|
||
async function checkParentPaths (src, srcStat, dest, funcName) {
|
||
const srcParent = path$o.resolve(path$o.dirname(src));
|
||
const destParent = path$o.resolve(path$o.dirname(dest));
|
||
if (destParent === srcParent || destParent === path$o.parse(destParent).root) return
|
||
|
||
let destStat;
|
||
try {
|
||
destStat = await fs$n.stat(destParent, { bigint: true });
|
||
} catch (err) {
|
||
if (err.code === 'ENOENT') return
|
||
throw err
|
||
}
|
||
|
||
if (areIdentical$2(srcStat, destStat)) {
|
||
throw new Error(errMsg(src, dest, funcName))
|
||
}
|
||
|
||
return checkParentPaths(src, srcStat, destParent, funcName)
|
||
}
|
||
|
||
function checkParentPathsSync (src, srcStat, dest, funcName) {
|
||
const srcParent = path$o.resolve(path$o.dirname(src));
|
||
const destParent = path$o.resolve(path$o.dirname(dest));
|
||
if (destParent === srcParent || destParent === path$o.parse(destParent).root) return
|
||
let destStat;
|
||
try {
|
||
destStat = fs$n.statSync(destParent, { bigint: true });
|
||
} catch (err) {
|
||
if (err.code === 'ENOENT') return
|
||
throw err
|
||
}
|
||
if (areIdentical$2(srcStat, destStat)) {
|
||
throw new Error(errMsg(src, dest, funcName))
|
||
}
|
||
return checkParentPathsSync(src, srcStat, destParent, funcName)
|
||
}
|
||
|
||
function areIdentical$2 (srcStat, destStat) {
|
||
return destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev
|
||
}
|
||
|
||
// return true if dest is a subdir of src, otherwise false.
|
||
// It only checks the path strings.
|
||
function isSrcSubdir (src, dest) {
|
||
const srcArr = path$o.resolve(src).split(path$o.sep).filter(i => i);
|
||
const destArr = path$o.resolve(dest).split(path$o.sep).filter(i => i);
|
||
return srcArr.every((cur, i) => destArr[i] === cur)
|
||
}
|
||
|
||
function errMsg (src, dest, funcName) {
|
||
return `Cannot ${funcName} '${src}' to a subdirectory of itself, '${dest}'.`
|
||
}
|
||
|
||
var stat$7 = {
|
||
// checkPaths
|
||
checkPaths: u$c(checkPaths),
|
||
checkPathsSync,
|
||
// checkParent
|
||
checkParentPaths: u$c(checkParentPaths),
|
||
checkParentPathsSync,
|
||
// Misc
|
||
isSrcSubdir,
|
||
areIdentical: areIdentical$2
|
||
};
|
||
|
||
const fs$m = fs$s;
|
||
const path$n = path$q;
|
||
const { mkdirs: mkdirs$1 } = mkdirs$2;
|
||
const { pathExists: pathExists$5 } = pathExists_1;
|
||
const { utimesMillis } = utimes;
|
||
const stat$6 = stat$7;
|
||
|
||
async function copy$2 (src, dest, opts = {}) {
|
||
if (typeof opts === 'function') {
|
||
opts = { filter: opts };
|
||
}
|
||
|
||
opts.clobber = 'clobber' in opts ? !!opts.clobber : true; // default to true for now
|
||
opts.overwrite = 'overwrite' in opts ? !!opts.overwrite : opts.clobber; // overwrite falls back to clobber
|
||
|
||
// Warn about using preserveTimestamps on 32-bit node
|
||
if (opts.preserveTimestamps && process.arch === 'ia32') {
|
||
process.emitWarning(
|
||
'Using the preserveTimestamps option in 32-bit node is not recommended;\n\n' +
|
||
'\tsee https://github.com/jprichardson/node-fs-extra/issues/269',
|
||
'Warning', 'fs-extra-WARN0001'
|
||
);
|
||
}
|
||
|
||
const { srcStat, destStat } = await stat$6.checkPaths(src, dest, 'copy', opts);
|
||
|
||
await stat$6.checkParentPaths(src, srcStat, dest, 'copy');
|
||
|
||
const include = await runFilter(src, dest, opts);
|
||
|
||
if (!include) return
|
||
|
||
// check if the parent of dest exists, and create it if it doesn't exist
|
||
const destParent = path$n.dirname(dest);
|
||
const dirExists = await pathExists$5(destParent);
|
||
if (!dirExists) {
|
||
await mkdirs$1(destParent);
|
||
}
|
||
|
||
await getStatsAndPerformCopy(destStat, src, dest, opts);
|
||
}
|
||
|
||
async function runFilter (src, dest, opts) {
|
||
if (!opts.filter) return true
|
||
return opts.filter(src, dest)
|
||
}
|
||
|
||
async function getStatsAndPerformCopy (destStat, src, dest, opts) {
|
||
const statFn = opts.dereference ? fs$m.stat : fs$m.lstat;
|
||
const srcStat = await statFn(src);
|
||
|
||
if (srcStat.isDirectory()) return onDir$1(srcStat, destStat, src, dest, opts)
|
||
|
||
if (
|
||
srcStat.isFile() ||
|
||
srcStat.isCharacterDevice() ||
|
||
srcStat.isBlockDevice()
|
||
) return onFile$1(srcStat, destStat, src, dest, opts)
|
||
|
||
if (srcStat.isSymbolicLink()) return onLink$1(destStat, src, dest, opts)
|
||
if (srcStat.isSocket()) throw new Error(`Cannot copy a socket file: ${src}`)
|
||
if (srcStat.isFIFO()) throw new Error(`Cannot copy a FIFO pipe: ${src}`)
|
||
throw new Error(`Unknown file: ${src}`)
|
||
}
|
||
|
||
async function onFile$1 (srcStat, destStat, src, dest, opts) {
|
||
if (!destStat) return copyFile$1(srcStat, src, dest, opts)
|
||
|
||
if (opts.overwrite) {
|
||
await fs$m.unlink(dest);
|
||
return copyFile$1(srcStat, src, dest, opts)
|
||
}
|
||
if (opts.errorOnExist) {
|
||
throw new Error(`'${dest}' already exists`)
|
||
}
|
||
}
|
||
|
||
async function copyFile$1 (srcStat, src, dest, opts) {
|
||
await fs$m.copyFile(src, dest);
|
||
if (opts.preserveTimestamps) {
|
||
// Make sure the file is writable before setting the timestamp
|
||
// otherwise open fails with EPERM when invoked with 'r+'
|
||
// (through utimes call)
|
||
if (fileIsNotWritable$1(srcStat.mode)) {
|
||
await makeFileWritable$1(dest, srcStat.mode);
|
||
}
|
||
|
||
// Set timestamps and mode correspondingly
|
||
|
||
// Note that The initial srcStat.atime cannot be trusted
|
||
// because it is modified by the read(2) system call
|
||
// (See https://nodejs.org/api/fs.html#fs_stat_time_values)
|
||
const updatedSrcStat = await fs$m.stat(src);
|
||
await utimesMillis(dest, updatedSrcStat.atime, updatedSrcStat.mtime);
|
||
}
|
||
|
||
return fs$m.chmod(dest, srcStat.mode)
|
||
}
|
||
|
||
function fileIsNotWritable$1 (srcMode) {
|
||
return (srcMode & 0o200) === 0
|
||
}
|
||
|
||
function makeFileWritable$1 (dest, srcMode) {
|
||
return fs$m.chmod(dest, srcMode | 0o200)
|
||
}
|
||
|
||
async function onDir$1 (srcStat, destStat, src, dest, opts) {
|
||
// the dest directory might not exist, create it
|
||
if (!destStat) {
|
||
await fs$m.mkdir(dest);
|
||
}
|
||
|
||
const items = await fs$m.readdir(src);
|
||
|
||
// loop through the files in the current directory to copy everything
|
||
await Promise.all(items.map(async item => {
|
||
const srcItem = path$n.join(src, item);
|
||
const destItem = path$n.join(dest, item);
|
||
|
||
// skip the item if it is matches by the filter function
|
||
const include = await runFilter(srcItem, destItem, opts);
|
||
if (!include) return
|
||
|
||
const { destStat } = await stat$6.checkPaths(srcItem, destItem, 'copy', opts);
|
||
|
||
// If the item is a copyable file, `getStatsAndPerformCopy` will copy it
|
||
// If the item is a directory, `getStatsAndPerformCopy` will call `onDir` recursively
|
||
return getStatsAndPerformCopy(destStat, srcItem, destItem, opts)
|
||
}));
|
||
|
||
if (!destStat) {
|
||
await fs$m.chmod(dest, srcStat.mode);
|
||
}
|
||
}
|
||
|
||
async function onLink$1 (destStat, src, dest, opts) {
|
||
let resolvedSrc = await fs$m.readlink(src);
|
||
if (opts.dereference) {
|
||
resolvedSrc = path$n.resolve(process.cwd(), resolvedSrc);
|
||
}
|
||
if (!destStat) {
|
||
return fs$m.symlink(resolvedSrc, dest)
|
||
}
|
||
|
||
let resolvedDest = null;
|
||
try {
|
||
resolvedDest = await fs$m.readlink(dest);
|
||
} catch (e) {
|
||
// dest exists and is a regular file or directory,
|
||
// Windows may throw UNKNOWN error. If dest already exists,
|
||
// fs throws error anyway, so no need to guard against it here.
|
||
if (e.code === 'EINVAL' || e.code === 'UNKNOWN') return fs$m.symlink(resolvedSrc, dest)
|
||
throw e
|
||
}
|
||
if (opts.dereference) {
|
||
resolvedDest = path$n.resolve(process.cwd(), resolvedDest);
|
||
}
|
||
if (stat$6.isSrcSubdir(resolvedSrc, resolvedDest)) {
|
||
throw new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`)
|
||
}
|
||
|
||
// do not copy if src is a subdir of dest since unlinking
|
||
// dest in this case would result in removing src contents
|
||
// and therefore a broken symlink would be created.
|
||
if (stat$6.isSrcSubdir(resolvedDest, resolvedSrc)) {
|
||
throw new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`)
|
||
}
|
||
|
||
// copy the link
|
||
await fs$m.unlink(dest);
|
||
return fs$m.symlink(resolvedSrc, dest)
|
||
}
|
||
|
||
var copy_1 = copy$2;
|
||
|
||
const fs$l = gracefulFs;
|
||
const path$m = path$q;
|
||
const mkdirsSync$1 = mkdirs$2.mkdirsSync;
|
||
const utimesMillisSync = utimes.utimesMillisSync;
|
||
const stat$5 = stat$7;
|
||
|
||
function copySync$1 (src, dest, opts) {
|
||
if (typeof opts === 'function') {
|
||
opts = { filter: opts };
|
||
}
|
||
|
||
opts = opts || {};
|
||
opts.clobber = 'clobber' in opts ? !!opts.clobber : true; // default to true for now
|
||
opts.overwrite = 'overwrite' in opts ? !!opts.overwrite : opts.clobber; // overwrite falls back to clobber
|
||
|
||
// Warn about using preserveTimestamps on 32-bit node
|
||
if (opts.preserveTimestamps && process.arch === 'ia32') {
|
||
process.emitWarning(
|
||
'Using the preserveTimestamps option in 32-bit node is not recommended;\n\n' +
|
||
'\tsee https://github.com/jprichardson/node-fs-extra/issues/269',
|
||
'Warning', 'fs-extra-WARN0002'
|
||
);
|
||
}
|
||
|
||
const { srcStat, destStat } = stat$5.checkPathsSync(src, dest, 'copy', opts);
|
||
stat$5.checkParentPathsSync(src, srcStat, dest, 'copy');
|
||
if (opts.filter && !opts.filter(src, dest)) return
|
||
const destParent = path$m.dirname(dest);
|
||
if (!fs$l.existsSync(destParent)) mkdirsSync$1(destParent);
|
||
return getStats(destStat, src, dest, opts)
|
||
}
|
||
|
||
function getStats (destStat, src, dest, opts) {
|
||
const statSync = opts.dereference ? fs$l.statSync : fs$l.lstatSync;
|
||
const srcStat = statSync(src);
|
||
|
||
if (srcStat.isDirectory()) return onDir(srcStat, destStat, src, dest, opts)
|
||
else if (srcStat.isFile() ||
|
||
srcStat.isCharacterDevice() ||
|
||
srcStat.isBlockDevice()) return onFile(srcStat, destStat, src, dest, opts)
|
||
else if (srcStat.isSymbolicLink()) return onLink(destStat, src, dest, opts)
|
||
else if (srcStat.isSocket()) throw new Error(`Cannot copy a socket file: ${src}`)
|
||
else if (srcStat.isFIFO()) throw new Error(`Cannot copy a FIFO pipe: ${src}`)
|
||
throw new Error(`Unknown file: ${src}`)
|
||
}
|
||
|
||
function onFile (srcStat, destStat, src, dest, opts) {
|
||
if (!destStat) return copyFile(srcStat, src, dest, opts)
|
||
return mayCopyFile(srcStat, src, dest, opts)
|
||
}
|
||
|
||
function mayCopyFile (srcStat, src, dest, opts) {
|
||
if (opts.overwrite) {
|
||
fs$l.unlinkSync(dest);
|
||
return copyFile(srcStat, src, dest, opts)
|
||
} else if (opts.errorOnExist) {
|
||
throw new Error(`'${dest}' already exists`)
|
||
}
|
||
}
|
||
|
||
function copyFile (srcStat, src, dest, opts) {
|
||
fs$l.copyFileSync(src, dest);
|
||
if (opts.preserveTimestamps) handleTimestamps(srcStat.mode, src, dest);
|
||
return setDestMode(dest, srcStat.mode)
|
||
}
|
||
|
||
function handleTimestamps (srcMode, src, dest) {
|
||
// Make sure the file is writable before setting the timestamp
|
||
// otherwise open fails with EPERM when invoked with 'r+'
|
||
// (through utimes call)
|
||
if (fileIsNotWritable(srcMode)) makeFileWritable(dest, srcMode);
|
||
return setDestTimestamps(src, dest)
|
||
}
|
||
|
||
function fileIsNotWritable (srcMode) {
|
||
return (srcMode & 0o200) === 0
|
||
}
|
||
|
||
function makeFileWritable (dest, srcMode) {
|
||
return setDestMode(dest, srcMode | 0o200)
|
||
}
|
||
|
||
function setDestMode (dest, srcMode) {
|
||
return fs$l.chmodSync(dest, srcMode)
|
||
}
|
||
|
||
function setDestTimestamps (src, dest) {
|
||
// The initial srcStat.atime cannot be trusted
|
||
// because it is modified by the read(2) system call
|
||
// (See https://nodejs.org/api/fs.html#fs_stat_time_values)
|
||
const updatedSrcStat = fs$l.statSync(src);
|
||
return utimesMillisSync(dest, updatedSrcStat.atime, updatedSrcStat.mtime)
|
||
}
|
||
|
||
function onDir (srcStat, destStat, src, dest, opts) {
|
||
if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts)
|
||
return copyDir(src, dest, opts)
|
||
}
|
||
|
||
function mkDirAndCopy (srcMode, src, dest, opts) {
|
||
fs$l.mkdirSync(dest);
|
||
copyDir(src, dest, opts);
|
||
return setDestMode(dest, srcMode)
|
||
}
|
||
|
||
function copyDir (src, dest, opts) {
|
||
fs$l.readdirSync(src).forEach(item => copyDirItem(item, src, dest, opts));
|
||
}
|
||
|
||
function copyDirItem (item, src, dest, opts) {
|
||
const srcItem = path$m.join(src, item);
|
||
const destItem = path$m.join(dest, item);
|
||
if (opts.filter && !opts.filter(srcItem, destItem)) return
|
||
const { destStat } = stat$5.checkPathsSync(srcItem, destItem, 'copy', opts);
|
||
return getStats(destStat, srcItem, destItem, opts)
|
||
}
|
||
|
||
function onLink (destStat, src, dest, opts) {
|
||
let resolvedSrc = fs$l.readlinkSync(src);
|
||
if (opts.dereference) {
|
||
resolvedSrc = path$m.resolve(process.cwd(), resolvedSrc);
|
||
}
|
||
|
||
if (!destStat) {
|
||
return fs$l.symlinkSync(resolvedSrc, dest)
|
||
} else {
|
||
let resolvedDest;
|
||
try {
|
||
resolvedDest = fs$l.readlinkSync(dest);
|
||
} catch (err) {
|
||
// dest exists and is a regular file or directory,
|
||
// Windows may throw UNKNOWN error. If dest already exists,
|
||
// fs throws error anyway, so no need to guard against it here.
|
||
if (err.code === 'EINVAL' || err.code === 'UNKNOWN') return fs$l.symlinkSync(resolvedSrc, dest)
|
||
throw err
|
||
}
|
||
if (opts.dereference) {
|
||
resolvedDest = path$m.resolve(process.cwd(), resolvedDest);
|
||
}
|
||
if (stat$5.isSrcSubdir(resolvedSrc, resolvedDest)) {
|
||
throw new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`)
|
||
}
|
||
|
||
// prevent copy if src is a subdir of dest since unlinking
|
||
// dest in this case would result in removing src contents
|
||
// and therefore a broken symlink would be created.
|
||
if (stat$5.isSrcSubdir(resolvedDest, resolvedSrc)) {
|
||
throw new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`)
|
||
}
|
||
return copyLink(resolvedSrc, dest)
|
||
}
|
||
}
|
||
|
||
function copyLink (resolvedSrc, dest) {
|
||
fs$l.unlinkSync(dest);
|
||
return fs$l.symlinkSync(resolvedSrc, dest)
|
||
}
|
||
|
||
var copySync_1 = copySync$1;
|
||
|
||
const u$b = universalify$1.fromPromise;
|
||
var copy$1 = {
|
||
copy: u$b(copy_1),
|
||
copySync: copySync_1
|
||
};
|
||
|
||
const fs$k = gracefulFs;
|
||
const u$a = universalify$1.fromCallback;
|
||
|
||
function remove$2 (path, callback) {
|
||
fs$k.rm(path, { recursive: true, force: true }, callback);
|
||
}
|
||
|
||
function removeSync$1 (path) {
|
||
fs$k.rmSync(path, { recursive: true, force: true });
|
||
}
|
||
|
||
var remove_1 = {
|
||
remove: u$a(remove$2),
|
||
removeSync: removeSync$1
|
||
};
|
||
|
||
const u$9 = universalify$1.fromPromise;
|
||
const fs$j = fs$s;
|
||
const path$l = path$q;
|
||
const mkdir$4 = mkdirs$2;
|
||
const remove$1 = remove_1;
|
||
|
||
const emptyDir = u$9(async function emptyDir (dir) {
|
||
let items;
|
||
try {
|
||
items = await fs$j.readdir(dir);
|
||
} catch {
|
||
return mkdir$4.mkdirs(dir)
|
||
}
|
||
|
||
return Promise.all(items.map(item => remove$1.remove(path$l.join(dir, item))))
|
||
});
|
||
|
||
function emptyDirSync (dir) {
|
||
let items;
|
||
try {
|
||
items = fs$j.readdirSync(dir);
|
||
} catch {
|
||
return mkdir$4.mkdirsSync(dir)
|
||
}
|
||
|
||
items.forEach(item => {
|
||
item = path$l.join(dir, item);
|
||
remove$1.removeSync(item);
|
||
});
|
||
}
|
||
|
||
var empty = {
|
||
emptyDirSync,
|
||
emptydirSync: emptyDirSync,
|
||
emptyDir,
|
||
emptydir: emptyDir
|
||
};
|
||
|
||
const u$8 = universalify$1.fromPromise;
|
||
const path$k = path$q;
|
||
const fs$i = fs$s;
|
||
const mkdir$3 = mkdirs$2;
|
||
|
||
async function createFile$1 (file) {
|
||
let stats;
|
||
try {
|
||
stats = await fs$i.stat(file);
|
||
} catch { }
|
||
if (stats && stats.isFile()) return
|
||
|
||
const dir = path$k.dirname(file);
|
||
|
||
let dirStats = null;
|
||
try {
|
||
dirStats = await fs$i.stat(dir);
|
||
} catch (err) {
|
||
// if the directory doesn't exist, make it
|
||
if (err.code === 'ENOENT') {
|
||
await mkdir$3.mkdirs(dir);
|
||
await fs$i.writeFile(file, '');
|
||
return
|
||
} else {
|
||
throw err
|
||
}
|
||
}
|
||
|
||
if (dirStats.isDirectory()) {
|
||
await fs$i.writeFile(file, '');
|
||
} else {
|
||
// parent is not a directory
|
||
// This is just to cause an internal ENOTDIR error to be thrown
|
||
await fs$i.readdir(dir);
|
||
}
|
||
}
|
||
|
||
function createFileSync$1 (file) {
|
||
let stats;
|
||
try {
|
||
stats = fs$i.statSync(file);
|
||
} catch { }
|
||
if (stats && stats.isFile()) return
|
||
|
||
const dir = path$k.dirname(file);
|
||
try {
|
||
if (!fs$i.statSync(dir).isDirectory()) {
|
||
// parent is not a directory
|
||
// This is just to cause an internal ENOTDIR error to be thrown
|
||
fs$i.readdirSync(dir);
|
||
}
|
||
} catch (err) {
|
||
// If the stat call above failed because the directory doesn't exist, create it
|
||
if (err && err.code === 'ENOENT') mkdir$3.mkdirsSync(dir);
|
||
else throw err
|
||
}
|
||
|
||
fs$i.writeFileSync(file, '');
|
||
}
|
||
|
||
var file = {
|
||
createFile: u$8(createFile$1),
|
||
createFileSync: createFileSync$1
|
||
};
|
||
|
||
const u$7 = universalify$1.fromPromise;
|
||
const path$j = path$q;
|
||
const fs$h = fs$s;
|
||
const mkdir$2 = mkdirs$2;
|
||
const { pathExists: pathExists$4 } = pathExists_1;
|
||
const { areIdentical: areIdentical$1 } = stat$7;
|
||
|
||
async function createLink$1 (srcpath, dstpath) {
|
||
let dstStat;
|
||
try {
|
||
dstStat = await fs$h.lstat(dstpath);
|
||
} catch {
|
||
// ignore error
|
||
}
|
||
|
||
let srcStat;
|
||
try {
|
||
srcStat = await fs$h.lstat(srcpath);
|
||
} catch (err) {
|
||
err.message = err.message.replace('lstat', 'ensureLink');
|
||
throw err
|
||
}
|
||
|
||
if (dstStat && areIdentical$1(srcStat, dstStat)) return
|
||
|
||
const dir = path$j.dirname(dstpath);
|
||
|
||
const dirExists = await pathExists$4(dir);
|
||
|
||
if (!dirExists) {
|
||
await mkdir$2.mkdirs(dir);
|
||
}
|
||
|
||
await fs$h.link(srcpath, dstpath);
|
||
}
|
||
|
||
function createLinkSync$1 (srcpath, dstpath) {
|
||
let dstStat;
|
||
try {
|
||
dstStat = fs$h.lstatSync(dstpath);
|
||
} catch {}
|
||
|
||
try {
|
||
const srcStat = fs$h.lstatSync(srcpath);
|
||
if (dstStat && areIdentical$1(srcStat, dstStat)) return
|
||
} catch (err) {
|
||
err.message = err.message.replace('lstat', 'ensureLink');
|
||
throw err
|
||
}
|
||
|
||
const dir = path$j.dirname(dstpath);
|
||
const dirExists = fs$h.existsSync(dir);
|
||
if (dirExists) return fs$h.linkSync(srcpath, dstpath)
|
||
mkdir$2.mkdirsSync(dir);
|
||
|
||
return fs$h.linkSync(srcpath, dstpath)
|
||
}
|
||
|
||
var link$1 = {
|
||
createLink: u$7(createLink$1),
|
||
createLinkSync: createLinkSync$1
|
||
};
|
||
|
||
const path$i = path$q;
|
||
const fs$g = fs$s;
|
||
const { pathExists: pathExists$3 } = pathExists_1;
|
||
|
||
const u$6 = universalify$1.fromPromise;
|
||
|
||
/**
|
||
* Function that returns two types of paths, one relative to symlink, and one
|
||
* relative to the current working directory. Checks if path is absolute or
|
||
* relative. If the path is relative, this function checks if the path is
|
||
* relative to symlink or relative to current working directory. This is an
|
||
* initiative to find a smarter `srcpath` to supply when building symlinks.
|
||
* This allows you to determine which path to use out of one of three possible
|
||
* types of source paths. The first is an absolute path. This is detected by
|
||
* `path.isAbsolute()`. When an absolute path is provided, it is checked to
|
||
* see if it exists. If it does it's used, if not an error is returned
|
||
* (callback)/ thrown (sync). The other two options for `srcpath` are a
|
||
* relative url. By default Node's `fs.symlink` works by creating a symlink
|
||
* using `dstpath` and expects the `srcpath` to be relative to the newly
|
||
* created symlink. If you provide a `srcpath` that does not exist on the file
|
||
* system it results in a broken symlink. To minimize this, the function
|
||
* checks to see if the 'relative to symlink' source file exists, and if it
|
||
* does it will use it. If it does not, it checks if there's a file that
|
||
* exists that is relative to the current working directory, if does its used.
|
||
* This preserves the expectations of the original fs.symlink spec and adds
|
||
* the ability to pass in `relative to current working direcotry` paths.
|
||
*/
|
||
|
||
async function symlinkPaths$1 (srcpath, dstpath) {
|
||
if (path$i.isAbsolute(srcpath)) {
|
||
try {
|
||
await fs$g.lstat(srcpath);
|
||
} catch (err) {
|
||
err.message = err.message.replace('lstat', 'ensureSymlink');
|
||
throw err
|
||
}
|
||
|
||
return {
|
||
toCwd: srcpath,
|
||
toDst: srcpath
|
||
}
|
||
}
|
||
|
||
const dstdir = path$i.dirname(dstpath);
|
||
const relativeToDst = path$i.join(dstdir, srcpath);
|
||
|
||
const exists = await pathExists$3(relativeToDst);
|
||
if (exists) {
|
||
return {
|
||
toCwd: relativeToDst,
|
||
toDst: srcpath
|
||
}
|
||
}
|
||
|
||
try {
|
||
await fs$g.lstat(srcpath);
|
||
} catch (err) {
|
||
err.message = err.message.replace('lstat', 'ensureSymlink');
|
||
throw err
|
||
}
|
||
|
||
return {
|
||
toCwd: srcpath,
|
||
toDst: path$i.relative(dstdir, srcpath)
|
||
}
|
||
}
|
||
|
||
function symlinkPathsSync$1 (srcpath, dstpath) {
|
||
if (path$i.isAbsolute(srcpath)) {
|
||
const exists = fs$g.existsSync(srcpath);
|
||
if (!exists) throw new Error('absolute srcpath does not exist')
|
||
return {
|
||
toCwd: srcpath,
|
||
toDst: srcpath
|
||
}
|
||
}
|
||
|
||
const dstdir = path$i.dirname(dstpath);
|
||
const relativeToDst = path$i.join(dstdir, srcpath);
|
||
const exists = fs$g.existsSync(relativeToDst);
|
||
if (exists) {
|
||
return {
|
||
toCwd: relativeToDst,
|
||
toDst: srcpath
|
||
}
|
||
}
|
||
|
||
const srcExists = fs$g.existsSync(srcpath);
|
||
if (!srcExists) throw new Error('relative srcpath does not exist')
|
||
return {
|
||
toCwd: srcpath,
|
||
toDst: path$i.relative(dstdir, srcpath)
|
||
}
|
||
}
|
||
|
||
var symlinkPaths_1 = {
|
||
symlinkPaths: u$6(symlinkPaths$1),
|
||
symlinkPathsSync: symlinkPathsSync$1
|
||
};
|
||
|
||
const fs$f = fs$s;
|
||
const u$5 = universalify$1.fromPromise;
|
||
|
||
async function symlinkType$1 (srcpath, type) {
|
||
if (type) return type
|
||
|
||
let stats;
|
||
try {
|
||
stats = await fs$f.lstat(srcpath);
|
||
} catch {
|
||
return 'file'
|
||
}
|
||
|
||
return (stats && stats.isDirectory()) ? 'dir' : 'file'
|
||
}
|
||
|
||
function symlinkTypeSync$1 (srcpath, type) {
|
||
if (type) return type
|
||
|
||
let stats;
|
||
try {
|
||
stats = fs$f.lstatSync(srcpath);
|
||
} catch {
|
||
return 'file'
|
||
}
|
||
return (stats && stats.isDirectory()) ? 'dir' : 'file'
|
||
}
|
||
|
||
var symlinkType_1 = {
|
||
symlinkType: u$5(symlinkType$1),
|
||
symlinkTypeSync: symlinkTypeSync$1
|
||
};
|
||
|
||
const u$4 = universalify$1.fromPromise;
|
||
const path$h = path$q;
|
||
const fs$e = fs$s;
|
||
|
||
const { mkdirs, mkdirsSync } = mkdirs$2;
|
||
|
||
const { symlinkPaths, symlinkPathsSync } = symlinkPaths_1;
|
||
const { symlinkType, symlinkTypeSync } = symlinkType_1;
|
||
|
||
const { pathExists: pathExists$2 } = pathExists_1;
|
||
|
||
const { areIdentical } = stat$7;
|
||
|
||
async function createSymlink$1 (srcpath, dstpath, type) {
|
||
let stats;
|
||
try {
|
||
stats = await fs$e.lstat(dstpath);
|
||
} catch { }
|
||
|
||
if (stats && stats.isSymbolicLink()) {
|
||
const [srcStat, dstStat] = await Promise.all([
|
||
fs$e.stat(srcpath),
|
||
fs$e.stat(dstpath)
|
||
]);
|
||
|
||
if (areIdentical(srcStat, dstStat)) return
|
||
}
|
||
|
||
const relative = await symlinkPaths(srcpath, dstpath);
|
||
srcpath = relative.toDst;
|
||
const toType = await symlinkType(relative.toCwd, type);
|
||
const dir = path$h.dirname(dstpath);
|
||
|
||
if (!(await pathExists$2(dir))) {
|
||
await mkdirs(dir);
|
||
}
|
||
|
||
return fs$e.symlink(srcpath, dstpath, toType)
|
||
}
|
||
|
||
function createSymlinkSync$1 (srcpath, dstpath, type) {
|
||
let stats;
|
||
try {
|
||
stats = fs$e.lstatSync(dstpath);
|
||
} catch { }
|
||
if (stats && stats.isSymbolicLink()) {
|
||
const srcStat = fs$e.statSync(srcpath);
|
||
const dstStat = fs$e.statSync(dstpath);
|
||
if (areIdentical(srcStat, dstStat)) return
|
||
}
|
||
|
||
const relative = symlinkPathsSync(srcpath, dstpath);
|
||
srcpath = relative.toDst;
|
||
type = symlinkTypeSync(relative.toCwd, type);
|
||
const dir = path$h.dirname(dstpath);
|
||
const exists = fs$e.existsSync(dir);
|
||
if (exists) return fs$e.symlinkSync(srcpath, dstpath, type)
|
||
mkdirsSync(dir);
|
||
return fs$e.symlinkSync(srcpath, dstpath, type)
|
||
}
|
||
|
||
var symlink = {
|
||
createSymlink: u$4(createSymlink$1),
|
||
createSymlinkSync: createSymlinkSync$1
|
||
};
|
||
|
||
const { createFile, createFileSync } = file;
|
||
const { createLink, createLinkSync } = link$1;
|
||
const { createSymlink, createSymlinkSync } = symlink;
|
||
|
||
var ensure = {
|
||
// file
|
||
createFile,
|
||
createFileSync,
|
||
ensureFile: createFile,
|
||
ensureFileSync: createFileSync,
|
||
// link
|
||
createLink,
|
||
createLinkSync,
|
||
ensureLink: createLink,
|
||
ensureLinkSync: createLinkSync,
|
||
// symlink
|
||
createSymlink,
|
||
createSymlinkSync,
|
||
ensureSymlink: createSymlink,
|
||
ensureSymlinkSync: createSymlinkSync
|
||
};
|
||
|
||
function stringify$b (obj, { EOL = '\n', finalEOL = true, replacer = null, spaces } = {}) {
|
||
const EOF = finalEOL ? EOL : '';
|
||
const str = JSON.stringify(obj, replacer, spaces);
|
||
|
||
return str.replace(/\n/g, EOL) + EOF
|
||
}
|
||
|
||
function stripBom$1 (content) {
|
||
// we do this because JSON.parse would convert it to a utf8 string if encoding wasn't specified
|
||
if (Buffer.isBuffer(content)) content = content.toString('utf8');
|
||
return content.replace(/^\uFEFF/, '')
|
||
}
|
||
|
||
var utils$t = { stringify: stringify$b, stripBom: stripBom$1 };
|
||
|
||
let _fs;
|
||
try {
|
||
_fs = gracefulFs;
|
||
} catch (_) {
|
||
_fs = fs__default;
|
||
}
|
||
const universalify = universalify$1;
|
||
const { stringify: stringify$a, stripBom } = utils$t;
|
||
|
||
async function _readFile (file, options = {}) {
|
||
if (typeof options === 'string') {
|
||
options = { encoding: options };
|
||
}
|
||
|
||
const fs = options.fs || _fs;
|
||
|
||
const shouldThrow = 'throws' in options ? options.throws : true;
|
||
|
||
let data = await universalify.fromCallback(fs.readFile)(file, options);
|
||
|
||
data = stripBom(data);
|
||
|
||
let obj;
|
||
try {
|
||
obj = JSON.parse(data, options ? options.reviver : null);
|
||
} catch (err) {
|
||
if (shouldThrow) {
|
||
err.message = `${file}: ${err.message}`;
|
||
throw err
|
||
} else {
|
||
return null
|
||
}
|
||
}
|
||
|
||
return obj
|
||
}
|
||
|
||
const readFile = universalify.fromPromise(_readFile);
|
||
|
||
function readFileSync (file, options = {}) {
|
||
if (typeof options === 'string') {
|
||
options = { encoding: options };
|
||
}
|
||
|
||
const fs = options.fs || _fs;
|
||
|
||
const shouldThrow = 'throws' in options ? options.throws : true;
|
||
|
||
try {
|
||
let content = fs.readFileSync(file, options);
|
||
content = stripBom(content);
|
||
return JSON.parse(content, options.reviver)
|
||
} catch (err) {
|
||
if (shouldThrow) {
|
||
err.message = `${file}: ${err.message}`;
|
||
throw err
|
||
} else {
|
||
return null
|
||
}
|
||
}
|
||
}
|
||
|
||
async function _writeFile (file, obj, options = {}) {
|
||
const fs = options.fs || _fs;
|
||
|
||
const str = stringify$a(obj, options);
|
||
|
||
await universalify.fromCallback(fs.writeFile)(file, str, options);
|
||
}
|
||
|
||
const writeFile = universalify.fromPromise(_writeFile);
|
||
|
||
function writeFileSync (file, obj, options = {}) {
|
||
const fs = options.fs || _fs;
|
||
|
||
const str = stringify$a(obj, options);
|
||
// not sure if fs.writeFileSync returns anything, but just in case
|
||
return fs.writeFileSync(file, str, options)
|
||
}
|
||
|
||
const jsonfile$1 = {
|
||
readFile,
|
||
readFileSync,
|
||
writeFile,
|
||
writeFileSync
|
||
};
|
||
|
||
var jsonfile_1 = jsonfile$1;
|
||
|
||
const jsonFile$1 = jsonfile_1;
|
||
|
||
var jsonfile = {
|
||
// jsonfile exports
|
||
readJson: jsonFile$1.readFile,
|
||
readJsonSync: jsonFile$1.readFileSync,
|
||
writeJson: jsonFile$1.writeFile,
|
||
writeJsonSync: jsonFile$1.writeFileSync
|
||
};
|
||
|
||
const u$3 = universalify$1.fromPromise;
|
||
const fs$d = fs$s;
|
||
const path$g = path$q;
|
||
const mkdir$1 = mkdirs$2;
|
||
const pathExists$1 = pathExists_1.pathExists;
|
||
|
||
async function outputFile$1 (file, data, encoding = 'utf-8') {
|
||
const dir = path$g.dirname(file);
|
||
|
||
if (!(await pathExists$1(dir))) {
|
||
await mkdir$1.mkdirs(dir);
|
||
}
|
||
|
||
return fs$d.writeFile(file, data, encoding)
|
||
}
|
||
|
||
function outputFileSync$1 (file, ...args) {
|
||
const dir = path$g.dirname(file);
|
||
if (!fs$d.existsSync(dir)) {
|
||
mkdir$1.mkdirsSync(dir);
|
||
}
|
||
|
||
fs$d.writeFileSync(file, ...args);
|
||
}
|
||
|
||
var outputFile_1 = {
|
||
outputFile: u$3(outputFile$1),
|
||
outputFileSync: outputFileSync$1
|
||
};
|
||
|
||
const { stringify: stringify$9 } = utils$t;
|
||
const { outputFile } = outputFile_1;
|
||
|
||
async function outputJson (file, data, options = {}) {
|
||
const str = stringify$9(data, options);
|
||
|
||
await outputFile(file, str, options);
|
||
}
|
||
|
||
var outputJson_1 = outputJson;
|
||
|
||
const { stringify: stringify$8 } = utils$t;
|
||
const { outputFileSync } = outputFile_1;
|
||
|
||
function outputJsonSync (file, data, options) {
|
||
const str = stringify$8(data, options);
|
||
|
||
outputFileSync(file, str, options);
|
||
}
|
||
|
||
var outputJsonSync_1 = outputJsonSync;
|
||
|
||
const u$2 = universalify$1.fromPromise;
|
||
const jsonFile = jsonfile;
|
||
|
||
jsonFile.outputJson = u$2(outputJson_1);
|
||
jsonFile.outputJsonSync = outputJsonSync_1;
|
||
// aliases
|
||
jsonFile.outputJSON = jsonFile.outputJson;
|
||
jsonFile.outputJSONSync = jsonFile.outputJsonSync;
|
||
jsonFile.writeJSON = jsonFile.writeJson;
|
||
jsonFile.writeJSONSync = jsonFile.writeJsonSync;
|
||
jsonFile.readJSON = jsonFile.readJson;
|
||
jsonFile.readJSONSync = jsonFile.readJsonSync;
|
||
|
||
var json$1 = jsonFile;
|
||
|
||
const fs$c = fs$s;
|
||
const path$f = path$q;
|
||
const { copy } = copy$1;
|
||
const { remove } = remove_1;
|
||
const { mkdirp } = mkdirs$2;
|
||
const { pathExists } = pathExists_1;
|
||
const stat$4 = stat$7;
|
||
|
||
async function move$1 (src, dest, opts = {}) {
|
||
const overwrite = opts.overwrite || opts.clobber || false;
|
||
|
||
const { srcStat, isChangingCase = false } = await stat$4.checkPaths(src, dest, 'move', opts);
|
||
|
||
await stat$4.checkParentPaths(src, srcStat, dest, 'move');
|
||
|
||
// If the parent of dest is not root, make sure it exists before proceeding
|
||
const destParent = path$f.dirname(dest);
|
||
const parsedParentPath = path$f.parse(destParent);
|
||
if (parsedParentPath.root !== destParent) {
|
||
await mkdirp(destParent);
|
||
}
|
||
|
||
return doRename$1(src, dest, overwrite, isChangingCase)
|
||
}
|
||
|
||
async function doRename$1 (src, dest, overwrite, isChangingCase) {
|
||
if (!isChangingCase) {
|
||
if (overwrite) {
|
||
await remove(dest);
|
||
} else if (await pathExists(dest)) {
|
||
throw new Error('dest already exists.')
|
||
}
|
||
}
|
||
|
||
try {
|
||
// Try w/ rename first, and try copy + remove if EXDEV
|
||
await fs$c.rename(src, dest);
|
||
} catch (err) {
|
||
if (err.code !== 'EXDEV') {
|
||
throw err
|
||
}
|
||
await moveAcrossDevice$1(src, dest, overwrite);
|
||
}
|
||
}
|
||
|
||
async function moveAcrossDevice$1 (src, dest, overwrite) {
|
||
const opts = {
|
||
overwrite,
|
||
errorOnExist: true,
|
||
preserveTimestamps: true
|
||
};
|
||
|
||
await copy(src, dest, opts);
|
||
return remove(src)
|
||
}
|
||
|
||
var move_1 = move$1;
|
||
|
||
const fs$b = gracefulFs;
|
||
const path$e = path$q;
|
||
const copySync = copy$1.copySync;
|
||
const removeSync = remove_1.removeSync;
|
||
const mkdirpSync = mkdirs$2.mkdirpSync;
|
||
const stat$3 = stat$7;
|
||
|
||
function moveSync (src, dest, opts) {
|
||
opts = opts || {};
|
||
const overwrite = opts.overwrite || opts.clobber || false;
|
||
|
||
const { srcStat, isChangingCase = false } = stat$3.checkPathsSync(src, dest, 'move', opts);
|
||
stat$3.checkParentPathsSync(src, srcStat, dest, 'move');
|
||
if (!isParentRoot(dest)) mkdirpSync(path$e.dirname(dest));
|
||
return doRename(src, dest, overwrite, isChangingCase)
|
||
}
|
||
|
||
function isParentRoot (dest) {
|
||
const parent = path$e.dirname(dest);
|
||
const parsedPath = path$e.parse(parent);
|
||
return parsedPath.root === parent
|
||
}
|
||
|
||
function doRename (src, dest, overwrite, isChangingCase) {
|
||
if (isChangingCase) return rename$2(src, dest, overwrite)
|
||
if (overwrite) {
|
||
removeSync(dest);
|
||
return rename$2(src, dest, overwrite)
|
||
}
|
||
if (fs$b.existsSync(dest)) throw new Error('dest already exists.')
|
||
return rename$2(src, dest, overwrite)
|
||
}
|
||
|
||
function rename$2 (src, dest, overwrite) {
|
||
try {
|
||
fs$b.renameSync(src, dest);
|
||
} catch (err) {
|
||
if (err.code !== 'EXDEV') throw err
|
||
return moveAcrossDevice(src, dest, overwrite)
|
||
}
|
||
}
|
||
|
||
function moveAcrossDevice (src, dest, overwrite) {
|
||
const opts = {
|
||
overwrite,
|
||
errorOnExist: true,
|
||
preserveTimestamps: true
|
||
};
|
||
copySync(src, dest, opts);
|
||
return removeSync(src)
|
||
}
|
||
|
||
var moveSync_1 = moveSync;
|
||
|
||
const u$1 = universalify$1.fromPromise;
|
||
var move = {
|
||
move: u$1(move_1),
|
||
moveSync: moveSync_1
|
||
};
|
||
|
||
var lib$1 = {
|
||
// Export promiseified graceful-fs:
|
||
...fs$s,
|
||
// Export extra methods:
|
||
...copy$1,
|
||
...empty,
|
||
...ensure,
|
||
...json$1,
|
||
...mkdirs$2,
|
||
...move,
|
||
...outputFile_1,
|
||
...pathExists_1,
|
||
...remove_1
|
||
};
|
||
|
||
var fs$a = /*@__PURE__*/getDefaultExportFromCjs(lib$1);
|
||
|
||
async function pMap(
|
||
iterable,
|
||
mapper,
|
||
{
|
||
concurrency = Number.POSITIVE_INFINITY,
|
||
stopOnError = true,
|
||
signal,
|
||
} = {},
|
||
) {
|
||
return new Promise((resolve, reject_) => {
|
||
if (iterable[Symbol.iterator] === undefined && iterable[Symbol.asyncIterator] === undefined) {
|
||
throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`);
|
||
}
|
||
|
||
if (typeof mapper !== 'function') {
|
||
throw new TypeError('Mapper function is required');
|
||
}
|
||
|
||
if (!((Number.isSafeInteger(concurrency) && concurrency >= 1) || concurrency === Number.POSITIVE_INFINITY)) {
|
||
throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
|
||
}
|
||
|
||
const result = [];
|
||
const errors = [];
|
||
const skippedIndexesMap = new Map();
|
||
let isRejected = false;
|
||
let isResolved = false;
|
||
let isIterableDone = false;
|
||
let resolvingCount = 0;
|
||
let currentIndex = 0;
|
||
const iterator = iterable[Symbol.iterator] === undefined ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
|
||
|
||
const reject = reason => {
|
||
isRejected = true;
|
||
isResolved = true;
|
||
reject_(reason);
|
||
};
|
||
|
||
if (signal) {
|
||
if (signal.aborted) {
|
||
reject(signal.reason);
|
||
}
|
||
|
||
signal.addEventListener('abort', () => {
|
||
reject(signal.reason);
|
||
});
|
||
}
|
||
|
||
const next = async () => {
|
||
if (isResolved) {
|
||
return;
|
||
}
|
||
|
||
const nextItem = await iterator.next();
|
||
|
||
const index = currentIndex;
|
||
currentIndex++;
|
||
|
||
// Note: `iterator.next()` can be called many times in parallel.
|
||
// This can cause multiple calls to this `next()` function to
|
||
// receive a `nextItem` with `done === true`.
|
||
// The shutdown logic that rejects/resolves must be protected
|
||
// so it runs only one time as the `skippedIndex` logic is
|
||
// non-idempotent.
|
||
if (nextItem.done) {
|
||
isIterableDone = true;
|
||
|
||
if (resolvingCount === 0 && !isResolved) {
|
||
if (!stopOnError && errors.length > 0) {
|
||
reject(new AggregateError(errors)); // eslint-disable-line unicorn/error-message
|
||
return;
|
||
}
|
||
|
||
isResolved = true;
|
||
|
||
if (skippedIndexesMap.size === 0) {
|
||
resolve(result);
|
||
return;
|
||
}
|
||
|
||
const pureResult = [];
|
||
|
||
// Support multiple `pMapSkip`'s.
|
||
for (const [index, value] of result.entries()) {
|
||
if (skippedIndexesMap.get(index) === pMapSkip) {
|
||
continue;
|
||
}
|
||
|
||
pureResult.push(value);
|
||
}
|
||
|
||
resolve(pureResult);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
resolvingCount++;
|
||
|
||
// Intentionally detached
|
||
(async () => {
|
||
try {
|
||
const element = await nextItem.value;
|
||
|
||
if (isResolved) {
|
||
return;
|
||
}
|
||
|
||
const value = await mapper(element, index);
|
||
|
||
// Use Map to stage the index of the element.
|
||
if (value === pMapSkip) {
|
||
skippedIndexesMap.set(index, value);
|
||
}
|
||
|
||
result[index] = value;
|
||
|
||
resolvingCount--;
|
||
await next();
|
||
} catch (error) {
|
||
if (stopOnError) {
|
||
reject(error);
|
||
} else {
|
||
errors.push(error);
|
||
resolvingCount--;
|
||
|
||
// In that case we can't really continue regardless of `stopOnError` state
|
||
// since an iterable is likely to continue throwing after it throws once.
|
||
// If we continue calling `next()` indefinitely we will likely end up
|
||
// in an infinite loop of failed iteration.
|
||
try {
|
||
await next();
|
||
} catch (error) {
|
||
reject(error);
|
||
}
|
||
}
|
||
}
|
||
})();
|
||
};
|
||
|
||
// Create the concurrent runners in a detached (non-awaited)
|
||
// promise. We need this so we can await the `next()` calls
|
||
// to stop creating runners before hitting the concurrency limit
|
||
// if the iterable has already been marked as done.
|
||
// NOTE: We *must* do this for async iterators otherwise we'll spin up
|
||
// infinite `next()` calls by default and never start the event loop.
|
||
(async () => {
|
||
for (let index = 0; index < concurrency; index++) {
|
||
try {
|
||
// eslint-disable-next-line no-await-in-loop
|
||
await next();
|
||
} catch (error) {
|
||
reject(error);
|
||
break;
|
||
}
|
||
|
||
if (isIterableDone || isRejected) {
|
||
break;
|
||
}
|
||
}
|
||
})();
|
||
});
|
||
}
|
||
|
||
const pMapSkip = Symbol('skip');
|
||
|
||
const toPath = urlOrPath => urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
|
||
|
||
function findUpSync(name, {
|
||
cwd = process$2.cwd(),
|
||
type = 'file',
|
||
stopAt,
|
||
} = {}) {
|
||
let directory = path$r.resolve(toPath(cwd) ?? '');
|
||
const {root} = path$r.parse(directory);
|
||
stopAt = path$r.resolve(directory, toPath(stopAt) ?? root);
|
||
|
||
while (directory && directory !== stopAt && directory !== root) {
|
||
const filePath = path$r.isAbsolute(name) ? name : path$r.join(directory, name);
|
||
|
||
try {
|
||
const stats = fs$u.statSync(filePath, {throwIfNoEntry: false});
|
||
if ((type === 'file' && stats?.isFile()) || (type === 'directory' && stats?.isDirectory())) {
|
||
return filePath;
|
||
}
|
||
} catch {}
|
||
|
||
directory = path$r.dirname(directory);
|
||
}
|
||
}
|
||
|
||
function packageDirectorySync({cwd} = {}) {
|
||
const filePath = findUpSync('package.json', {cwd});
|
||
return filePath && path$r.dirname(filePath);
|
||
}
|
||
|
||
var balancedMatch = balanced$1;
|
||
function balanced$1(a, b, str) {
|
||
if (a instanceof RegExp) a = maybeMatch(a, str);
|
||
if (b instanceof RegExp) b = maybeMatch(b, str);
|
||
|
||
var r = range(a, b, str);
|
||
|
||
return r && {
|
||
start: r[0],
|
||
end: r[1],
|
||
pre: str.slice(0, r[0]),
|
||
body: str.slice(r[0] + a.length, r[1]),
|
||
post: str.slice(r[1] + b.length)
|
||
};
|
||
}
|
||
|
||
function maybeMatch(reg, str) {
|
||
var m = str.match(reg);
|
||
return m ? m[0] : null;
|
||
}
|
||
|
||
balanced$1.range = range;
|
||
function range(a, b, str) {
|
||
var begs, beg, left, right, result;
|
||
var ai = str.indexOf(a);
|
||
var bi = str.indexOf(b, ai + 1);
|
||
var i = ai;
|
||
|
||
if (ai >= 0 && bi > 0) {
|
||
if(a===b) {
|
||
return [ai, bi];
|
||
}
|
||
begs = [];
|
||
left = str.length;
|
||
|
||
while (i >= 0 && !result) {
|
||
if (i == ai) {
|
||
begs.push(i);
|
||
ai = str.indexOf(a, i + 1);
|
||
} else if (begs.length == 1) {
|
||
result = [ begs.pop(), bi ];
|
||
} else {
|
||
beg = begs.pop();
|
||
if (beg < left) {
|
||
left = beg;
|
||
right = bi;
|
||
}
|
||
|
||
bi = str.indexOf(b, i + 1);
|
||
}
|
||
|
||
i = ai < bi && ai >= 0 ? ai : bi;
|
||
}
|
||
|
||
if (begs.length) {
|
||
result = [ left, right ];
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
var balanced = balancedMatch;
|
||
|
||
var braceExpansion = expandTop;
|
||
|
||
var escSlash = '\0SLASH'+Math.random()+'\0';
|
||
var escOpen = '\0OPEN'+Math.random()+'\0';
|
||
var escClose = '\0CLOSE'+Math.random()+'\0';
|
||
var escComma = '\0COMMA'+Math.random()+'\0';
|
||
var escPeriod = '\0PERIOD'+Math.random()+'\0';
|
||
|
||
function numeric(str) {
|
||
return parseInt(str, 10) == str
|
||
? parseInt(str, 10)
|
||
: str.charCodeAt(0);
|
||
}
|
||
|
||
function escapeBraces(str) {
|
||
return str.split('\\\\').join(escSlash)
|
||
.split('\\{').join(escOpen)
|
||
.split('\\}').join(escClose)
|
||
.split('\\,').join(escComma)
|
||
.split('\\.').join(escPeriod);
|
||
}
|
||
|
||
function unescapeBraces(str) {
|
||
return str.split(escSlash).join('\\')
|
||
.split(escOpen).join('{')
|
||
.split(escClose).join('}')
|
||
.split(escComma).join(',')
|
||
.split(escPeriod).join('.');
|
||
}
|
||
|
||
|
||
// Basically just str.split(","), but handling cases
|
||
// where we have nested braced sections, which should be
|
||
// treated as individual members, like {a,{b,c},d}
|
||
function parseCommaParts(str) {
|
||
if (!str)
|
||
return [''];
|
||
|
||
var parts = [];
|
||
var m = balanced('{', '}', str);
|
||
|
||
if (!m)
|
||
return str.split(',');
|
||
|
||
var pre = m.pre;
|
||
var body = m.body;
|
||
var post = m.post;
|
||
var p = pre.split(',');
|
||
|
||
p[p.length-1] += '{' + body + '}';
|
||
var postParts = parseCommaParts(post);
|
||
if (post.length) {
|
||
p[p.length-1] += postParts.shift();
|
||
p.push.apply(p, postParts);
|
||
}
|
||
|
||
parts.push.apply(parts, p);
|
||
|
||
return parts;
|
||
}
|
||
|
||
function expandTop(str) {
|
||
if (!str)
|
||
return [];
|
||
|
||
// I don't know why Bash 4.3 does this, but it does.
|
||
// Anything starting with {} will have the first two bytes preserved
|
||
// but *only* at the top level, so {},a}b will not expand to anything,
|
||
// but a{},b}c will be expanded to [a}c,abc].
|
||
// One could argue that this is a bug in Bash, but since the goal of
|
||
// this module is to match Bash's rules, we escape a leading {}
|
||
if (str.substr(0, 2) === '{}') {
|
||
str = '\\{\\}' + str.substr(2);
|
||
}
|
||
|
||
return expand$2(escapeBraces(str), true).map(unescapeBraces);
|
||
}
|
||
|
||
function embrace(str) {
|
||
return '{' + str + '}';
|
||
}
|
||
function isPadded(el) {
|
||
return /^-?0\d/.test(el);
|
||
}
|
||
|
||
function lte(i, y) {
|
||
return i <= y;
|
||
}
|
||
function gte(i, y) {
|
||
return i >= y;
|
||
}
|
||
|
||
function expand$2(str, isTop) {
|
||
var expansions = [];
|
||
|
||
var m = balanced('{', '}', str);
|
||
if (!m) return [str];
|
||
|
||
// no need to expand pre, since it is guaranteed to be free of brace-sets
|
||
var pre = m.pre;
|
||
var post = m.post.length
|
||
? expand$2(m.post, false)
|
||
: [''];
|
||
|
||
if (/\$$/.test(m.pre)) {
|
||
for (var k = 0; k < post.length; k++) {
|
||
var expansion = pre+ '{' + m.body + '}' + post[k];
|
||
expansions.push(expansion);
|
||
}
|
||
} else {
|
||
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
|
||
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
|
||
var isSequence = isNumericSequence || isAlphaSequence;
|
||
var isOptions = m.body.indexOf(',') >= 0;
|
||
if (!isSequence && !isOptions) {
|
||
// {a},b}
|
||
if (m.post.match(/,.*\}/)) {
|
||
str = m.pre + '{' + m.body + escClose + m.post;
|
||
return expand$2(str);
|
||
}
|
||
return [str];
|
||
}
|
||
|
||
var n;
|
||
if (isSequence) {
|
||
n = m.body.split(/\.\./);
|
||
} else {
|
||
n = parseCommaParts(m.body);
|
||
if (n.length === 1) {
|
||
// x{{a,b}}y ==> x{a}y x{b}y
|
||
n = expand$2(n[0], false).map(embrace);
|
||
if (n.length === 1) {
|
||
return post.map(function(p) {
|
||
return m.pre + n[0] + p;
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
// at this point, n is the parts, and we know it's not a comma set
|
||
// with a single entry.
|
||
var N;
|
||
|
||
if (isSequence) {
|
||
var x = numeric(n[0]);
|
||
var y = numeric(n[1]);
|
||
var width = Math.max(n[0].length, n[1].length);
|
||
var incr = n.length == 3
|
||
? Math.abs(numeric(n[2]))
|
||
: 1;
|
||
var test = lte;
|
||
var reverse = y < x;
|
||
if (reverse) {
|
||
incr *= -1;
|
||
test = gte;
|
||
}
|
||
var pad = n.some(isPadded);
|
||
|
||
N = [];
|
||
|
||
for (var i = x; test(i, y); i += incr) {
|
||
var c;
|
||
if (isAlphaSequence) {
|
||
c = String.fromCharCode(i);
|
||
if (c === '\\')
|
||
c = '';
|
||
} else {
|
||
c = String(i);
|
||
if (pad) {
|
||
var need = width - c.length;
|
||
if (need > 0) {
|
||
var z = new Array(need + 1).join('0');
|
||
if (i < 0)
|
||
c = '-' + z + c.slice(1);
|
||
else
|
||
c = z + c;
|
||
}
|
||
}
|
||
}
|
||
N.push(c);
|
||
}
|
||
} else {
|
||
N = [];
|
||
|
||
for (var j = 0; j < n.length; j++) {
|
||
N.push.apply(N, expand$2(n[j], false));
|
||
}
|
||
}
|
||
|
||
for (var j = 0; j < N.length; j++) {
|
||
for (var k = 0; k < post.length; k++) {
|
||
var expansion = pre + N[j] + post[k];
|
||
if (!isTop || isSequence || expansion)
|
||
expansions.push(expansion);
|
||
}
|
||
}
|
||
}
|
||
|
||
return expansions;
|
||
}
|
||
|
||
var expand$3 = /*@__PURE__*/getDefaultExportFromCjs(braceExpansion);
|
||
|
||
const MAX_PATTERN_LENGTH = 1024 * 64;
|
||
const assertValidPattern = (pattern) => {
|
||
if (typeof pattern !== 'string') {
|
||
throw new TypeError('invalid pattern');
|
||
}
|
||
if (pattern.length > MAX_PATTERN_LENGTH) {
|
||
throw new TypeError('pattern is too long');
|
||
}
|
||
};
|
||
|
||
// translate the various posix character classes into unicode properties
|
||
// this works across all unicode locales
|
||
// { <posix class>: [<translation>, /u flag required, negated]
|
||
const posixClasses = {
|
||
'[:alnum:]': ['\\p{L}\\p{Nl}\\p{Nd}', true],
|
||
'[:alpha:]': ['\\p{L}\\p{Nl}', true],
|
||
'[:ascii:]': ['\\x' + '00-\\x' + '7f', false],
|
||
'[:blank:]': ['\\p{Zs}\\t', true],
|
||
'[:cntrl:]': ['\\p{Cc}', true],
|
||
'[:digit:]': ['\\p{Nd}', true],
|
||
'[:graph:]': ['\\p{Z}\\p{C}', true, true],
|
||
'[:lower:]': ['\\p{Ll}', true],
|
||
'[:print:]': ['\\p{C}', true],
|
||
'[:punct:]': ['\\p{P}', true],
|
||
'[:space:]': ['\\p{Z}\\t\\r\\n\\v\\f', true],
|
||
'[:upper:]': ['\\p{Lu}', true],
|
||
'[:word:]': ['\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}', true],
|
||
'[:xdigit:]': ['A-Fa-f0-9', false],
|
||
};
|
||
// only need to escape a few things inside of brace expressions
|
||
// escapes: [ \ ] -
|
||
const braceEscape = (s) => s.replace(/[[\]\\-]/g, '\\$&');
|
||
// escape all regexp magic characters
|
||
const regexpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||
// everything has already been escaped, we just have to join
|
||
const rangesToString = (ranges) => ranges.join('');
|
||
// takes a glob string at a posix brace expression, and returns
|
||
// an equivalent regular expression source, and boolean indicating
|
||
// whether the /u flag needs to be applied, and the number of chars
|
||
// consumed to parse the character class.
|
||
// This also removes out of order ranges, and returns ($.) if the
|
||
// entire class just no good.
|
||
const parseClass = (glob, position) => {
|
||
const pos = position;
|
||
/* c8 ignore start */
|
||
if (glob.charAt(pos) !== '[') {
|
||
throw new Error('not in a brace expression');
|
||
}
|
||
/* c8 ignore stop */
|
||
const ranges = [];
|
||
const negs = [];
|
||
let i = pos + 1;
|
||
let sawStart = false;
|
||
let uflag = false;
|
||
let escaping = false;
|
||
let negate = false;
|
||
let endPos = pos;
|
||
let rangeStart = '';
|
||
WHILE: while (i < glob.length) {
|
||
const c = glob.charAt(i);
|
||
if ((c === '!' || c === '^') && i === pos + 1) {
|
||
negate = true;
|
||
i++;
|
||
continue;
|
||
}
|
||
if (c === ']' && sawStart && !escaping) {
|
||
endPos = i + 1;
|
||
break;
|
||
}
|
||
sawStart = true;
|
||
if (c === '\\') {
|
||
if (!escaping) {
|
||
escaping = true;
|
||
i++;
|
||
continue;
|
||
}
|
||
// escaped \ char, fall through and treat like normal char
|
||
}
|
||
if (c === '[' && !escaping) {
|
||
// either a posix class, a collation equivalent, or just a [
|
||
for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {
|
||
if (glob.startsWith(cls, i)) {
|
||
// invalid, [a-[] is fine, but not [a-[:alpha]]
|
||
if (rangeStart) {
|
||
return ['$.', false, glob.length - pos, true];
|
||
}
|
||
i += cls.length;
|
||
if (neg)
|
||
negs.push(unip);
|
||
else
|
||
ranges.push(unip);
|
||
uflag = uflag || u;
|
||
continue WHILE;
|
||
}
|
||
}
|
||
}
|
||
// now it's just a normal character, effectively
|
||
escaping = false;
|
||
if (rangeStart) {
|
||
// throw this range away if it's not valid, but others
|
||
// can still match.
|
||
if (c > rangeStart) {
|
||
ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c));
|
||
}
|
||
else if (c === rangeStart) {
|
||
ranges.push(braceEscape(c));
|
||
}
|
||
rangeStart = '';
|
||
i++;
|
||
continue;
|
||
}
|
||
// now might be the start of a range.
|
||
// can be either c-d or c-] or c<more...>] or c] at this point
|
||
if (glob.startsWith('-]', i + 1)) {
|
||
ranges.push(braceEscape(c + '-'));
|
||
i += 2;
|
||
continue;
|
||
}
|
||
if (glob.startsWith('-', i + 1)) {
|
||
rangeStart = c;
|
||
i += 2;
|
||
continue;
|
||
}
|
||
// not the start of a range, just a single character
|
||
ranges.push(braceEscape(c));
|
||
i++;
|
||
}
|
||
if (endPos < i) {
|
||
// didn't see the end of the class, not a valid class,
|
||
// but might still be valid as a literal match.
|
||
return ['', false, 0, false];
|
||
}
|
||
// if we got no ranges and no negates, then we have a range that
|
||
// cannot possibly match anything, and that poisons the whole glob
|
||
if (!ranges.length && !negs.length) {
|
||
return ['$.', false, glob.length - pos, true];
|
||
}
|
||
// if we got one positive range, and it's a single character, then that's
|
||
// not actually a magic pattern, it's just that one literal character.
|
||
// we should not treat that as "magic", we should just return the literal
|
||
// character. [_] is a perfectly valid way to escape glob magic chars.
|
||
if (negs.length === 0 &&
|
||
ranges.length === 1 &&
|
||
/^\\?.$/.test(ranges[0]) &&
|
||
!negate) {
|
||
const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0];
|
||
return [regexpEscape(r), false, endPos - pos, false];
|
||
}
|
||
const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']';
|
||
const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']';
|
||
const comb = ranges.length && negs.length
|
||
? '(' + sranges + '|' + snegs + ')'
|
||
: ranges.length
|
||
? sranges
|
||
: snegs;
|
||
return [comb, uflag, endPos - pos, true];
|
||
};
|
||
|
||
/**
|
||
* Un-escape a string that has been escaped with {@link escape}.
|
||
*
|
||
* If the {@link windowsPathsNoEscape} option is used, then square-brace
|
||
* escapes are removed, but not backslash escapes. For example, it will turn
|
||
* the string `'[*]'` into `*`, but it will not turn `'\\*'` into `'*'`,
|
||
* becuase `\` is a path separator in `windowsPathsNoEscape` mode.
|
||
*
|
||
* When `windowsPathsNoEscape` is not set, then both brace escapes and
|
||
* backslash escapes are removed.
|
||
*
|
||
* Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped
|
||
* or unescaped.
|
||
*/
|
||
const unescape = (s, { windowsPathsNoEscape = false, } = {}) => {
|
||
return windowsPathsNoEscape
|
||
? s.replace(/\[([^\/\\])\]/g, '$1')
|
||
: s.replace(/((?!\\).|^)\[([^\/\\])\]/g, '$1$2').replace(/\\([^\/])/g, '$1');
|
||
};
|
||
|
||
// parse a single path portion
|
||
const types$1 = new Set(['!', '?', '+', '*', '@']);
|
||
const isExtglobType = (c) => types$1.has(c);
|
||
// Patterns that get prepended to bind to the start of either the
|
||
// entire string, or just a single path portion, to prevent dots
|
||
// and/or traversal patterns, when needed.
|
||
// Exts don't need the ^ or / bit, because the root binds that already.
|
||
const startNoTraversal = '(?!(?:^|/)\\.\\.?(?:$|/))';
|
||
const startNoDot = '(?!\\.)';
|
||
// characters that indicate a start of pattern needs the "no dots" bit,
|
||
// because a dot *might* be matched. ( is not in the list, because in
|
||
// the case of a child extglob, it will handle the prevention itself.
|
||
const addPatternStart = new Set(['[', '.']);
|
||
// cases where traversal is A-OK, no dot prevention needed
|
||
const justDots = new Set(['..', '.']);
|
||
const reSpecials = new Set('().*{}+?[]^$\\!');
|
||
const regExpEscape$1 = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||
// any single thing other than /
|
||
const qmark$1 = '[^/]';
|
||
// * => any number of characters
|
||
const star$2 = qmark$1 + '*?';
|
||
// use + when we need to ensure that *something* matches, because the * is
|
||
// the only thing in the path portion.
|
||
const starNoEmpty = qmark$1 + '+?';
|
||
// remove the \ chars that we added if we end up doing a nonmagic compare
|
||
// const deslash = (s: string) => s.replace(/\\(.)/g, '$1')
|
||
class AST {
|
||
type;
|
||
#root;
|
||
#hasMagic;
|
||
#uflag = false;
|
||
#parts = [];
|
||
#parent;
|
||
#parentIndex;
|
||
#negs;
|
||
#filledNegs = false;
|
||
#options;
|
||
#toString;
|
||
// set to true if it's an extglob with no children
|
||
// (which really means one child of '')
|
||
#emptyExt = false;
|
||
constructor(type, parent, options = {}) {
|
||
this.type = type;
|
||
// extglobs are inherently magical
|
||
if (type)
|
||
this.#hasMagic = true;
|
||
this.#parent = parent;
|
||
this.#root = this.#parent ? this.#parent.#root : this;
|
||
this.#options = this.#root === this ? options : this.#root.#options;
|
||
this.#negs = this.#root === this ? [] : this.#root.#negs;
|
||
if (type === '!' && !this.#root.#filledNegs)
|
||
this.#negs.push(this);
|
||
this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0;
|
||
}
|
||
get hasMagic() {
|
||
/* c8 ignore start */
|
||
if (this.#hasMagic !== undefined)
|
||
return this.#hasMagic;
|
||
/* c8 ignore stop */
|
||
for (const p of this.#parts) {
|
||
if (typeof p === 'string')
|
||
continue;
|
||
if (p.type || p.hasMagic)
|
||
return (this.#hasMagic = true);
|
||
}
|
||
// note: will be undefined until we generate the regexp src and find out
|
||
return this.#hasMagic;
|
||
}
|
||
// reconstructs the pattern
|
||
toString() {
|
||
if (this.#toString !== undefined)
|
||
return this.#toString;
|
||
if (!this.type) {
|
||
return (this.#toString = this.#parts.map(p => String(p)).join(''));
|
||
}
|
||
else {
|
||
return (this.#toString =
|
||
this.type + '(' + this.#parts.map(p => String(p)).join('|') + ')');
|
||
}
|
||
}
|
||
#fillNegs() {
|
||
/* c8 ignore start */
|
||
if (this !== this.#root)
|
||
throw new Error('should only call on root');
|
||
if (this.#filledNegs)
|
||
return this;
|
||
/* c8 ignore stop */
|
||
// call toString() once to fill this out
|
||
this.toString();
|
||
this.#filledNegs = true;
|
||
let n;
|
||
while ((n = this.#negs.pop())) {
|
||
if (n.type !== '!')
|
||
continue;
|
||
// walk up the tree, appending everthing that comes AFTER parentIndex
|
||
let p = n;
|
||
let pp = p.#parent;
|
||
while (pp) {
|
||
for (let i = p.#parentIndex + 1; !pp.type && i < pp.#parts.length; i++) {
|
||
for (const part of n.#parts) {
|
||
/* c8 ignore start */
|
||
if (typeof part === 'string') {
|
||
throw new Error('string part in extglob AST??');
|
||
}
|
||
/* c8 ignore stop */
|
||
part.copyIn(pp.#parts[i]);
|
||
}
|
||
}
|
||
p = pp;
|
||
pp = p.#parent;
|
||
}
|
||
}
|
||
return this;
|
||
}
|
||
push(...parts) {
|
||
for (const p of parts) {
|
||
if (p === '')
|
||
continue;
|
||
/* c8 ignore start */
|
||
if (typeof p !== 'string' && !(p instanceof AST && p.#parent === this)) {
|
||
throw new Error('invalid part: ' + p);
|
||
}
|
||
/* c8 ignore stop */
|
||
this.#parts.push(p);
|
||
}
|
||
}
|
||
toJSON() {
|
||
const ret = this.type === null
|
||
? this.#parts.slice().map(p => (typeof p === 'string' ? p : p.toJSON()))
|
||
: [this.type, ...this.#parts.map(p => p.toJSON())];
|
||
if (this.isStart() && !this.type)
|
||
ret.unshift([]);
|
||
if (this.isEnd() &&
|
||
(this === this.#root ||
|
||
(this.#root.#filledNegs && this.#parent?.type === '!'))) {
|
||
ret.push({});
|
||
}
|
||
return ret;
|
||
}
|
||
isStart() {
|
||
if (this.#root === this)
|
||
return true;
|
||
// if (this.type) return !!this.#parent?.isStart()
|
||
if (!this.#parent?.isStart())
|
||
return false;
|
||
if (this.#parentIndex === 0)
|
||
return true;
|
||
// if everything AHEAD of this is a negation, then it's still the "start"
|
||
const p = this.#parent;
|
||
for (let i = 0; i < this.#parentIndex; i++) {
|
||
const pp = p.#parts[i];
|
||
if (!(pp instanceof AST && pp.type === '!')) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
isEnd() {
|
||
if (this.#root === this)
|
||
return true;
|
||
if (this.#parent?.type === '!')
|
||
return true;
|
||
if (!this.#parent?.isEnd())
|
||
return false;
|
||
if (!this.type)
|
||
return this.#parent?.isEnd();
|
||
// if not root, it'll always have a parent
|
||
/* c8 ignore start */
|
||
const pl = this.#parent ? this.#parent.#parts.length : 0;
|
||
/* c8 ignore stop */
|
||
return this.#parentIndex === pl - 1;
|
||
}
|
||
copyIn(part) {
|
||
if (typeof part === 'string')
|
||
this.push(part);
|
||
else
|
||
this.push(part.clone(this));
|
||
}
|
||
clone(parent) {
|
||
const c = new AST(this.type, parent);
|
||
for (const p of this.#parts) {
|
||
c.copyIn(p);
|
||
}
|
||
return c;
|
||
}
|
||
static #parseAST(str, ast, pos, opt) {
|
||
let escaping = false;
|
||
let inBrace = false;
|
||
let braceStart = -1;
|
||
let braceNeg = false;
|
||
if (ast.type === null) {
|
||
// outside of a extglob, append until we find a start
|
||
let i = pos;
|
||
let acc = '';
|
||
while (i < str.length) {
|
||
const c = str.charAt(i++);
|
||
// still accumulate escapes at this point, but we do ignore
|
||
// starts that are escaped
|
||
if (escaping || c === '\\') {
|
||
escaping = !escaping;
|
||
acc += c;
|
||
continue;
|
||
}
|
||
if (inBrace) {
|
||
if (i === braceStart + 1) {
|
||
if (c === '^' || c === '!') {
|
||
braceNeg = true;
|
||
}
|
||
}
|
||
else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {
|
||
inBrace = false;
|
||
}
|
||
acc += c;
|
||
continue;
|
||
}
|
||
else if (c === '[') {
|
||
inBrace = true;
|
||
braceStart = i;
|
||
braceNeg = false;
|
||
acc += c;
|
||
continue;
|
||
}
|
||
if (!opt.noext && isExtglobType(c) && str.charAt(i) === '(') {
|
||
ast.push(acc);
|
||
acc = '';
|
||
const ext = new AST(c, ast);
|
||
i = AST.#parseAST(str, ext, i, opt);
|
||
ast.push(ext);
|
||
continue;
|
||
}
|
||
acc += c;
|
||
}
|
||
ast.push(acc);
|
||
return i;
|
||
}
|
||
// some kind of extglob, pos is at the (
|
||
// find the next | or )
|
||
let i = pos + 1;
|
||
let part = new AST(null, ast);
|
||
const parts = [];
|
||
let acc = '';
|
||
while (i < str.length) {
|
||
const c = str.charAt(i++);
|
||
// still accumulate escapes at this point, but we do ignore
|
||
// starts that are escaped
|
||
if (escaping || c === '\\') {
|
||
escaping = !escaping;
|
||
acc += c;
|
||
continue;
|
||
}
|
||
if (inBrace) {
|
||
if (i === braceStart + 1) {
|
||
if (c === '^' || c === '!') {
|
||
braceNeg = true;
|
||
}
|
||
}
|
||
else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {
|
||
inBrace = false;
|
||
}
|
||
acc += c;
|
||
continue;
|
||
}
|
||
else if (c === '[') {
|
||
inBrace = true;
|
||
braceStart = i;
|
||
braceNeg = false;
|
||
acc += c;
|
||
continue;
|
||
}
|
||
if (isExtglobType(c) && str.charAt(i) === '(') {
|
||
part.push(acc);
|
||
acc = '';
|
||
const ext = new AST(c, part);
|
||
part.push(ext);
|
||
i = AST.#parseAST(str, ext, i, opt);
|
||
continue;
|
||
}
|
||
if (c === '|') {
|
||
part.push(acc);
|
||
acc = '';
|
||
parts.push(part);
|
||
part = new AST(null, ast);
|
||
continue;
|
||
}
|
||
if (c === ')') {
|
||
if (acc === '' && ast.#parts.length === 0) {
|
||
ast.#emptyExt = true;
|
||
}
|
||
part.push(acc);
|
||
acc = '';
|
||
ast.push(...parts, part);
|
||
return i;
|
||
}
|
||
acc += c;
|
||
}
|
||
// unfinished extglob
|
||
// if we got here, it was a malformed extglob! not an extglob, but
|
||
// maybe something else in there.
|
||
ast.type = null;
|
||
ast.#hasMagic = undefined;
|
||
ast.#parts = [str.substring(pos - 1)];
|
||
return i;
|
||
}
|
||
static fromGlob(pattern, options = {}) {
|
||
const ast = new AST(null, undefined, options);
|
||
AST.#parseAST(pattern, ast, 0, options);
|
||
return ast;
|
||
}
|
||
// returns the regular expression if there's magic, or the unescaped
|
||
// string if not.
|
||
toMMPattern() {
|
||
// should only be called on root
|
||
/* c8 ignore start */
|
||
if (this !== this.#root)
|
||
return this.#root.toMMPattern();
|
||
/* c8 ignore stop */
|
||
const glob = this.toString();
|
||
const [re, body, hasMagic, uflag] = this.toRegExpSource();
|
||
// if we're in nocase mode, and not nocaseMagicOnly, then we do
|
||
// still need a regular expression if we have to case-insensitively
|
||
// match capital/lowercase characters.
|
||
const anyMagic = hasMagic ||
|
||
this.#hasMagic ||
|
||
(this.#options.nocase &&
|
||
!this.#options.nocaseMagicOnly &&
|
||
glob.toUpperCase() !== glob.toLowerCase());
|
||
if (!anyMagic) {
|
||
return body;
|
||
}
|
||
const flags = (this.#options.nocase ? 'i' : '') + (uflag ? 'u' : '');
|
||
return Object.assign(new RegExp(`^${re}$`, flags), {
|
||
_src: re,
|
||
_glob: glob,
|
||
});
|
||
}
|
||
// returns the string match, the regexp source, whether there's magic
|
||
// in the regexp (so a regular expression is required) and whether or
|
||
// not the uflag is needed for the regular expression (for posix classes)
|
||
// TODO: instead of injecting the start/end at this point, just return
|
||
// the BODY of the regexp, along with the start/end portions suitable
|
||
// for binding the start/end in either a joined full-path makeRe context
|
||
// (where we bind to (^|/), or a standalone matchPart context (where
|
||
// we bind to ^, and not /). Otherwise slashes get duped!
|
||
//
|
||
// In part-matching mode, the start is:
|
||
// - if not isStart: nothing
|
||
// - if traversal possible, but not allowed: ^(?!\.\.?$)
|
||
// - if dots allowed or not possible: ^
|
||
// - if dots possible and not allowed: ^(?!\.)
|
||
// end is:
|
||
// - if not isEnd(): nothing
|
||
// - else: $
|
||
//
|
||
// In full-path matching mode, we put the slash at the START of the
|
||
// pattern, so start is:
|
||
// - if first pattern: same as part-matching mode
|
||
// - if not isStart(): nothing
|
||
// - if traversal possible, but not allowed: /(?!\.\.?(?:$|/))
|
||
// - if dots allowed or not possible: /
|
||
// - if dots possible and not allowed: /(?!\.)
|
||
// end is:
|
||
// - if last pattern, same as part-matching mode
|
||
// - else nothing
|
||
//
|
||
// Always put the (?:$|/) on negated tails, though, because that has to be
|
||
// there to bind the end of the negated pattern portion, and it's easier to
|
||
// just stick it in now rather than try to inject it later in the middle of
|
||
// the pattern.
|
||
//
|
||
// We can just always return the same end, and leave it up to the caller
|
||
// to know whether it's going to be used joined or in parts.
|
||
// And, if the start is adjusted slightly, can do the same there:
|
||
// - if not isStart: nothing
|
||
// - if traversal possible, but not allowed: (?:/|^)(?!\.\.?$)
|
||
// - if dots allowed or not possible: (?:/|^)
|
||
// - if dots possible and not allowed: (?:/|^)(?!\.)
|
||
//
|
||
// But it's better to have a simpler binding without a conditional, for
|
||
// performance, so probably better to return both start options.
|
||
//
|
||
// Then the caller just ignores the end if it's not the first pattern,
|
||
// and the start always gets applied.
|
||
//
|
||
// But that's always going to be $ if it's the ending pattern, or nothing,
|
||
// so the caller can just attach $ at the end of the pattern when building.
|
||
//
|
||
// So the todo is:
|
||
// - better detect what kind of start is needed
|
||
// - return both flavors of starting pattern
|
||
// - attach $ at the end of the pattern when creating the actual RegExp
|
||
//
|
||
// Ah, but wait, no, that all only applies to the root when the first pattern
|
||
// is not an extglob. If the first pattern IS an extglob, then we need all
|
||
// that dot prevention biz to live in the extglob portions, because eg
|
||
// +(*|.x*) can match .xy but not .yx.
|
||
//
|
||
// So, return the two flavors if it's #root and the first child is not an
|
||
// AST, otherwise leave it to the child AST to handle it, and there,
|
||
// use the (?:^|/) style of start binding.
|
||
//
|
||
// Even simplified further:
|
||
// - Since the start for a join is eg /(?!\.) and the start for a part
|
||
// is ^(?!\.), we can just prepend (?!\.) to the pattern (either root
|
||
// or start or whatever) and prepend ^ or / at the Regexp construction.
|
||
toRegExpSource(allowDot) {
|
||
const dot = allowDot ?? !!this.#options.dot;
|
||
if (this.#root === this)
|
||
this.#fillNegs();
|
||
if (!this.type) {
|
||
const noEmpty = this.isStart() && this.isEnd();
|
||
const src = this.#parts
|
||
.map(p => {
|
||
const [re, _, hasMagic, uflag] = typeof p === 'string'
|
||
? AST.#parseGlob(p, this.#hasMagic, noEmpty)
|
||
: p.toRegExpSource(allowDot);
|
||
this.#hasMagic = this.#hasMagic || hasMagic;
|
||
this.#uflag = this.#uflag || uflag;
|
||
return re;
|
||
})
|
||
.join('');
|
||
let start = '';
|
||
if (this.isStart()) {
|
||
if (typeof this.#parts[0] === 'string') {
|
||
// this is the string that will match the start of the pattern,
|
||
// so we need to protect against dots and such.
|
||
// '.' and '..' cannot match unless the pattern is that exactly,
|
||
// even if it starts with . or dot:true is set.
|
||
const dotTravAllowed = this.#parts.length === 1 && justDots.has(this.#parts[0]);
|
||
if (!dotTravAllowed) {
|
||
const aps = addPatternStart;
|
||
// check if we have a possibility of matching . or ..,
|
||
// and prevent that.
|
||
const needNoTrav =
|
||
// dots are allowed, and the pattern starts with [ or .
|
||
(dot && aps.has(src.charAt(0))) ||
|
||
// the pattern starts with \., and then [ or .
|
||
(src.startsWith('\\.') && aps.has(src.charAt(2))) ||
|
||
// the pattern starts with \.\., and then [ or .
|
||
(src.startsWith('\\.\\.') && aps.has(src.charAt(4)));
|
||
// no need to prevent dots if it can't match a dot, or if a
|
||
// sub-pattern will be preventing it anyway.
|
||
const needNoDot = !dot && !allowDot && aps.has(src.charAt(0));
|
||
start = needNoTrav ? startNoTraversal : needNoDot ? startNoDot : '';
|
||
}
|
||
}
|
||
}
|
||
// append the "end of path portion" pattern to negation tails
|
||
let end = '';
|
||
if (this.isEnd() &&
|
||
this.#root.#filledNegs &&
|
||
this.#parent?.type === '!') {
|
||
end = '(?:$|\\/)';
|
||
}
|
||
const final = start + src + end;
|
||
return [
|
||
final,
|
||
unescape(src),
|
||
(this.#hasMagic = !!this.#hasMagic),
|
||
this.#uflag,
|
||
];
|
||
}
|
||
// We need to calculate the body *twice* if it's a repeat pattern
|
||
// at the start, once in nodot mode, then again in dot mode, so a
|
||
// pattern like *(?) can match 'x.y'
|
||
const repeated = this.type === '*' || this.type === '+';
|
||
// some kind of extglob
|
||
const start = this.type === '!' ? '(?:(?!(?:' : '(?:';
|
||
let body = this.#partsToRegExp(dot);
|
||
if (this.isStart() && this.isEnd() && !body && this.type !== '!') {
|
||
// invalid extglob, has to at least be *something* present, if it's
|
||
// the entire path portion.
|
||
const s = this.toString();
|
||
this.#parts = [s];
|
||
this.type = null;
|
||
this.#hasMagic = undefined;
|
||
return [s, unescape(this.toString()), false, false];
|
||
}
|
||
// XXX abstract out this map method
|
||
let bodyDotAllowed = !repeated || allowDot || dot || !startNoDot
|
||
? ''
|
||
: this.#partsToRegExp(true);
|
||
if (bodyDotAllowed === body) {
|
||
bodyDotAllowed = '';
|
||
}
|
||
if (bodyDotAllowed) {
|
||
body = `(?:${body})(?:${bodyDotAllowed})*?`;
|
||
}
|
||
// an empty !() is exactly equivalent to a starNoEmpty
|
||
let final = '';
|
||
if (this.type === '!' && this.#emptyExt) {
|
||
final = (this.isStart() && !dot ? startNoDot : '') + starNoEmpty;
|
||
}
|
||
else {
|
||
const close = this.type === '!'
|
||
? // !() must match something,but !(x) can match ''
|
||
'))' +
|
||
(this.isStart() && !dot && !allowDot ? startNoDot : '') +
|
||
star$2 +
|
||
')'
|
||
: this.type === '@'
|
||
? ')'
|
||
: this.type === '?'
|
||
? ')?'
|
||
: this.type === '+' && bodyDotAllowed
|
||
? ')'
|
||
: this.type === '*' && bodyDotAllowed
|
||
? `)?`
|
||
: `)${this.type}`;
|
||
final = start + body + close;
|
||
}
|
||
return [
|
||
final,
|
||
unescape(body),
|
||
(this.#hasMagic = !!this.#hasMagic),
|
||
this.#uflag,
|
||
];
|
||
}
|
||
#partsToRegExp(dot) {
|
||
return this.#parts
|
||
.map(p => {
|
||
// extglob ASTs should only contain parent ASTs
|
||
/* c8 ignore start */
|
||
if (typeof p === 'string') {
|
||
throw new Error('string type in extglob ast??');
|
||
}
|
||
/* c8 ignore stop */
|
||
// can ignore hasMagic, because extglobs are already always magic
|
||
const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot);
|
||
this.#uflag = this.#uflag || uflag;
|
||
return re;
|
||
})
|
||
.filter(p => !(this.isStart() && this.isEnd()) || !!p)
|
||
.join('|');
|
||
}
|
||
static #parseGlob(glob, hasMagic, noEmpty = false) {
|
||
let escaping = false;
|
||
let re = '';
|
||
let uflag = false;
|
||
for (let i = 0; i < glob.length; i++) {
|
||
const c = glob.charAt(i);
|
||
if (escaping) {
|
||
escaping = false;
|
||
re += (reSpecials.has(c) ? '\\' : '') + c;
|
||
continue;
|
||
}
|
||
if (c === '\\') {
|
||
if (i === glob.length - 1) {
|
||
re += '\\\\';
|
||
}
|
||
else {
|
||
escaping = true;
|
||
}
|
||
continue;
|
||
}
|
||
if (c === '[') {
|
||
const [src, needUflag, consumed, magic] = parseClass(glob, i);
|
||
if (consumed) {
|
||
re += src;
|
||
uflag = uflag || needUflag;
|
||
i += consumed - 1;
|
||
hasMagic = hasMagic || magic;
|
||
continue;
|
||
}
|
||
}
|
||
if (c === '*') {
|
||
if (noEmpty && glob === '*')
|
||
re += starNoEmpty;
|
||
else
|
||
re += star$2;
|
||
hasMagic = true;
|
||
continue;
|
||
}
|
||
if (c === '?') {
|
||
re += qmark$1;
|
||
hasMagic = true;
|
||
continue;
|
||
}
|
||
re += regExpEscape$1(c);
|
||
}
|
||
return [re, unescape(glob), !!hasMagic, uflag];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Escape all magic characters in a glob pattern.
|
||
*
|
||
* If the {@link windowsPathsNoEscape | GlobOptions.windowsPathsNoEscape}
|
||
* option is used, then characters are escaped by wrapping in `[]`, because
|
||
* a magic character wrapped in a character class can only be satisfied by
|
||
* that exact character. In this mode, `\` is _not_ escaped, because it is
|
||
* not interpreted as a magic character, but instead as a path separator.
|
||
*/
|
||
const escape$4 = (s, { windowsPathsNoEscape = false, } = {}) => {
|
||
// don't need to escape +@! because we escape the parens
|
||
// that make those magic, and escaping ! as [!] isn't valid,
|
||
// because [!]] is a valid glob class meaning not ']'.
|
||
return windowsPathsNoEscape
|
||
? s.replace(/[?*()[\]]/g, '[$&]')
|
||
: s.replace(/[?*()[\]\\]/g, '\\$&');
|
||
};
|
||
|
||
const minimatch = (p, pattern, options = {}) => {
|
||
assertValidPattern(pattern);
|
||
// shortcut: comments match nothing.
|
||
if (!options.nocomment && pattern.charAt(0) === '#') {
|
||
return false;
|
||
}
|
||
return new Minimatch(pattern, options).match(p);
|
||
};
|
||
// Optimized checking for the most common glob patterns.
|
||
const starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/;
|
||
const starDotExtTest = (ext) => (f) => !f.startsWith('.') && f.endsWith(ext);
|
||
const starDotExtTestDot = (ext) => (f) => f.endsWith(ext);
|
||
const starDotExtTestNocase = (ext) => {
|
||
ext = ext.toLowerCase();
|
||
return (f) => !f.startsWith('.') && f.toLowerCase().endsWith(ext);
|
||
};
|
||
const starDotExtTestNocaseDot = (ext) => {
|
||
ext = ext.toLowerCase();
|
||
return (f) => f.toLowerCase().endsWith(ext);
|
||
};
|
||
const starDotStarRE = /^\*+\.\*+$/;
|
||
const starDotStarTest = (f) => !f.startsWith('.') && f.includes('.');
|
||
const starDotStarTestDot = (f) => f !== '.' && f !== '..' && f.includes('.');
|
||
const dotStarRE = /^\.\*+$/;
|
||
const dotStarTest = (f) => f !== '.' && f !== '..' && f.startsWith('.');
|
||
const starRE = /^\*+$/;
|
||
const starTest = (f) => f.length !== 0 && !f.startsWith('.');
|
||
const starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..';
|
||
const qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/;
|
||
const qmarksTestNocase = ([$0, ext = '']) => {
|
||
const noext = qmarksTestNoExt([$0]);
|
||
if (!ext)
|
||
return noext;
|
||
ext = ext.toLowerCase();
|
||
return (f) => noext(f) && f.toLowerCase().endsWith(ext);
|
||
};
|
||
const qmarksTestNocaseDot = ([$0, ext = '']) => {
|
||
const noext = qmarksTestNoExtDot([$0]);
|
||
if (!ext)
|
||
return noext;
|
||
ext = ext.toLowerCase();
|
||
return (f) => noext(f) && f.toLowerCase().endsWith(ext);
|
||
};
|
||
const qmarksTestDot = ([$0, ext = '']) => {
|
||
const noext = qmarksTestNoExtDot([$0]);
|
||
return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
|
||
};
|
||
const qmarksTest = ([$0, ext = '']) => {
|
||
const noext = qmarksTestNoExt([$0]);
|
||
return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
|
||
};
|
||
const qmarksTestNoExt = ([$0]) => {
|
||
const len = $0.length;
|
||
return (f) => f.length === len && !f.startsWith('.');
|
||
};
|
||
const qmarksTestNoExtDot = ([$0]) => {
|
||
const len = $0.length;
|
||
return (f) => f.length === len && f !== '.' && f !== '..';
|
||
};
|
||
/* c8 ignore start */
|
||
const defaultPlatform$2 = (typeof process === 'object' && process
|
||
? (typeof process.env === 'object' &&
|
||
process.env &&
|
||
process.env.__MINIMATCH_TESTING_PLATFORM__) ||
|
||
process.platform
|
||
: 'posix');
|
||
const path$d = {
|
||
win32: { sep: '\\' },
|
||
posix: { sep: '/' },
|
||
};
|
||
/* c8 ignore stop */
|
||
const sep = defaultPlatform$2 === 'win32' ? path$d.win32.sep : path$d.posix.sep;
|
||
minimatch.sep = sep;
|
||
const GLOBSTAR$1 = Symbol('globstar **');
|
||
minimatch.GLOBSTAR = GLOBSTAR$1;
|
||
// any single thing other than /
|
||
// don't need to escape / when using new RegExp()
|
||
const qmark = '[^/]';
|
||
// * => any number of characters
|
||
const star$1 = qmark + '*?';
|
||
// ** when dots are allowed. Anything goes, except .. and .
|
||
// not (^ or / followed by one or two dots followed by $ or /),
|
||
// followed by anything, any number of times.
|
||
const twoStarDot = '(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?';
|
||
// not a ^ or / followed by a dot,
|
||
// followed by anything, any number of times.
|
||
const twoStarNoDot = '(?:(?!(?:\\/|^)\\.).)*?';
|
||
const filter = (pattern, options = {}) => (p) => minimatch(p, pattern, options);
|
||
minimatch.filter = filter;
|
||
const ext = (a, b = {}) => Object.assign({}, a, b);
|
||
const defaults$5 = (def) => {
|
||
if (!def || typeof def !== 'object' || !Object.keys(def).length) {
|
||
return minimatch;
|
||
}
|
||
const orig = minimatch;
|
||
const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options));
|
||
return Object.assign(m, {
|
||
Minimatch: class Minimatch extends orig.Minimatch {
|
||
constructor(pattern, options = {}) {
|
||
super(pattern, ext(def, options));
|
||
}
|
||
static defaults(options) {
|
||
return orig.defaults(ext(def, options)).Minimatch;
|
||
}
|
||
},
|
||
AST: class AST extends orig.AST {
|
||
/* c8 ignore start */
|
||
constructor(type, parent, options = {}) {
|
||
super(type, parent, ext(def, options));
|
||
}
|
||
/* c8 ignore stop */
|
||
static fromGlob(pattern, options = {}) {
|
||
return orig.AST.fromGlob(pattern, ext(def, options));
|
||
}
|
||
},
|
||
unescape: (s, options = {}) => orig.unescape(s, ext(def, options)),
|
||
escape: (s, options = {}) => orig.escape(s, ext(def, options)),
|
||
filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)),
|
||
defaults: (options) => orig.defaults(ext(def, options)),
|
||
makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
|
||
braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
|
||
match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
|
||
sep: orig.sep,
|
||
GLOBSTAR: GLOBSTAR$1,
|
||
});
|
||
};
|
||
minimatch.defaults = defaults$5;
|
||
// Brace expansion:
|
||
// a{b,c}d -> abd acd
|
||
// a{b,}c -> abc ac
|
||
// a{0..3}d -> a0d a1d a2d a3d
|
||
// a{b,c{d,e}f}g -> abg acdfg acefg
|
||
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
|
||
//
|
||
// Invalid sets are not expanded.
|
||
// a{2..}b -> a{2..}b
|
||
// a{b}c -> a{b}c
|
||
const braceExpand = (pattern, options = {}) => {
|
||
assertValidPattern(pattern);
|
||
// Thanks to Yeting Li <https://github.com/yetingli> for
|
||
// improving this regexp to avoid a ReDOS vulnerability.
|
||
if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
|
||
// shortcut. no need to expand.
|
||
return [pattern];
|
||
}
|
||
return expand$3(pattern);
|
||
};
|
||
minimatch.braceExpand = braceExpand;
|
||
// parse a component of the expanded set.
|
||
// At this point, no pattern may contain "/" in it
|
||
// so we're going to return a 2d array, where each entry is the full
|
||
// pattern, split on '/', and then turned into a regular expression.
|
||
// A regexp is made at the end which joins each array with an
|
||
// escaped /, and another full one which joins each regexp with |.
|
||
//
|
||
// Following the lead of Bash 4.1, note that "**" only has special meaning
|
||
// when it is the *only* thing in a path portion. Otherwise, any series
|
||
// of * is equivalent to a single *. Globstar behavior is enabled by
|
||
// default, and can be disabled by setting options.noglobstar.
|
||
const makeRe$1 = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
|
||
minimatch.makeRe = makeRe$1;
|
||
const match$1 = (list, pattern, options = {}) => {
|
||
const mm = new Minimatch(pattern, options);
|
||
list = list.filter(f => mm.match(f));
|
||
if (mm.options.nonull && !list.length) {
|
||
list.push(pattern);
|
||
}
|
||
return list;
|
||
};
|
||
minimatch.match = match$1;
|
||
// replace stuff like \* with *
|
||
const globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/;
|
||
const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||
class Minimatch {
|
||
options;
|
||
set;
|
||
pattern;
|
||
windowsPathsNoEscape;
|
||
nonegate;
|
||
negate;
|
||
comment;
|
||
empty;
|
||
preserveMultipleSlashes;
|
||
partial;
|
||
globSet;
|
||
globParts;
|
||
nocase;
|
||
isWindows;
|
||
platform;
|
||
windowsNoMagicRoot;
|
||
regexp;
|
||
constructor(pattern, options = {}) {
|
||
assertValidPattern(pattern);
|
||
options = options || {};
|
||
this.options = options;
|
||
this.pattern = pattern;
|
||
this.platform = options.platform || defaultPlatform$2;
|
||
this.isWindows = this.platform === 'win32';
|
||
this.windowsPathsNoEscape =
|
||
!!options.windowsPathsNoEscape || options.allowWindowsEscape === false;
|
||
if (this.windowsPathsNoEscape) {
|
||
this.pattern = this.pattern.replace(/\\/g, '/');
|
||
}
|
||
this.preserveMultipleSlashes = !!options.preserveMultipleSlashes;
|
||
this.regexp = null;
|
||
this.negate = false;
|
||
this.nonegate = !!options.nonegate;
|
||
this.comment = false;
|
||
this.empty = false;
|
||
this.partial = !!options.partial;
|
||
this.nocase = !!this.options.nocase;
|
||
this.windowsNoMagicRoot =
|
||
options.windowsNoMagicRoot !== undefined
|
||
? options.windowsNoMagicRoot
|
||
: !!(this.isWindows && this.nocase);
|
||
this.globSet = [];
|
||
this.globParts = [];
|
||
this.set = [];
|
||
// make the set of regexps etc.
|
||
this.make();
|
||
}
|
||
hasMagic() {
|
||
if (this.options.magicalBraces && this.set.length > 1) {
|
||
return true;
|
||
}
|
||
for (const pattern of this.set) {
|
||
for (const part of pattern) {
|
||
if (typeof part !== 'string')
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
debug(..._) { }
|
||
make() {
|
||
const pattern = this.pattern;
|
||
const options = this.options;
|
||
// empty patterns and comments match nothing.
|
||
if (!options.nocomment && pattern.charAt(0) === '#') {
|
||
this.comment = true;
|
||
return;
|
||
}
|
||
if (!pattern) {
|
||
this.empty = true;
|
||
return;
|
||
}
|
||
// step 1: figure out negation, etc.
|
||
this.parseNegate();
|
||
// step 2: expand braces
|
||
this.globSet = [...new Set(this.braceExpand())];
|
||
if (options.debug) {
|
||
this.debug = (...args) => console.error(...args);
|
||
}
|
||
this.debug(this.pattern, this.globSet);
|
||
// step 3: now we have a set, so turn each one into a series of
|
||
// path-portion matching patterns.
|
||
// These will be regexps, except in the case of "**", which is
|
||
// set to the GLOBSTAR object for globstar behavior,
|
||
// and will not contain any / characters
|
||
//
|
||
// First, we preprocess to make the glob pattern sets a bit simpler
|
||
// and deduped. There are some perf-killing patterns that can cause
|
||
// problems with a glob walk, but we can simplify them down a bit.
|
||
const rawGlobParts = this.globSet.map(s => this.slashSplit(s));
|
||
this.globParts = this.preprocess(rawGlobParts);
|
||
this.debug(this.pattern, this.globParts);
|
||
// glob --> regexps
|
||
let set = this.globParts.map((s, _, __) => {
|
||
if (this.isWindows && this.windowsNoMagicRoot) {
|
||
// check if it's a drive or unc path.
|
||
const isUNC = s[0] === '' &&
|
||
s[1] === '' &&
|
||
(s[2] === '?' || !globMagic.test(s[2])) &&
|
||
!globMagic.test(s[3]);
|
||
const isDrive = /^[a-z]:/i.test(s[0]);
|
||
if (isUNC) {
|
||
return [...s.slice(0, 4), ...s.slice(4).map(ss => this.parse(ss))];
|
||
}
|
||
else if (isDrive) {
|
||
return [s[0], ...s.slice(1).map(ss => this.parse(ss))];
|
||
}
|
||
}
|
||
return s.map(ss => this.parse(ss));
|
||
});
|
||
this.debug(this.pattern, set);
|
||
// filter out everything that didn't compile properly.
|
||
this.set = set.filter(s => s.indexOf(false) === -1);
|
||
// do not treat the ? in UNC paths as magic
|
||
if (this.isWindows) {
|
||
for (let i = 0; i < this.set.length; i++) {
|
||
const p = this.set[i];
|
||
if (p[0] === '' &&
|
||
p[1] === '' &&
|
||
this.globParts[i][2] === '?' &&
|
||
typeof p[3] === 'string' &&
|
||
/^[a-z]:$/i.test(p[3])) {
|
||
p[2] = '?';
|
||
}
|
||
}
|
||
}
|
||
this.debug(this.pattern, this.set);
|
||
}
|
||
// various transforms to equivalent pattern sets that are
|
||
// faster to process in a filesystem walk. The goal is to
|
||
// eliminate what we can, and push all ** patterns as far
|
||
// to the right as possible, even if it increases the number
|
||
// of patterns that we have to process.
|
||
preprocess(globParts) {
|
||
// if we're not in globstar mode, then turn all ** into *
|
||
if (this.options.noglobstar) {
|
||
for (let i = 0; i < globParts.length; i++) {
|
||
for (let j = 0; j < globParts[i].length; j++) {
|
||
if (globParts[i][j] === '**') {
|
||
globParts[i][j] = '*';
|
||
}
|
||
}
|
||
}
|
||
}
|
||
const { optimizationLevel = 1 } = this.options;
|
||
if (optimizationLevel >= 2) {
|
||
// aggressive optimization for the purpose of fs walking
|
||
globParts = this.firstPhasePreProcess(globParts);
|
||
globParts = this.secondPhasePreProcess(globParts);
|
||
}
|
||
else if (optimizationLevel >= 1) {
|
||
// just basic optimizations to remove some .. parts
|
||
globParts = this.levelOneOptimize(globParts);
|
||
}
|
||
else {
|
||
globParts = this.adjascentGlobstarOptimize(globParts);
|
||
}
|
||
return globParts;
|
||
}
|
||
// just get rid of adjascent ** portions
|
||
adjascentGlobstarOptimize(globParts) {
|
||
return globParts.map(parts => {
|
||
let gs = -1;
|
||
while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
|
||
let i = gs;
|
||
while (parts[i + 1] === '**') {
|
||
i++;
|
||
}
|
||
if (i !== gs) {
|
||
parts.splice(gs, i - gs);
|
||
}
|
||
}
|
||
return parts;
|
||
});
|
||
}
|
||
// get rid of adjascent ** and resolve .. portions
|
||
levelOneOptimize(globParts) {
|
||
return globParts.map(parts => {
|
||
parts = parts.reduce((set, part) => {
|
||
const prev = set[set.length - 1];
|
||
if (part === '**' && prev === '**') {
|
||
return set;
|
||
}
|
||
if (part === '..') {
|
||
if (prev && prev !== '..' && prev !== '.' && prev !== '**') {
|
||
set.pop();
|
||
return set;
|
||
}
|
||
}
|
||
set.push(part);
|
||
return set;
|
||
}, []);
|
||
return parts.length === 0 ? [''] : parts;
|
||
});
|
||
}
|
||
levelTwoFileOptimize(parts) {
|
||
if (!Array.isArray(parts)) {
|
||
parts = this.slashSplit(parts);
|
||
}
|
||
let didSomething = false;
|
||
do {
|
||
didSomething = false;
|
||
// <pre>/<e>/<rest> -> <pre>/<rest>
|
||
if (!this.preserveMultipleSlashes) {
|
||
for (let i = 1; i < parts.length - 1; i++) {
|
||
const p = parts[i];
|
||
// don't squeeze out UNC patterns
|
||
if (i === 1 && p === '' && parts[0] === '')
|
||
continue;
|
||
if (p === '.' || p === '') {
|
||
didSomething = true;
|
||
parts.splice(i, 1);
|
||
i--;
|
||
}
|
||
}
|
||
if (parts[0] === '.' &&
|
||
parts.length === 2 &&
|
||
(parts[1] === '.' || parts[1] === '')) {
|
||
didSomething = true;
|
||
parts.pop();
|
||
}
|
||
}
|
||
// <pre>/<p>/../<rest> -> <pre>/<rest>
|
||
let dd = 0;
|
||
while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
|
||
const p = parts[dd - 1];
|
||
if (p && p !== '.' && p !== '..' && p !== '**') {
|
||
didSomething = true;
|
||
parts.splice(dd - 1, 2);
|
||
dd -= 2;
|
||
}
|
||
}
|
||
} while (didSomething);
|
||
return parts.length === 0 ? [''] : parts;
|
||
}
|
||
// First phase: single-pattern processing
|
||
// <pre> is 1 or more portions
|
||
// <rest> is 1 or more portions
|
||
// <p> is any portion other than ., .., '', or **
|
||
// <e> is . or ''
|
||
//
|
||
// **/.. is *brutal* for filesystem walking performance, because
|
||
// it effectively resets the recursive walk each time it occurs,
|
||
// and ** cannot be reduced out by a .. pattern part like a regexp
|
||
// or most strings (other than .., ., and '') can be.
|
||
//
|
||
// <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
|
||
// <pre>/<e>/<rest> -> <pre>/<rest>
|
||
// <pre>/<p>/../<rest> -> <pre>/<rest>
|
||
// **/**/<rest> -> **/<rest>
|
||
//
|
||
// **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow
|
||
// this WOULD be allowed if ** did follow symlinks, or * didn't
|
||
firstPhasePreProcess(globParts) {
|
||
let didSomething = false;
|
||
do {
|
||
didSomething = false;
|
||
// <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
|
||
for (let parts of globParts) {
|
||
let gs = -1;
|
||
while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
|
||
let gss = gs;
|
||
while (parts[gss + 1] === '**') {
|
||
// <pre>/**/**/<rest> -> <pre>/**/<rest>
|
||
gss++;
|
||
}
|
||
// eg, if gs is 2 and gss is 4, that means we have 3 **
|
||
// parts, and can remove 2 of them.
|
||
if (gss > gs) {
|
||
parts.splice(gs + 1, gss - gs);
|
||
}
|
||
let next = parts[gs + 1];
|
||
const p = parts[gs + 2];
|
||
const p2 = parts[gs + 3];
|
||
if (next !== '..')
|
||
continue;
|
||
if (!p ||
|
||
p === '.' ||
|
||
p === '..' ||
|
||
!p2 ||
|
||
p2 === '.' ||
|
||
p2 === '..') {
|
||
continue;
|
||
}
|
||
didSomething = true;
|
||
// edit parts in place, and push the new one
|
||
parts.splice(gs, 1);
|
||
const other = parts.slice(0);
|
||
other[gs] = '**';
|
||
globParts.push(other);
|
||
gs--;
|
||
}
|
||
// <pre>/<e>/<rest> -> <pre>/<rest>
|
||
if (!this.preserveMultipleSlashes) {
|
||
for (let i = 1; i < parts.length - 1; i++) {
|
||
const p = parts[i];
|
||
// don't squeeze out UNC patterns
|
||
if (i === 1 && p === '' && parts[0] === '')
|
||
continue;
|
||
if (p === '.' || p === '') {
|
||
didSomething = true;
|
||
parts.splice(i, 1);
|
||
i--;
|
||
}
|
||
}
|
||
if (parts[0] === '.' &&
|
||
parts.length === 2 &&
|
||
(parts[1] === '.' || parts[1] === '')) {
|
||
didSomething = true;
|
||
parts.pop();
|
||
}
|
||
}
|
||
// <pre>/<p>/../<rest> -> <pre>/<rest>
|
||
let dd = 0;
|
||
while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
|
||
const p = parts[dd - 1];
|
||
if (p && p !== '.' && p !== '..' && p !== '**') {
|
||
didSomething = true;
|
||
const needDot = dd === 1 && parts[dd + 1] === '**';
|
||
const splin = needDot ? ['.'] : [];
|
||
parts.splice(dd - 1, 2, ...splin);
|
||
if (parts.length === 0)
|
||
parts.push('');
|
||
dd -= 2;
|
||
}
|
||
}
|
||
}
|
||
} while (didSomething);
|
||
return globParts;
|
||
}
|
||
// second phase: multi-pattern dedupes
|
||
// {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>
|
||
// {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>
|
||
// {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>
|
||
//
|
||
// {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>
|
||
// ^-- not valid because ** doens't follow symlinks
|
||
secondPhasePreProcess(globParts) {
|
||
for (let i = 0; i < globParts.length - 1; i++) {
|
||
for (let j = i + 1; j < globParts.length; j++) {
|
||
const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes);
|
||
if (!matched)
|
||
continue;
|
||
globParts[i] = matched;
|
||
globParts[j] = [];
|
||
}
|
||
}
|
||
return globParts.filter(gs => gs.length);
|
||
}
|
||
partsMatch(a, b, emptyGSMatch = false) {
|
||
let ai = 0;
|
||
let bi = 0;
|
||
let result = [];
|
||
let which = '';
|
||
while (ai < a.length && bi < b.length) {
|
||
if (a[ai] === b[bi]) {
|
||
result.push(which === 'b' ? b[bi] : a[ai]);
|
||
ai++;
|
||
bi++;
|
||
}
|
||
else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) {
|
||
result.push(a[ai]);
|
||
ai++;
|
||
}
|
||
else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) {
|
||
result.push(b[bi]);
|
||
bi++;
|
||
}
|
||
else if (a[ai] === '*' &&
|
||
b[bi] &&
|
||
(this.options.dot || !b[bi].startsWith('.')) &&
|
||
b[bi] !== '**') {
|
||
if (which === 'b')
|
||
return false;
|
||
which = 'a';
|
||
result.push(a[ai]);
|
||
ai++;
|
||
bi++;
|
||
}
|
||
else if (b[bi] === '*' &&
|
||
a[ai] &&
|
||
(this.options.dot || !a[ai].startsWith('.')) &&
|
||
a[ai] !== '**') {
|
||
if (which === 'a')
|
||
return false;
|
||
which = 'b';
|
||
result.push(b[bi]);
|
||
ai++;
|
||
bi++;
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
}
|
||
// if we fall out of the loop, it means they two are identical
|
||
// as long as their lengths match
|
||
return a.length === b.length && result;
|
||
}
|
||
parseNegate() {
|
||
if (this.nonegate)
|
||
return;
|
||
const pattern = this.pattern;
|
||
let negate = false;
|
||
let negateOffset = 0;
|
||
for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
|
||
negate = !negate;
|
||
negateOffset++;
|
||
}
|
||
if (negateOffset)
|
||
this.pattern = pattern.slice(negateOffset);
|
||
this.negate = negate;
|
||
}
|
||
// set partial to true to test if, for example,
|
||
// "/a/b" matches the start of "/*/b/*/d"
|
||
// Partial means, if you run out of file before you run
|
||
// out of pattern, then that's fine, as long as all
|
||
// the parts match.
|
||
matchOne(file, pattern, partial = false) {
|
||
const options = this.options;
|
||
// UNC paths like //?/X:/... can match X:/... and vice versa
|
||
// Drive letters in absolute drive or unc paths are always compared
|
||
// case-insensitively.
|
||
if (this.isWindows) {
|
||
const fileDrive = typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0]);
|
||
const fileUNC = !fileDrive &&
|
||
file[0] === '' &&
|
||
file[1] === '' &&
|
||
file[2] === '?' &&
|
||
/^[a-z]:$/i.test(file[3]);
|
||
const patternDrive = typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0]);
|
||
const patternUNC = !patternDrive &&
|
||
pattern[0] === '' &&
|
||
pattern[1] === '' &&
|
||
pattern[2] === '?' &&
|
||
typeof pattern[3] === 'string' &&
|
||
/^[a-z]:$/i.test(pattern[3]);
|
||
const fdi = fileUNC ? 3 : fileDrive ? 0 : undefined;
|
||
const pdi = patternUNC ? 3 : patternDrive ? 0 : undefined;
|
||
if (typeof fdi === 'number' && typeof pdi === 'number') {
|
||
const [fd, pd] = [file[fdi], pattern[pdi]];
|
||
if (fd.toLowerCase() === pd.toLowerCase()) {
|
||
pattern[pdi] = fd;
|
||
if (pdi > fdi) {
|
||
pattern = pattern.slice(pdi);
|
||
}
|
||
else if (fdi > pdi) {
|
||
file = file.slice(fdi);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// resolve and reduce . and .. portions in the file as well.
|
||
// dont' need to do the second phase, because it's only one string[]
|
||
const { optimizationLevel = 1 } = this.options;
|
||
if (optimizationLevel >= 2) {
|
||
file = this.levelTwoFileOptimize(file);
|
||
}
|
||
this.debug('matchOne', this, { file, pattern });
|
||
this.debug('matchOne', file.length, pattern.length);
|
||
for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
|
||
this.debug('matchOne loop');
|
||
var p = pattern[pi];
|
||
var f = file[fi];
|
||
this.debug(pattern, p, f);
|
||
// should be impossible.
|
||
// some invalid regexp stuff in the set.
|
||
/* c8 ignore start */
|
||
if (p === false) {
|
||
return false;
|
||
}
|
||
/* c8 ignore stop */
|
||
if (p === GLOBSTAR$1) {
|
||
this.debug('GLOBSTAR', [pattern, p, f]);
|
||
// "**"
|
||
// a/**/b/**/c would match the following:
|
||
// a/b/x/y/z/c
|
||
// a/x/y/z/b/c
|
||
// a/b/x/b/x/c
|
||
// a/b/c
|
||
// To do this, take the rest of the pattern after
|
||
// the **, and see if it would match the file remainder.
|
||
// If so, return success.
|
||
// If not, the ** "swallows" a segment, and try again.
|
||
// This is recursively awful.
|
||
//
|
||
// a/**/b/**/c matching a/b/x/y/z/c
|
||
// - a matches a
|
||
// - doublestar
|
||
// - matchOne(b/x/y/z/c, b/**/c)
|
||
// - b matches b
|
||
// - doublestar
|
||
// - matchOne(x/y/z/c, c) -> no
|
||
// - matchOne(y/z/c, c) -> no
|
||
// - matchOne(z/c, c) -> no
|
||
// - matchOne(c, c) yes, hit
|
||
var fr = fi;
|
||
var pr = pi + 1;
|
||
if (pr === pl) {
|
||
this.debug('** at the end');
|
||
// a ** at the end will just swallow the rest.
|
||
// We have found a match.
|
||
// however, it will not swallow /.x, unless
|
||
// options.dot is set.
|
||
// . and .. are *never* matched by **, for explosively
|
||
// exponential reasons.
|
||
for (; fi < fl; fi++) {
|
||
if (file[fi] === '.' ||
|
||
file[fi] === '..' ||
|
||
(!options.dot && file[fi].charAt(0) === '.'))
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
// ok, let's see if we can swallow whatever we can.
|
||
while (fr < fl) {
|
||
var swallowee = file[fr];
|
||
this.debug('\nglobstar while', file, fr, pattern, pr, swallowee);
|
||
// XXX remove this slice. Just pass the start index.
|
||
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
|
||
this.debug('globstar found match!', fr, fl, swallowee);
|
||
// found a match.
|
||
return true;
|
||
}
|
||
else {
|
||
// can't swallow "." or ".." ever.
|
||
// can only swallow ".foo" when explicitly asked.
|
||
if (swallowee === '.' ||
|
||
swallowee === '..' ||
|
||
(!options.dot && swallowee.charAt(0) === '.')) {
|
||
this.debug('dot detected!', file, fr, pattern, pr);
|
||
break;
|
||
}
|
||
// ** swallows a segment, and continue.
|
||
this.debug('globstar swallow a segment, and continue');
|
||
fr++;
|
||
}
|
||
}
|
||
// no match was found.
|
||
// However, in partial mode, we can't say this is necessarily over.
|
||
/* c8 ignore start */
|
||
if (partial) {
|
||
// ran out of file
|
||
this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
|
||
if (fr === fl) {
|
||
return true;
|
||
}
|
||
}
|
||
/* c8 ignore stop */
|
||
return false;
|
||
}
|
||
// something other than **
|
||
// non-magic patterns just have to match exactly
|
||
// patterns with magic have been turned into regexps.
|
||
let hit;
|
||
if (typeof p === 'string') {
|
||
hit = f === p;
|
||
this.debug('string match', p, f, hit);
|
||
}
|
||
else {
|
||
hit = p.test(f);
|
||
this.debug('pattern match', p, f, hit);
|
||
}
|
||
if (!hit)
|
||
return false;
|
||
}
|
||
// Note: ending in / means that we'll get a final ""
|
||
// at the end of the pattern. This can only match a
|
||
// corresponding "" at the end of the file.
|
||
// If the file ends in /, then it can only match a
|
||
// a pattern that ends in /, unless the pattern just
|
||
// doesn't have any more for it. But, a/b/ should *not*
|
||
// match "a/b/*", even though "" matches against the
|
||
// [^/]*? pattern, except in partial mode, where it might
|
||
// simply not be reached yet.
|
||
// However, a/b/ should still satisfy a/*
|
||
// now either we fell off the end of the pattern, or we're done.
|
||
if (fi === fl && pi === pl) {
|
||
// ran out of pattern and filename at the same time.
|
||
// an exact hit!
|
||
return true;
|
||
}
|
||
else if (fi === fl) {
|
||
// ran out of file, but still had pattern left.
|
||
// this is ok if we're doing the match as part of
|
||
// a glob fs traversal.
|
||
return partial;
|
||
}
|
||
else if (pi === pl) {
|
||
// ran out of pattern, still have file left.
|
||
// this is only acceptable if we're on the very last
|
||
// empty segment of a file with a trailing slash.
|
||
// a/* should match a/b/
|
||
return fi === fl - 1 && file[fi] === '';
|
||
/* c8 ignore start */
|
||
}
|
||
else {
|
||
// should be unreachable.
|
||
throw new Error('wtf?');
|
||
}
|
||
/* c8 ignore stop */
|
||
}
|
||
braceExpand() {
|
||
return braceExpand(this.pattern, this.options);
|
||
}
|
||
parse(pattern) {
|
||
assertValidPattern(pattern);
|
||
const options = this.options;
|
||
// shortcuts
|
||
if (pattern === '**')
|
||
return GLOBSTAR$1;
|
||
if (pattern === '')
|
||
return '';
|
||
// far and away, the most common glob pattern parts are
|
||
// *, *.*, and *.<ext> Add a fast check method for those.
|
||
let m;
|
||
let fastTest = null;
|
||
if ((m = pattern.match(starRE))) {
|
||
fastTest = options.dot ? starTestDot : starTest;
|
||
}
|
||
else if ((m = pattern.match(starDotExtRE))) {
|
||
fastTest = (options.nocase
|
||
? options.dot
|
||
? starDotExtTestNocaseDot
|
||
: starDotExtTestNocase
|
||
: options.dot
|
||
? starDotExtTestDot
|
||
: starDotExtTest)(m[1]);
|
||
}
|
||
else if ((m = pattern.match(qmarksRE))) {
|
||
fastTest = (options.nocase
|
||
? options.dot
|
||
? qmarksTestNocaseDot
|
||
: qmarksTestNocase
|
||
: options.dot
|
||
? qmarksTestDot
|
||
: qmarksTest)(m);
|
||
}
|
||
else if ((m = pattern.match(starDotStarRE))) {
|
||
fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
|
||
}
|
||
else if ((m = pattern.match(dotStarRE))) {
|
||
fastTest = dotStarTest;
|
||
}
|
||
const re = AST.fromGlob(pattern, this.options).toMMPattern();
|
||
return fastTest ? Object.assign(re, { test: fastTest }) : re;
|
||
}
|
||
makeRe() {
|
||
if (this.regexp || this.regexp === false)
|
||
return this.regexp;
|
||
// at this point, this.set is a 2d array of partial
|
||
// pattern strings, or "**".
|
||
//
|
||
// It's better to use .match(). This function shouldn't
|
||
// be used, really, but it's pretty convenient sometimes,
|
||
// when you just want to work with a regex.
|
||
const set = this.set;
|
||
if (!set.length) {
|
||
this.regexp = false;
|
||
return this.regexp;
|
||
}
|
||
const options = this.options;
|
||
const twoStar = options.noglobstar
|
||
? star$1
|
||
: options.dot
|
||
? twoStarDot
|
||
: twoStarNoDot;
|
||
const flags = new Set(options.nocase ? ['i'] : []);
|
||
// regexpify non-globstar patterns
|
||
// if ** is only item, then we just do one twoStar
|
||
// if ** is first, and there are more, prepend (\/|twoStar\/)? to next
|
||
// if ** is last, append (\/twoStar|) to previous
|
||
// if ** is in the middle, append (\/|\/twoStar\/) to previous
|
||
// then filter out GLOBSTAR symbols
|
||
let re = set
|
||
.map(pattern => {
|
||
const pp = pattern.map(p => {
|
||
if (p instanceof RegExp) {
|
||
for (const f of p.flags.split(''))
|
||
flags.add(f);
|
||
}
|
||
return typeof p === 'string'
|
||
? regExpEscape(p)
|
||
: p === GLOBSTAR$1
|
||
? GLOBSTAR$1
|
||
: p._src;
|
||
});
|
||
pp.forEach((p, i) => {
|
||
const next = pp[i + 1];
|
||
const prev = pp[i - 1];
|
||
if (p !== GLOBSTAR$1 || prev === GLOBSTAR$1) {
|
||
return;
|
||
}
|
||
if (prev === undefined) {
|
||
if (next !== undefined && next !== GLOBSTAR$1) {
|
||
pp[i + 1] = '(?:\\/|' + twoStar + '\\/)?' + next;
|
||
}
|
||
else {
|
||
pp[i] = twoStar;
|
||
}
|
||
}
|
||
else if (next === undefined) {
|
||
pp[i - 1] = prev + '(?:\\/|' + twoStar + ')?';
|
||
}
|
||
else if (next !== GLOBSTAR$1) {
|
||
pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + '\\/)' + next;
|
||
pp[i + 1] = GLOBSTAR$1;
|
||
}
|
||
});
|
||
return pp.filter(p => p !== GLOBSTAR$1).join('/');
|
||
})
|
||
.join('|');
|
||
// need to wrap in parens if we had more than one thing with |,
|
||
// otherwise only the first will be anchored to ^ and the last to $
|
||
const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', ''];
|
||
// must match entire pattern
|
||
// ending in a * or ** will make it less strict.
|
||
re = '^' + open + re + close + '$';
|
||
// can match anything, as long as it's not this.
|
||
if (this.negate)
|
||
re = '^(?!' + re + ').+$';
|
||
try {
|
||
this.regexp = new RegExp(re, [...flags].join(''));
|
||
/* c8 ignore start */
|
||
}
|
||
catch (ex) {
|
||
// should be impossible
|
||
this.regexp = false;
|
||
}
|
||
/* c8 ignore stop */
|
||
return this.regexp;
|
||
}
|
||
slashSplit(p) {
|
||
// if p starts with // on windows, we preserve that
|
||
// so that UNC paths aren't broken. Otherwise, any number of
|
||
// / characters are coalesced into one, unless
|
||
// preserveMultipleSlashes is set to true.
|
||
if (this.preserveMultipleSlashes) {
|
||
return p.split('/');
|
||
}
|
||
else if (this.isWindows && /^\/\/[^\/]+/.test(p)) {
|
||
// add an extra '' for the one we lose
|
||
return ['', ...p.split(/\/+/)];
|
||
}
|
||
else {
|
||
return p.split(/\/+/);
|
||
}
|
||
}
|
||
match(f, partial = this.partial) {
|
||
this.debug('match', f, this.pattern);
|
||
// short-circuit in the case of busted things.
|
||
// comments, etc.
|
||
if (this.comment) {
|
||
return false;
|
||
}
|
||
if (this.empty) {
|
||
return f === '';
|
||
}
|
||
if (f === '/' && partial) {
|
||
return true;
|
||
}
|
||
const options = this.options;
|
||
// windows: need to use /, not \
|
||
if (this.isWindows) {
|
||
f = f.split('\\').join('/');
|
||
}
|
||
// treat the test path as a set of pathparts.
|
||
const ff = this.slashSplit(f);
|
||
this.debug(this.pattern, 'split', ff);
|
||
// just ONE of the pattern sets in this.set needs to match
|
||
// in order for it to be valid. If negating, then just one
|
||
// match means that we have failed.
|
||
// Either way, return on the first hit.
|
||
const set = this.set;
|
||
this.debug(this.pattern, 'set', set);
|
||
// Find the basename of the path by looking for the last non-empty segment
|
||
let filename = ff[ff.length - 1];
|
||
if (!filename) {
|
||
for (let i = ff.length - 2; !filename && i >= 0; i--) {
|
||
filename = ff[i];
|
||
}
|
||
}
|
||
for (let i = 0; i < set.length; i++) {
|
||
const pattern = set[i];
|
||
let file = ff;
|
||
if (options.matchBase && pattern.length === 1) {
|
||
file = [filename];
|
||
}
|
||
const hit = this.matchOne(file, pattern, partial);
|
||
if (hit) {
|
||
if (options.flipNegate) {
|
||
return true;
|
||
}
|
||
return !this.negate;
|
||
}
|
||
}
|
||
// didn't get any hits. this is success if it's a negative
|
||
// pattern, failure otherwise.
|
||
if (options.flipNegate) {
|
||
return false;
|
||
}
|
||
return this.negate;
|
||
}
|
||
static defaults(def) {
|
||
return minimatch.defaults(def).Minimatch;
|
||
}
|
||
}
|
||
/* c8 ignore stop */
|
||
minimatch.AST = AST;
|
||
minimatch.Minimatch = Minimatch;
|
||
minimatch.escape = escape$4;
|
||
minimatch.unescape = unescape;
|
||
|
||
/**
|
||
* @module LRUCache
|
||
*/
|
||
const perf = typeof performance === 'object' &&
|
||
performance &&
|
||
typeof performance.now === 'function'
|
||
? performance
|
||
: Date;
|
||
const warned = new Set();
|
||
/* c8 ignore start */
|
||
const PROCESS = (typeof process === 'object' && !!process ? process : {});
|
||
/* c8 ignore start */
|
||
const emitWarning = (msg, type, code, fn) => {
|
||
typeof PROCESS.emitWarning === 'function'
|
||
? PROCESS.emitWarning(msg, type, code, fn)
|
||
: console.error(`[${code}] ${type}: ${msg}`);
|
||
};
|
||
let AC = globalThis.AbortController;
|
||
let AS = globalThis.AbortSignal;
|
||
/* c8 ignore start */
|
||
if (typeof AC === 'undefined') {
|
||
//@ts-ignore
|
||
AS = class AbortSignal {
|
||
onabort;
|
||
_onabort = [];
|
||
reason;
|
||
aborted = false;
|
||
addEventListener(_, fn) {
|
||
this._onabort.push(fn);
|
||
}
|
||
};
|
||
//@ts-ignore
|
||
AC = class AbortController {
|
||
constructor() {
|
||
warnACPolyfill();
|
||
}
|
||
signal = new AS();
|
||
abort(reason) {
|
||
if (this.signal.aborted)
|
||
return;
|
||
//@ts-ignore
|
||
this.signal.reason = reason;
|
||
//@ts-ignore
|
||
this.signal.aborted = true;
|
||
//@ts-ignore
|
||
for (const fn of this.signal._onabort) {
|
||
fn(reason);
|
||
}
|
||
this.signal.onabort?.(reason);
|
||
}
|
||
};
|
||
let printACPolyfillWarning = PROCESS.env?.LRU_CACHE_IGNORE_AC_WARNING !== '1';
|
||
const warnACPolyfill = () => {
|
||
if (!printACPolyfillWarning)
|
||
return;
|
||
printACPolyfillWarning = false;
|
||
emitWarning('AbortController is not defined. If using lru-cache in ' +
|
||
'node 14, load an AbortController polyfill from the ' +
|
||
'`node-abort-controller` package. A minimal polyfill is ' +
|
||
'provided for use by LRUCache.fetch(), but it should not be ' +
|
||
'relied upon in other contexts (eg, passing it to other APIs that ' +
|
||
'use AbortController/AbortSignal might have undesirable effects). ' +
|
||
'You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.', 'NO_ABORT_CONTROLLER', 'ENOTSUP', warnACPolyfill);
|
||
};
|
||
}
|
||
/* c8 ignore stop */
|
||
const shouldWarn = (code) => !warned.has(code);
|
||
const isPosInt = (n) => n && n === Math.floor(n) && n > 0 && isFinite(n);
|
||
/* c8 ignore start */
|
||
// This is a little bit ridiculous, tbh.
|
||
// The maximum array length is 2^32-1 or thereabouts on most JS impls.
|
||
// And well before that point, you're caching the entire world, I mean,
|
||
// that's ~32GB of just integers for the next/prev links, plus whatever
|
||
// else to hold that many keys and values. Just filling the memory with
|
||
// zeroes at init time is brutal when you get that big.
|
||
// But why not be complete?
|
||
// Maybe in the future, these limits will have expanded.
|
||
const getUintArray = (max) => !isPosInt(max)
|
||
? null
|
||
: max <= Math.pow(2, 8)
|
||
? Uint8Array
|
||
: max <= Math.pow(2, 16)
|
||
? Uint16Array
|
||
: max <= Math.pow(2, 32)
|
||
? Uint32Array
|
||
: max <= Number.MAX_SAFE_INTEGER
|
||
? ZeroArray
|
||
: null;
|
||
/* c8 ignore stop */
|
||
class ZeroArray extends Array {
|
||
constructor(size) {
|
||
super(size);
|
||
this.fill(0);
|
||
}
|
||
}
|
||
class Stack {
|
||
heap;
|
||
length;
|
||
// private constructor
|
||
static #constructing = false;
|
||
static create(max) {
|
||
const HeapCls = getUintArray(max);
|
||
if (!HeapCls)
|
||
return [];
|
||
Stack.#constructing = true;
|
||
const s = new Stack(max, HeapCls);
|
||
Stack.#constructing = false;
|
||
return s;
|
||
}
|
||
constructor(max, HeapCls) {
|
||
/* c8 ignore start */
|
||
if (!Stack.#constructing) {
|
||
throw new TypeError('instantiate Stack using Stack.create(n)');
|
||
}
|
||
/* c8 ignore stop */
|
||
this.heap = new HeapCls(max);
|
||
this.length = 0;
|
||
}
|
||
push(n) {
|
||
this.heap[this.length++] = n;
|
||
}
|
||
pop() {
|
||
return this.heap[--this.length];
|
||
}
|
||
}
|
||
/**
|
||
* Default export, the thing you're using this module to get.
|
||
*
|
||
* All properties from the options object (with the exception of
|
||
* {@link OptionsBase.max} and {@link OptionsBase.maxSize}) are added as
|
||
* normal public members. (`max` and `maxBase` are read-only getters.)
|
||
* Changing any of these will alter the defaults for subsequent method calls,
|
||
* but is otherwise safe.
|
||
*/
|
||
class LRUCache {
|
||
// properties coming in from the options of these, only max and maxSize
|
||
// really *need* to be protected. The rest can be modified, as they just
|
||
// set defaults for various methods.
|
||
#max;
|
||
#maxSize;
|
||
#dispose;
|
||
#disposeAfter;
|
||
#fetchMethod;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.ttl}
|
||
*/
|
||
ttl;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.ttlResolution}
|
||
*/
|
||
ttlResolution;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.ttlAutopurge}
|
||
*/
|
||
ttlAutopurge;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.updateAgeOnGet}
|
||
*/
|
||
updateAgeOnGet;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.updateAgeOnHas}
|
||
*/
|
||
updateAgeOnHas;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.allowStale}
|
||
*/
|
||
allowStale;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.noDisposeOnSet}
|
||
*/
|
||
noDisposeOnSet;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.noUpdateTTL}
|
||
*/
|
||
noUpdateTTL;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.maxEntrySize}
|
||
*/
|
||
maxEntrySize;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.sizeCalculation}
|
||
*/
|
||
sizeCalculation;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.noDeleteOnFetchRejection}
|
||
*/
|
||
noDeleteOnFetchRejection;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.noDeleteOnStaleGet}
|
||
*/
|
||
noDeleteOnStaleGet;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.allowStaleOnFetchAbort}
|
||
*/
|
||
allowStaleOnFetchAbort;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.allowStaleOnFetchRejection}
|
||
*/
|
||
allowStaleOnFetchRejection;
|
||
/**
|
||
* {@link LRUCache.OptionsBase.ignoreFetchAbort}
|
||
*/
|
||
ignoreFetchAbort;
|
||
// computed properties
|
||
#size;
|
||
#calculatedSize;
|
||
#keyMap;
|
||
#keyList;
|
||
#valList;
|
||
#next;
|
||
#prev;
|
||
#head;
|
||
#tail;
|
||
#free;
|
||
#disposed;
|
||
#sizes;
|
||
#starts;
|
||
#ttls;
|
||
#hasDispose;
|
||
#hasFetchMethod;
|
||
#hasDisposeAfter;
|
||
/**
|
||
* Do not call this method unless you need to inspect the
|
||
* inner workings of the cache. If anything returned by this
|
||
* object is modified in any way, strange breakage may occur.
|
||
*
|
||
* These fields are private for a reason!
|
||
*
|
||
* @internal
|
||
*/
|
||
static unsafeExposeInternals(c) {
|
||
return {
|
||
// properties
|
||
starts: c.#starts,
|
||
ttls: c.#ttls,
|
||
sizes: c.#sizes,
|
||
keyMap: c.#keyMap,
|
||
keyList: c.#keyList,
|
||
valList: c.#valList,
|
||
next: c.#next,
|
||
prev: c.#prev,
|
||
get head() {
|
||
return c.#head;
|
||
},
|
||
get tail() {
|
||
return c.#tail;
|
||
},
|
||
free: c.#free,
|
||
// methods
|
||
isBackgroundFetch: (p) => c.#isBackgroundFetch(p),
|
||
backgroundFetch: (k, index, options, context) => c.#backgroundFetch(k, index, options, context),
|
||
moveToTail: (index) => c.#moveToTail(index),
|
||
indexes: (options) => c.#indexes(options),
|
||
rindexes: (options) => c.#rindexes(options),
|
||
isStale: (index) => c.#isStale(index),
|
||
};
|
||
}
|
||
// Protected read-only members
|
||
/**
|
||
* {@link LRUCache.OptionsBase.max} (read-only)
|
||
*/
|
||
get max() {
|
||
return this.#max;
|
||
}
|
||
/**
|
||
* {@link LRUCache.OptionsBase.maxSize} (read-only)
|
||
*/
|
||
get maxSize() {
|
||
return this.#maxSize;
|
||
}
|
||
/**
|
||
* The total computed size of items in the cache (read-only)
|
||
*/
|
||
get calculatedSize() {
|
||
return this.#calculatedSize;
|
||
}
|
||
/**
|
||
* The number of items stored in the cache (read-only)
|
||
*/
|
||
get size() {
|
||
return this.#size;
|
||
}
|
||
/**
|
||
* {@link LRUCache.OptionsBase.fetchMethod} (read-only)
|
||
*/
|
||
get fetchMethod() {
|
||
return this.#fetchMethod;
|
||
}
|
||
/**
|
||
* {@link LRUCache.OptionsBase.dispose} (read-only)
|
||
*/
|
||
get dispose() {
|
||
return this.#dispose;
|
||
}
|
||
/**
|
||
* {@link LRUCache.OptionsBase.disposeAfter} (read-only)
|
||
*/
|
||
get disposeAfter() {
|
||
return this.#disposeAfter;
|
||
}
|
||
constructor(options) {
|
||
const { max = 0, ttl, ttlResolution = 1, ttlAutopurge, updateAgeOnGet, updateAgeOnHas, allowStale, dispose, disposeAfter, noDisposeOnSet, noUpdateTTL, maxSize = 0, maxEntrySize = 0, sizeCalculation, fetchMethod, noDeleteOnFetchRejection, noDeleteOnStaleGet, allowStaleOnFetchRejection, allowStaleOnFetchAbort, ignoreFetchAbort, } = options;
|
||
if (max !== 0 && !isPosInt(max)) {
|
||
throw new TypeError('max option must be a nonnegative integer');
|
||
}
|
||
const UintArray = max ? getUintArray(max) : Array;
|
||
if (!UintArray) {
|
||
throw new Error('invalid max value: ' + max);
|
||
}
|
||
this.#max = max;
|
||
this.#maxSize = maxSize;
|
||
this.maxEntrySize = maxEntrySize || this.#maxSize;
|
||
this.sizeCalculation = sizeCalculation;
|
||
if (this.sizeCalculation) {
|
||
if (!this.#maxSize && !this.maxEntrySize) {
|
||
throw new TypeError('cannot set sizeCalculation without setting maxSize or maxEntrySize');
|
||
}
|
||
if (typeof this.sizeCalculation !== 'function') {
|
||
throw new TypeError('sizeCalculation set to non-function');
|
||
}
|
||
}
|
||
if (fetchMethod !== undefined &&
|
||
typeof fetchMethod !== 'function') {
|
||
throw new TypeError('fetchMethod must be a function if specified');
|
||
}
|
||
this.#fetchMethod = fetchMethod;
|
||
this.#hasFetchMethod = !!fetchMethod;
|
||
this.#keyMap = new Map();
|
||
this.#keyList = new Array(max).fill(undefined);
|
||
this.#valList = new Array(max).fill(undefined);
|
||
this.#next = new UintArray(max);
|
||
this.#prev = new UintArray(max);
|
||
this.#head = 0;
|
||
this.#tail = 0;
|
||
this.#free = Stack.create(max);
|
||
this.#size = 0;
|
||
this.#calculatedSize = 0;
|
||
if (typeof dispose === 'function') {
|
||
this.#dispose = dispose;
|
||
}
|
||
if (typeof disposeAfter === 'function') {
|
||
this.#disposeAfter = disposeAfter;
|
||
this.#disposed = [];
|
||
}
|
||
else {
|
||
this.#disposeAfter = undefined;
|
||
this.#disposed = undefined;
|
||
}
|
||
this.#hasDispose = !!this.#dispose;
|
||
this.#hasDisposeAfter = !!this.#disposeAfter;
|
||
this.noDisposeOnSet = !!noDisposeOnSet;
|
||
this.noUpdateTTL = !!noUpdateTTL;
|
||
this.noDeleteOnFetchRejection = !!noDeleteOnFetchRejection;
|
||
this.allowStaleOnFetchRejection = !!allowStaleOnFetchRejection;
|
||
this.allowStaleOnFetchAbort = !!allowStaleOnFetchAbort;
|
||
this.ignoreFetchAbort = !!ignoreFetchAbort;
|
||
// NB: maxEntrySize is set to maxSize if it's set
|
||
if (this.maxEntrySize !== 0) {
|
||
if (this.#maxSize !== 0) {
|
||
if (!isPosInt(this.#maxSize)) {
|
||
throw new TypeError('maxSize must be a positive integer if specified');
|
||
}
|
||
}
|
||
if (!isPosInt(this.maxEntrySize)) {
|
||
throw new TypeError('maxEntrySize must be a positive integer if specified');
|
||
}
|
||
this.#initializeSizeTracking();
|
||
}
|
||
this.allowStale = !!allowStale;
|
||
this.noDeleteOnStaleGet = !!noDeleteOnStaleGet;
|
||
this.updateAgeOnGet = !!updateAgeOnGet;
|
||
this.updateAgeOnHas = !!updateAgeOnHas;
|
||
this.ttlResolution =
|
||
isPosInt(ttlResolution) || ttlResolution === 0
|
||
? ttlResolution
|
||
: 1;
|
||
this.ttlAutopurge = !!ttlAutopurge;
|
||
this.ttl = ttl || 0;
|
||
if (this.ttl) {
|
||
if (!isPosInt(this.ttl)) {
|
||
throw new TypeError('ttl must be a positive integer if specified');
|
||
}
|
||
this.#initializeTTLTracking();
|
||
}
|
||
// do not allow completely unbounded caches
|
||
if (this.#max === 0 && this.ttl === 0 && this.#maxSize === 0) {
|
||
throw new TypeError('At least one of max, maxSize, or ttl is required');
|
||
}
|
||
if (!this.ttlAutopurge && !this.#max && !this.#maxSize) {
|
||
const code = 'LRU_CACHE_UNBOUNDED';
|
||
if (shouldWarn(code)) {
|
||
warned.add(code);
|
||
const msg = 'TTL caching without ttlAutopurge, max, or maxSize can ' +
|
||
'result in unbounded memory consumption.';
|
||
emitWarning(msg, 'UnboundedCacheWarning', code, LRUCache);
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Return the remaining TTL time for a given entry key
|
||
*/
|
||
getRemainingTTL(key) {
|
||
return this.#keyMap.has(key) ? Infinity : 0;
|
||
}
|
||
#initializeTTLTracking() {
|
||
const ttls = new ZeroArray(this.#max);
|
||
const starts = new ZeroArray(this.#max);
|
||
this.#ttls = ttls;
|
||
this.#starts = starts;
|
||
this.#setItemTTL = (index, ttl, start = perf.now()) => {
|
||
starts[index] = ttl !== 0 ? start : 0;
|
||
ttls[index] = ttl;
|
||
if (ttl !== 0 && this.ttlAutopurge) {
|
||
const t = setTimeout(() => {
|
||
if (this.#isStale(index)) {
|
||
this.delete(this.#keyList[index]);
|
||
}
|
||
}, ttl + 1);
|
||
// unref() not supported on all platforms
|
||
/* c8 ignore start */
|
||
if (t.unref) {
|
||
t.unref();
|
||
}
|
||
/* c8 ignore stop */
|
||
}
|
||
};
|
||
this.#updateItemAge = index => {
|
||
starts[index] = ttls[index] !== 0 ? perf.now() : 0;
|
||
};
|
||
this.#statusTTL = (status, index) => {
|
||
if (ttls[index]) {
|
||
const ttl = ttls[index];
|
||
const start = starts[index];
|
||
/* c8 ignore next */
|
||
if (!ttl || !start)
|
||
return;
|
||
status.ttl = ttl;
|
||
status.start = start;
|
||
status.now = cachedNow || getNow();
|
||
const age = status.now - start;
|
||
status.remainingTTL = ttl - age;
|
||
}
|
||
};
|
||
// debounce calls to perf.now() to 1s so we're not hitting
|
||
// that costly call repeatedly.
|
||
let cachedNow = 0;
|
||
const getNow = () => {
|
||
const n = perf.now();
|
||
if (this.ttlResolution > 0) {
|
||
cachedNow = n;
|
||
const t = setTimeout(() => (cachedNow = 0), this.ttlResolution);
|
||
// not available on all platforms
|
||
/* c8 ignore start */
|
||
if (t.unref) {
|
||
t.unref();
|
||
}
|
||
/* c8 ignore stop */
|
||
}
|
||
return n;
|
||
};
|
||
this.getRemainingTTL = key => {
|
||
const index = this.#keyMap.get(key);
|
||
if (index === undefined) {
|
||
return 0;
|
||
}
|
||
const ttl = ttls[index];
|
||
const start = starts[index];
|
||
if (!ttl || !start) {
|
||
return Infinity;
|
||
}
|
||
const age = (cachedNow || getNow()) - start;
|
||
return ttl - age;
|
||
};
|
||
this.#isStale = index => {
|
||
const s = starts[index];
|
||
const t = ttls[index];
|
||
return !!t && !!s && (cachedNow || getNow()) - s > t;
|
||
};
|
||
}
|
||
// conditionally set private methods related to TTL
|
||
#updateItemAge = () => { };
|
||
#statusTTL = () => { };
|
||
#setItemTTL = () => { };
|
||
/* c8 ignore stop */
|
||
#isStale = () => false;
|
||
#initializeSizeTracking() {
|
||
const sizes = new ZeroArray(this.#max);
|
||
this.#calculatedSize = 0;
|
||
this.#sizes = sizes;
|
||
this.#removeItemSize = index => {
|
||
this.#calculatedSize -= sizes[index];
|
||
sizes[index] = 0;
|
||
};
|
||
this.#requireSize = (k, v, size, sizeCalculation) => {
|
||
// provisionally accept background fetches.
|
||
// actual value size will be checked when they return.
|
||
if (this.#isBackgroundFetch(v)) {
|
||
return 0;
|
||
}
|
||
if (!isPosInt(size)) {
|
||
if (sizeCalculation) {
|
||
if (typeof sizeCalculation !== 'function') {
|
||
throw new TypeError('sizeCalculation must be a function');
|
||
}
|
||
size = sizeCalculation(v, k);
|
||
if (!isPosInt(size)) {
|
||
throw new TypeError('sizeCalculation return invalid (expect positive integer)');
|
||
}
|
||
}
|
||
else {
|
||
throw new TypeError('invalid size value (must be positive integer). ' +
|
||
'When maxSize or maxEntrySize is used, sizeCalculation ' +
|
||
'or size must be set.');
|
||
}
|
||
}
|
||
return size;
|
||
};
|
||
this.#addItemSize = (index, size, status) => {
|
||
sizes[index] = size;
|
||
if (this.#maxSize) {
|
||
const maxSize = this.#maxSize - sizes[index];
|
||
while (this.#calculatedSize > maxSize) {
|
||
this.#evict(true);
|
||
}
|
||
}
|
||
this.#calculatedSize += sizes[index];
|
||
if (status) {
|
||
status.entrySize = size;
|
||
status.totalCalculatedSize = this.#calculatedSize;
|
||
}
|
||
};
|
||
}
|
||
#removeItemSize = _i => { };
|
||
#addItemSize = (_i, _s, _st) => { };
|
||
#requireSize = (_k, _v, size, sizeCalculation) => {
|
||
if (size || sizeCalculation) {
|
||
throw new TypeError('cannot set size without setting maxSize or maxEntrySize on cache');
|
||
}
|
||
return 0;
|
||
};
|
||
*#indexes({ allowStale = this.allowStale } = {}) {
|
||
if (this.#size) {
|
||
for (let i = this.#tail; true;) {
|
||
if (!this.#isValidIndex(i)) {
|
||
break;
|
||
}
|
||
if (allowStale || !this.#isStale(i)) {
|
||
yield i;
|
||
}
|
||
if (i === this.#head) {
|
||
break;
|
||
}
|
||
else {
|
||
i = this.#prev[i];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
*#rindexes({ allowStale = this.allowStale } = {}) {
|
||
if (this.#size) {
|
||
for (let i = this.#head; true;) {
|
||
if (!this.#isValidIndex(i)) {
|
||
break;
|
||
}
|
||
if (allowStale || !this.#isStale(i)) {
|
||
yield i;
|
||
}
|
||
if (i === this.#tail) {
|
||
break;
|
||
}
|
||
else {
|
||
i = this.#next[i];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#isValidIndex(index) {
|
||
return (index !== undefined &&
|
||
this.#keyMap.get(this.#keyList[index]) === index);
|
||
}
|
||
/**
|
||
* Return a generator yielding `[key, value]` pairs,
|
||
* in order from most recently used to least recently used.
|
||
*/
|
||
*entries() {
|
||
for (const i of this.#indexes()) {
|
||
if (this.#valList[i] !== undefined &&
|
||
this.#keyList[i] !== undefined &&
|
||
!this.#isBackgroundFetch(this.#valList[i])) {
|
||
yield [this.#keyList[i], this.#valList[i]];
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Inverse order version of {@link LRUCache.entries}
|
||
*
|
||
* Return a generator yielding `[key, value]` pairs,
|
||
* in order from least recently used to most recently used.
|
||
*/
|
||
*rentries() {
|
||
for (const i of this.#rindexes()) {
|
||
if (this.#valList[i] !== undefined &&
|
||
this.#keyList[i] !== undefined &&
|
||
!this.#isBackgroundFetch(this.#valList[i])) {
|
||
yield [this.#keyList[i], this.#valList[i]];
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Return a generator yielding the keys in the cache,
|
||
* in order from most recently used to least recently used.
|
||
*/
|
||
*keys() {
|
||
for (const i of this.#indexes()) {
|
||
const k = this.#keyList[i];
|
||
if (k !== undefined &&
|
||
!this.#isBackgroundFetch(this.#valList[i])) {
|
||
yield k;
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Inverse order version of {@link LRUCache.keys}
|
||
*
|
||
* Return a generator yielding the keys in the cache,
|
||
* in order from least recently used to most recently used.
|
||
*/
|
||
*rkeys() {
|
||
for (const i of this.#rindexes()) {
|
||
const k = this.#keyList[i];
|
||
if (k !== undefined &&
|
||
!this.#isBackgroundFetch(this.#valList[i])) {
|
||
yield k;
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Return a generator yielding the values in the cache,
|
||
* in order from most recently used to least recently used.
|
||
*/
|
||
*values() {
|
||
for (const i of this.#indexes()) {
|
||
const v = this.#valList[i];
|
||
if (v !== undefined &&
|
||
!this.#isBackgroundFetch(this.#valList[i])) {
|
||
yield this.#valList[i];
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Inverse order version of {@link LRUCache.values}
|
||
*
|
||
* Return a generator yielding the values in the cache,
|
||
* in order from least recently used to most recently used.
|
||
*/
|
||
*rvalues() {
|
||
for (const i of this.#rindexes()) {
|
||
const v = this.#valList[i];
|
||
if (v !== undefined &&
|
||
!this.#isBackgroundFetch(this.#valList[i])) {
|
||
yield this.#valList[i];
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Iterating over the cache itself yields the same results as
|
||
* {@link LRUCache.entries}
|
||
*/
|
||
[Symbol.iterator]() {
|
||
return this.entries();
|
||
}
|
||
/**
|
||
* Find a value for which the supplied fn method returns a truthy value,
|
||
* similar to Array.find(). fn is called as fn(value, key, cache).
|
||
*/
|
||
find(fn, getOptions = {}) {
|
||
for (const i of this.#indexes()) {
|
||
const v = this.#valList[i];
|
||
const value = this.#isBackgroundFetch(v)
|
||
? v.__staleWhileFetching
|
||
: v;
|
||
if (value === undefined)
|
||
continue;
|
||
if (fn(value, this.#keyList[i], this)) {
|
||
return this.get(this.#keyList[i], getOptions);
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Call the supplied function on each item in the cache, in order from
|
||
* most recently used to least recently used. fn is called as
|
||
* fn(value, key, cache). Does not update age or recenty of use.
|
||
* Does not iterate over stale values.
|
||
*/
|
||
forEach(fn, thisp = this) {
|
||
for (const i of this.#indexes()) {
|
||
const v = this.#valList[i];
|
||
const value = this.#isBackgroundFetch(v)
|
||
? v.__staleWhileFetching
|
||
: v;
|
||
if (value === undefined)
|
||
continue;
|
||
fn.call(thisp, value, this.#keyList[i], this);
|
||
}
|
||
}
|
||
/**
|
||
* The same as {@link LRUCache.forEach} but items are iterated over in
|
||
* reverse order. (ie, less recently used items are iterated over first.)
|
||
*/
|
||
rforEach(fn, thisp = this) {
|
||
for (const i of this.#rindexes()) {
|
||
const v = this.#valList[i];
|
||
const value = this.#isBackgroundFetch(v)
|
||
? v.__staleWhileFetching
|
||
: v;
|
||
if (value === undefined)
|
||
continue;
|
||
fn.call(thisp, value, this.#keyList[i], this);
|
||
}
|
||
}
|
||
/**
|
||
* Delete any stale entries. Returns true if anything was removed,
|
||
* false otherwise.
|
||
*/
|
||
purgeStale() {
|
||
let deleted = false;
|
||
for (const i of this.#rindexes({ allowStale: true })) {
|
||
if (this.#isStale(i)) {
|
||
this.delete(this.#keyList[i]);
|
||
deleted = true;
|
||
}
|
||
}
|
||
return deleted;
|
||
}
|
||
/**
|
||
* Get the extended info about a given entry, to get its value, size, and
|
||
* TTL info simultaneously. Like {@link LRUCache#dump}, but just for a
|
||
* single key. Always returns stale values, if their info is found in the
|
||
* cache, so be sure to check for expired TTLs if relevant.
|
||
*/
|
||
info(key) {
|
||
const i = this.#keyMap.get(key);
|
||
if (i === undefined)
|
||
return undefined;
|
||
const v = this.#valList[i];
|
||
const value = this.#isBackgroundFetch(v)
|
||
? v.__staleWhileFetching
|
||
: v;
|
||
if (value === undefined)
|
||
return undefined;
|
||
const entry = { value };
|
||
if (this.#ttls && this.#starts) {
|
||
const ttl = this.#ttls[i];
|
||
const start = this.#starts[i];
|
||
if (ttl && start) {
|
||
const remain = ttl - (perf.now() - start);
|
||
entry.ttl = remain;
|
||
entry.start = Date.now();
|
||
}
|
||
}
|
||
if (this.#sizes) {
|
||
entry.size = this.#sizes[i];
|
||
}
|
||
return entry;
|
||
}
|
||
/**
|
||
* Return an array of [key, {@link LRUCache.Entry}] tuples which can be
|
||
* passed to cache.load()
|
||
*/
|
||
dump() {
|
||
const arr = [];
|
||
for (const i of this.#indexes({ allowStale: true })) {
|
||
const key = this.#keyList[i];
|
||
const v = this.#valList[i];
|
||
const value = this.#isBackgroundFetch(v)
|
||
? v.__staleWhileFetching
|
||
: v;
|
||
if (value === undefined || key === undefined)
|
||
continue;
|
||
const entry = { value };
|
||
if (this.#ttls && this.#starts) {
|
||
entry.ttl = this.#ttls[i];
|
||
// always dump the start relative to a portable timestamp
|
||
// it's ok for this to be a bit slow, it's a rare operation.
|
||
const age = perf.now() - this.#starts[i];
|
||
entry.start = Math.floor(Date.now() - age);
|
||
}
|
||
if (this.#sizes) {
|
||
entry.size = this.#sizes[i];
|
||
}
|
||
arr.unshift([key, entry]);
|
||
}
|
||
return arr;
|
||
}
|
||
/**
|
||
* Reset the cache and load in the items in entries in the order listed.
|
||
* Note that the shape of the resulting cache may be different if the
|
||
* same options are not used in both caches.
|
||
*/
|
||
load(arr) {
|
||
this.clear();
|
||
for (const [key, entry] of arr) {
|
||
if (entry.start) {
|
||
// entry.start is a portable timestamp, but we may be using
|
||
// node's performance.now(), so calculate the offset, so that
|
||
// we get the intended remaining TTL, no matter how long it's
|
||
// been on ice.
|
||
//
|
||
// it's ok for this to be a bit slow, it's a rare operation.
|
||
const age = Date.now() - entry.start;
|
||
entry.start = perf.now() - age;
|
||
}
|
||
this.set(key, entry.value, entry);
|
||
}
|
||
}
|
||
/**
|
||
* Add a value to the cache.
|
||
*
|
||
* Note: if `undefined` is specified as a value, this is an alias for
|
||
* {@link LRUCache#delete}
|
||
*/
|
||
set(k, v, setOptions = {}) {
|
||
if (v === undefined) {
|
||
this.delete(k);
|
||
return this;
|
||
}
|
||
const { ttl = this.ttl, start, noDisposeOnSet = this.noDisposeOnSet, sizeCalculation = this.sizeCalculation, status, } = setOptions;
|
||
let { noUpdateTTL = this.noUpdateTTL } = setOptions;
|
||
const size = this.#requireSize(k, v, setOptions.size || 0, sizeCalculation);
|
||
// if the item doesn't fit, don't do anything
|
||
// NB: maxEntrySize set to maxSize by default
|
||
if (this.maxEntrySize && size > this.maxEntrySize) {
|
||
if (status) {
|
||
status.set = 'miss';
|
||
status.maxEntrySizeExceeded = true;
|
||
}
|
||
// have to delete, in case something is there already.
|
||
this.delete(k);
|
||
return this;
|
||
}
|
||
let index = this.#size === 0 ? undefined : this.#keyMap.get(k);
|
||
if (index === undefined) {
|
||
// addition
|
||
index = (this.#size === 0
|
||
? this.#tail
|
||
: this.#free.length !== 0
|
||
? this.#free.pop()
|
||
: this.#size === this.#max
|
||
? this.#evict(false)
|
||
: this.#size);
|
||
this.#keyList[index] = k;
|
||
this.#valList[index] = v;
|
||
this.#keyMap.set(k, index);
|
||
this.#next[this.#tail] = index;
|
||
this.#prev[index] = this.#tail;
|
||
this.#tail = index;
|
||
this.#size++;
|
||
this.#addItemSize(index, size, status);
|
||
if (status)
|
||
status.set = 'add';
|
||
noUpdateTTL = false;
|
||
}
|
||
else {
|
||
// update
|
||
this.#moveToTail(index);
|
||
const oldVal = this.#valList[index];
|
||
if (v !== oldVal) {
|
||
if (this.#hasFetchMethod && this.#isBackgroundFetch(oldVal)) {
|
||
oldVal.__abortController.abort(new Error('replaced'));
|
||
const { __staleWhileFetching: s } = oldVal;
|
||
if (s !== undefined && !noDisposeOnSet) {
|
||
if (this.#hasDispose) {
|
||
this.#dispose?.(s, k, 'set');
|
||
}
|
||
if (this.#hasDisposeAfter) {
|
||
this.#disposed?.push([s, k, 'set']);
|
||
}
|
||
}
|
||
}
|
||
else if (!noDisposeOnSet) {
|
||
if (this.#hasDispose) {
|
||
this.#dispose?.(oldVal, k, 'set');
|
||
}
|
||
if (this.#hasDisposeAfter) {
|
||
this.#disposed?.push([oldVal, k, 'set']);
|
||
}
|
||
}
|
||
this.#removeItemSize(index);
|
||
this.#addItemSize(index, size, status);
|
||
this.#valList[index] = v;
|
||
if (status) {
|
||
status.set = 'replace';
|
||
const oldValue = oldVal && this.#isBackgroundFetch(oldVal)
|
||
? oldVal.__staleWhileFetching
|
||
: oldVal;
|
||
if (oldValue !== undefined)
|
||
status.oldValue = oldValue;
|
||
}
|
||
}
|
||
else if (status) {
|
||
status.set = 'update';
|
||
}
|
||
}
|
||
if (ttl !== 0 && !this.#ttls) {
|
||
this.#initializeTTLTracking();
|
||
}
|
||
if (this.#ttls) {
|
||
if (!noUpdateTTL) {
|
||
this.#setItemTTL(index, ttl, start);
|
||
}
|
||
if (status)
|
||
this.#statusTTL(status, index);
|
||
}
|
||
if (!noDisposeOnSet && this.#hasDisposeAfter && this.#disposed) {
|
||
const dt = this.#disposed;
|
||
let task;
|
||
while ((task = dt?.shift())) {
|
||
this.#disposeAfter?.(...task);
|
||
}
|
||
}
|
||
return this;
|
||
}
|
||
/**
|
||
* Evict the least recently used item, returning its value or
|
||
* `undefined` if cache is empty.
|
||
*/
|
||
pop() {
|
||
try {
|
||
while (this.#size) {
|
||
const val = this.#valList[this.#head];
|
||
this.#evict(true);
|
||
if (this.#isBackgroundFetch(val)) {
|
||
if (val.__staleWhileFetching) {
|
||
return val.__staleWhileFetching;
|
||
}
|
||
}
|
||
else if (val !== undefined) {
|
||
return val;
|
||
}
|
||
}
|
||
}
|
||
finally {
|
||
if (this.#hasDisposeAfter && this.#disposed) {
|
||
const dt = this.#disposed;
|
||
let task;
|
||
while ((task = dt?.shift())) {
|
||
this.#disposeAfter?.(...task);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#evict(free) {
|
||
const head = this.#head;
|
||
const k = this.#keyList[head];
|
||
const v = this.#valList[head];
|
||
if (this.#hasFetchMethod && this.#isBackgroundFetch(v)) {
|
||
v.__abortController.abort(new Error('evicted'));
|
||
}
|
||
else if (this.#hasDispose || this.#hasDisposeAfter) {
|
||
if (this.#hasDispose) {
|
||
this.#dispose?.(v, k, 'evict');
|
||
}
|
||
if (this.#hasDisposeAfter) {
|
||
this.#disposed?.push([v, k, 'evict']);
|
||
}
|
||
}
|
||
this.#removeItemSize(head);
|
||
// if we aren't about to use the index, then null these out
|
||
if (free) {
|
||
this.#keyList[head] = undefined;
|
||
this.#valList[head] = undefined;
|
||
this.#free.push(head);
|
||
}
|
||
if (this.#size === 1) {
|
||
this.#head = this.#tail = 0;
|
||
this.#free.length = 0;
|
||
}
|
||
else {
|
||
this.#head = this.#next[head];
|
||
}
|
||
this.#keyMap.delete(k);
|
||
this.#size--;
|
||
return head;
|
||
}
|
||
/**
|
||
* Check if a key is in the cache, without updating the recency of use.
|
||
* Will return false if the item is stale, even though it is technically
|
||
* in the cache.
|
||
*
|
||
* Will not update item age unless
|
||
* {@link LRUCache.OptionsBase.updateAgeOnHas} is set.
|
||
*/
|
||
has(k, hasOptions = {}) {
|
||
const { updateAgeOnHas = this.updateAgeOnHas, status } = hasOptions;
|
||
const index = this.#keyMap.get(k);
|
||
if (index !== undefined) {
|
||
const v = this.#valList[index];
|
||
if (this.#isBackgroundFetch(v) &&
|
||
v.__staleWhileFetching === undefined) {
|
||
return false;
|
||
}
|
||
if (!this.#isStale(index)) {
|
||
if (updateAgeOnHas) {
|
||
this.#updateItemAge(index);
|
||
}
|
||
if (status) {
|
||
status.has = 'hit';
|
||
this.#statusTTL(status, index);
|
||
}
|
||
return true;
|
||
}
|
||
else if (status) {
|
||
status.has = 'stale';
|
||
this.#statusTTL(status, index);
|
||
}
|
||
}
|
||
else if (status) {
|
||
status.has = 'miss';
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Like {@link LRUCache#get} but doesn't update recency or delete stale
|
||
* items.
|
||
*
|
||
* Returns `undefined` if the item is stale, unless
|
||
* {@link LRUCache.OptionsBase.allowStale} is set.
|
||
*/
|
||
peek(k, peekOptions = {}) {
|
||
const { allowStale = this.allowStale } = peekOptions;
|
||
const index = this.#keyMap.get(k);
|
||
if (index === undefined ||
|
||
(!allowStale && this.#isStale(index))) {
|
||
return;
|
||
}
|
||
const v = this.#valList[index];
|
||
// either stale and allowed, or forcing a refresh of non-stale value
|
||
return this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
||
}
|
||
#backgroundFetch(k, index, options, context) {
|
||
const v = index === undefined ? undefined : this.#valList[index];
|
||
if (this.#isBackgroundFetch(v)) {
|
||
return v;
|
||
}
|
||
const ac = new AC();
|
||
const { signal } = options;
|
||
// when/if our AC signals, then stop listening to theirs.
|
||
signal?.addEventListener('abort', () => ac.abort(signal.reason), {
|
||
signal: ac.signal,
|
||
});
|
||
const fetchOpts = {
|
||
signal: ac.signal,
|
||
options,
|
||
context,
|
||
};
|
||
const cb = (v, updateCache = false) => {
|
||
const { aborted } = ac.signal;
|
||
const ignoreAbort = options.ignoreFetchAbort && v !== undefined;
|
||
if (options.status) {
|
||
if (aborted && !updateCache) {
|
||
options.status.fetchAborted = true;
|
||
options.status.fetchError = ac.signal.reason;
|
||
if (ignoreAbort)
|
||
options.status.fetchAbortIgnored = true;
|
||
}
|
||
else {
|
||
options.status.fetchResolved = true;
|
||
}
|
||
}
|
||
if (aborted && !ignoreAbort && !updateCache) {
|
||
return fetchFail(ac.signal.reason);
|
||
}
|
||
// either we didn't abort, and are still here, or we did, and ignored
|
||
const bf = p;
|
||
if (this.#valList[index] === p) {
|
||
if (v === undefined) {
|
||
if (bf.__staleWhileFetching) {
|
||
this.#valList[index] = bf.__staleWhileFetching;
|
||
}
|
||
else {
|
||
this.delete(k);
|
||
}
|
||
}
|
||
else {
|
||
if (options.status)
|
||
options.status.fetchUpdated = true;
|
||
this.set(k, v, fetchOpts.options);
|
||
}
|
||
}
|
||
return v;
|
||
};
|
||
const eb = (er) => {
|
||
if (options.status) {
|
||
options.status.fetchRejected = true;
|
||
options.status.fetchError = er;
|
||
}
|
||
return fetchFail(er);
|
||
};
|
||
const fetchFail = (er) => {
|
||
const { aborted } = ac.signal;
|
||
const allowStaleAborted = aborted && options.allowStaleOnFetchAbort;
|
||
const allowStale = allowStaleAborted || options.allowStaleOnFetchRejection;
|
||
const noDelete = allowStale || options.noDeleteOnFetchRejection;
|
||
const bf = p;
|
||
if (this.#valList[index] === p) {
|
||
// if we allow stale on fetch rejections, then we need to ensure that
|
||
// the stale value is not removed from the cache when the fetch fails.
|
||
const del = !noDelete || bf.__staleWhileFetching === undefined;
|
||
if (del) {
|
||
this.delete(k);
|
||
}
|
||
else if (!allowStaleAborted) {
|
||
// still replace the *promise* with the stale value,
|
||
// since we are done with the promise at this point.
|
||
// leave it untouched if we're still waiting for an
|
||
// aborted background fetch that hasn't yet returned.
|
||
this.#valList[index] = bf.__staleWhileFetching;
|
||
}
|
||
}
|
||
if (allowStale) {
|
||
if (options.status && bf.__staleWhileFetching !== undefined) {
|
||
options.status.returnedStale = true;
|
||
}
|
||
return bf.__staleWhileFetching;
|
||
}
|
||
else if (bf.__returned === bf) {
|
||
throw er;
|
||
}
|
||
};
|
||
const pcall = (res, rej) => {
|
||
const fmp = this.#fetchMethod?.(k, v, fetchOpts);
|
||
if (fmp && fmp instanceof Promise) {
|
||
fmp.then(v => res(v === undefined ? undefined : v), rej);
|
||
}
|
||
// ignored, we go until we finish, regardless.
|
||
// defer check until we are actually aborting,
|
||
// so fetchMethod can override.
|
||
ac.signal.addEventListener('abort', () => {
|
||
if (!options.ignoreFetchAbort ||
|
||
options.allowStaleOnFetchAbort) {
|
||
res(undefined);
|
||
// when it eventually resolves, update the cache.
|
||
if (options.allowStaleOnFetchAbort) {
|
||
res = v => cb(v, true);
|
||
}
|
||
}
|
||
});
|
||
};
|
||
if (options.status)
|
||
options.status.fetchDispatched = true;
|
||
const p = new Promise(pcall).then(cb, eb);
|
||
const bf = Object.assign(p, {
|
||
__abortController: ac,
|
||
__staleWhileFetching: v,
|
||
__returned: undefined,
|
||
});
|
||
if (index === undefined) {
|
||
// internal, don't expose status.
|
||
this.set(k, bf, { ...fetchOpts.options, status: undefined });
|
||
index = this.#keyMap.get(k);
|
||
}
|
||
else {
|
||
this.#valList[index] = bf;
|
||
}
|
||
return bf;
|
||
}
|
||
#isBackgroundFetch(p) {
|
||
if (!this.#hasFetchMethod)
|
||
return false;
|
||
const b = p;
|
||
return (!!b &&
|
||
b instanceof Promise &&
|
||
b.hasOwnProperty('__staleWhileFetching') &&
|
||
b.__abortController instanceof AC);
|
||
}
|
||
async fetch(k, fetchOptions = {}) {
|
||
const {
|
||
// get options
|
||
allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet,
|
||
// set options
|
||
ttl = this.ttl, noDisposeOnSet = this.noDisposeOnSet, size = 0, sizeCalculation = this.sizeCalculation, noUpdateTTL = this.noUpdateTTL,
|
||
// fetch exclusive options
|
||
noDeleteOnFetchRejection = this.noDeleteOnFetchRejection, allowStaleOnFetchRejection = this.allowStaleOnFetchRejection, ignoreFetchAbort = this.ignoreFetchAbort, allowStaleOnFetchAbort = this.allowStaleOnFetchAbort, context, forceRefresh = false, status, signal, } = fetchOptions;
|
||
if (!this.#hasFetchMethod) {
|
||
if (status)
|
||
status.fetch = 'get';
|
||
return this.get(k, {
|
||
allowStale,
|
||
updateAgeOnGet,
|
||
noDeleteOnStaleGet,
|
||
status,
|
||
});
|
||
}
|
||
const options = {
|
||
allowStale,
|
||
updateAgeOnGet,
|
||
noDeleteOnStaleGet,
|
||
ttl,
|
||
noDisposeOnSet,
|
||
size,
|
||
sizeCalculation,
|
||
noUpdateTTL,
|
||
noDeleteOnFetchRejection,
|
||
allowStaleOnFetchRejection,
|
||
allowStaleOnFetchAbort,
|
||
ignoreFetchAbort,
|
||
status,
|
||
signal,
|
||
};
|
||
let index = this.#keyMap.get(k);
|
||
if (index === undefined) {
|
||
if (status)
|
||
status.fetch = 'miss';
|
||
const p = this.#backgroundFetch(k, index, options, context);
|
||
return (p.__returned = p);
|
||
}
|
||
else {
|
||
// in cache, maybe already fetching
|
||
const v = this.#valList[index];
|
||
if (this.#isBackgroundFetch(v)) {
|
||
const stale = allowStale && v.__staleWhileFetching !== undefined;
|
||
if (status) {
|
||
status.fetch = 'inflight';
|
||
if (stale)
|
||
status.returnedStale = true;
|
||
}
|
||
return stale ? v.__staleWhileFetching : (v.__returned = v);
|
||
}
|
||
// if we force a refresh, that means do NOT serve the cached value,
|
||
// unless we are already in the process of refreshing the cache.
|
||
const isStale = this.#isStale(index);
|
||
if (!forceRefresh && !isStale) {
|
||
if (status)
|
||
status.fetch = 'hit';
|
||
this.#moveToTail(index);
|
||
if (updateAgeOnGet) {
|
||
this.#updateItemAge(index);
|
||
}
|
||
if (status)
|
||
this.#statusTTL(status, index);
|
||
return v;
|
||
}
|
||
// ok, it is stale or a forced refresh, and not already fetching.
|
||
// refresh the cache.
|
||
const p = this.#backgroundFetch(k, index, options, context);
|
||
const hasStale = p.__staleWhileFetching !== undefined;
|
||
const staleVal = hasStale && allowStale;
|
||
if (status) {
|
||
status.fetch = isStale ? 'stale' : 'refresh';
|
||
if (staleVal && isStale)
|
||
status.returnedStale = true;
|
||
}
|
||
return staleVal ? p.__staleWhileFetching : (p.__returned = p);
|
||
}
|
||
}
|
||
/**
|
||
* Return a value from the cache. Will update the recency of the cache
|
||
* entry found.
|
||
*
|
||
* If the key is not found, get() will return `undefined`.
|
||
*/
|
||
get(k, getOptions = {}) {
|
||
const { allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet, status, } = getOptions;
|
||
const index = this.#keyMap.get(k);
|
||
if (index !== undefined) {
|
||
const value = this.#valList[index];
|
||
const fetching = this.#isBackgroundFetch(value);
|
||
if (status)
|
||
this.#statusTTL(status, index);
|
||
if (this.#isStale(index)) {
|
||
if (status)
|
||
status.get = 'stale';
|
||
// delete only if not an in-flight background fetch
|
||
if (!fetching) {
|
||
if (!noDeleteOnStaleGet) {
|
||
this.delete(k);
|
||
}
|
||
if (status && allowStale)
|
||
status.returnedStale = true;
|
||
return allowStale ? value : undefined;
|
||
}
|
||
else {
|
||
if (status &&
|
||
allowStale &&
|
||
value.__staleWhileFetching !== undefined) {
|
||
status.returnedStale = true;
|
||
}
|
||
return allowStale ? value.__staleWhileFetching : undefined;
|
||
}
|
||
}
|
||
else {
|
||
if (status)
|
||
status.get = 'hit';
|
||
// if we're currently fetching it, we don't actually have it yet
|
||
// it's not stale, which means this isn't a staleWhileRefetching.
|
||
// If it's not stale, and fetching, AND has a __staleWhileFetching
|
||
// value, then that means the user fetched with {forceRefresh:true},
|
||
// so it's safe to return that value.
|
||
if (fetching) {
|
||
return value.__staleWhileFetching;
|
||
}
|
||
this.#moveToTail(index);
|
||
if (updateAgeOnGet) {
|
||
this.#updateItemAge(index);
|
||
}
|
||
return value;
|
||
}
|
||
}
|
||
else if (status) {
|
||
status.get = 'miss';
|
||
}
|
||
}
|
||
#connect(p, n) {
|
||
this.#prev[n] = p;
|
||
this.#next[p] = n;
|
||
}
|
||
#moveToTail(index) {
|
||
// if tail already, nothing to do
|
||
// if head, move head to next[index]
|
||
// else
|
||
// move next[prev[index]] to next[index] (head has no prev)
|
||
// move prev[next[index]] to prev[index]
|
||
// prev[index] = tail
|
||
// next[tail] = index
|
||
// tail = index
|
||
if (index !== this.#tail) {
|
||
if (index === this.#head) {
|
||
this.#head = this.#next[index];
|
||
}
|
||
else {
|
||
this.#connect(this.#prev[index], this.#next[index]);
|
||
}
|
||
this.#connect(this.#tail, index);
|
||
this.#tail = index;
|
||
}
|
||
}
|
||
/**
|
||
* Deletes a key out of the cache.
|
||
* Returns true if the key was deleted, false otherwise.
|
||
*/
|
||
delete(k) {
|
||
let deleted = false;
|
||
if (this.#size !== 0) {
|
||
const index = this.#keyMap.get(k);
|
||
if (index !== undefined) {
|
||
deleted = true;
|
||
if (this.#size === 1) {
|
||
this.clear();
|
||
}
|
||
else {
|
||
this.#removeItemSize(index);
|
||
const v = this.#valList[index];
|
||
if (this.#isBackgroundFetch(v)) {
|
||
v.__abortController.abort(new Error('deleted'));
|
||
}
|
||
else if (this.#hasDispose || this.#hasDisposeAfter) {
|
||
if (this.#hasDispose) {
|
||
this.#dispose?.(v, k, 'delete');
|
||
}
|
||
if (this.#hasDisposeAfter) {
|
||
this.#disposed?.push([v, k, 'delete']);
|
||
}
|
||
}
|
||
this.#keyMap.delete(k);
|
||
this.#keyList[index] = undefined;
|
||
this.#valList[index] = undefined;
|
||
if (index === this.#tail) {
|
||
this.#tail = this.#prev[index];
|
||
}
|
||
else if (index === this.#head) {
|
||
this.#head = this.#next[index];
|
||
}
|
||
else {
|
||
const pi = this.#prev[index];
|
||
this.#next[pi] = this.#next[index];
|
||
const ni = this.#next[index];
|
||
this.#prev[ni] = this.#prev[index];
|
||
}
|
||
this.#size--;
|
||
this.#free.push(index);
|
||
}
|
||
}
|
||
}
|
||
if (this.#hasDisposeAfter && this.#disposed?.length) {
|
||
const dt = this.#disposed;
|
||
let task;
|
||
while ((task = dt?.shift())) {
|
||
this.#disposeAfter?.(...task);
|
||
}
|
||
}
|
||
return deleted;
|
||
}
|
||
/**
|
||
* Clear the cache entirely, throwing away all values.
|
||
*/
|
||
clear() {
|
||
for (const index of this.#rindexes({ allowStale: true })) {
|
||
const v = this.#valList[index];
|
||
if (this.#isBackgroundFetch(v)) {
|
||
v.__abortController.abort(new Error('deleted'));
|
||
}
|
||
else {
|
||
const k = this.#keyList[index];
|
||
if (this.#hasDispose) {
|
||
this.#dispose?.(v, k, 'delete');
|
||
}
|
||
if (this.#hasDisposeAfter) {
|
||
this.#disposed?.push([v, k, 'delete']);
|
||
}
|
||
}
|
||
}
|
||
this.#keyMap.clear();
|
||
this.#valList.fill(undefined);
|
||
this.#keyList.fill(undefined);
|
||
if (this.#ttls && this.#starts) {
|
||
this.#ttls.fill(0);
|
||
this.#starts.fill(0);
|
||
}
|
||
if (this.#sizes) {
|
||
this.#sizes.fill(0);
|
||
}
|
||
this.#head = 0;
|
||
this.#tail = 0;
|
||
this.#free.length = 0;
|
||
this.#calculatedSize = 0;
|
||
this.#size = 0;
|
||
if (this.#hasDisposeAfter && this.#disposed) {
|
||
const dt = this.#disposed;
|
||
let task;
|
||
while ((task = dt?.shift())) {
|
||
this.#disposeAfter?.(...task);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
const proc = typeof process === 'object' && process
|
||
? process
|
||
: {
|
||
stdout: null,
|
||
stderr: null,
|
||
};
|
||
/**
|
||
* Return true if the argument is a Minipass stream, Node stream, or something
|
||
* else that Minipass can interact with.
|
||
*/
|
||
const isStream = (s) => !!s &&
|
||
typeof s === 'object' &&
|
||
(s instanceof Minipass ||
|
||
s instanceof require$$0$3 ||
|
||
isReadable(s) ||
|
||
isWritable(s));
|
||
/**
|
||
* Return true if the argument is a valid {@link Minipass.Readable}
|
||
*/
|
||
const isReadable = (s) => !!s &&
|
||
typeof s === 'object' &&
|
||
s instanceof EventEmitter &&
|
||
typeof s.pipe === 'function' &&
|
||
// node core Writable streams have a pipe() method, but it throws
|
||
s.pipe !== require$$0$3.Writable.prototype.pipe;
|
||
/**
|
||
* Return true if the argument is a valid {@link Minipass.Writable}
|
||
*/
|
||
const isWritable = (s) => !!s &&
|
||
typeof s === 'object' &&
|
||
s instanceof EventEmitter &&
|
||
typeof s.write === 'function' &&
|
||
typeof s.end === 'function';
|
||
const EOF = Symbol('EOF');
|
||
const MAYBE_EMIT_END = Symbol('maybeEmitEnd');
|
||
const EMITTED_END = Symbol('emittedEnd');
|
||
const EMITTING_END = Symbol('emittingEnd');
|
||
const EMITTED_ERROR = Symbol('emittedError');
|
||
const CLOSED = Symbol('closed');
|
||
const READ = Symbol('read');
|
||
const FLUSH = Symbol('flush');
|
||
const FLUSHCHUNK = Symbol('flushChunk');
|
||
const ENCODING$1 = Symbol('encoding');
|
||
const DECODER = Symbol('decoder');
|
||
const FLOWING = Symbol('flowing');
|
||
const PAUSED = Symbol('paused');
|
||
const RESUME = Symbol('resume');
|
||
const BUFFER = Symbol('buffer');
|
||
const PIPES = Symbol('pipes');
|
||
const BUFFERLENGTH = Symbol('bufferLength');
|
||
const BUFFERPUSH = Symbol('bufferPush');
|
||
const BUFFERSHIFT = Symbol('bufferShift');
|
||
const OBJECTMODE = Symbol('objectMode');
|
||
// internal event when stream is destroyed
|
||
const DESTROYED = Symbol('destroyed');
|
||
// internal event when stream has an error
|
||
const ERROR = Symbol('error');
|
||
const EMITDATA = Symbol('emitData');
|
||
const EMITEND = Symbol('emitEnd');
|
||
const EMITEND2 = Symbol('emitEnd2');
|
||
const ASYNC = Symbol('async');
|
||
const ABORT = Symbol('abort');
|
||
const ABORTED = Symbol('aborted');
|
||
const SIGNAL = Symbol('signal');
|
||
const DATALISTENERS = Symbol('dataListeners');
|
||
const DISCARDED = Symbol('discarded');
|
||
const defer = (fn) => Promise.resolve().then(fn);
|
||
const nodefer = (fn) => fn();
|
||
const isEndish = (ev) => ev === 'end' || ev === 'finish' || ev === 'prefinish';
|
||
const isArrayBufferLike = (b) => b instanceof ArrayBuffer ||
|
||
(!!b &&
|
||
typeof b === 'object' &&
|
||
b.constructor &&
|
||
b.constructor.name === 'ArrayBuffer' &&
|
||
b.byteLength >= 0);
|
||
const isArrayBufferView = (b) => !Buffer.isBuffer(b) && ArrayBuffer.isView(b);
|
||
/**
|
||
* Internal class representing a pipe to a destination stream.
|
||
*
|
||
* @internal
|
||
*/
|
||
class Pipe {
|
||
src;
|
||
dest;
|
||
opts;
|
||
ondrain;
|
||
constructor(src, dest, opts) {
|
||
this.src = src;
|
||
this.dest = dest;
|
||
this.opts = opts;
|
||
this.ondrain = () => src[RESUME]();
|
||
this.dest.on('drain', this.ondrain);
|
||
}
|
||
unpipe() {
|
||
this.dest.removeListener('drain', this.ondrain);
|
||
}
|
||
// only here for the prototype
|
||
/* c8 ignore start */
|
||
proxyErrors(_er) { }
|
||
/* c8 ignore stop */
|
||
end() {
|
||
this.unpipe();
|
||
if (this.opts.end)
|
||
this.dest.end();
|
||
}
|
||
}
|
||
/**
|
||
* Internal class representing a pipe to a destination stream where
|
||
* errors are proxied.
|
||
*
|
||
* @internal
|
||
*/
|
||
class PipeProxyErrors extends Pipe {
|
||
unpipe() {
|
||
this.src.removeListener('error', this.proxyErrors);
|
||
super.unpipe();
|
||
}
|
||
constructor(src, dest, opts) {
|
||
super(src, dest, opts);
|
||
this.proxyErrors = er => dest.emit('error', er);
|
||
src.on('error', this.proxyErrors);
|
||
}
|
||
}
|
||
const isObjectModeOptions = (o) => !!o.objectMode;
|
||
const isEncodingOptions = (o) => !o.objectMode && !!o.encoding && o.encoding !== 'buffer';
|
||
/**
|
||
* Main export, the Minipass class
|
||
*
|
||
* `RType` is the type of data emitted, defaults to Buffer
|
||
*
|
||
* `WType` is the type of data to be written, if RType is buffer or string,
|
||
* then any {@link Minipass.ContiguousData} is allowed.
|
||
*
|
||
* `Events` is the set of event handler signatures that this object
|
||
* will emit, see {@link Minipass.Events}
|
||
*/
|
||
class Minipass extends EventEmitter {
|
||
[FLOWING] = false;
|
||
[PAUSED] = false;
|
||
[PIPES] = [];
|
||
[BUFFER] = [];
|
||
[OBJECTMODE];
|
||
[ENCODING$1];
|
||
[ASYNC];
|
||
[DECODER];
|
||
[EOF] = false;
|
||
[EMITTED_END] = false;
|
||
[EMITTING_END] = false;
|
||
[CLOSED] = false;
|
||
[EMITTED_ERROR] = null;
|
||
[BUFFERLENGTH] = 0;
|
||
[DESTROYED] = false;
|
||
[SIGNAL];
|
||
[ABORTED] = false;
|
||
[DATALISTENERS] = 0;
|
||
[DISCARDED] = false;
|
||
/**
|
||
* true if the stream can be written
|
||
*/
|
||
writable = true;
|
||
/**
|
||
* true if the stream can be read
|
||
*/
|
||
readable = true;
|
||
/**
|
||
* If `RType` is Buffer, then options do not need to be provided.
|
||
* Otherwise, an options object must be provided to specify either
|
||
* {@link Minipass.SharedOptions.objectMode} or
|
||
* {@link Minipass.SharedOptions.encoding}, as appropriate.
|
||
*/
|
||
constructor(...args) {
|
||
const options = (args[0] ||
|
||
{});
|
||
super();
|
||
if (options.objectMode && typeof options.encoding === 'string') {
|
||
throw new TypeError('Encoding and objectMode may not be used together');
|
||
}
|
||
if (isObjectModeOptions(options)) {
|
||
this[OBJECTMODE] = true;
|
||
this[ENCODING$1] = null;
|
||
}
|
||
else if (isEncodingOptions(options)) {
|
||
this[ENCODING$1] = options.encoding;
|
||
this[OBJECTMODE] = false;
|
||
}
|
||
else {
|
||
this[OBJECTMODE] = false;
|
||
this[ENCODING$1] = null;
|
||
}
|
||
this[ASYNC] = !!options.async;
|
||
this[DECODER] = this[ENCODING$1]
|
||
? new StringDecoder(this[ENCODING$1])
|
||
: null;
|
||
//@ts-ignore - private option for debugging and testing
|
||
if (options && options.debugExposeBuffer === true) {
|
||
Object.defineProperty(this, 'buffer', { get: () => this[BUFFER] });
|
||
}
|
||
//@ts-ignore - private option for debugging and testing
|
||
if (options && options.debugExposePipes === true) {
|
||
Object.defineProperty(this, 'pipes', { get: () => this[PIPES] });
|
||
}
|
||
const { signal } = options;
|
||
if (signal) {
|
||
this[SIGNAL] = signal;
|
||
if (signal.aborted) {
|
||
this[ABORT]();
|
||
}
|
||
else {
|
||
signal.addEventListener('abort', () => this[ABORT]());
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* The amount of data stored in the buffer waiting to be read.
|
||
*
|
||
* For Buffer strings, this will be the total byte length.
|
||
* For string encoding streams, this will be the string character length,
|
||
* according to JavaScript's `string.length` logic.
|
||
* For objectMode streams, this is a count of the items waiting to be
|
||
* emitted.
|
||
*/
|
||
get bufferLength() {
|
||
return this[BUFFERLENGTH];
|
||
}
|
||
/**
|
||
* The `BufferEncoding` currently in use, or `null`
|
||
*/
|
||
get encoding() {
|
||
return this[ENCODING$1];
|
||
}
|
||
/**
|
||
* @deprecated - This is a read only property
|
||
*/
|
||
set encoding(_enc) {
|
||
throw new Error('Encoding must be set at instantiation time');
|
||
}
|
||
/**
|
||
* @deprecated - Encoding may only be set at instantiation time
|
||
*/
|
||
setEncoding(_enc) {
|
||
throw new Error('Encoding must be set at instantiation time');
|
||
}
|
||
/**
|
||
* True if this is an objectMode stream
|
||
*/
|
||
get objectMode() {
|
||
return this[OBJECTMODE];
|
||
}
|
||
/**
|
||
* @deprecated - This is a read-only property
|
||
*/
|
||
set objectMode(_om) {
|
||
throw new Error('objectMode must be set at instantiation time');
|
||
}
|
||
/**
|
||
* true if this is an async stream
|
||
*/
|
||
get ['async']() {
|
||
return this[ASYNC];
|
||
}
|
||
/**
|
||
* Set to true to make this stream async.
|
||
*
|
||
* Once set, it cannot be unset, as this would potentially cause incorrect
|
||
* behavior. Ie, a sync stream can be made async, but an async stream
|
||
* cannot be safely made sync.
|
||
*/
|
||
set ['async'](a) {
|
||
this[ASYNC] = this[ASYNC] || !!a;
|
||
}
|
||
// drop everything and get out of the flow completely
|
||
[ABORT]() {
|
||
this[ABORTED] = true;
|
||
this.emit('abort', this[SIGNAL]?.reason);
|
||
this.destroy(this[SIGNAL]?.reason);
|
||
}
|
||
/**
|
||
* True if the stream has been aborted.
|
||
*/
|
||
get aborted() {
|
||
return this[ABORTED];
|
||
}
|
||
/**
|
||
* No-op setter. Stream aborted status is set via the AbortSignal provided
|
||
* in the constructor options.
|
||
*/
|
||
set aborted(_) { }
|
||
write(chunk, encoding, cb) {
|
||
if (this[ABORTED])
|
||
return false;
|
||
if (this[EOF])
|
||
throw new Error('write after end');
|
||
if (this[DESTROYED]) {
|
||
this.emit('error', Object.assign(new Error('Cannot call write after a stream was destroyed'), { code: 'ERR_STREAM_DESTROYED' }));
|
||
return true;
|
||
}
|
||
if (typeof encoding === 'function') {
|
||
cb = encoding;
|
||
encoding = 'utf8';
|
||
}
|
||
if (!encoding)
|
||
encoding = 'utf8';
|
||
const fn = this[ASYNC] ? defer : nodefer;
|
||
// convert array buffers and typed array views into buffers
|
||
// at some point in the future, we may want to do the opposite!
|
||
// leave strings and buffers as-is
|
||
// anything is only allowed if in object mode, so throw
|
||
if (!this[OBJECTMODE] && !Buffer.isBuffer(chunk)) {
|
||
if (isArrayBufferView(chunk)) {
|
||
//@ts-ignore - sinful unsafe type changing
|
||
chunk = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);
|
||
}
|
||
else if (isArrayBufferLike(chunk)) {
|
||
//@ts-ignore - sinful unsafe type changing
|
||
chunk = Buffer.from(chunk);
|
||
}
|
||
else if (typeof chunk !== 'string') {
|
||
throw new Error('Non-contiguous data written to non-objectMode stream');
|
||
}
|
||
}
|
||
// handle object mode up front, since it's simpler
|
||
// this yields better performance, fewer checks later.
|
||
if (this[OBJECTMODE]) {
|
||
// maybe impossible?
|
||
/* c8 ignore start */
|
||
if (this[FLOWING] && this[BUFFERLENGTH] !== 0)
|
||
this[FLUSH](true);
|
||
/* c8 ignore stop */
|
||
if (this[FLOWING])
|
||
this.emit('data', chunk);
|
||
else
|
||
this[BUFFERPUSH](chunk);
|
||
if (this[BUFFERLENGTH] !== 0)
|
||
this.emit('readable');
|
||
if (cb)
|
||
fn(cb);
|
||
return this[FLOWING];
|
||
}
|
||
// at this point the chunk is a buffer or string
|
||
// don't buffer it up or send it to the decoder
|
||
if (!chunk.length) {
|
||
if (this[BUFFERLENGTH] !== 0)
|
||
this.emit('readable');
|
||
if (cb)
|
||
fn(cb);
|
||
return this[FLOWING];
|
||
}
|
||
// fast-path writing strings of same encoding to a stream with
|
||
// an empty buffer, skipping the buffer/decoder dance
|
||
if (typeof chunk === 'string' &&
|
||
// unless it is a string already ready for us to use
|
||
!(encoding === this[ENCODING$1] && !this[DECODER]?.lastNeed)) {
|
||
//@ts-ignore - sinful unsafe type change
|
||
chunk = Buffer.from(chunk, encoding);
|
||
}
|
||
if (Buffer.isBuffer(chunk) && this[ENCODING$1]) {
|
||
//@ts-ignore - sinful unsafe type change
|
||
chunk = this[DECODER].write(chunk);
|
||
}
|
||
// Note: flushing CAN potentially switch us into not-flowing mode
|
||
if (this[FLOWING] && this[BUFFERLENGTH] !== 0)
|
||
this[FLUSH](true);
|
||
if (this[FLOWING])
|
||
this.emit('data', chunk);
|
||
else
|
||
this[BUFFERPUSH](chunk);
|
||
if (this[BUFFERLENGTH] !== 0)
|
||
this.emit('readable');
|
||
if (cb)
|
||
fn(cb);
|
||
return this[FLOWING];
|
||
}
|
||
/**
|
||
* Low-level explicit read method.
|
||
*
|
||
* In objectMode, the argument is ignored, and one item is returned if
|
||
* available.
|
||
*
|
||
* `n` is the number of bytes (or in the case of encoding streams,
|
||
* characters) to consume. If `n` is not provided, then the entire buffer
|
||
* is returned, or `null` is returned if no data is available.
|
||
*
|
||
* If `n` is greater that the amount of data in the internal buffer,
|
||
* then `null` is returned.
|
||
*/
|
||
read(n) {
|
||
if (this[DESTROYED])
|
||
return null;
|
||
this[DISCARDED] = false;
|
||
if (this[BUFFERLENGTH] === 0 ||
|
||
n === 0 ||
|
||
(n && n > this[BUFFERLENGTH])) {
|
||
this[MAYBE_EMIT_END]();
|
||
return null;
|
||
}
|
||
if (this[OBJECTMODE])
|
||
n = null;
|
||
if (this[BUFFER].length > 1 && !this[OBJECTMODE]) {
|
||
// not object mode, so if we have an encoding, then RType is string
|
||
// otherwise, must be Buffer
|
||
this[BUFFER] = [
|
||
(this[ENCODING$1]
|
||
? this[BUFFER].join('')
|
||
: Buffer.concat(this[BUFFER], this[BUFFERLENGTH])),
|
||
];
|
||
}
|
||
const ret = this[READ](n || null, this[BUFFER][0]);
|
||
this[MAYBE_EMIT_END]();
|
||
return ret;
|
||
}
|
||
[READ](n, chunk) {
|
||
if (this[OBJECTMODE])
|
||
this[BUFFERSHIFT]();
|
||
else {
|
||
const c = chunk;
|
||
if (n === c.length || n === null)
|
||
this[BUFFERSHIFT]();
|
||
else if (typeof c === 'string') {
|
||
this[BUFFER][0] = c.slice(n);
|
||
chunk = c.slice(0, n);
|
||
this[BUFFERLENGTH] -= n;
|
||
}
|
||
else {
|
||
this[BUFFER][0] = c.subarray(n);
|
||
chunk = c.subarray(0, n);
|
||
this[BUFFERLENGTH] -= n;
|
||
}
|
||
}
|
||
this.emit('data', chunk);
|
||
if (!this[BUFFER].length && !this[EOF])
|
||
this.emit('drain');
|
||
return chunk;
|
||
}
|
||
end(chunk, encoding, cb) {
|
||
if (typeof chunk === 'function') {
|
||
cb = chunk;
|
||
chunk = undefined;
|
||
}
|
||
if (typeof encoding === 'function') {
|
||
cb = encoding;
|
||
encoding = 'utf8';
|
||
}
|
||
if (chunk !== undefined)
|
||
this.write(chunk, encoding);
|
||
if (cb)
|
||
this.once('end', cb);
|
||
this[EOF] = true;
|
||
this.writable = false;
|
||
// if we haven't written anything, then go ahead and emit,
|
||
// even if we're not reading.
|
||
// we'll re-emit if a new 'end' listener is added anyway.
|
||
// This makes MP more suitable to write-only use cases.
|
||
if (this[FLOWING] || !this[PAUSED])
|
||
this[MAYBE_EMIT_END]();
|
||
return this;
|
||
}
|
||
// don't let the internal resume be overwritten
|
||
[RESUME]() {
|
||
if (this[DESTROYED])
|
||
return;
|
||
if (!this[DATALISTENERS] && !this[PIPES].length) {
|
||
this[DISCARDED] = true;
|
||
}
|
||
this[PAUSED] = false;
|
||
this[FLOWING] = true;
|
||
this.emit('resume');
|
||
if (this[BUFFER].length)
|
||
this[FLUSH]();
|
||
else if (this[EOF])
|
||
this[MAYBE_EMIT_END]();
|
||
else
|
||
this.emit('drain');
|
||
}
|
||
/**
|
||
* Resume the stream if it is currently in a paused state
|
||
*
|
||
* If called when there are no pipe destinations or `data` event listeners,
|
||
* this will place the stream in a "discarded" state, where all data will
|
||
* be thrown away. The discarded state is removed if a pipe destination or
|
||
* data handler is added, if pause() is called, or if any synchronous or
|
||
* asynchronous iteration is started.
|
||
*/
|
||
resume() {
|
||
return this[RESUME]();
|
||
}
|
||
/**
|
||
* Pause the stream
|
||
*/
|
||
pause() {
|
||
this[FLOWING] = false;
|
||
this[PAUSED] = true;
|
||
this[DISCARDED] = false;
|
||
}
|
||
/**
|
||
* true if the stream has been forcibly destroyed
|
||
*/
|
||
get destroyed() {
|
||
return this[DESTROYED];
|
||
}
|
||
/**
|
||
* true if the stream is currently in a flowing state, meaning that
|
||
* any writes will be immediately emitted.
|
||
*/
|
||
get flowing() {
|
||
return this[FLOWING];
|
||
}
|
||
/**
|
||
* true if the stream is currently in a paused state
|
||
*/
|
||
get paused() {
|
||
return this[PAUSED];
|
||
}
|
||
[BUFFERPUSH](chunk) {
|
||
if (this[OBJECTMODE])
|
||
this[BUFFERLENGTH] += 1;
|
||
else
|
||
this[BUFFERLENGTH] += chunk.length;
|
||
this[BUFFER].push(chunk);
|
||
}
|
||
[BUFFERSHIFT]() {
|
||
if (this[OBJECTMODE])
|
||
this[BUFFERLENGTH] -= 1;
|
||
else
|
||
this[BUFFERLENGTH] -= this[BUFFER][0].length;
|
||
return this[BUFFER].shift();
|
||
}
|
||
[FLUSH](noDrain = false) {
|
||
do { } while (this[FLUSHCHUNK](this[BUFFERSHIFT]()) &&
|
||
this[BUFFER].length);
|
||
if (!noDrain && !this[BUFFER].length && !this[EOF])
|
||
this.emit('drain');
|
||
}
|
||
[FLUSHCHUNK](chunk) {
|
||
this.emit('data', chunk);
|
||
return this[FLOWING];
|
||
}
|
||
/**
|
||
* Pipe all data emitted by this stream into the destination provided.
|
||
*
|
||
* Triggers the flow of data.
|
||
*/
|
||
pipe(dest, opts) {
|
||
if (this[DESTROYED])
|
||
return dest;
|
||
this[DISCARDED] = false;
|
||
const ended = this[EMITTED_END];
|
||
opts = opts || {};
|
||
if (dest === proc.stdout || dest === proc.stderr)
|
||
opts.end = false;
|
||
else
|
||
opts.end = opts.end !== false;
|
||
opts.proxyErrors = !!opts.proxyErrors;
|
||
// piping an ended stream ends immediately
|
||
if (ended) {
|
||
if (opts.end)
|
||
dest.end();
|
||
}
|
||
else {
|
||
// "as" here just ignores the WType, which pipes don't care about,
|
||
// since they're only consuming from us, and writing to the dest
|
||
this[PIPES].push(!opts.proxyErrors
|
||
? new Pipe(this, dest, opts)
|
||
: new PipeProxyErrors(this, dest, opts));
|
||
if (this[ASYNC])
|
||
defer(() => this[RESUME]());
|
||
else
|
||
this[RESUME]();
|
||
}
|
||
return dest;
|
||
}
|
||
/**
|
||
* Fully unhook a piped destination stream.
|
||
*
|
||
* If the destination stream was the only consumer of this stream (ie,
|
||
* there are no other piped destinations or `'data'` event listeners)
|
||
* then the flow of data will stop until there is another consumer or
|
||
* {@link Minipass#resume} is explicitly called.
|
||
*/
|
||
unpipe(dest) {
|
||
const p = this[PIPES].find(p => p.dest === dest);
|
||
if (p) {
|
||
if (this[PIPES].length === 1) {
|
||
if (this[FLOWING] && this[DATALISTENERS] === 0) {
|
||
this[FLOWING] = false;
|
||
}
|
||
this[PIPES] = [];
|
||
}
|
||
else
|
||
this[PIPES].splice(this[PIPES].indexOf(p), 1);
|
||
p.unpipe();
|
||
}
|
||
}
|
||
/**
|
||
* Alias for {@link Minipass#on}
|
||
*/
|
||
addListener(ev, handler) {
|
||
return this.on(ev, handler);
|
||
}
|
||
/**
|
||
* Mostly identical to `EventEmitter.on`, with the following
|
||
* behavior differences to prevent data loss and unnecessary hangs:
|
||
*
|
||
* - Adding a 'data' event handler will trigger the flow of data
|
||
*
|
||
* - Adding a 'readable' event handler when there is data waiting to be read
|
||
* will cause 'readable' to be emitted immediately.
|
||
*
|
||
* - Adding an 'endish' event handler ('end', 'finish', etc.) which has
|
||
* already passed will cause the event to be emitted immediately and all
|
||
* handlers removed.
|
||
*
|
||
* - Adding an 'error' event handler after an error has been emitted will
|
||
* cause the event to be re-emitted immediately with the error previously
|
||
* raised.
|
||
*/
|
||
on(ev, handler) {
|
||
const ret = super.on(ev, handler);
|
||
if (ev === 'data') {
|
||
this[DISCARDED] = false;
|
||
this[DATALISTENERS]++;
|
||
if (!this[PIPES].length && !this[FLOWING]) {
|
||
this[RESUME]();
|
||
}
|
||
}
|
||
else if (ev === 'readable' && this[BUFFERLENGTH] !== 0) {
|
||
super.emit('readable');
|
||
}
|
||
else if (isEndish(ev) && this[EMITTED_END]) {
|
||
super.emit(ev);
|
||
this.removeAllListeners(ev);
|
||
}
|
||
else if (ev === 'error' && this[EMITTED_ERROR]) {
|
||
const h = handler;
|
||
if (this[ASYNC])
|
||
defer(() => h.call(this, this[EMITTED_ERROR]));
|
||
else
|
||
h.call(this, this[EMITTED_ERROR]);
|
||
}
|
||
return ret;
|
||
}
|
||
/**
|
||
* Alias for {@link Minipass#off}
|
||
*/
|
||
removeListener(ev, handler) {
|
||
return this.off(ev, handler);
|
||
}
|
||
/**
|
||
* Mostly identical to `EventEmitter.off`
|
||
*
|
||
* If a 'data' event handler is removed, and it was the last consumer
|
||
* (ie, there are no pipe destinations or other 'data' event listeners),
|
||
* then the flow of data will stop until there is another consumer or
|
||
* {@link Minipass#resume} is explicitly called.
|
||
*/
|
||
off(ev, handler) {
|
||
const ret = super.off(ev, handler);
|
||
// if we previously had listeners, and now we don't, and we don't
|
||
// have any pipes, then stop the flow, unless it's been explicitly
|
||
// put in a discarded flowing state via stream.resume().
|
||
if (ev === 'data') {
|
||
this[DATALISTENERS] = this.listeners('data').length;
|
||
if (this[DATALISTENERS] === 0 &&
|
||
!this[DISCARDED] &&
|
||
!this[PIPES].length) {
|
||
this[FLOWING] = false;
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
/**
|
||
* Mostly identical to `EventEmitter.removeAllListeners`
|
||
*
|
||
* If all 'data' event handlers are removed, and they were the last consumer
|
||
* (ie, there are no pipe destinations), then the flow of data will stop
|
||
* until there is another consumer or {@link Minipass#resume} is explicitly
|
||
* called.
|
||
*/
|
||
removeAllListeners(ev) {
|
||
const ret = super.removeAllListeners(ev);
|
||
if (ev === 'data' || ev === undefined) {
|
||
this[DATALISTENERS] = 0;
|
||
if (!this[DISCARDED] && !this[PIPES].length) {
|
||
this[FLOWING] = false;
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
/**
|
||
* true if the 'end' event has been emitted
|
||
*/
|
||
get emittedEnd() {
|
||
return this[EMITTED_END];
|
||
}
|
||
[MAYBE_EMIT_END]() {
|
||
if (!this[EMITTING_END] &&
|
||
!this[EMITTED_END] &&
|
||
!this[DESTROYED] &&
|
||
this[BUFFER].length === 0 &&
|
||
this[EOF]) {
|
||
this[EMITTING_END] = true;
|
||
this.emit('end');
|
||
this.emit('prefinish');
|
||
this.emit('finish');
|
||
if (this[CLOSED])
|
||
this.emit('close');
|
||
this[EMITTING_END] = false;
|
||
}
|
||
}
|
||
/**
|
||
* Mostly identical to `EventEmitter.emit`, with the following
|
||
* behavior differences to prevent data loss and unnecessary hangs:
|
||
*
|
||
* If the stream has been destroyed, and the event is something other
|
||
* than 'close' or 'error', then `false` is returned and no handlers
|
||
* are called.
|
||
*
|
||
* If the event is 'end', and has already been emitted, then the event
|
||
* is ignored. If the stream is in a paused or non-flowing state, then
|
||
* the event will be deferred until data flow resumes. If the stream is
|
||
* async, then handlers will be called on the next tick rather than
|
||
* immediately.
|
||
*
|
||
* If the event is 'close', and 'end' has not yet been emitted, then
|
||
* the event will be deferred until after 'end' is emitted.
|
||
*
|
||
* If the event is 'error', and an AbortSignal was provided for the stream,
|
||
* and there are no listeners, then the event is ignored, matching the
|
||
* behavior of node core streams in the presense of an AbortSignal.
|
||
*
|
||
* If the event is 'finish' or 'prefinish', then all listeners will be
|
||
* removed after emitting the event, to prevent double-firing.
|
||
*/
|
||
emit(ev, ...args) {
|
||
const data = args[0];
|
||
// error and close are only events allowed after calling destroy()
|
||
if (ev !== 'error' &&
|
||
ev !== 'close' &&
|
||
ev !== DESTROYED &&
|
||
this[DESTROYED]) {
|
||
return false;
|
||
}
|
||
else if (ev === 'data') {
|
||
return !this[OBJECTMODE] && !data
|
||
? false
|
||
: this[ASYNC]
|
||
? (defer(() => this[EMITDATA](data)), true)
|
||
: this[EMITDATA](data);
|
||
}
|
||
else if (ev === 'end') {
|
||
return this[EMITEND]();
|
||
}
|
||
else if (ev === 'close') {
|
||
this[CLOSED] = true;
|
||
// don't emit close before 'end' and 'finish'
|
||
if (!this[EMITTED_END] && !this[DESTROYED])
|
||
return false;
|
||
const ret = super.emit('close');
|
||
this.removeAllListeners('close');
|
||
return ret;
|
||
}
|
||
else if (ev === 'error') {
|
||
this[EMITTED_ERROR] = data;
|
||
super.emit(ERROR, data);
|
||
const ret = !this[SIGNAL] || this.listeners('error').length
|
||
? super.emit('error', data)
|
||
: false;
|
||
this[MAYBE_EMIT_END]();
|
||
return ret;
|
||
}
|
||
else if (ev === 'resume') {
|
||
const ret = super.emit('resume');
|
||
this[MAYBE_EMIT_END]();
|
||
return ret;
|
||
}
|
||
else if (ev === 'finish' || ev === 'prefinish') {
|
||
const ret = super.emit(ev);
|
||
this.removeAllListeners(ev);
|
||
return ret;
|
||
}
|
||
// Some other unknown event
|
||
const ret = super.emit(ev, ...args);
|
||
this[MAYBE_EMIT_END]();
|
||
return ret;
|
||
}
|
||
[EMITDATA](data) {
|
||
for (const p of this[PIPES]) {
|
||
if (p.dest.write(data) === false)
|
||
this.pause();
|
||
}
|
||
const ret = this[DISCARDED] ? false : super.emit('data', data);
|
||
this[MAYBE_EMIT_END]();
|
||
return ret;
|
||
}
|
||
[EMITEND]() {
|
||
if (this[EMITTED_END])
|
||
return false;
|
||
this[EMITTED_END] = true;
|
||
this.readable = false;
|
||
return this[ASYNC]
|
||
? (defer(() => this[EMITEND2]()), true)
|
||
: this[EMITEND2]();
|
||
}
|
||
[EMITEND2]() {
|
||
if (this[DECODER]) {
|
||
const data = this[DECODER].end();
|
||
if (data) {
|
||
for (const p of this[PIPES]) {
|
||
p.dest.write(data);
|
||
}
|
||
if (!this[DISCARDED])
|
||
super.emit('data', data);
|
||
}
|
||
}
|
||
for (const p of this[PIPES]) {
|
||
p.end();
|
||
}
|
||
const ret = super.emit('end');
|
||
this.removeAllListeners('end');
|
||
return ret;
|
||
}
|
||
/**
|
||
* Return a Promise that resolves to an array of all emitted data once
|
||
* the stream ends.
|
||
*/
|
||
async collect() {
|
||
const buf = Object.assign([], {
|
||
dataLength: 0,
|
||
});
|
||
if (!this[OBJECTMODE])
|
||
buf.dataLength = 0;
|
||
// set the promise first, in case an error is raised
|
||
// by triggering the flow here.
|
||
const p = this.promise();
|
||
this.on('data', c => {
|
||
buf.push(c);
|
||
if (!this[OBJECTMODE])
|
||
buf.dataLength += c.length;
|
||
});
|
||
await p;
|
||
return buf;
|
||
}
|
||
/**
|
||
* Return a Promise that resolves to the concatenation of all emitted data
|
||
* once the stream ends.
|
||
*
|
||
* Not allowed on objectMode streams.
|
||
*/
|
||
async concat() {
|
||
if (this[OBJECTMODE]) {
|
||
throw new Error('cannot concat in objectMode');
|
||
}
|
||
const buf = await this.collect();
|
||
return (this[ENCODING$1]
|
||
? buf.join('')
|
||
: Buffer.concat(buf, buf.dataLength));
|
||
}
|
||
/**
|
||
* Return a void Promise that resolves once the stream ends.
|
||
*/
|
||
async promise() {
|
||
return new Promise((resolve, reject) => {
|
||
this.on(DESTROYED, () => reject(new Error('stream destroyed')));
|
||
this.on('error', er => reject(er));
|
||
this.on('end', () => resolve());
|
||
});
|
||
}
|
||
/**
|
||
* Asynchronous `for await of` iteration.
|
||
*
|
||
* This will continue emitting all chunks until the stream terminates.
|
||
*/
|
||
[Symbol.asyncIterator]() {
|
||
// set this up front, in case the consumer doesn't call next()
|
||
// right away.
|
||
this[DISCARDED] = false;
|
||
let stopped = false;
|
||
const stop = async () => {
|
||
this.pause();
|
||
stopped = true;
|
||
return { value: undefined, done: true };
|
||
};
|
||
const next = () => {
|
||
if (stopped)
|
||
return stop();
|
||
const res = this.read();
|
||
if (res !== null)
|
||
return Promise.resolve({ done: false, value: res });
|
||
if (this[EOF])
|
||
return stop();
|
||
let resolve;
|
||
let reject;
|
||
const onerr = (er) => {
|
||
this.off('data', ondata);
|
||
this.off('end', onend);
|
||
this.off(DESTROYED, ondestroy);
|
||
stop();
|
||
reject(er);
|
||
};
|
||
const ondata = (value) => {
|
||
this.off('error', onerr);
|
||
this.off('end', onend);
|
||
this.off(DESTROYED, ondestroy);
|
||
this.pause();
|
||
resolve({ value, done: !!this[EOF] });
|
||
};
|
||
const onend = () => {
|
||
this.off('error', onerr);
|
||
this.off('data', ondata);
|
||
this.off(DESTROYED, ondestroy);
|
||
stop();
|
||
resolve({ done: true, value: undefined });
|
||
};
|
||
const ondestroy = () => onerr(new Error('stream destroyed'));
|
||
return new Promise((res, rej) => {
|
||
reject = rej;
|
||
resolve = res;
|
||
this.once(DESTROYED, ondestroy);
|
||
this.once('error', onerr);
|
||
this.once('end', onend);
|
||
this.once('data', ondata);
|
||
});
|
||
};
|
||
return {
|
||
next,
|
||
throw: stop,
|
||
return: stop,
|
||
[Symbol.asyncIterator]() {
|
||
return this;
|
||
},
|
||
};
|
||
}
|
||
/**
|
||
* Synchronous `for of` iteration.
|
||
*
|
||
* The iteration will terminate when the internal buffer runs out, even
|
||
* if the stream has not yet terminated.
|
||
*/
|
||
[Symbol.iterator]() {
|
||
// set this up front, in case the consumer doesn't call next()
|
||
// right away.
|
||
this[DISCARDED] = false;
|
||
let stopped = false;
|
||
const stop = () => {
|
||
this.pause();
|
||
this.off(ERROR, stop);
|
||
this.off(DESTROYED, stop);
|
||
this.off('end', stop);
|
||
stopped = true;
|
||
return { done: true, value: undefined };
|
||
};
|
||
const next = () => {
|
||
if (stopped)
|
||
return stop();
|
||
const value = this.read();
|
||
return value === null ? stop() : { done: false, value };
|
||
};
|
||
this.once('end', stop);
|
||
this.once(ERROR, stop);
|
||
this.once(DESTROYED, stop);
|
||
return {
|
||
next,
|
||
throw: stop,
|
||
return: stop,
|
||
[Symbol.iterator]() {
|
||
return this;
|
||
},
|
||
};
|
||
}
|
||
/**
|
||
* Destroy a stream, preventing it from being used for any further purpose.
|
||
*
|
||
* If the stream has a `close()` method, then it will be called on
|
||
* destruction.
|
||
*
|
||
* After destruction, any attempt to write data, read data, or emit most
|
||
* events will be ignored.
|
||
*
|
||
* If an error argument is provided, then it will be emitted in an
|
||
* 'error' event.
|
||
*/
|
||
destroy(er) {
|
||
if (this[DESTROYED]) {
|
||
if (er)
|
||
this.emit('error', er);
|
||
else
|
||
this.emit(DESTROYED);
|
||
return this;
|
||
}
|
||
this[DESTROYED] = true;
|
||
this[DISCARDED] = true;
|
||
// throw away all buffered data, it's never coming out
|
||
this[BUFFER].length = 0;
|
||
this[BUFFERLENGTH] = 0;
|
||
const wc = this;
|
||
if (typeof wc.close === 'function' && !this[CLOSED])
|
||
wc.close();
|
||
if (er)
|
||
this.emit('error', er);
|
||
// if no error to emit, still reject pending promises
|
||
else
|
||
this.emit(DESTROYED);
|
||
return this;
|
||
}
|
||
/**
|
||
* Alias for {@link isStream}
|
||
*
|
||
* Former export location, maintained for backwards compatibility.
|
||
*
|
||
* @deprecated
|
||
*/
|
||
static get isStream() {
|
||
return isStream;
|
||
}
|
||
}
|
||
|
||
const realpathSync = realpathSync$1.native;
|
||
const defaultFS = {
|
||
lstatSync,
|
||
readdir: readdir$4,
|
||
readdirSync: readdirSync$1,
|
||
readlinkSync,
|
||
realpathSync,
|
||
promises: {
|
||
lstat: lstat$4,
|
||
readdir: readdir$5,
|
||
readlink,
|
||
realpath,
|
||
},
|
||
};
|
||
// if they just gave us require('fs') then use our default
|
||
const fsFromOption = (fsOption) => !fsOption || fsOption === defaultFS || fsOption === fs$t
|
||
? defaultFS
|
||
: {
|
||
...defaultFS,
|
||
...fsOption,
|
||
promises: {
|
||
...defaultFS.promises,
|
||
...(fsOption.promises || {}),
|
||
},
|
||
};
|
||
// turn something like //?/c:/ into c:\
|
||
const uncDriveRegexp = /^\\\\\?\\([a-z]:)\\?$/i;
|
||
const uncToDrive = (rootPath) => rootPath.replace(/\//g, '\\').replace(uncDriveRegexp, '$1\\');
|
||
// windows paths are separated by either / or \
|
||
const eitherSep = /[\\\/]/;
|
||
const UNKNOWN = 0; // may not even exist, for all we know
|
||
const IFIFO = 0b0001;
|
||
const IFCHR = 0b0010;
|
||
const IFDIR = 0b0100;
|
||
const IFBLK = 0b0110;
|
||
const IFREG = 0b1000;
|
||
const IFLNK = 0b1010;
|
||
const IFSOCK = 0b1100;
|
||
const IFMT = 0b1111;
|
||
// mask to unset low 4 bits
|
||
const IFMT_UNKNOWN = ~IFMT;
|
||
// set after successfully calling readdir() and getting entries.
|
||
const READDIR_CALLED = 16;
|
||
// set after a successful lstat()
|
||
const LSTAT_CALLED = 32;
|
||
// set if an entry (or one of its parents) is definitely not a dir
|
||
const ENOTDIR = 64;
|
||
// set if an entry (or one of its parents) does not exist
|
||
// (can also be set on lstat errors like EACCES or ENAMETOOLONG)
|
||
const ENOENT = 128;
|
||
// cannot have child entries -- also verify &IFMT is either IFDIR or IFLNK
|
||
// set if we fail to readlink
|
||
const ENOREADLINK = 256;
|
||
// set if we know realpath() will fail
|
||
const ENOREALPATH = 512;
|
||
const ENOCHILD = ENOTDIR | ENOENT | ENOREALPATH;
|
||
const TYPEMASK = 1023;
|
||
const entToType = (s) => s.isFile()
|
||
? IFREG
|
||
: s.isDirectory()
|
||
? IFDIR
|
||
: s.isSymbolicLink()
|
||
? IFLNK
|
||
: s.isCharacterDevice()
|
||
? IFCHR
|
||
: s.isBlockDevice()
|
||
? IFBLK
|
||
: s.isSocket()
|
||
? IFSOCK
|
||
: s.isFIFO()
|
||
? IFIFO
|
||
: UNKNOWN;
|
||
// normalize unicode path names
|
||
const normalizeCache = new Map();
|
||
const normalize$2 = (s) => {
|
||
const c = normalizeCache.get(s);
|
||
if (c)
|
||
return c;
|
||
const n = s.normalize('NFKD');
|
||
normalizeCache.set(s, n);
|
||
return n;
|
||
};
|
||
const normalizeNocaseCache = new Map();
|
||
const normalizeNocase = (s) => {
|
||
const c = normalizeNocaseCache.get(s);
|
||
if (c)
|
||
return c;
|
||
const n = normalize$2(s.toLowerCase());
|
||
normalizeNocaseCache.set(s, n);
|
||
return n;
|
||
};
|
||
/**
|
||
* An LRUCache for storing resolved path strings or Path objects.
|
||
* @internal
|
||
*/
|
||
class ResolveCache extends LRUCache {
|
||
constructor() {
|
||
super({ max: 256 });
|
||
}
|
||
}
|
||
// In order to prevent blowing out the js heap by allocating hundreds of
|
||
// thousands of Path entries when walking extremely large trees, the "children"
|
||
// in this tree are represented by storing an array of Path entries in an
|
||
// LRUCache, indexed by the parent. At any time, Path.children() may return an
|
||
// empty array, indicating that it doesn't know about any of its children, and
|
||
// thus has to rebuild that cache. This is fine, it just means that we don't
|
||
// benefit as much from having the cached entries, but huge directory walks
|
||
// don't blow out the stack, and smaller ones are still as fast as possible.
|
||
//
|
||
//It does impose some complexity when building up the readdir data, because we
|
||
//need to pass a reference to the children array that we started with.
|
||
/**
|
||
* an LRUCache for storing child entries.
|
||
* @internal
|
||
*/
|
||
class ChildrenCache extends LRUCache {
|
||
constructor(maxSize = 16 * 1024) {
|
||
super({
|
||
maxSize,
|
||
// parent + children
|
||
sizeCalculation: a => a.length + 1,
|
||
});
|
||
}
|
||
}
|
||
const setAsCwd = Symbol('PathScurry setAsCwd');
|
||
/**
|
||
* Path objects are sort of like a super-powered
|
||
* {@link https://nodejs.org/docs/latest/api/fs.html#class-fsdirent fs.Dirent}
|
||
*
|
||
* Each one represents a single filesystem entry on disk, which may or may not
|
||
* exist. It includes methods for reading various types of information via
|
||
* lstat, readlink, and readdir, and caches all information to the greatest
|
||
* degree possible.
|
||
*
|
||
* Note that fs operations that would normally throw will instead return an
|
||
* "empty" value. This is in order to prevent excessive overhead from error
|
||
* stack traces.
|
||
*/
|
||
class PathBase {
|
||
/**
|
||
* the basename of this path
|
||
*
|
||
* **Important**: *always* test the path name against any test string
|
||
* usingthe {@link isNamed} method, and not by directly comparing this
|
||
* string. Otherwise, unicode path strings that the system sees as identical
|
||
* will not be properly treated as the same path, leading to incorrect
|
||
* behavior and possible security issues.
|
||
*/
|
||
name;
|
||
/**
|
||
* the Path entry corresponding to the path root.
|
||
*
|
||
* @internal
|
||
*/
|
||
root;
|
||
/**
|
||
* All roots found within the current PathScurry family
|
||
*
|
||
* @internal
|
||
*/
|
||
roots;
|
||
/**
|
||
* a reference to the parent path, or undefined in the case of root entries
|
||
*
|
||
* @internal
|
||
*/
|
||
parent;
|
||
/**
|
||
* boolean indicating whether paths are compared case-insensitively
|
||
* @internal
|
||
*/
|
||
nocase;
|
||
// potential default fs override
|
||
#fs;
|
||
// Stats fields
|
||
#dev;
|
||
get dev() {
|
||
return this.#dev;
|
||
}
|
||
#mode;
|
||
get mode() {
|
||
return this.#mode;
|
||
}
|
||
#nlink;
|
||
get nlink() {
|
||
return this.#nlink;
|
||
}
|
||
#uid;
|
||
get uid() {
|
||
return this.#uid;
|
||
}
|
||
#gid;
|
||
get gid() {
|
||
return this.#gid;
|
||
}
|
||
#rdev;
|
||
get rdev() {
|
||
return this.#rdev;
|
||
}
|
||
#blksize;
|
||
get blksize() {
|
||
return this.#blksize;
|
||
}
|
||
#ino;
|
||
get ino() {
|
||
return this.#ino;
|
||
}
|
||
#size;
|
||
get size() {
|
||
return this.#size;
|
||
}
|
||
#blocks;
|
||
get blocks() {
|
||
return this.#blocks;
|
||
}
|
||
#atimeMs;
|
||
get atimeMs() {
|
||
return this.#atimeMs;
|
||
}
|
||
#mtimeMs;
|
||
get mtimeMs() {
|
||
return this.#mtimeMs;
|
||
}
|
||
#ctimeMs;
|
||
get ctimeMs() {
|
||
return this.#ctimeMs;
|
||
}
|
||
#birthtimeMs;
|
||
get birthtimeMs() {
|
||
return this.#birthtimeMs;
|
||
}
|
||
#atime;
|
||
get atime() {
|
||
return this.#atime;
|
||
}
|
||
#mtime;
|
||
get mtime() {
|
||
return this.#mtime;
|
||
}
|
||
#ctime;
|
||
get ctime() {
|
||
return this.#ctime;
|
||
}
|
||
#birthtime;
|
||
get birthtime() {
|
||
return this.#birthtime;
|
||
}
|
||
#matchName;
|
||
#depth;
|
||
#fullpath;
|
||
#fullpathPosix;
|
||
#relative;
|
||
#relativePosix;
|
||
#type;
|
||
#children;
|
||
#linkTarget;
|
||
#realpath;
|
||
/**
|
||
* This property is for compatibility with the Dirent class as of
|
||
* Node v20, where Dirent['path'] refers to the path of the directory
|
||
* that was passed to readdir. So, somewhat counterintuitively, this
|
||
* property refers to the *parent* path, not the path object itself.
|
||
* For root entries, it's the path to the entry itself.
|
||
*/
|
||
get path() {
|
||
return (this.parent || this).fullpath();
|
||
}
|
||
/**
|
||
* Do not create new Path objects directly. They should always be accessed
|
||
* via the PathScurry class or other methods on the Path class.
|
||
*
|
||
* @internal
|
||
*/
|
||
constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
|
||
this.name = name;
|
||
this.#matchName = nocase ? normalizeNocase(name) : normalize$2(name);
|
||
this.#type = type & TYPEMASK;
|
||
this.nocase = nocase;
|
||
this.roots = roots;
|
||
this.root = root || this;
|
||
this.#children = children;
|
||
this.#fullpath = opts.fullpath;
|
||
this.#relative = opts.relative;
|
||
this.#relativePosix = opts.relativePosix;
|
||
this.parent = opts.parent;
|
||
if (this.parent) {
|
||
this.#fs = this.parent.#fs;
|
||
}
|
||
else {
|
||
this.#fs = fsFromOption(opts.fs);
|
||
}
|
||
}
|
||
/**
|
||
* Returns the depth of the Path object from its root.
|
||
*
|
||
* For example, a path at `/foo/bar` would have a depth of 2.
|
||
*/
|
||
depth() {
|
||
if (this.#depth !== undefined)
|
||
return this.#depth;
|
||
if (!this.parent)
|
||
return (this.#depth = 0);
|
||
return (this.#depth = this.parent.depth() + 1);
|
||
}
|
||
/**
|
||
* @internal
|
||
*/
|
||
childrenCache() {
|
||
return this.#children;
|
||
}
|
||
/**
|
||
* Get the Path object referenced by the string path, resolved from this Path
|
||
*/
|
||
resolve(path) {
|
||
if (!path) {
|
||
return this;
|
||
}
|
||
const rootPath = this.getRootString(path);
|
||
const dir = path.substring(rootPath.length);
|
||
const dirParts = dir.split(this.splitSep);
|
||
const result = rootPath
|
||
? this.getRoot(rootPath).#resolveParts(dirParts)
|
||
: this.#resolveParts(dirParts);
|
||
return result;
|
||
}
|
||
#resolveParts(dirParts) {
|
||
let p = this;
|
||
for (const part of dirParts) {
|
||
p = p.child(part);
|
||
}
|
||
return p;
|
||
}
|
||
/**
|
||
* Returns the cached children Path objects, if still available. If they
|
||
* have fallen out of the cache, then returns an empty array, and resets the
|
||
* READDIR_CALLED bit, so that future calls to readdir() will require an fs
|
||
* lookup.
|
||
*
|
||
* @internal
|
||
*/
|
||
children() {
|
||
const cached = this.#children.get(this);
|
||
if (cached) {
|
||
return cached;
|
||
}
|
||
const children = Object.assign([], { provisional: 0 });
|
||
this.#children.set(this, children);
|
||
this.#type &= ~READDIR_CALLED;
|
||
return children;
|
||
}
|
||
/**
|
||
* Resolves a path portion and returns or creates the child Path.
|
||
*
|
||
* Returns `this` if pathPart is `''` or `'.'`, or `parent` if pathPart is
|
||
* `'..'`.
|
||
*
|
||
* This should not be called directly. If `pathPart` contains any path
|
||
* separators, it will lead to unsafe undefined behavior.
|
||
*
|
||
* Use `Path.resolve()` instead.
|
||
*
|
||
* @internal
|
||
*/
|
||
child(pathPart, opts) {
|
||
if (pathPart === '' || pathPart === '.') {
|
||
return this;
|
||
}
|
||
if (pathPart === '..') {
|
||
return this.parent || this;
|
||
}
|
||
// find the child
|
||
const children = this.children();
|
||
const name = this.nocase
|
||
? normalizeNocase(pathPart)
|
||
: normalize$2(pathPart);
|
||
for (const p of children) {
|
||
if (p.#matchName === name) {
|
||
return p;
|
||
}
|
||
}
|
||
// didn't find it, create provisional child, since it might not
|
||
// actually exist. If we know the parent isn't a dir, then
|
||
// in fact it CAN'T exist.
|
||
const s = this.parent ? this.sep : '';
|
||
const fullpath = this.#fullpath
|
||
? this.#fullpath + s + pathPart
|
||
: undefined;
|
||
const pchild = this.newChild(pathPart, UNKNOWN, {
|
||
...opts,
|
||
parent: this,
|
||
fullpath,
|
||
});
|
||
if (!this.canReaddir()) {
|
||
pchild.#type |= ENOENT;
|
||
}
|
||
// don't have to update provisional, because if we have real children,
|
||
// then provisional is set to children.length, otherwise a lower number
|
||
children.push(pchild);
|
||
return pchild;
|
||
}
|
||
/**
|
||
* The relative path from the cwd. If it does not share an ancestor with
|
||
* the cwd, then this ends up being equivalent to the fullpath()
|
||
*/
|
||
relative() {
|
||
if (this.#relative !== undefined) {
|
||
return this.#relative;
|
||
}
|
||
const name = this.name;
|
||
const p = this.parent;
|
||
if (!p) {
|
||
return (this.#relative = this.name);
|
||
}
|
||
const pv = p.relative();
|
||
return pv + (!pv || !p.parent ? '' : this.sep) + name;
|
||
}
|
||
/**
|
||
* The relative path from the cwd, using / as the path separator.
|
||
* If it does not share an ancestor with
|
||
* the cwd, then this ends up being equivalent to the fullpathPosix()
|
||
* On posix systems, this is identical to relative().
|
||
*/
|
||
relativePosix() {
|
||
if (this.sep === '/')
|
||
return this.relative();
|
||
if (this.#relativePosix !== undefined)
|
||
return this.#relativePosix;
|
||
const name = this.name;
|
||
const p = this.parent;
|
||
if (!p) {
|
||
return (this.#relativePosix = this.fullpathPosix());
|
||
}
|
||
const pv = p.relativePosix();
|
||
return pv + (!pv || !p.parent ? '' : '/') + name;
|
||
}
|
||
/**
|
||
* The fully resolved path string for this Path entry
|
||
*/
|
||
fullpath() {
|
||
if (this.#fullpath !== undefined) {
|
||
return this.#fullpath;
|
||
}
|
||
const name = this.name;
|
||
const p = this.parent;
|
||
if (!p) {
|
||
return (this.#fullpath = this.name);
|
||
}
|
||
const pv = p.fullpath();
|
||
const fp = pv + (!p.parent ? '' : this.sep) + name;
|
||
return (this.#fullpath = fp);
|
||
}
|
||
/**
|
||
* On platforms other than windows, this is identical to fullpath.
|
||
*
|
||
* On windows, this is overridden to return the forward-slash form of the
|
||
* full UNC path.
|
||
*/
|
||
fullpathPosix() {
|
||
if (this.#fullpathPosix !== undefined)
|
||
return this.#fullpathPosix;
|
||
if (this.sep === '/')
|
||
return (this.#fullpathPosix = this.fullpath());
|
||
if (!this.parent) {
|
||
const p = this.fullpath().replace(/\\/g, '/');
|
||
if (/^[a-z]:\//i.test(p)) {
|
||
return (this.#fullpathPosix = `//?/${p}`);
|
||
}
|
||
else {
|
||
return (this.#fullpathPosix = p);
|
||
}
|
||
}
|
||
const p = this.parent;
|
||
const pfpp = p.fullpathPosix();
|
||
const fpp = pfpp + (!pfpp || !p.parent ? '' : '/') + this.name;
|
||
return (this.#fullpathPosix = fpp);
|
||
}
|
||
/**
|
||
* Is the Path of an unknown type?
|
||
*
|
||
* Note that we might know *something* about it if there has been a previous
|
||
* filesystem operation, for example that it does not exist, or is not a
|
||
* link, or whether it has child entries.
|
||
*/
|
||
isUnknown() {
|
||
return (this.#type & IFMT) === UNKNOWN;
|
||
}
|
||
isType(type) {
|
||
return this[`is${type}`]();
|
||
}
|
||
getType() {
|
||
return this.isUnknown()
|
||
? 'Unknown'
|
||
: this.isDirectory()
|
||
? 'Directory'
|
||
: this.isFile()
|
||
? 'File'
|
||
: this.isSymbolicLink()
|
||
? 'SymbolicLink'
|
||
: this.isFIFO()
|
||
? 'FIFO'
|
||
: this.isCharacterDevice()
|
||
? 'CharacterDevice'
|
||
: this.isBlockDevice()
|
||
? 'BlockDevice'
|
||
: /* c8 ignore start */ this.isSocket()
|
||
? 'Socket'
|
||
: 'Unknown';
|
||
/* c8 ignore stop */
|
||
}
|
||
/**
|
||
* Is the Path a regular file?
|
||
*/
|
||
isFile() {
|
||
return (this.#type & IFMT) === IFREG;
|
||
}
|
||
/**
|
||
* Is the Path a directory?
|
||
*/
|
||
isDirectory() {
|
||
return (this.#type & IFMT) === IFDIR;
|
||
}
|
||
/**
|
||
* Is the path a character device?
|
||
*/
|
||
isCharacterDevice() {
|
||
return (this.#type & IFMT) === IFCHR;
|
||
}
|
||
/**
|
||
* Is the path a block device?
|
||
*/
|
||
isBlockDevice() {
|
||
return (this.#type & IFMT) === IFBLK;
|
||
}
|
||
/**
|
||
* Is the path a FIFO pipe?
|
||
*/
|
||
isFIFO() {
|
||
return (this.#type & IFMT) === IFIFO;
|
||
}
|
||
/**
|
||
* Is the path a socket?
|
||
*/
|
||
isSocket() {
|
||
return (this.#type & IFMT) === IFSOCK;
|
||
}
|
||
/**
|
||
* Is the path a symbolic link?
|
||
*/
|
||
isSymbolicLink() {
|
||
return (this.#type & IFLNK) === IFLNK;
|
||
}
|
||
/**
|
||
* Return the entry if it has been subject of a successful lstat, or
|
||
* undefined otherwise.
|
||
*
|
||
* Does not read the filesystem, so an undefined result *could* simply
|
||
* mean that we haven't called lstat on it.
|
||
*/
|
||
lstatCached() {
|
||
return this.#type & LSTAT_CALLED ? this : undefined;
|
||
}
|
||
/**
|
||
* Return the cached link target if the entry has been the subject of a
|
||
* successful readlink, or undefined otherwise.
|
||
*
|
||
* Does not read the filesystem, so an undefined result *could* just mean we
|
||
* don't have any cached data. Only use it if you are very sure that a
|
||
* readlink() has been called at some point.
|
||
*/
|
||
readlinkCached() {
|
||
return this.#linkTarget;
|
||
}
|
||
/**
|
||
* Returns the cached realpath target if the entry has been the subject
|
||
* of a successful realpath, or undefined otherwise.
|
||
*
|
||
* Does not read the filesystem, so an undefined result *could* just mean we
|
||
* don't have any cached data. Only use it if you are very sure that a
|
||
* realpath() has been called at some point.
|
||
*/
|
||
realpathCached() {
|
||
return this.#realpath;
|
||
}
|
||
/**
|
||
* Returns the cached child Path entries array if the entry has been the
|
||
* subject of a successful readdir(), or [] otherwise.
|
||
*
|
||
* Does not read the filesystem, so an empty array *could* just mean we
|
||
* don't have any cached data. Only use it if you are very sure that a
|
||
* readdir() has been called recently enough to still be valid.
|
||
*/
|
||
readdirCached() {
|
||
const children = this.children();
|
||
return children.slice(0, children.provisional);
|
||
}
|
||
/**
|
||
* Return true if it's worth trying to readlink. Ie, we don't (yet) have
|
||
* any indication that readlink will definitely fail.
|
||
*
|
||
* Returns false if the path is known to not be a symlink, if a previous
|
||
* readlink failed, or if the entry does not exist.
|
||
*/
|
||
canReadlink() {
|
||
if (this.#linkTarget)
|
||
return true;
|
||
if (!this.parent)
|
||
return false;
|
||
// cases where it cannot possibly succeed
|
||
const ifmt = this.#type & IFMT;
|
||
return !((ifmt !== UNKNOWN && ifmt !== IFLNK) ||
|
||
this.#type & ENOREADLINK ||
|
||
this.#type & ENOENT);
|
||
}
|
||
/**
|
||
* Return true if readdir has previously been successfully called on this
|
||
* path, indicating that cachedReaddir() is likely valid.
|
||
*/
|
||
calledReaddir() {
|
||
return !!(this.#type & READDIR_CALLED);
|
||
}
|
||
/**
|
||
* Returns true if the path is known to not exist. That is, a previous lstat
|
||
* or readdir failed to verify its existence when that would have been
|
||
* expected, or a parent entry was marked either enoent or enotdir.
|
||
*/
|
||
isENOENT() {
|
||
return !!(this.#type & ENOENT);
|
||
}
|
||
/**
|
||
* Return true if the path is a match for the given path name. This handles
|
||
* case sensitivity and unicode normalization.
|
||
*
|
||
* Note: even on case-sensitive systems, it is **not** safe to test the
|
||
* equality of the `.name` property to determine whether a given pathname
|
||
* matches, due to unicode normalization mismatches.
|
||
*
|
||
* Always use this method instead of testing the `path.name` property
|
||
* directly.
|
||
*/
|
||
isNamed(n) {
|
||
return !this.nocase
|
||
? this.#matchName === normalize$2(n)
|
||
: this.#matchName === normalizeNocase(n);
|
||
}
|
||
/**
|
||
* Return the Path object corresponding to the target of a symbolic link.
|
||
*
|
||
* If the Path is not a symbolic link, or if the readlink call fails for any
|
||
* reason, `undefined` is returned.
|
||
*
|
||
* Result is cached, and thus may be outdated if the filesystem is mutated.
|
||
*/
|
||
async readlink() {
|
||
const target = this.#linkTarget;
|
||
if (target) {
|
||
return target;
|
||
}
|
||
if (!this.canReadlink()) {
|
||
return undefined;
|
||
}
|
||
/* c8 ignore start */
|
||
// already covered by the canReadlink test, here for ts grumples
|
||
if (!this.parent) {
|
||
return undefined;
|
||
}
|
||
/* c8 ignore stop */
|
||
try {
|
||
const read = await this.#fs.promises.readlink(this.fullpath());
|
||
const linkTarget = this.parent.resolve(read);
|
||
if (linkTarget) {
|
||
return (this.#linkTarget = linkTarget);
|
||
}
|
||
}
|
||
catch (er) {
|
||
this.#readlinkFail(er.code);
|
||
return undefined;
|
||
}
|
||
}
|
||
/**
|
||
* Synchronous {@link PathBase.readlink}
|
||
*/
|
||
readlinkSync() {
|
||
const target = this.#linkTarget;
|
||
if (target) {
|
||
return target;
|
||
}
|
||
if (!this.canReadlink()) {
|
||
return undefined;
|
||
}
|
||
/* c8 ignore start */
|
||
// already covered by the canReadlink test, here for ts grumples
|
||
if (!this.parent) {
|
||
return undefined;
|
||
}
|
||
/* c8 ignore stop */
|
||
try {
|
||
const read = this.#fs.readlinkSync(this.fullpath());
|
||
const linkTarget = this.parent.resolve(read);
|
||
if (linkTarget) {
|
||
return (this.#linkTarget = linkTarget);
|
||
}
|
||
}
|
||
catch (er) {
|
||
this.#readlinkFail(er.code);
|
||
return undefined;
|
||
}
|
||
}
|
||
#readdirSuccess(children) {
|
||
// succeeded, mark readdir called bit
|
||
this.#type |= READDIR_CALLED;
|
||
// mark all remaining provisional children as ENOENT
|
||
for (let p = children.provisional; p < children.length; p++) {
|
||
children[p].#markENOENT();
|
||
}
|
||
}
|
||
#markENOENT() {
|
||
// mark as UNKNOWN and ENOENT
|
||
if (this.#type & ENOENT)
|
||
return;
|
||
this.#type = (this.#type | ENOENT) & IFMT_UNKNOWN;
|
||
this.#markChildrenENOENT();
|
||
}
|
||
#markChildrenENOENT() {
|
||
// all children are provisional and do not exist
|
||
const children = this.children();
|
||
children.provisional = 0;
|
||
for (const p of children) {
|
||
p.#markENOENT();
|
||
}
|
||
}
|
||
#markENOREALPATH() {
|
||
this.#type |= ENOREALPATH;
|
||
this.#markENOTDIR();
|
||
}
|
||
// save the information when we know the entry is not a dir
|
||
#markENOTDIR() {
|
||
// entry is not a directory, so any children can't exist.
|
||
// this *should* be impossible, since any children created
|
||
// after it's been marked ENOTDIR should be marked ENOENT,
|
||
// so it won't even get to this point.
|
||
/* c8 ignore start */
|
||
if (this.#type & ENOTDIR)
|
||
return;
|
||
/* c8 ignore stop */
|
||
let t = this.#type;
|
||
// this could happen if we stat a dir, then delete it,
|
||
// then try to read it or one of its children.
|
||
if ((t & IFMT) === IFDIR)
|
||
t &= IFMT_UNKNOWN;
|
||
this.#type = t | ENOTDIR;
|
||
this.#markChildrenENOENT();
|
||
}
|
||
#readdirFail(code = '') {
|
||
// markENOTDIR and markENOENT also set provisional=0
|
||
if (code === 'ENOTDIR' || code === 'EPERM') {
|
||
this.#markENOTDIR();
|
||
}
|
||
else if (code === 'ENOENT') {
|
||
this.#markENOENT();
|
||
}
|
||
else {
|
||
this.children().provisional = 0;
|
||
}
|
||
}
|
||
#lstatFail(code = '') {
|
||
// Windows just raises ENOENT in this case, disable for win CI
|
||
/* c8 ignore start */
|
||
if (code === 'ENOTDIR') {
|
||
// already know it has a parent by this point
|
||
const p = this.parent;
|
||
p.#markENOTDIR();
|
||
}
|
||
else if (code === 'ENOENT') {
|
||
/* c8 ignore stop */
|
||
this.#markENOENT();
|
||
}
|
||
}
|
||
#readlinkFail(code = '') {
|
||
let ter = this.#type;
|
||
ter |= ENOREADLINK;
|
||
if (code === 'ENOENT')
|
||
ter |= ENOENT;
|
||
// windows gets a weird error when you try to readlink a file
|
||
if (code === 'EINVAL' || code === 'UNKNOWN') {
|
||
// exists, but not a symlink, we don't know WHAT it is, so remove
|
||
// all IFMT bits.
|
||
ter &= IFMT_UNKNOWN;
|
||
}
|
||
this.#type = ter;
|
||
// windows just gets ENOENT in this case. We do cover the case,
|
||
// just disabled because it's impossible on Windows CI
|
||
/* c8 ignore start */
|
||
if (code === 'ENOTDIR' && this.parent) {
|
||
this.parent.#markENOTDIR();
|
||
}
|
||
/* c8 ignore stop */
|
||
}
|
||
#readdirAddChild(e, c) {
|
||
return (this.#readdirMaybePromoteChild(e, c) ||
|
||
this.#readdirAddNewChild(e, c));
|
||
}
|
||
#readdirAddNewChild(e, c) {
|
||
// alloc new entry at head, so it's never provisional
|
||
const type = entToType(e);
|
||
const child = this.newChild(e.name, type, { parent: this });
|
||
const ifmt = child.#type & IFMT;
|
||
if (ifmt !== IFDIR && ifmt !== IFLNK && ifmt !== UNKNOWN) {
|
||
child.#type |= ENOTDIR;
|
||
}
|
||
c.unshift(child);
|
||
c.provisional++;
|
||
return child;
|
||
}
|
||
#readdirMaybePromoteChild(e, c) {
|
||
for (let p = c.provisional; p < c.length; p++) {
|
||
const pchild = c[p];
|
||
const name = this.nocase
|
||
? normalizeNocase(e.name)
|
||
: normalize$2(e.name);
|
||
if (name !== pchild.#matchName) {
|
||
continue;
|
||
}
|
||
return this.#readdirPromoteChild(e, pchild, p, c);
|
||
}
|
||
}
|
||
#readdirPromoteChild(e, p, index, c) {
|
||
const v = p.name;
|
||
// retain any other flags, but set ifmt from dirent
|
||
p.#type = (p.#type & IFMT_UNKNOWN) | entToType(e);
|
||
// case sensitivity fixing when we learn the true name.
|
||
if (v !== e.name)
|
||
p.name = e.name;
|
||
// just advance provisional index (potentially off the list),
|
||
// otherwise we have to splice/pop it out and re-insert at head
|
||
if (index !== c.provisional) {
|
||
if (index === c.length - 1)
|
||
c.pop();
|
||
else
|
||
c.splice(index, 1);
|
||
c.unshift(p);
|
||
}
|
||
c.provisional++;
|
||
return p;
|
||
}
|
||
/**
|
||
* Call lstat() on this Path, and update all known information that can be
|
||
* determined.
|
||
*
|
||
* Note that unlike `fs.lstat()`, the returned value does not contain some
|
||
* information, such as `mode`, `dev`, `nlink`, and `ino`. If that
|
||
* information is required, you will need to call `fs.lstat` yourself.
|
||
*
|
||
* If the Path refers to a nonexistent file, or if the lstat call fails for
|
||
* any reason, `undefined` is returned. Otherwise the updated Path object is
|
||
* returned.
|
||
*
|
||
* Results are cached, and thus may be out of date if the filesystem is
|
||
* mutated.
|
||
*/
|
||
async lstat() {
|
||
if ((this.#type & ENOENT) === 0) {
|
||
try {
|
||
this.#applyStat(await this.#fs.promises.lstat(this.fullpath()));
|
||
return this;
|
||
}
|
||
catch (er) {
|
||
this.#lstatFail(er.code);
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* synchronous {@link PathBase.lstat}
|
||
*/
|
||
lstatSync() {
|
||
if ((this.#type & ENOENT) === 0) {
|
||
try {
|
||
this.#applyStat(this.#fs.lstatSync(this.fullpath()));
|
||
return this;
|
||
}
|
||
catch (er) {
|
||
this.#lstatFail(er.code);
|
||
}
|
||
}
|
||
}
|
||
#applyStat(st) {
|
||
const { atime, atimeMs, birthtime, birthtimeMs, blksize, blocks, ctime, ctimeMs, dev, gid, ino, mode, mtime, mtimeMs, nlink, rdev, size, uid, } = st;
|
||
this.#atime = atime;
|
||
this.#atimeMs = atimeMs;
|
||
this.#birthtime = birthtime;
|
||
this.#birthtimeMs = birthtimeMs;
|
||
this.#blksize = blksize;
|
||
this.#blocks = blocks;
|
||
this.#ctime = ctime;
|
||
this.#ctimeMs = ctimeMs;
|
||
this.#dev = dev;
|
||
this.#gid = gid;
|
||
this.#ino = ino;
|
||
this.#mode = mode;
|
||
this.#mtime = mtime;
|
||
this.#mtimeMs = mtimeMs;
|
||
this.#nlink = nlink;
|
||
this.#rdev = rdev;
|
||
this.#size = size;
|
||
this.#uid = uid;
|
||
const ifmt = entToType(st);
|
||
// retain any other flags, but set the ifmt
|
||
this.#type = (this.#type & IFMT_UNKNOWN) | ifmt | LSTAT_CALLED;
|
||
if (ifmt !== UNKNOWN && ifmt !== IFDIR && ifmt !== IFLNK) {
|
||
this.#type |= ENOTDIR;
|
||
}
|
||
}
|
||
#onReaddirCB = [];
|
||
#readdirCBInFlight = false;
|
||
#callOnReaddirCB(children) {
|
||
this.#readdirCBInFlight = false;
|
||
const cbs = this.#onReaddirCB.slice();
|
||
this.#onReaddirCB.length = 0;
|
||
cbs.forEach(cb => cb(null, children));
|
||
}
|
||
/**
|
||
* Standard node-style callback interface to get list of directory entries.
|
||
*
|
||
* If the Path cannot or does not contain any children, then an empty array
|
||
* is returned.
|
||
*
|
||
* Results are cached, and thus may be out of date if the filesystem is
|
||
* mutated.
|
||
*
|
||
* @param cb The callback called with (er, entries). Note that the `er`
|
||
* param is somewhat extraneous, as all readdir() errors are handled and
|
||
* simply result in an empty set of entries being returned.
|
||
* @param allowZalgo Boolean indicating that immediately known results should
|
||
* *not* be deferred with `queueMicrotask`. Defaults to `false`. Release
|
||
* zalgo at your peril, the dark pony lord is devious and unforgiving.
|
||
*/
|
||
readdirCB(cb, allowZalgo = false) {
|
||
if (!this.canReaddir()) {
|
||
if (allowZalgo)
|
||
cb(null, []);
|
||
else
|
||
queueMicrotask(() => cb(null, []));
|
||
return;
|
||
}
|
||
const children = this.children();
|
||
if (this.calledReaddir()) {
|
||
const c = children.slice(0, children.provisional);
|
||
if (allowZalgo)
|
||
cb(null, c);
|
||
else
|
||
queueMicrotask(() => cb(null, c));
|
||
return;
|
||
}
|
||
// don't have to worry about zalgo at this point.
|
||
this.#onReaddirCB.push(cb);
|
||
if (this.#readdirCBInFlight) {
|
||
return;
|
||
}
|
||
this.#readdirCBInFlight = true;
|
||
// else read the directory, fill up children
|
||
// de-provisionalize any provisional children.
|
||
const fullpath = this.fullpath();
|
||
this.#fs.readdir(fullpath, { withFileTypes: true }, (er, entries) => {
|
||
if (er) {
|
||
this.#readdirFail(er.code);
|
||
children.provisional = 0;
|
||
}
|
||
else {
|
||
// if we didn't get an error, we always get entries.
|
||
//@ts-ignore
|
||
for (const e of entries) {
|
||
this.#readdirAddChild(e, children);
|
||
}
|
||
this.#readdirSuccess(children);
|
||
}
|
||
this.#callOnReaddirCB(children.slice(0, children.provisional));
|
||
return;
|
||
});
|
||
}
|
||
#asyncReaddirInFlight;
|
||
/**
|
||
* Return an array of known child entries.
|
||
*
|
||
* If the Path cannot or does not contain any children, then an empty array
|
||
* is returned.
|
||
*
|
||
* Results are cached, and thus may be out of date if the filesystem is
|
||
* mutated.
|
||
*/
|
||
async readdir() {
|
||
if (!this.canReaddir()) {
|
||
return [];
|
||
}
|
||
const children = this.children();
|
||
if (this.calledReaddir()) {
|
||
return children.slice(0, children.provisional);
|
||
}
|
||
// else read the directory, fill up children
|
||
// de-provisionalize any provisional children.
|
||
const fullpath = this.fullpath();
|
||
if (this.#asyncReaddirInFlight) {
|
||
await this.#asyncReaddirInFlight;
|
||
}
|
||
else {
|
||
/* c8 ignore start */
|
||
let resolve = () => { };
|
||
/* c8 ignore stop */
|
||
this.#asyncReaddirInFlight = new Promise(res => (resolve = res));
|
||
try {
|
||
for (const e of await this.#fs.promises.readdir(fullpath, {
|
||
withFileTypes: true,
|
||
})) {
|
||
this.#readdirAddChild(e, children);
|
||
}
|
||
this.#readdirSuccess(children);
|
||
}
|
||
catch (er) {
|
||
this.#readdirFail(er.code);
|
||
children.provisional = 0;
|
||
}
|
||
this.#asyncReaddirInFlight = undefined;
|
||
resolve();
|
||
}
|
||
return children.slice(0, children.provisional);
|
||
}
|
||
/**
|
||
* synchronous {@link PathBase.readdir}
|
||
*/
|
||
readdirSync() {
|
||
if (!this.canReaddir()) {
|
||
return [];
|
||
}
|
||
const children = this.children();
|
||
if (this.calledReaddir()) {
|
||
return children.slice(0, children.provisional);
|
||
}
|
||
// else read the directory, fill up children
|
||
// de-provisionalize any provisional children.
|
||
const fullpath = this.fullpath();
|
||
try {
|
||
for (const e of this.#fs.readdirSync(fullpath, {
|
||
withFileTypes: true,
|
||
})) {
|
||
this.#readdirAddChild(e, children);
|
||
}
|
||
this.#readdirSuccess(children);
|
||
}
|
||
catch (er) {
|
||
this.#readdirFail(er.code);
|
||
children.provisional = 0;
|
||
}
|
||
return children.slice(0, children.provisional);
|
||
}
|
||
canReaddir() {
|
||
if (this.#type & ENOCHILD)
|
||
return false;
|
||
const ifmt = IFMT & this.#type;
|
||
// we always set ENOTDIR when setting IFMT, so should be impossible
|
||
/* c8 ignore start */
|
||
if (!(ifmt === UNKNOWN || ifmt === IFDIR || ifmt === IFLNK)) {
|
||
return false;
|
||
}
|
||
/* c8 ignore stop */
|
||
return true;
|
||
}
|
||
shouldWalk(dirs, walkFilter) {
|
||
return ((this.#type & IFDIR) === IFDIR &&
|
||
!(this.#type & ENOCHILD) &&
|
||
!dirs.has(this) &&
|
||
(!walkFilter || walkFilter(this)));
|
||
}
|
||
/**
|
||
* Return the Path object corresponding to path as resolved
|
||
* by realpath(3).
|
||
*
|
||
* If the realpath call fails for any reason, `undefined` is returned.
|
||
*
|
||
* Result is cached, and thus may be outdated if the filesystem is mutated.
|
||
* On success, returns a Path object.
|
||
*/
|
||
async realpath() {
|
||
if (this.#realpath)
|
||
return this.#realpath;
|
||
if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type)
|
||
return undefined;
|
||
try {
|
||
const rp = await this.#fs.promises.realpath(this.fullpath());
|
||
return (this.#realpath = this.resolve(rp));
|
||
}
|
||
catch (_) {
|
||
this.#markENOREALPATH();
|
||
}
|
||
}
|
||
/**
|
||
* Synchronous {@link realpath}
|
||
*/
|
||
realpathSync() {
|
||
if (this.#realpath)
|
||
return this.#realpath;
|
||
if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type)
|
||
return undefined;
|
||
try {
|
||
const rp = this.#fs.realpathSync(this.fullpath());
|
||
return (this.#realpath = this.resolve(rp));
|
||
}
|
||
catch (_) {
|
||
this.#markENOREALPATH();
|
||
}
|
||
}
|
||
/**
|
||
* Internal method to mark this Path object as the scurry cwd,
|
||
* called by {@link PathScurry#chdir}
|
||
*
|
||
* @internal
|
||
*/
|
||
[setAsCwd](oldCwd) {
|
||
if (oldCwd === this)
|
||
return;
|
||
const changed = new Set([]);
|
||
let rp = [];
|
||
let p = this;
|
||
while (p && p.parent) {
|
||
changed.add(p);
|
||
p.#relative = rp.join(this.sep);
|
||
p.#relativePosix = rp.join('/');
|
||
p = p.parent;
|
||
rp.push('..');
|
||
}
|
||
// now un-memoize parents of old cwd
|
||
p = oldCwd;
|
||
while (p && p.parent && !changed.has(p)) {
|
||
p.#relative = undefined;
|
||
p.#relativePosix = undefined;
|
||
p = p.parent;
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Path class used on win32 systems
|
||
*
|
||
* Uses `'\\'` as the path separator for returned paths, either `'\\'` or `'/'`
|
||
* as the path separator for parsing paths.
|
||
*/
|
||
class PathWin32 extends PathBase {
|
||
/**
|
||
* Separator for generating path strings.
|
||
*/
|
||
sep = '\\';
|
||
/**
|
||
* Separator for parsing path strings.
|
||
*/
|
||
splitSep = eitherSep;
|
||
/**
|
||
* Do not create new Path objects directly. They should always be accessed
|
||
* via the PathScurry class or other methods on the Path class.
|
||
*
|
||
* @internal
|
||
*/
|
||
constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
|
||
super(name, type, root, roots, nocase, children, opts);
|
||
}
|
||
/**
|
||
* @internal
|
||
*/
|
||
newChild(name, type = UNKNOWN, opts = {}) {
|
||
return new PathWin32(name, type, this.root, this.roots, this.nocase, this.childrenCache(), opts);
|
||
}
|
||
/**
|
||
* @internal
|
||
*/
|
||
getRootString(path) {
|
||
return win32.parse(path).root;
|
||
}
|
||
/**
|
||
* @internal
|
||
*/
|
||
getRoot(rootPath) {
|
||
rootPath = uncToDrive(rootPath.toUpperCase());
|
||
if (rootPath === this.root.name) {
|
||
return this.root;
|
||
}
|
||
// ok, not that one, check if it matches another we know about
|
||
for (const [compare, root] of Object.entries(this.roots)) {
|
||
if (this.sameRoot(rootPath, compare)) {
|
||
return (this.roots[rootPath] = root);
|
||
}
|
||
}
|
||
// otherwise, have to create a new one.
|
||
return (this.roots[rootPath] = new PathScurryWin32(rootPath, this).root);
|
||
}
|
||
/**
|
||
* @internal
|
||
*/
|
||
sameRoot(rootPath, compare = this.root.name) {
|
||
// windows can (rarely) have case-sensitive filesystem, but
|
||
// UNC and drive letters are always case-insensitive, and canonically
|
||
// represented uppercase.
|
||
rootPath = rootPath
|
||
.toUpperCase()
|
||
.replace(/\//g, '\\')
|
||
.replace(uncDriveRegexp, '$1\\');
|
||
return rootPath === compare;
|
||
}
|
||
}
|
||
/**
|
||
* Path class used on all posix systems.
|
||
*
|
||
* Uses `'/'` as the path separator.
|
||
*/
|
||
class PathPosix extends PathBase {
|
||
/**
|
||
* separator for parsing path strings
|
||
*/
|
||
splitSep = '/';
|
||
/**
|
||
* separator for generating path strings
|
||
*/
|
||
sep = '/';
|
||
/**
|
||
* Do not create new Path objects directly. They should always be accessed
|
||
* via the PathScurry class or other methods on the Path class.
|
||
*
|
||
* @internal
|
||
*/
|
||
constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
|
||
super(name, type, root, roots, nocase, children, opts);
|
||
}
|
||
/**
|
||
* @internal
|
||
*/
|
||
getRootString(path) {
|
||
return path.startsWith('/') ? '/' : '';
|
||
}
|
||
/**
|
||
* @internal
|
||
*/
|
||
getRoot(_rootPath) {
|
||
return this.root;
|
||
}
|
||
/**
|
||
* @internal
|
||
*/
|
||
newChild(name, type = UNKNOWN, opts = {}) {
|
||
return new PathPosix(name, type, this.root, this.roots, this.nocase, this.childrenCache(), opts);
|
||
}
|
||
}
|
||
/**
|
||
* The base class for all PathScurry classes, providing the interface for path
|
||
* resolution and filesystem operations.
|
||
*
|
||
* Typically, you should *not* instantiate this class directly, but rather one
|
||
* of the platform-specific classes, or the exported {@link PathScurry} which
|
||
* defaults to the current platform.
|
||
*/
|
||
class PathScurryBase {
|
||
/**
|
||
* The root Path entry for the current working directory of this Scurry
|
||
*/
|
||
root;
|
||
/**
|
||
* The string path for the root of this Scurry's current working directory
|
||
*/
|
||
rootPath;
|
||
/**
|
||
* A collection of all roots encountered, referenced by rootPath
|
||
*/
|
||
roots;
|
||
/**
|
||
* The Path entry corresponding to this PathScurry's current working directory.
|
||
*/
|
||
cwd;
|
||
#resolveCache;
|
||
#resolvePosixCache;
|
||
#children;
|
||
/**
|
||
* Perform path comparisons case-insensitively.
|
||
*
|
||
* Defaults true on Darwin and Windows systems, false elsewhere.
|
||
*/
|
||
nocase;
|
||
#fs;
|
||
/**
|
||
* This class should not be instantiated directly.
|
||
*
|
||
* Use PathScurryWin32, PathScurryDarwin, PathScurryPosix, or PathScurry
|
||
*
|
||
* @internal
|
||
*/
|
||
constructor(cwd = process.cwd(), pathImpl, sep, { nocase, childrenCacheSize = 16 * 1024, fs = defaultFS, } = {}) {
|
||
this.#fs = fsFromOption(fs);
|
||
if (cwd instanceof URL || cwd.startsWith('file://')) {
|
||
cwd = fileURLToPath$1(cwd);
|
||
}
|
||
// resolve and split root, and then add to the store.
|
||
// this is the only time we call path.resolve()
|
||
const cwdPath = pathImpl.resolve(cwd);
|
||
this.roots = Object.create(null);
|
||
this.rootPath = this.parseRootPath(cwdPath);
|
||
this.#resolveCache = new ResolveCache();
|
||
this.#resolvePosixCache = new ResolveCache();
|
||
this.#children = new ChildrenCache(childrenCacheSize);
|
||
const split = cwdPath.substring(this.rootPath.length).split(sep);
|
||
// resolve('/') leaves '', splits to [''], we don't want that.
|
||
if (split.length === 1 && !split[0]) {
|
||
split.pop();
|
||
}
|
||
/* c8 ignore start */
|
||
if (nocase === undefined) {
|
||
throw new TypeError('must provide nocase setting to PathScurryBase ctor');
|
||
}
|
||
/* c8 ignore stop */
|
||
this.nocase = nocase;
|
||
this.root = this.newRoot(this.#fs);
|
||
this.roots[this.rootPath] = this.root;
|
||
let prev = this.root;
|
||
let len = split.length - 1;
|
||
const joinSep = pathImpl.sep;
|
||
let abs = this.rootPath;
|
||
let sawFirst = false;
|
||
for (const part of split) {
|
||
const l = len--;
|
||
prev = prev.child(part, {
|
||
relative: new Array(l).fill('..').join(joinSep),
|
||
relativePosix: new Array(l).fill('..').join('/'),
|
||
fullpath: (abs += (sawFirst ? '' : joinSep) + part),
|
||
});
|
||
sawFirst = true;
|
||
}
|
||
this.cwd = prev;
|
||
}
|
||
/**
|
||
* Get the depth of a provided path, string, or the cwd
|
||
*/
|
||
depth(path = this.cwd) {
|
||
if (typeof path === 'string') {
|
||
path = this.cwd.resolve(path);
|
||
}
|
||
return path.depth();
|
||
}
|
||
/**
|
||
* Return the cache of child entries. Exposed so subclasses can create
|
||
* child Path objects in a platform-specific way.
|
||
*
|
||
* @internal
|
||
*/
|
||
childrenCache() {
|
||
return this.#children;
|
||
}
|
||
/**
|
||
* Resolve one or more path strings to a resolved string
|
||
*
|
||
* Same interface as require('path').resolve.
|
||
*
|
||
* Much faster than path.resolve() when called multiple times for the same
|
||
* path, because the resolved Path objects are cached. Much slower
|
||
* otherwise.
|
||
*/
|
||
resolve(...paths) {
|
||
// first figure out the minimum number of paths we have to test
|
||
// we always start at cwd, but any absolutes will bump the start
|
||
let r = '';
|
||
for (let i = paths.length - 1; i >= 0; i--) {
|
||
const p = paths[i];
|
||
if (!p || p === '.')
|
||
continue;
|
||
r = r ? `${p}/${r}` : p;
|
||
if (this.isAbsolute(p)) {
|
||
break;
|
||
}
|
||
}
|
||
const cached = this.#resolveCache.get(r);
|
||
if (cached !== undefined) {
|
||
return cached;
|
||
}
|
||
const result = this.cwd.resolve(r).fullpath();
|
||
this.#resolveCache.set(r, result);
|
||
return result;
|
||
}
|
||
/**
|
||
* Resolve one or more path strings to a resolved string, returning
|
||
* the posix path. Identical to .resolve() on posix systems, but on
|
||
* windows will return a forward-slash separated UNC path.
|
||
*
|
||
* Same interface as require('path').resolve.
|
||
*
|
||
* Much faster than path.resolve() when called multiple times for the same
|
||
* path, because the resolved Path objects are cached. Much slower
|
||
* otherwise.
|
||
*/
|
||
resolvePosix(...paths) {
|
||
// first figure out the minimum number of paths we have to test
|
||
// we always start at cwd, but any absolutes will bump the start
|
||
let r = '';
|
||
for (let i = paths.length - 1; i >= 0; i--) {
|
||
const p = paths[i];
|
||
if (!p || p === '.')
|
||
continue;
|
||
r = r ? `${p}/${r}` : p;
|
||
if (this.isAbsolute(p)) {
|
||
break;
|
||
}
|
||
}
|
||
const cached = this.#resolvePosixCache.get(r);
|
||
if (cached !== undefined) {
|
||
return cached;
|
||
}
|
||
const result = this.cwd.resolve(r).fullpathPosix();
|
||
this.#resolvePosixCache.set(r, result);
|
||
return result;
|
||
}
|
||
/**
|
||
* find the relative path from the cwd to the supplied path string or entry
|
||
*/
|
||
relative(entry = this.cwd) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
return entry.relative();
|
||
}
|
||
/**
|
||
* find the relative path from the cwd to the supplied path string or
|
||
* entry, using / as the path delimiter, even on Windows.
|
||
*/
|
||
relativePosix(entry = this.cwd) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
return entry.relativePosix();
|
||
}
|
||
/**
|
||
* Return the basename for the provided string or Path object
|
||
*/
|
||
basename(entry = this.cwd) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
return entry.name;
|
||
}
|
||
/**
|
||
* Return the dirname for the provided string or Path object
|
||
*/
|
||
dirname(entry = this.cwd) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
return (entry.parent || entry).fullpath();
|
||
}
|
||
async readdir(entry = this.cwd, opts = {
|
||
withFileTypes: true,
|
||
}) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
else if (!(entry instanceof PathBase)) {
|
||
opts = entry;
|
||
entry = this.cwd;
|
||
}
|
||
const { withFileTypes } = opts;
|
||
if (!entry.canReaddir()) {
|
||
return [];
|
||
}
|
||
else {
|
||
const p = await entry.readdir();
|
||
return withFileTypes ? p : p.map(e => e.name);
|
||
}
|
||
}
|
||
readdirSync(entry = this.cwd, opts = {
|
||
withFileTypes: true,
|
||
}) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
else if (!(entry instanceof PathBase)) {
|
||
opts = entry;
|
||
entry = this.cwd;
|
||
}
|
||
const { withFileTypes = true } = opts;
|
||
if (!entry.canReaddir()) {
|
||
return [];
|
||
}
|
||
else if (withFileTypes) {
|
||
return entry.readdirSync();
|
||
}
|
||
else {
|
||
return entry.readdirSync().map(e => e.name);
|
||
}
|
||
}
|
||
/**
|
||
* Call lstat() on the string or Path object, and update all known
|
||
* information that can be determined.
|
||
*
|
||
* Note that unlike `fs.lstat()`, the returned value does not contain some
|
||
* information, such as `mode`, `dev`, `nlink`, and `ino`. If that
|
||
* information is required, you will need to call `fs.lstat` yourself.
|
||
*
|
||
* If the Path refers to a nonexistent file, or if the lstat call fails for
|
||
* any reason, `undefined` is returned. Otherwise the updated Path object is
|
||
* returned.
|
||
*
|
||
* Results are cached, and thus may be out of date if the filesystem is
|
||
* mutated.
|
||
*/
|
||
async lstat(entry = this.cwd) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
return entry.lstat();
|
||
}
|
||
/**
|
||
* synchronous {@link PathScurryBase.lstat}
|
||
*/
|
||
lstatSync(entry = this.cwd) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
return entry.lstatSync();
|
||
}
|
||
async readlink(entry = this.cwd, { withFileTypes } = {
|
||
withFileTypes: false,
|
||
}) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
else if (!(entry instanceof PathBase)) {
|
||
withFileTypes = entry.withFileTypes;
|
||
entry = this.cwd;
|
||
}
|
||
const e = await entry.readlink();
|
||
return withFileTypes ? e : e?.fullpath();
|
||
}
|
||
readlinkSync(entry = this.cwd, { withFileTypes } = {
|
||
withFileTypes: false,
|
||
}) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
else if (!(entry instanceof PathBase)) {
|
||
withFileTypes = entry.withFileTypes;
|
||
entry = this.cwd;
|
||
}
|
||
const e = entry.readlinkSync();
|
||
return withFileTypes ? e : e?.fullpath();
|
||
}
|
||
async realpath(entry = this.cwd, { withFileTypes } = {
|
||
withFileTypes: false,
|
||
}) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
else if (!(entry instanceof PathBase)) {
|
||
withFileTypes = entry.withFileTypes;
|
||
entry = this.cwd;
|
||
}
|
||
const e = await entry.realpath();
|
||
return withFileTypes ? e : e?.fullpath();
|
||
}
|
||
realpathSync(entry = this.cwd, { withFileTypes } = {
|
||
withFileTypes: false,
|
||
}) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
else if (!(entry instanceof PathBase)) {
|
||
withFileTypes = entry.withFileTypes;
|
||
entry = this.cwd;
|
||
}
|
||
const e = entry.realpathSync();
|
||
return withFileTypes ? e : e?.fullpath();
|
||
}
|
||
async walk(entry = this.cwd, opts = {}) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
else if (!(entry instanceof PathBase)) {
|
||
opts = entry;
|
||
entry = this.cwd;
|
||
}
|
||
const { withFileTypes = true, follow = false, filter, walkFilter, } = opts;
|
||
const results = [];
|
||
if (!filter || filter(entry)) {
|
||
results.push(withFileTypes ? entry : entry.fullpath());
|
||
}
|
||
const dirs = new Set();
|
||
const walk = (dir, cb) => {
|
||
dirs.add(dir);
|
||
dir.readdirCB((er, entries) => {
|
||
/* c8 ignore start */
|
||
if (er) {
|
||
return cb(er);
|
||
}
|
||
/* c8 ignore stop */
|
||
let len = entries.length;
|
||
if (!len)
|
||
return cb();
|
||
const next = () => {
|
||
if (--len === 0) {
|
||
cb();
|
||
}
|
||
};
|
||
for (const e of entries) {
|
||
if (!filter || filter(e)) {
|
||
results.push(withFileTypes ? e : e.fullpath());
|
||
}
|
||
if (follow && e.isSymbolicLink()) {
|
||
e.realpath()
|
||
.then(r => (r?.isUnknown() ? r.lstat() : r))
|
||
.then(r => r?.shouldWalk(dirs, walkFilter) ? walk(r, next) : next());
|
||
}
|
||
else {
|
||
if (e.shouldWalk(dirs, walkFilter)) {
|
||
walk(e, next);
|
||
}
|
||
else {
|
||
next();
|
||
}
|
||
}
|
||
}
|
||
}, true); // zalgooooooo
|
||
};
|
||
const start = entry;
|
||
return new Promise((res, rej) => {
|
||
walk(start, er => {
|
||
/* c8 ignore start */
|
||
if (er)
|
||
return rej(er);
|
||
/* c8 ignore stop */
|
||
res(results);
|
||
});
|
||
});
|
||
}
|
||
walkSync(entry = this.cwd, opts = {}) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
else if (!(entry instanceof PathBase)) {
|
||
opts = entry;
|
||
entry = this.cwd;
|
||
}
|
||
const { withFileTypes = true, follow = false, filter, walkFilter, } = opts;
|
||
const results = [];
|
||
if (!filter || filter(entry)) {
|
||
results.push(withFileTypes ? entry : entry.fullpath());
|
||
}
|
||
const dirs = new Set([entry]);
|
||
for (const dir of dirs) {
|
||
const entries = dir.readdirSync();
|
||
for (const e of entries) {
|
||
if (!filter || filter(e)) {
|
||
results.push(withFileTypes ? e : e.fullpath());
|
||
}
|
||
let r = e;
|
||
if (e.isSymbolicLink()) {
|
||
if (!(follow && (r = e.realpathSync())))
|
||
continue;
|
||
if (r.isUnknown())
|
||
r.lstatSync();
|
||
}
|
||
if (r.shouldWalk(dirs, walkFilter)) {
|
||
dirs.add(r);
|
||
}
|
||
}
|
||
}
|
||
return results;
|
||
}
|
||
/**
|
||
* Support for `for await`
|
||
*
|
||
* Alias for {@link PathScurryBase.iterate}
|
||
*
|
||
* Note: As of Node 19, this is very slow, compared to other methods of
|
||
* walking. Consider using {@link PathScurryBase.stream} if memory overhead
|
||
* and backpressure are concerns, or {@link PathScurryBase.walk} if not.
|
||
*/
|
||
[Symbol.asyncIterator]() {
|
||
return this.iterate();
|
||
}
|
||
iterate(entry = this.cwd, options = {}) {
|
||
// iterating async over the stream is significantly more performant,
|
||
// especially in the warm-cache scenario, because it buffers up directory
|
||
// entries in the background instead of waiting for a yield for each one.
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
else if (!(entry instanceof PathBase)) {
|
||
options = entry;
|
||
entry = this.cwd;
|
||
}
|
||
return this.stream(entry, options)[Symbol.asyncIterator]();
|
||
}
|
||
/**
|
||
* Iterating over a PathScurry performs a synchronous walk.
|
||
*
|
||
* Alias for {@link PathScurryBase.iterateSync}
|
||
*/
|
||
[Symbol.iterator]() {
|
||
return this.iterateSync();
|
||
}
|
||
*iterateSync(entry = this.cwd, opts = {}) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
else if (!(entry instanceof PathBase)) {
|
||
opts = entry;
|
||
entry = this.cwd;
|
||
}
|
||
const { withFileTypes = true, follow = false, filter, walkFilter, } = opts;
|
||
if (!filter || filter(entry)) {
|
||
yield withFileTypes ? entry : entry.fullpath();
|
||
}
|
||
const dirs = new Set([entry]);
|
||
for (const dir of dirs) {
|
||
const entries = dir.readdirSync();
|
||
for (const e of entries) {
|
||
if (!filter || filter(e)) {
|
||
yield withFileTypes ? e : e.fullpath();
|
||
}
|
||
let r = e;
|
||
if (e.isSymbolicLink()) {
|
||
if (!(follow && (r = e.realpathSync())))
|
||
continue;
|
||
if (r.isUnknown())
|
||
r.lstatSync();
|
||
}
|
||
if (r.shouldWalk(dirs, walkFilter)) {
|
||
dirs.add(r);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
stream(entry = this.cwd, opts = {}) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
else if (!(entry instanceof PathBase)) {
|
||
opts = entry;
|
||
entry = this.cwd;
|
||
}
|
||
const { withFileTypes = true, follow = false, filter, walkFilter, } = opts;
|
||
const results = new Minipass({ objectMode: true });
|
||
if (!filter || filter(entry)) {
|
||
results.write(withFileTypes ? entry : entry.fullpath());
|
||
}
|
||
const dirs = new Set();
|
||
const queue = [entry];
|
||
let processing = 0;
|
||
const process = () => {
|
||
let paused = false;
|
||
while (!paused) {
|
||
const dir = queue.shift();
|
||
if (!dir) {
|
||
if (processing === 0)
|
||
results.end();
|
||
return;
|
||
}
|
||
processing++;
|
||
dirs.add(dir);
|
||
const onReaddir = (er, entries, didRealpaths = false) => {
|
||
/* c8 ignore start */
|
||
if (er)
|
||
return results.emit('error', er);
|
||
/* c8 ignore stop */
|
||
if (follow && !didRealpaths) {
|
||
const promises = [];
|
||
for (const e of entries) {
|
||
if (e.isSymbolicLink()) {
|
||
promises.push(e
|
||
.realpath()
|
||
.then((r) => r?.isUnknown() ? r.lstat() : r));
|
||
}
|
||
}
|
||
if (promises.length) {
|
||
Promise.all(promises).then(() => onReaddir(null, entries, true));
|
||
return;
|
||
}
|
||
}
|
||
for (const e of entries) {
|
||
if (e && (!filter || filter(e))) {
|
||
if (!results.write(withFileTypes ? e : e.fullpath())) {
|
||
paused = true;
|
||
}
|
||
}
|
||
}
|
||
processing--;
|
||
for (const e of entries) {
|
||
const r = e.realpathCached() || e;
|
||
if (r.shouldWalk(dirs, walkFilter)) {
|
||
queue.push(r);
|
||
}
|
||
}
|
||
if (paused && !results.flowing) {
|
||
results.once('drain', process);
|
||
}
|
||
else if (!sync) {
|
||
process();
|
||
}
|
||
};
|
||
// zalgo containment
|
||
let sync = true;
|
||
dir.readdirCB(onReaddir, true);
|
||
sync = false;
|
||
}
|
||
};
|
||
process();
|
||
return results;
|
||
}
|
||
streamSync(entry = this.cwd, opts = {}) {
|
||
if (typeof entry === 'string') {
|
||
entry = this.cwd.resolve(entry);
|
||
}
|
||
else if (!(entry instanceof PathBase)) {
|
||
opts = entry;
|
||
entry = this.cwd;
|
||
}
|
||
const { withFileTypes = true, follow = false, filter, walkFilter, } = opts;
|
||
const results = new Minipass({ objectMode: true });
|
||
const dirs = new Set();
|
||
if (!filter || filter(entry)) {
|
||
results.write(withFileTypes ? entry : entry.fullpath());
|
||
}
|
||
const queue = [entry];
|
||
let processing = 0;
|
||
const process = () => {
|
||
let paused = false;
|
||
while (!paused) {
|
||
const dir = queue.shift();
|
||
if (!dir) {
|
||
if (processing === 0)
|
||
results.end();
|
||
return;
|
||
}
|
||
processing++;
|
||
dirs.add(dir);
|
||
const entries = dir.readdirSync();
|
||
for (const e of entries) {
|
||
if (!filter || filter(e)) {
|
||
if (!results.write(withFileTypes ? e : e.fullpath())) {
|
||
paused = true;
|
||
}
|
||
}
|
||
}
|
||
processing--;
|
||
for (const e of entries) {
|
||
let r = e;
|
||
if (e.isSymbolicLink()) {
|
||
if (!(follow && (r = e.realpathSync())))
|
||
continue;
|
||
if (r.isUnknown())
|
||
r.lstatSync();
|
||
}
|
||
if (r.shouldWalk(dirs, walkFilter)) {
|
||
queue.push(r);
|
||
}
|
||
}
|
||
}
|
||
if (paused && !results.flowing)
|
||
results.once('drain', process);
|
||
};
|
||
process();
|
||
return results;
|
||
}
|
||
chdir(path = this.cwd) {
|
||
const oldCwd = this.cwd;
|
||
this.cwd = typeof path === 'string' ? this.cwd.resolve(path) : path;
|
||
this.cwd[setAsCwd](oldCwd);
|
||
}
|
||
}
|
||
/**
|
||
* Windows implementation of {@link PathScurryBase}
|
||
*
|
||
* Defaults to case insensitve, uses `'\\'` to generate path strings. Uses
|
||
* {@link PathWin32} for Path objects.
|
||
*/
|
||
class PathScurryWin32 extends PathScurryBase {
|
||
/**
|
||
* separator for generating path strings
|
||
*/
|
||
sep = '\\';
|
||
constructor(cwd = process.cwd(), opts = {}) {
|
||
const { nocase = true } = opts;
|
||
super(cwd, win32, '\\', { ...opts, nocase });
|
||
this.nocase = nocase;
|
||
for (let p = this.cwd; p; p = p.parent) {
|
||
p.nocase = this.nocase;
|
||
}
|
||
}
|
||
/**
|
||
* @internal
|
||
*/
|
||
parseRootPath(dir) {
|
||
// if the path starts with a single separator, it's not a UNC, and we'll
|
||
// just get separator as the root, and driveFromUNC will return \
|
||
// In that case, mount \ on the root from the cwd.
|
||
return win32.parse(dir).root.toUpperCase();
|
||
}
|
||
/**
|
||
* @internal
|
||
*/
|
||
newRoot(fs) {
|
||
return new PathWin32(this.rootPath, IFDIR, undefined, this.roots, this.nocase, this.childrenCache(), { fs });
|
||
}
|
||
/**
|
||
* Return true if the provided path string is an absolute path
|
||
*/
|
||
isAbsolute(p) {
|
||
return (p.startsWith('/') || p.startsWith('\\') || /^[a-z]:(\/|\\)/i.test(p));
|
||
}
|
||
}
|
||
/**
|
||
* {@link PathScurryBase} implementation for all posix systems other than Darwin.
|
||
*
|
||
* Defaults to case-sensitive matching, uses `'/'` to generate path strings.
|
||
*
|
||
* Uses {@link PathPosix} for Path objects.
|
||
*/
|
||
class PathScurryPosix extends PathScurryBase {
|
||
/**
|
||
* separator for generating path strings
|
||
*/
|
||
sep = '/';
|
||
constructor(cwd = process.cwd(), opts = {}) {
|
||
const { nocase = false } = opts;
|
||
super(cwd, posix$1, '/', { ...opts, nocase });
|
||
this.nocase = nocase;
|
||
}
|
||
/**
|
||
* @internal
|
||
*/
|
||
parseRootPath(_dir) {
|
||
return '/';
|
||
}
|
||
/**
|
||
* @internal
|
||
*/
|
||
newRoot(fs) {
|
||
return new PathPosix(this.rootPath, IFDIR, undefined, this.roots, this.nocase, this.childrenCache(), { fs });
|
||
}
|
||
/**
|
||
* Return true if the provided path string is an absolute path
|
||
*/
|
||
isAbsolute(p) {
|
||
return p.startsWith('/');
|
||
}
|
||
}
|
||
/**
|
||
* {@link PathScurryBase} implementation for Darwin (macOS) systems.
|
||
*
|
||
* Defaults to case-insensitive matching, uses `'/'` for generating path
|
||
* strings.
|
||
*
|
||
* Uses {@link PathPosix} for Path objects.
|
||
*/
|
||
class PathScurryDarwin extends PathScurryPosix {
|
||
constructor(cwd = process.cwd(), opts = {}) {
|
||
const { nocase = true } = opts;
|
||
super(cwd, { ...opts, nocase });
|
||
}
|
||
}
|
||
/**
|
||
* Default {@link PathBase} implementation for the current platform.
|
||
*
|
||
* {@link PathWin32} on Windows systems, {@link PathPosix} on all others.
|
||
*/
|
||
process.platform === 'win32' ? PathWin32 : PathPosix;
|
||
/**
|
||
* Default {@link PathScurryBase} implementation for the current platform.
|
||
*
|
||
* {@link PathScurryWin32} on Windows systems, {@link PathScurryDarwin} on
|
||
* Darwin (macOS) systems, {@link PathScurryPosix} on all others.
|
||
*/
|
||
const PathScurry = process.platform === 'win32'
|
||
? PathScurryWin32
|
||
: process.platform === 'darwin'
|
||
? PathScurryDarwin
|
||
: PathScurryPosix;
|
||
|
||
// this is just a very light wrapper around 2 arrays with an offset index
|
||
const isPatternList = (pl) => pl.length >= 1;
|
||
const isGlobList = (gl) => gl.length >= 1;
|
||
/**
|
||
* An immutable-ish view on an array of glob parts and their parsed
|
||
* results
|
||
*/
|
||
class Pattern {
|
||
#patternList;
|
||
#globList;
|
||
#index;
|
||
length;
|
||
#platform;
|
||
#rest;
|
||
#globString;
|
||
#isDrive;
|
||
#isUNC;
|
||
#isAbsolute;
|
||
#followGlobstar = true;
|
||
constructor(patternList, globList, index, platform) {
|
||
if (!isPatternList(patternList)) {
|
||
throw new TypeError('empty pattern list');
|
||
}
|
||
if (!isGlobList(globList)) {
|
||
throw new TypeError('empty glob list');
|
||
}
|
||
if (globList.length !== patternList.length) {
|
||
throw new TypeError('mismatched pattern list and glob list lengths');
|
||
}
|
||
this.length = patternList.length;
|
||
if (index < 0 || index >= this.length) {
|
||
throw new TypeError('index out of range');
|
||
}
|
||
this.#patternList = patternList;
|
||
this.#globList = globList;
|
||
this.#index = index;
|
||
this.#platform = platform;
|
||
// normalize root entries of absolute patterns on initial creation.
|
||
if (this.#index === 0) {
|
||
// c: => ['c:/']
|
||
// C:/ => ['C:/']
|
||
// C:/x => ['C:/', 'x']
|
||
// //host/share => ['//host/share/']
|
||
// //host/share/ => ['//host/share/']
|
||
// //host/share/x => ['//host/share/', 'x']
|
||
// /etc => ['/', 'etc']
|
||
// / => ['/']
|
||
if (this.isUNC()) {
|
||
// '' / '' / 'host' / 'share'
|
||
const [p0, p1, p2, p3, ...prest] = this.#patternList;
|
||
const [g0, g1, g2, g3, ...grest] = this.#globList;
|
||
if (prest[0] === '') {
|
||
// ends in /
|
||
prest.shift();
|
||
grest.shift();
|
||
}
|
||
const p = [p0, p1, p2, p3, ''].join('/');
|
||
const g = [g0, g1, g2, g3, ''].join('/');
|
||
this.#patternList = [p, ...prest];
|
||
this.#globList = [g, ...grest];
|
||
this.length = this.#patternList.length;
|
||
}
|
||
else if (this.isDrive() || this.isAbsolute()) {
|
||
const [p1, ...prest] = this.#patternList;
|
||
const [g1, ...grest] = this.#globList;
|
||
if (prest[0] === '') {
|
||
// ends in /
|
||
prest.shift();
|
||
grest.shift();
|
||
}
|
||
const p = p1 + '/';
|
||
const g = g1 + '/';
|
||
this.#patternList = [p, ...prest];
|
||
this.#globList = [g, ...grest];
|
||
this.length = this.#patternList.length;
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* The first entry in the parsed list of patterns
|
||
*/
|
||
pattern() {
|
||
return this.#patternList[this.#index];
|
||
}
|
||
/**
|
||
* true of if pattern() returns a string
|
||
*/
|
||
isString() {
|
||
return typeof this.#patternList[this.#index] === 'string';
|
||
}
|
||
/**
|
||
* true of if pattern() returns GLOBSTAR
|
||
*/
|
||
isGlobstar() {
|
||
return this.#patternList[this.#index] === GLOBSTAR$1;
|
||
}
|
||
/**
|
||
* true if pattern() returns a regexp
|
||
*/
|
||
isRegExp() {
|
||
return this.#patternList[this.#index] instanceof RegExp;
|
||
}
|
||
/**
|
||
* The /-joined set of glob parts that make up this pattern
|
||
*/
|
||
globString() {
|
||
return (this.#globString =
|
||
this.#globString ||
|
||
(this.#index === 0
|
||
? this.isAbsolute()
|
||
? this.#globList[0] + this.#globList.slice(1).join('/')
|
||
: this.#globList.join('/')
|
||
: this.#globList.slice(this.#index).join('/')));
|
||
}
|
||
/**
|
||
* true if there are more pattern parts after this one
|
||
*/
|
||
hasMore() {
|
||
return this.length > this.#index + 1;
|
||
}
|
||
/**
|
||
* The rest of the pattern after this part, or null if this is the end
|
||
*/
|
||
rest() {
|
||
if (this.#rest !== undefined)
|
||
return this.#rest;
|
||
if (!this.hasMore())
|
||
return (this.#rest = null);
|
||
this.#rest = new Pattern(this.#patternList, this.#globList, this.#index + 1, this.#platform);
|
||
this.#rest.#isAbsolute = this.#isAbsolute;
|
||
this.#rest.#isUNC = this.#isUNC;
|
||
this.#rest.#isDrive = this.#isDrive;
|
||
return this.#rest;
|
||
}
|
||
/**
|
||
* true if the pattern represents a //unc/path/ on windows
|
||
*/
|
||
isUNC() {
|
||
const pl = this.#patternList;
|
||
return this.#isUNC !== undefined
|
||
? this.#isUNC
|
||
: (this.#isUNC =
|
||
this.#platform === 'win32' &&
|
||
this.#index === 0 &&
|
||
pl[0] === '' &&
|
||
pl[1] === '' &&
|
||
typeof pl[2] === 'string' &&
|
||
!!pl[2] &&
|
||
typeof pl[3] === 'string' &&
|
||
!!pl[3]);
|
||
}
|
||
// pattern like C:/...
|
||
// split = ['C:', ...]
|
||
// XXX: would be nice to handle patterns like `c:*` to test the cwd
|
||
// in c: for *, but I don't know of a way to even figure out what that
|
||
// cwd is without actually chdir'ing into it?
|
||
/**
|
||
* True if the pattern starts with a drive letter on Windows
|
||
*/
|
||
isDrive() {
|
||
const pl = this.#patternList;
|
||
return this.#isDrive !== undefined
|
||
? this.#isDrive
|
||
: (this.#isDrive =
|
||
this.#platform === 'win32' &&
|
||
this.#index === 0 &&
|
||
this.length > 1 &&
|
||
typeof pl[0] === 'string' &&
|
||
/^[a-z]:$/i.test(pl[0]));
|
||
}
|
||
// pattern = '/' or '/...' or '/x/...'
|
||
// split = ['', ''] or ['', ...] or ['', 'x', ...]
|
||
// Drive and UNC both considered absolute on windows
|
||
/**
|
||
* True if the pattern is rooted on an absolute path
|
||
*/
|
||
isAbsolute() {
|
||
const pl = this.#patternList;
|
||
return this.#isAbsolute !== undefined
|
||
? this.#isAbsolute
|
||
: (this.#isAbsolute =
|
||
(pl[0] === '' && pl.length > 1) ||
|
||
this.isDrive() ||
|
||
this.isUNC());
|
||
}
|
||
/**
|
||
* consume the root of the pattern, and return it
|
||
*/
|
||
root() {
|
||
const p = this.#patternList[0];
|
||
return typeof p === 'string' && this.isAbsolute() && this.#index === 0
|
||
? p
|
||
: '';
|
||
}
|
||
/**
|
||
* Check to see if the current globstar pattern is allowed to follow
|
||
* a symbolic link.
|
||
*/
|
||
checkFollowGlobstar() {
|
||
return !(this.#index === 0 ||
|
||
!this.isGlobstar() ||
|
||
!this.#followGlobstar);
|
||
}
|
||
/**
|
||
* Mark that the current globstar pattern is following a symbolic link
|
||
*/
|
||
markFollowGlobstar() {
|
||
if (this.#index === 0 || !this.isGlobstar() || !this.#followGlobstar)
|
||
return false;
|
||
this.#followGlobstar = false;
|
||
return true;
|
||
}
|
||
}
|
||
|
||
// give it a pattern, and it'll be able to tell you if
|
||
// a given path should be ignored.
|
||
// Ignoring a path ignores its children if the pattern ends in /**
|
||
// Ignores are always parsed in dot:true mode
|
||
const defaultPlatform$1 = typeof process === 'object' &&
|
||
process &&
|
||
typeof process.platform === 'string'
|
||
? process.platform
|
||
: 'linux';
|
||
/**
|
||
* Class used to process ignored patterns
|
||
*/
|
||
class Ignore {
|
||
relative;
|
||
relativeChildren;
|
||
absolute;
|
||
absoluteChildren;
|
||
constructor(ignored, { nobrace, nocase, noext, noglobstar, platform = defaultPlatform$1, }) {
|
||
this.relative = [];
|
||
this.absolute = [];
|
||
this.relativeChildren = [];
|
||
this.absoluteChildren = [];
|
||
const mmopts = {
|
||
dot: true,
|
||
nobrace,
|
||
nocase,
|
||
noext,
|
||
noglobstar,
|
||
optimizationLevel: 2,
|
||
platform,
|
||
nocomment: true,
|
||
nonegate: true,
|
||
};
|
||
// this is a little weird, but it gives us a clean set of optimized
|
||
// minimatch matchers, without getting tripped up if one of them
|
||
// ends in /** inside a brace section, and it's only inefficient at
|
||
// the start of the walk, not along it.
|
||
// It'd be nice if the Pattern class just had a .test() method, but
|
||
// handling globstars is a bit of a pita, and that code already lives
|
||
// in minimatch anyway.
|
||
// Another way would be if maybe Minimatch could take its set/globParts
|
||
// as an option, and then we could at least just use Pattern to test
|
||
// for absolute-ness.
|
||
// Yet another way, Minimatch could take an array of glob strings, and
|
||
// a cwd option, and do the right thing.
|
||
for (const ign of ignored) {
|
||
const mm = new Minimatch(ign, mmopts);
|
||
for (let i = 0; i < mm.set.length; i++) {
|
||
const parsed = mm.set[i];
|
||
const globParts = mm.globParts[i];
|
||
/* c8 ignore start */
|
||
if (!parsed || !globParts) {
|
||
throw new Error('invalid pattern object');
|
||
}
|
||
/* c8 ignore stop */
|
||
const p = new Pattern(parsed, globParts, 0, platform);
|
||
const m = new Minimatch(p.globString(), mmopts);
|
||
const children = globParts[globParts.length - 1] === '**';
|
||
const absolute = p.isAbsolute();
|
||
if (absolute)
|
||
this.absolute.push(m);
|
||
else
|
||
this.relative.push(m);
|
||
if (children) {
|
||
if (absolute)
|
||
this.absoluteChildren.push(m);
|
||
else
|
||
this.relativeChildren.push(m);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
ignored(p) {
|
||
const fullpath = p.fullpath();
|
||
const fullpaths = `${fullpath}/`;
|
||
const relative = p.relative() || '.';
|
||
const relatives = `${relative}/`;
|
||
for (const m of this.relative) {
|
||
if (m.match(relative) || m.match(relatives))
|
||
return true;
|
||
}
|
||
for (const m of this.absolute) {
|
||
if (m.match(fullpath) || m.match(fullpaths))
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
childrenIgnored(p) {
|
||
const fullpath = p.fullpath() + '/';
|
||
const relative = (p.relative() || '.') + '/';
|
||
for (const m of this.relativeChildren) {
|
||
if (m.match(relative))
|
||
return true;
|
||
}
|
||
for (const m of this.absoluteChildren) {
|
||
if (m.match(fullpath))
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// synchronous utility for filtering entries and calculating subwalks
|
||
/**
|
||
* A cache of which patterns have been processed for a given Path
|
||
*/
|
||
class HasWalkedCache {
|
||
store;
|
||
constructor(store = new Map()) {
|
||
this.store = store;
|
||
}
|
||
copy() {
|
||
return new HasWalkedCache(new Map(this.store));
|
||
}
|
||
hasWalked(target, pattern) {
|
||
return this.store.get(target.fullpath())?.has(pattern.globString());
|
||
}
|
||
storeWalked(target, pattern) {
|
||
const fullpath = target.fullpath();
|
||
const cached = this.store.get(fullpath);
|
||
if (cached)
|
||
cached.add(pattern.globString());
|
||
else
|
||
this.store.set(fullpath, new Set([pattern.globString()]));
|
||
}
|
||
}
|
||
/**
|
||
* A record of which paths have been matched in a given walk step,
|
||
* and whether they only are considered a match if they are a directory,
|
||
* and whether their absolute or relative path should be returned.
|
||
*/
|
||
class MatchRecord {
|
||
store = new Map();
|
||
add(target, absolute, ifDir) {
|
||
const n = (absolute ? 2 : 0) | (ifDir ? 1 : 0);
|
||
const current = this.store.get(target);
|
||
this.store.set(target, current === undefined ? n : n & current);
|
||
}
|
||
// match, absolute, ifdir
|
||
entries() {
|
||
return [...this.store.entries()].map(([path, n]) => [
|
||
path,
|
||
!!(n & 2),
|
||
!!(n & 1),
|
||
]);
|
||
}
|
||
}
|
||
/**
|
||
* A collection of patterns that must be processed in a subsequent step
|
||
* for a given path.
|
||
*/
|
||
class SubWalks {
|
||
store = new Map();
|
||
add(target, pattern) {
|
||
if (!target.canReaddir()) {
|
||
return;
|
||
}
|
||
const subs = this.store.get(target);
|
||
if (subs) {
|
||
if (!subs.find(p => p.globString() === pattern.globString())) {
|
||
subs.push(pattern);
|
||
}
|
||
}
|
||
else
|
||
this.store.set(target, [pattern]);
|
||
}
|
||
get(target) {
|
||
const subs = this.store.get(target);
|
||
/* c8 ignore start */
|
||
if (!subs) {
|
||
throw new Error('attempting to walk unknown path');
|
||
}
|
||
/* c8 ignore stop */
|
||
return subs;
|
||
}
|
||
entries() {
|
||
return this.keys().map(k => [k, this.store.get(k)]);
|
||
}
|
||
keys() {
|
||
return [...this.store.keys()].filter(t => t.canReaddir());
|
||
}
|
||
}
|
||
/**
|
||
* The class that processes patterns for a given path.
|
||
*
|
||
* Handles child entry filtering, and determining whether a path's
|
||
* directory contents must be read.
|
||
*/
|
||
class Processor {
|
||
hasWalkedCache;
|
||
matches = new MatchRecord();
|
||
subwalks = new SubWalks();
|
||
patterns;
|
||
follow;
|
||
dot;
|
||
opts;
|
||
constructor(opts, hasWalkedCache) {
|
||
this.opts = opts;
|
||
this.follow = !!opts.follow;
|
||
this.dot = !!opts.dot;
|
||
this.hasWalkedCache = hasWalkedCache
|
||
? hasWalkedCache.copy()
|
||
: new HasWalkedCache();
|
||
}
|
||
processPatterns(target, patterns) {
|
||
this.patterns = patterns;
|
||
const processingSet = patterns.map(p => [target, p]);
|
||
// map of paths to the magic-starting subwalks they need to walk
|
||
// first item in patterns is the filter
|
||
for (let [t, pattern] of processingSet) {
|
||
this.hasWalkedCache.storeWalked(t, pattern);
|
||
const root = pattern.root();
|
||
const absolute = pattern.isAbsolute() && this.opts.absolute !== false;
|
||
// start absolute patterns at root
|
||
if (root) {
|
||
t = t.resolve(root === '/' && this.opts.root !== undefined
|
||
? this.opts.root
|
||
: root);
|
||
const rest = pattern.rest();
|
||
if (!rest) {
|
||
this.matches.add(t, true, false);
|
||
continue;
|
||
}
|
||
else {
|
||
pattern = rest;
|
||
}
|
||
}
|
||
if (t.isENOENT())
|
||
continue;
|
||
let p;
|
||
let rest;
|
||
let changed = false;
|
||
while (typeof (p = pattern.pattern()) === 'string' &&
|
||
(rest = pattern.rest())) {
|
||
const c = t.resolve(p);
|
||
t = c;
|
||
pattern = rest;
|
||
changed = true;
|
||
}
|
||
p = pattern.pattern();
|
||
rest = pattern.rest();
|
||
if (changed) {
|
||
if (this.hasWalkedCache.hasWalked(t, pattern))
|
||
continue;
|
||
this.hasWalkedCache.storeWalked(t, pattern);
|
||
}
|
||
// now we have either a final string for a known entry,
|
||
// more strings for an unknown entry,
|
||
// or a pattern starting with magic, mounted on t.
|
||
if (typeof p === 'string') {
|
||
// must not be final entry, otherwise we would have
|
||
// concatenated it earlier.
|
||
const ifDir = p === '..' || p === '' || p === '.';
|
||
this.matches.add(t.resolve(p), absolute, ifDir);
|
||
continue;
|
||
}
|
||
else if (p === GLOBSTAR$1) {
|
||
// if no rest, match and subwalk pattern
|
||
// if rest, process rest and subwalk pattern
|
||
// if it's a symlink, but we didn't get here by way of a
|
||
// globstar match (meaning it's the first time THIS globstar
|
||
// has traversed a symlink), then we follow it. Otherwise, stop.
|
||
if (!t.isSymbolicLink() ||
|
||
this.follow ||
|
||
pattern.checkFollowGlobstar()) {
|
||
this.subwalks.add(t, pattern);
|
||
}
|
||
const rp = rest?.pattern();
|
||
const rrest = rest?.rest();
|
||
if (!rest || ((rp === '' || rp === '.') && !rrest)) {
|
||
// only HAS to be a dir if it ends in **/ or **/.
|
||
// but ending in ** will match files as well.
|
||
this.matches.add(t, absolute, rp === '' || rp === '.');
|
||
}
|
||
else {
|
||
if (rp === '..') {
|
||
// this would mean you're matching **/.. at the fs root,
|
||
// and no thanks, I'm not gonna test that specific case.
|
||
/* c8 ignore start */
|
||
const tp = t.parent || t;
|
||
/* c8 ignore stop */
|
||
if (!rrest)
|
||
this.matches.add(tp, absolute, true);
|
||
else if (!this.hasWalkedCache.hasWalked(tp, rrest)) {
|
||
this.subwalks.add(tp, rrest);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (p instanceof RegExp) {
|
||
this.subwalks.add(t, pattern);
|
||
}
|
||
}
|
||
return this;
|
||
}
|
||
subwalkTargets() {
|
||
return this.subwalks.keys();
|
||
}
|
||
child() {
|
||
return new Processor(this.opts, this.hasWalkedCache);
|
||
}
|
||
// return a new Processor containing the subwalks for each
|
||
// child entry, and a set of matches, and
|
||
// a hasWalkedCache that's a copy of this one
|
||
// then we're going to call
|
||
filterEntries(parent, entries) {
|
||
const patterns = this.subwalks.get(parent);
|
||
// put matches and entry walks into the results processor
|
||
const results = this.child();
|
||
for (const e of entries) {
|
||
for (const pattern of patterns) {
|
||
const absolute = pattern.isAbsolute();
|
||
const p = pattern.pattern();
|
||
const rest = pattern.rest();
|
||
if (p === GLOBSTAR$1) {
|
||
results.testGlobstar(e, pattern, rest, absolute);
|
||
}
|
||
else if (p instanceof RegExp) {
|
||
results.testRegExp(e, p, rest, absolute);
|
||
}
|
||
else {
|
||
results.testString(e, p, rest, absolute);
|
||
}
|
||
}
|
||
}
|
||
return results;
|
||
}
|
||
testGlobstar(e, pattern, rest, absolute) {
|
||
if (this.dot || !e.name.startsWith('.')) {
|
||
if (!pattern.hasMore()) {
|
||
this.matches.add(e, absolute, false);
|
||
}
|
||
if (e.canReaddir()) {
|
||
// if we're in follow mode or it's not a symlink, just keep
|
||
// testing the same pattern. If there's more after the globstar,
|
||
// then this symlink consumes the globstar. If not, then we can
|
||
// follow at most ONE symlink along the way, so we mark it, which
|
||
// also checks to ensure that it wasn't already marked.
|
||
if (this.follow || !e.isSymbolicLink()) {
|
||
this.subwalks.add(e, pattern);
|
||
}
|
||
else if (e.isSymbolicLink()) {
|
||
if (rest && pattern.checkFollowGlobstar()) {
|
||
this.subwalks.add(e, rest);
|
||
}
|
||
else if (pattern.markFollowGlobstar()) {
|
||
this.subwalks.add(e, pattern);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// if the NEXT thing matches this entry, then also add
|
||
// the rest.
|
||
if (rest) {
|
||
const rp = rest.pattern();
|
||
if (typeof rp === 'string' &&
|
||
// dots and empty were handled already
|
||
rp !== '..' &&
|
||
rp !== '' &&
|
||
rp !== '.') {
|
||
this.testString(e, rp, rest.rest(), absolute);
|
||
}
|
||
else if (rp === '..') {
|
||
/* c8 ignore start */
|
||
const ep = e.parent || e;
|
||
/* c8 ignore stop */
|
||
this.subwalks.add(ep, rest);
|
||
}
|
||
else if (rp instanceof RegExp) {
|
||
this.testRegExp(e, rp, rest.rest(), absolute);
|
||
}
|
||
}
|
||
}
|
||
testRegExp(e, p, rest, absolute) {
|
||
if (!p.test(e.name))
|
||
return;
|
||
if (!rest) {
|
||
this.matches.add(e, absolute, false);
|
||
}
|
||
else {
|
||
this.subwalks.add(e, rest);
|
||
}
|
||
}
|
||
testString(e, p, rest, absolute) {
|
||
// should never happen?
|
||
if (!e.isNamed(p))
|
||
return;
|
||
if (!rest) {
|
||
this.matches.add(e, absolute, false);
|
||
}
|
||
else {
|
||
this.subwalks.add(e, rest);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Single-use utility classes to provide functionality to the {@link Glob}
|
||
* methods.
|
||
*
|
||
* @module
|
||
*/
|
||
const makeIgnore = (ignore, opts) => typeof ignore === 'string'
|
||
? new Ignore([ignore], opts)
|
||
: Array.isArray(ignore)
|
||
? new Ignore(ignore, opts)
|
||
: ignore;
|
||
/**
|
||
* basic walking utilities that all the glob walker types use
|
||
*/
|
||
class GlobUtil {
|
||
path;
|
||
patterns;
|
||
opts;
|
||
seen = new Set();
|
||
paused = false;
|
||
aborted = false;
|
||
#onResume = [];
|
||
#ignore;
|
||
#sep;
|
||
signal;
|
||
maxDepth;
|
||
constructor(patterns, path, opts) {
|
||
this.patterns = patterns;
|
||
this.path = path;
|
||
this.opts = opts;
|
||
this.#sep = !opts.posix && opts.platform === 'win32' ? '\\' : '/';
|
||
if (opts.ignore) {
|
||
this.#ignore = makeIgnore(opts.ignore, opts);
|
||
}
|
||
// ignore, always set with maxDepth, but it's optional on the
|
||
// GlobOptions type
|
||
/* c8 ignore start */
|
||
this.maxDepth = opts.maxDepth || Infinity;
|
||
/* c8 ignore stop */
|
||
if (opts.signal) {
|
||
this.signal = opts.signal;
|
||
this.signal.addEventListener('abort', () => {
|
||
this.#onResume.length = 0;
|
||
});
|
||
}
|
||
}
|
||
#ignored(path) {
|
||
return this.seen.has(path) || !!this.#ignore?.ignored?.(path);
|
||
}
|
||
#childrenIgnored(path) {
|
||
return !!this.#ignore?.childrenIgnored?.(path);
|
||
}
|
||
// backpressure mechanism
|
||
pause() {
|
||
this.paused = true;
|
||
}
|
||
resume() {
|
||
/* c8 ignore start */
|
||
if (this.signal?.aborted)
|
||
return;
|
||
/* c8 ignore stop */
|
||
this.paused = false;
|
||
let fn = undefined;
|
||
while (!this.paused && (fn = this.#onResume.shift())) {
|
||
fn();
|
||
}
|
||
}
|
||
onResume(fn) {
|
||
if (this.signal?.aborted)
|
||
return;
|
||
/* c8 ignore start */
|
||
if (!this.paused) {
|
||
fn();
|
||
}
|
||
else {
|
||
/* c8 ignore stop */
|
||
this.#onResume.push(fn);
|
||
}
|
||
}
|
||
// do the requisite realpath/stat checking, and return the path
|
||
// to add or undefined to filter it out.
|
||
async matchCheck(e, ifDir) {
|
||
if (ifDir && this.opts.nodir)
|
||
return undefined;
|
||
let rpc;
|
||
if (this.opts.realpath) {
|
||
rpc = e.realpathCached() || (await e.realpath());
|
||
if (!rpc)
|
||
return undefined;
|
||
e = rpc;
|
||
}
|
||
const needStat = e.isUnknown() || this.opts.stat;
|
||
return this.matchCheckTest(needStat ? await e.lstat() : e, ifDir);
|
||
}
|
||
matchCheckTest(e, ifDir) {
|
||
return e &&
|
||
(this.maxDepth === Infinity || e.depth() <= this.maxDepth) &&
|
||
(!ifDir || e.canReaddir()) &&
|
||
(!this.opts.nodir || !e.isDirectory()) &&
|
||
!this.#ignored(e)
|
||
? e
|
||
: undefined;
|
||
}
|
||
matchCheckSync(e, ifDir) {
|
||
if (ifDir && this.opts.nodir)
|
||
return undefined;
|
||
let rpc;
|
||
if (this.opts.realpath) {
|
||
rpc = e.realpathCached() || e.realpathSync();
|
||
if (!rpc)
|
||
return undefined;
|
||
e = rpc;
|
||
}
|
||
const needStat = e.isUnknown() || this.opts.stat;
|
||
return this.matchCheckTest(needStat ? e.lstatSync() : e, ifDir);
|
||
}
|
||
matchFinish(e, absolute) {
|
||
if (this.#ignored(e))
|
||
return;
|
||
const abs = this.opts.absolute === undefined ? absolute : this.opts.absolute;
|
||
this.seen.add(e);
|
||
const mark = this.opts.mark && e.isDirectory() ? this.#sep : '';
|
||
// ok, we have what we need!
|
||
if (this.opts.withFileTypes) {
|
||
this.matchEmit(e);
|
||
}
|
||
else if (abs) {
|
||
const abs = this.opts.posix ? e.fullpathPosix() : e.fullpath();
|
||
this.matchEmit(abs + mark);
|
||
}
|
||
else {
|
||
const rel = this.opts.posix ? e.relativePosix() : e.relative();
|
||
const pre = this.opts.dotRelative && !rel.startsWith('..' + this.#sep)
|
||
? '.' + this.#sep
|
||
: '';
|
||
this.matchEmit(!rel ? '.' + mark : pre + rel + mark);
|
||
}
|
||
}
|
||
async match(e, absolute, ifDir) {
|
||
const p = await this.matchCheck(e, ifDir);
|
||
if (p)
|
||
this.matchFinish(p, absolute);
|
||
}
|
||
matchSync(e, absolute, ifDir) {
|
||
const p = this.matchCheckSync(e, ifDir);
|
||
if (p)
|
||
this.matchFinish(p, absolute);
|
||
}
|
||
walkCB(target, patterns, cb) {
|
||
/* c8 ignore start */
|
||
if (this.signal?.aborted)
|
||
cb();
|
||
/* c8 ignore stop */
|
||
this.walkCB2(target, patterns, new Processor(this.opts), cb);
|
||
}
|
||
walkCB2(target, patterns, processor, cb) {
|
||
if (this.#childrenIgnored(target))
|
||
return cb();
|
||
if (this.signal?.aborted)
|
||
cb();
|
||
if (this.paused) {
|
||
this.onResume(() => this.walkCB2(target, patterns, processor, cb));
|
||
return;
|
||
}
|
||
processor.processPatterns(target, patterns);
|
||
// done processing. all of the above is sync, can be abstracted out.
|
||
// subwalks is a map of paths to the entry filters they need
|
||
// matches is a map of paths to [absolute, ifDir] tuples.
|
||
let tasks = 1;
|
||
const next = () => {
|
||
if (--tasks === 0)
|
||
cb();
|
||
};
|
||
for (const [m, absolute, ifDir] of processor.matches.entries()) {
|
||
if (this.#ignored(m))
|
||
continue;
|
||
tasks++;
|
||
this.match(m, absolute, ifDir).then(() => next());
|
||
}
|
||
for (const t of processor.subwalkTargets()) {
|
||
if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
|
||
continue;
|
||
}
|
||
tasks++;
|
||
const childrenCached = t.readdirCached();
|
||
if (t.calledReaddir())
|
||
this.walkCB3(t, childrenCached, processor, next);
|
||
else {
|
||
t.readdirCB((_, entries) => this.walkCB3(t, entries, processor, next), true);
|
||
}
|
||
}
|
||
next();
|
||
}
|
||
walkCB3(target, entries, processor, cb) {
|
||
processor = processor.filterEntries(target, entries);
|
||
let tasks = 1;
|
||
const next = () => {
|
||
if (--tasks === 0)
|
||
cb();
|
||
};
|
||
for (const [m, absolute, ifDir] of processor.matches.entries()) {
|
||
if (this.#ignored(m))
|
||
continue;
|
||
tasks++;
|
||
this.match(m, absolute, ifDir).then(() => next());
|
||
}
|
||
for (const [target, patterns] of processor.subwalks.entries()) {
|
||
tasks++;
|
||
this.walkCB2(target, patterns, processor.child(), next);
|
||
}
|
||
next();
|
||
}
|
||
walkCBSync(target, patterns, cb) {
|
||
/* c8 ignore start */
|
||
if (this.signal?.aborted)
|
||
cb();
|
||
/* c8 ignore stop */
|
||
this.walkCB2Sync(target, patterns, new Processor(this.opts), cb);
|
||
}
|
||
walkCB2Sync(target, patterns, processor, cb) {
|
||
if (this.#childrenIgnored(target))
|
||
return cb();
|
||
if (this.signal?.aborted)
|
||
cb();
|
||
if (this.paused) {
|
||
this.onResume(() => this.walkCB2Sync(target, patterns, processor, cb));
|
||
return;
|
||
}
|
||
processor.processPatterns(target, patterns);
|
||
// done processing. all of the above is sync, can be abstracted out.
|
||
// subwalks is a map of paths to the entry filters they need
|
||
// matches is a map of paths to [absolute, ifDir] tuples.
|
||
let tasks = 1;
|
||
const next = () => {
|
||
if (--tasks === 0)
|
||
cb();
|
||
};
|
||
for (const [m, absolute, ifDir] of processor.matches.entries()) {
|
||
if (this.#ignored(m))
|
||
continue;
|
||
this.matchSync(m, absolute, ifDir);
|
||
}
|
||
for (const t of processor.subwalkTargets()) {
|
||
if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
|
||
continue;
|
||
}
|
||
tasks++;
|
||
const children = t.readdirSync();
|
||
this.walkCB3Sync(t, children, processor, next);
|
||
}
|
||
next();
|
||
}
|
||
walkCB3Sync(target, entries, processor, cb) {
|
||
processor = processor.filterEntries(target, entries);
|
||
let tasks = 1;
|
||
const next = () => {
|
||
if (--tasks === 0)
|
||
cb();
|
||
};
|
||
for (const [m, absolute, ifDir] of processor.matches.entries()) {
|
||
if (this.#ignored(m))
|
||
continue;
|
||
this.matchSync(m, absolute, ifDir);
|
||
}
|
||
for (const [target, patterns] of processor.subwalks.entries()) {
|
||
tasks++;
|
||
this.walkCB2Sync(target, patterns, processor.child(), next);
|
||
}
|
||
next();
|
||
}
|
||
}
|
||
class GlobWalker extends GlobUtil {
|
||
matches;
|
||
constructor(patterns, path, opts) {
|
||
super(patterns, path, opts);
|
||
this.matches = new Set();
|
||
}
|
||
matchEmit(e) {
|
||
this.matches.add(e);
|
||
}
|
||
async walk() {
|
||
if (this.signal?.aborted)
|
||
throw this.signal.reason;
|
||
if (this.path.isUnknown()) {
|
||
await this.path.lstat();
|
||
}
|
||
await new Promise((res, rej) => {
|
||
this.walkCB(this.path, this.patterns, () => {
|
||
if (this.signal?.aborted) {
|
||
rej(this.signal.reason);
|
||
}
|
||
else {
|
||
res(this.matches);
|
||
}
|
||
});
|
||
});
|
||
return this.matches;
|
||
}
|
||
walkSync() {
|
||
if (this.signal?.aborted)
|
||
throw this.signal.reason;
|
||
if (this.path.isUnknown()) {
|
||
this.path.lstatSync();
|
||
}
|
||
// nothing for the callback to do, because this never pauses
|
||
this.walkCBSync(this.path, this.patterns, () => {
|
||
if (this.signal?.aborted)
|
||
throw this.signal.reason;
|
||
});
|
||
return this.matches;
|
||
}
|
||
}
|
||
class GlobStream extends GlobUtil {
|
||
results;
|
||
constructor(patterns, path, opts) {
|
||
super(patterns, path, opts);
|
||
this.results = new Minipass({
|
||
signal: this.signal,
|
||
objectMode: true,
|
||
});
|
||
this.results.on('drain', () => this.resume());
|
||
this.results.on('resume', () => this.resume());
|
||
}
|
||
matchEmit(e) {
|
||
this.results.write(e);
|
||
if (!this.results.flowing)
|
||
this.pause();
|
||
}
|
||
stream() {
|
||
const target = this.path;
|
||
if (target.isUnknown()) {
|
||
target.lstat().then(() => {
|
||
this.walkCB(target, this.patterns, () => this.results.end());
|
||
});
|
||
}
|
||
else {
|
||
this.walkCB(target, this.patterns, () => this.results.end());
|
||
}
|
||
return this.results;
|
||
}
|
||
streamSync() {
|
||
if (this.path.isUnknown()) {
|
||
this.path.lstatSync();
|
||
}
|
||
this.walkCBSync(this.path, this.patterns, () => this.results.end());
|
||
return this.results;
|
||
}
|
||
}
|
||
|
||
// if no process global, just call it linux.
|
||
// so we default to case-sensitive, / separators
|
||
const defaultPlatform = typeof process === 'object' &&
|
||
process &&
|
||
typeof process.platform === 'string'
|
||
? process.platform
|
||
: 'linux';
|
||
/**
|
||
* An object that can perform glob pattern traversals.
|
||
*/
|
||
class Glob {
|
||
absolute;
|
||
cwd;
|
||
root;
|
||
dot;
|
||
dotRelative;
|
||
follow;
|
||
ignore;
|
||
magicalBraces;
|
||
mark;
|
||
matchBase;
|
||
maxDepth;
|
||
nobrace;
|
||
nocase;
|
||
nodir;
|
||
noext;
|
||
noglobstar;
|
||
pattern;
|
||
platform;
|
||
realpath;
|
||
scurry;
|
||
stat;
|
||
signal;
|
||
windowsPathsNoEscape;
|
||
withFileTypes;
|
||
/**
|
||
* The options provided to the constructor.
|
||
*/
|
||
opts;
|
||
/**
|
||
* An array of parsed immutable {@link Pattern} objects.
|
||
*/
|
||
patterns;
|
||
/**
|
||
* All options are stored as properties on the `Glob` object.
|
||
*
|
||
* See {@link GlobOptions} for full options descriptions.
|
||
*
|
||
* Note that a previous `Glob` object can be passed as the
|
||
* `GlobOptions` to another `Glob` instantiation to re-use settings
|
||
* and caches with a new pattern.
|
||
*
|
||
* Traversal functions can be called multiple times to run the walk
|
||
* again.
|
||
*/
|
||
constructor(pattern, opts) {
|
||
/* c8 ignore start */
|
||
if (!opts)
|
||
throw new TypeError('glob options required');
|
||
/* c8 ignore stop */
|
||
this.withFileTypes = !!opts.withFileTypes;
|
||
this.signal = opts.signal;
|
||
this.follow = !!opts.follow;
|
||
this.dot = !!opts.dot;
|
||
this.dotRelative = !!opts.dotRelative;
|
||
this.nodir = !!opts.nodir;
|
||
this.mark = !!opts.mark;
|
||
if (!opts.cwd) {
|
||
this.cwd = '';
|
||
}
|
||
else if (opts.cwd instanceof URL || opts.cwd.startsWith('file://')) {
|
||
opts.cwd = fileURLToPath$1(opts.cwd);
|
||
}
|
||
this.cwd = opts.cwd || '';
|
||
this.root = opts.root;
|
||
this.magicalBraces = !!opts.magicalBraces;
|
||
this.nobrace = !!opts.nobrace;
|
||
this.noext = !!opts.noext;
|
||
this.realpath = !!opts.realpath;
|
||
this.absolute = opts.absolute;
|
||
this.noglobstar = !!opts.noglobstar;
|
||
this.matchBase = !!opts.matchBase;
|
||
this.maxDepth =
|
||
typeof opts.maxDepth === 'number' ? opts.maxDepth : Infinity;
|
||
this.stat = !!opts.stat;
|
||
this.ignore = opts.ignore;
|
||
if (this.withFileTypes && this.absolute !== undefined) {
|
||
throw new Error('cannot set absolute and withFileTypes:true');
|
||
}
|
||
if (typeof pattern === 'string') {
|
||
pattern = [pattern];
|
||
}
|
||
this.windowsPathsNoEscape =
|
||
!!opts.windowsPathsNoEscape ||
|
||
opts.allowWindowsEscape === false;
|
||
if (this.windowsPathsNoEscape) {
|
||
pattern = pattern.map(p => p.replace(/\\/g, '/'));
|
||
}
|
||
if (this.matchBase) {
|
||
if (opts.noglobstar) {
|
||
throw new TypeError('base matching requires globstar');
|
||
}
|
||
pattern = pattern.map(p => (p.includes('/') ? p : `./**/${p}`));
|
||
}
|
||
this.pattern = pattern;
|
||
this.platform = opts.platform || defaultPlatform;
|
||
this.opts = { ...opts, platform: this.platform };
|
||
if (opts.scurry) {
|
||
this.scurry = opts.scurry;
|
||
if (opts.nocase !== undefined &&
|
||
opts.nocase !== opts.scurry.nocase) {
|
||
throw new Error('nocase option contradicts provided scurry option');
|
||
}
|
||
}
|
||
else {
|
||
const Scurry = opts.platform === 'win32'
|
||
? PathScurryWin32
|
||
: opts.platform === 'darwin'
|
||
? PathScurryDarwin
|
||
: opts.platform
|
||
? PathScurryPosix
|
||
: PathScurry;
|
||
this.scurry = new Scurry(this.cwd, {
|
||
nocase: opts.nocase,
|
||
fs: opts.fs,
|
||
});
|
||
}
|
||
this.nocase = this.scurry.nocase;
|
||
// If you do nocase:true on a case-sensitive file system, then
|
||
// we need to use regexps instead of strings for non-magic
|
||
// path portions, because statting `aBc` won't return results
|
||
// for the file `AbC` for example.
|
||
const nocaseMagicOnly = this.platform === 'darwin' || this.platform === 'win32';
|
||
const mmo = {
|
||
// default nocase based on platform
|
||
...opts,
|
||
dot: this.dot,
|
||
matchBase: this.matchBase,
|
||
nobrace: this.nobrace,
|
||
nocase: this.nocase,
|
||
nocaseMagicOnly,
|
||
nocomment: true,
|
||
noext: this.noext,
|
||
nonegate: true,
|
||
optimizationLevel: 2,
|
||
platform: this.platform,
|
||
windowsPathsNoEscape: this.windowsPathsNoEscape,
|
||
debug: !!this.opts.debug,
|
||
};
|
||
const mms = this.pattern.map(p => new Minimatch(p, mmo));
|
||
const [matchSet, globParts] = mms.reduce((set, m) => {
|
||
set[0].push(...m.set);
|
||
set[1].push(...m.globParts);
|
||
return set;
|
||
}, [[], []]);
|
||
this.patterns = matchSet.map((set, i) => {
|
||
const g = globParts[i];
|
||
/* c8 ignore start */
|
||
if (!g)
|
||
throw new Error('invalid pattern object');
|
||
/* c8 ignore stop */
|
||
return new Pattern(set, g, 0, this.platform);
|
||
});
|
||
}
|
||
async walk() {
|
||
// Walkers always return array of Path objects, so we just have to
|
||
// coerce them into the right shape. It will have already called
|
||
// realpath() if the option was set to do so, so we know that's cached.
|
||
// start out knowing the cwd, at least
|
||
return [
|
||
...(await new GlobWalker(this.patterns, this.scurry.cwd, {
|
||
...this.opts,
|
||
maxDepth: this.maxDepth !== Infinity
|
||
? this.maxDepth + this.scurry.cwd.depth()
|
||
: Infinity,
|
||
platform: this.platform,
|
||
nocase: this.nocase,
|
||
}).walk()),
|
||
];
|
||
}
|
||
walkSync() {
|
||
return [
|
||
...new GlobWalker(this.patterns, this.scurry.cwd, {
|
||
...this.opts,
|
||
maxDepth: this.maxDepth !== Infinity
|
||
? this.maxDepth + this.scurry.cwd.depth()
|
||
: Infinity,
|
||
platform: this.platform,
|
||
nocase: this.nocase,
|
||
}).walkSync(),
|
||
];
|
||
}
|
||
stream() {
|
||
return new GlobStream(this.patterns, this.scurry.cwd, {
|
||
...this.opts,
|
||
maxDepth: this.maxDepth !== Infinity
|
||
? this.maxDepth + this.scurry.cwd.depth()
|
||
: Infinity,
|
||
platform: this.platform,
|
||
nocase: this.nocase,
|
||
}).stream();
|
||
}
|
||
streamSync() {
|
||
return new GlobStream(this.patterns, this.scurry.cwd, {
|
||
...this.opts,
|
||
maxDepth: this.maxDepth !== Infinity
|
||
? this.maxDepth + this.scurry.cwd.depth()
|
||
: Infinity,
|
||
platform: this.platform,
|
||
nocase: this.nocase,
|
||
}).streamSync();
|
||
}
|
||
/**
|
||
* Default sync iteration function. Returns a Generator that
|
||
* iterates over the results.
|
||
*/
|
||
iterateSync() {
|
||
return this.streamSync()[Symbol.iterator]();
|
||
}
|
||
[Symbol.iterator]() {
|
||
return this.iterateSync();
|
||
}
|
||
/**
|
||
* Default async iteration function. Returns an AsyncGenerator that
|
||
* iterates over the results.
|
||
*/
|
||
iterate() {
|
||
return this.stream()[Symbol.asyncIterator]();
|
||
}
|
||
[Symbol.asyncIterator]() {
|
||
return this.iterate();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Return true if the patterns provided contain any magic glob characters,
|
||
* given the options provided.
|
||
*
|
||
* Brace expansion is not considered "magic" unless the `magicalBraces` option
|
||
* is set, as brace expansion just turns one string into an array of strings.
|
||
* So a pattern like `'x{a,b}y'` would return `false`, because `'xay'` and
|
||
* `'xby'` both do not contain any magic glob characters, and it's treated the
|
||
* same as if you had called it on `['xay', 'xby']`. When `magicalBraces:true`
|
||
* is in the options, brace expansion _is_ treated as a pattern having magic.
|
||
*/
|
||
const hasMagic = (pattern, options = {}) => {
|
||
if (!Array.isArray(pattern)) {
|
||
pattern = [pattern];
|
||
}
|
||
for (const p of pattern) {
|
||
if (new Minimatch(p, options).hasMagic())
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
function globStreamSync(pattern, options = {}) {
|
||
return new Glob(pattern, options).streamSync();
|
||
}
|
||
function globStream(pattern, options = {}) {
|
||
return new Glob(pattern, options).stream();
|
||
}
|
||
function globSync(pattern, options = {}) {
|
||
return new Glob(pattern, options).walkSync();
|
||
}
|
||
async function glob_(pattern, options = {}) {
|
||
return new Glob(pattern, options).walk();
|
||
}
|
||
function globIterateSync(pattern, options = {}) {
|
||
return new Glob(pattern, options).iterateSync();
|
||
}
|
||
function globIterate(pattern, options = {}) {
|
||
return new Glob(pattern, options).iterate();
|
||
}
|
||
// aliases: glob.sync.stream() glob.stream.sync() glob.sync() etc
|
||
const streamSync = globStreamSync;
|
||
const stream$5 = Object.assign(globStream, { sync: globStreamSync });
|
||
const iterateSync = globIterateSync;
|
||
const iterate = Object.assign(globIterate, {
|
||
sync: globIterateSync,
|
||
});
|
||
const sync$9 = Object.assign(globSync, {
|
||
stream: globStreamSync,
|
||
iterate: globIterateSync,
|
||
});
|
||
/* c8 ignore stop */
|
||
const glob$1 = Object.assign(glob_, {
|
||
glob: glob_,
|
||
globSync,
|
||
sync: sync$9,
|
||
globStream,
|
||
stream: stream$5,
|
||
globStreamSync,
|
||
streamSync,
|
||
globIterate,
|
||
iterate,
|
||
globIterateSync,
|
||
iterateSync,
|
||
Glob,
|
||
hasMagic,
|
||
escape: escape$4,
|
||
unescape,
|
||
});
|
||
glob$1.glob = glob$1;
|
||
|
||
const typeOrUndef = (val, t) => typeof val === 'undefined' || typeof val === t;
|
||
const isRimrafOptions = (o) => !!o &&
|
||
typeof o === 'object' &&
|
||
typeOrUndef(o.preserveRoot, 'boolean') &&
|
||
typeOrUndef(o.tmp, 'string') &&
|
||
typeOrUndef(o.maxRetries, 'number') &&
|
||
typeOrUndef(o.retryDelay, 'number') &&
|
||
typeOrUndef(o.backoff, 'number') &&
|
||
typeOrUndef(o.maxBackoff, 'number') &&
|
||
(typeOrUndef(o.glob, 'boolean') || (o.glob && typeof o.glob === 'object')) &&
|
||
typeOrUndef(o.filter, 'function');
|
||
const assertRimrafOptions = (o) => {
|
||
if (!isRimrafOptions(o)) {
|
||
throw new Error('invalid rimraf options');
|
||
}
|
||
};
|
||
const optArgT = (opt) => {
|
||
assertRimrafOptions(opt);
|
||
const { glob, ...options } = opt;
|
||
if (!glob) {
|
||
return options;
|
||
}
|
||
const globOpt = glob === true
|
||
? opt.signal
|
||
? { signal: opt.signal }
|
||
: {}
|
||
: opt.signal
|
||
? {
|
||
signal: opt.signal,
|
||
...glob,
|
||
}
|
||
: glob;
|
||
return {
|
||
...options,
|
||
glob: {
|
||
...globOpt,
|
||
// always get absolute paths from glob, to ensure
|
||
// that we are referencing the correct thing.
|
||
absolute: true,
|
||
withFileTypes: false,
|
||
},
|
||
};
|
||
};
|
||
const optArg = (opt = {}) => optArgT(opt);
|
||
const optArgSync = (opt = {}) => optArgT(opt);
|
||
|
||
var platform = process.env.__TESTING_RIMRAF_PLATFORM__ || process.platform;
|
||
|
||
const pathArg = (path, opt = {}) => {
|
||
const type = typeof path;
|
||
if (type !== 'string') {
|
||
const ctor = path && type === 'object' && path.constructor;
|
||
const received = ctor && ctor.name
|
||
? `an instance of ${ctor.name}`
|
||
: type === 'object'
|
||
? inspect(path)
|
||
: `type ${type} ${path}`;
|
||
const msg = 'The "path" argument must be of type string. ' + `Received ${received}`;
|
||
throw Object.assign(new TypeError(msg), {
|
||
path,
|
||
code: 'ERR_INVALID_ARG_TYPE',
|
||
});
|
||
}
|
||
if (/\0/.test(path)) {
|
||
// simulate same failure that node raises
|
||
const msg = 'path must be a string without null bytes';
|
||
throw Object.assign(new TypeError(msg), {
|
||
path,
|
||
code: 'ERR_INVALID_ARG_VALUE',
|
||
});
|
||
}
|
||
path = resolve$1(path);
|
||
const { root } = parse$d(path);
|
||
if (path === root && opt.preserveRoot !== false) {
|
||
const msg = 'refusing to remove root directory without preserveRoot:false';
|
||
throw Object.assign(new Error(msg), {
|
||
path,
|
||
code: 'ERR_PRESERVE_ROOT',
|
||
});
|
||
}
|
||
if (platform === 'win32') {
|
||
const badWinChars = /[*|"<>?:]/;
|
||
const { root } = parse$d(path);
|
||
if (badWinChars.test(path.substring(root.length))) {
|
||
throw Object.assign(new Error('Illegal characters in path.'), {
|
||
path,
|
||
code: 'EINVAL',
|
||
});
|
||
}
|
||
}
|
||
return path;
|
||
};
|
||
|
||
// promisify ourselves, because older nodes don't have fs.promises
|
||
const readdirSync = (path) => readdirSync$1(path, { withFileTypes: true });
|
||
// unrolled for better inlining, this seems to get better performance
|
||
// than something like:
|
||
// const makeCb = (res, rej) => (er, ...d) => er ? rej(er) : res(...d)
|
||
// which would be a bit cleaner.
|
||
const chmod$2 = (path, mode) => new Promise((res, rej) => fs__default.chmod(path, mode, (er, ...d) => (er ? rej(er) : res(...d))));
|
||
const mkdir = (path, options) => new Promise((res, rej) => fs__default.mkdir(path, options, (er, made) => (er ? rej(er) : res(made))));
|
||
const readdir$3 = (path) => new Promise((res, rej) => fs__default.readdir(path, { withFileTypes: true }, (er, data) => er ? rej(er) : res(data)));
|
||
const rename$1 = (oldPath, newPath) => new Promise((res, rej) => fs__default.rename(oldPath, newPath, (er, ...d) => (er ? rej(er) : res(...d))));
|
||
const rm$1 = (path, options) => new Promise((res, rej) => fs__default.rm(path, options, (er, ...d) => (er ? rej(er) : res(...d))));
|
||
const rmdir$3 = (path) => new Promise((res, rej) => fs__default.rmdir(path, (er, ...d) => (er ? rej(er) : res(...d))));
|
||
const stat$2 = (path) => new Promise((res, rej) => fs__default.stat(path, (er, data) => (er ? rej(er) : res(data))));
|
||
const lstat$3 = (path) => new Promise((res, rej) => fs__default.lstat(path, (er, data) => (er ? rej(er) : res(data))));
|
||
const unlink$3 = (path) => new Promise((res, rej) => fs__default.unlink(path, (er, ...d) => (er ? rej(er) : res(...d))));
|
||
const promises = {
|
||
chmod: chmod$2,
|
||
mkdir,
|
||
readdir: readdir$3,
|
||
rename: rename$1,
|
||
rm: rm$1,
|
||
rmdir: rmdir$3,
|
||
stat: stat$2,
|
||
lstat: lstat$3,
|
||
unlink: unlink$3,
|
||
};
|
||
|
||
// returns an array of entries if readdir() works,
|
||
// or the error that readdir() raised if not.
|
||
const { readdir: readdir$2 } = promises;
|
||
const readdirOrError = (path) => readdir$2(path).catch(er => er);
|
||
const readdirOrErrorSync = (path) => {
|
||
try {
|
||
return readdirSync(path);
|
||
}
|
||
catch (er) {
|
||
return er;
|
||
}
|
||
};
|
||
|
||
const ignoreENOENT = async (p) => p.catch(er => {
|
||
if (er.code !== 'ENOENT') {
|
||
throw er;
|
||
}
|
||
});
|
||
const ignoreENOENTSync = (fn) => {
|
||
try {
|
||
return fn();
|
||
}
|
||
catch (er) {
|
||
if (er?.code !== 'ENOENT') {
|
||
throw er;
|
||
}
|
||
}
|
||
};
|
||
|
||
// the simple recursive removal, where unlink and rmdir are atomic
|
||
// Note that this approach does NOT work on Windows!
|
||
// We stat first and only unlink if the Dirent isn't a directory,
|
||
// because sunos will let root unlink a directory, and some
|
||
// SUPER weird breakage happens as a result.
|
||
const { lstat: lstat$2, rmdir: rmdir$2, unlink: unlink$2 } = promises;
|
||
const rimrafPosix = async (path, opt) => {
|
||
if (opt?.signal?.aborted) {
|
||
throw opt.signal.reason;
|
||
}
|
||
try {
|
||
return await rimrafPosixDir(path, opt, await lstat$2(path));
|
||
}
|
||
catch (er) {
|
||
if (er?.code === 'ENOENT')
|
||
return true;
|
||
throw er;
|
||
}
|
||
};
|
||
const rimrafPosixSync = (path, opt) => {
|
||
if (opt?.signal?.aborted) {
|
||
throw opt.signal.reason;
|
||
}
|
||
try {
|
||
return rimrafPosixDirSync(path, opt, lstatSync(path));
|
||
}
|
||
catch (er) {
|
||
if (er?.code === 'ENOENT')
|
||
return true;
|
||
throw er;
|
||
}
|
||
};
|
||
const rimrafPosixDir = async (path, opt, ent) => {
|
||
if (opt?.signal?.aborted) {
|
||
throw opt.signal.reason;
|
||
}
|
||
const entries = ent.isDirectory() ? await readdirOrError(path) : null;
|
||
if (!Array.isArray(entries)) {
|
||
// this can only happen if lstat/readdir lied, or if the dir was
|
||
// swapped out with a file at just the right moment.
|
||
/* c8 ignore start */
|
||
if (entries) {
|
||
if (entries.code === 'ENOENT') {
|
||
return true;
|
||
}
|
||
if (entries.code !== 'ENOTDIR') {
|
||
throw entries;
|
||
}
|
||
}
|
||
/* c8 ignore stop */
|
||
if (opt.filter && !(await opt.filter(path, ent))) {
|
||
return false;
|
||
}
|
||
await ignoreENOENT(unlink$2(path));
|
||
return true;
|
||
}
|
||
const removedAll = (await Promise.all(entries.map(ent => rimrafPosixDir(resolve$1(path, ent.name), opt, ent)))).reduce((a, b) => a && b, true);
|
||
if (!removedAll) {
|
||
return false;
|
||
}
|
||
// we don't ever ACTUALLY try to unlink /, because that can never work
|
||
// but when preserveRoot is false, we could be operating on it.
|
||
// No need to check if preserveRoot is not false.
|
||
if (opt.preserveRoot === false && path === parse$d(path).root) {
|
||
return false;
|
||
}
|
||
if (opt.filter && !(await opt.filter(path, ent))) {
|
||
return false;
|
||
}
|
||
await ignoreENOENT(rmdir$2(path));
|
||
return true;
|
||
};
|
||
const rimrafPosixDirSync = (path, opt, ent) => {
|
||
if (opt?.signal?.aborted) {
|
||
throw opt.signal.reason;
|
||
}
|
||
const entries = ent.isDirectory() ? readdirOrErrorSync(path) : null;
|
||
if (!Array.isArray(entries)) {
|
||
// this can only happen if lstat/readdir lied, or if the dir was
|
||
// swapped out with a file at just the right moment.
|
||
/* c8 ignore start */
|
||
if (entries) {
|
||
if (entries.code === 'ENOENT') {
|
||
return true;
|
||
}
|
||
if (entries.code !== 'ENOTDIR') {
|
||
throw entries;
|
||
}
|
||
}
|
||
/* c8 ignore stop */
|
||
if (opt.filter && !opt.filter(path, ent)) {
|
||
return false;
|
||
}
|
||
ignoreENOENTSync(() => unlinkSync(path));
|
||
return true;
|
||
}
|
||
let removedAll = true;
|
||
for (const ent of entries) {
|
||
const p = resolve$1(path, ent.name);
|
||
removedAll = rimrafPosixDirSync(p, opt, ent) && removedAll;
|
||
}
|
||
if (opt.preserveRoot === false && path === parse$d(path).root) {
|
||
return false;
|
||
}
|
||
if (!removedAll) {
|
||
return false;
|
||
}
|
||
if (opt.filter && !opt.filter(path, ent)) {
|
||
return false;
|
||
}
|
||
ignoreENOENTSync(() => rmdirSync(path));
|
||
return true;
|
||
};
|
||
|
||
const { chmod: chmod$1 } = promises;
|
||
const fixEPERM = (fn) => async (path) => {
|
||
try {
|
||
return await fn(path);
|
||
}
|
||
catch (er) {
|
||
const fer = er;
|
||
if (fer?.code === 'ENOENT') {
|
||
return;
|
||
}
|
||
if (fer?.code === 'EPERM') {
|
||
try {
|
||
await chmod$1(path, 0o666);
|
||
}
|
||
catch (er2) {
|
||
const fer2 = er2;
|
||
if (fer2?.code === 'ENOENT') {
|
||
return;
|
||
}
|
||
throw er;
|
||
}
|
||
return await fn(path);
|
||
}
|
||
throw er;
|
||
}
|
||
};
|
||
const fixEPERMSync = (fn) => (path) => {
|
||
try {
|
||
return fn(path);
|
||
}
|
||
catch (er) {
|
||
const fer = er;
|
||
if (fer?.code === 'ENOENT') {
|
||
return;
|
||
}
|
||
if (fer?.code === 'EPERM') {
|
||
try {
|
||
chmodSync(path, 0o666);
|
||
}
|
||
catch (er2) {
|
||
const fer2 = er2;
|
||
if (fer2?.code === 'ENOENT') {
|
||
return;
|
||
}
|
||
throw er;
|
||
}
|
||
return fn(path);
|
||
}
|
||
throw er;
|
||
}
|
||
};
|
||
|
||
// note: max backoff is the maximum that any *single* backoff will do
|
||
const MAXBACKOFF = 200;
|
||
const RATE = 1.2;
|
||
const MAXRETRIES = 10;
|
||
const codes = new Set(['EMFILE', 'ENFILE', 'EBUSY']);
|
||
const retryBusy = (fn) => {
|
||
const method = async (path, opt, backoff = 1, total = 0) => {
|
||
const mbo = opt.maxBackoff || MAXBACKOFF;
|
||
const rate = opt.backoff || RATE;
|
||
const max = opt.maxRetries || MAXRETRIES;
|
||
let retries = 0;
|
||
while (true) {
|
||
try {
|
||
return await fn(path);
|
||
}
|
||
catch (er) {
|
||
const fer = er;
|
||
if (fer?.path === path && fer?.code && codes.has(fer.code)) {
|
||
backoff = Math.ceil(backoff * rate);
|
||
total = backoff + total;
|
||
if (total < mbo) {
|
||
return new Promise((res, rej) => {
|
||
setTimeout(() => {
|
||
method(path, opt, backoff, total).then(res, rej);
|
||
}, backoff);
|
||
});
|
||
}
|
||
if (retries < max) {
|
||
retries++;
|
||
continue;
|
||
}
|
||
}
|
||
throw er;
|
||
}
|
||
}
|
||
};
|
||
return method;
|
||
};
|
||
// just retries, no async so no backoff
|
||
const retryBusySync = (fn) => {
|
||
const method = (path, opt) => {
|
||
const max = opt.maxRetries || MAXRETRIES;
|
||
let retries = 0;
|
||
while (true) {
|
||
try {
|
||
return fn(path);
|
||
}
|
||
catch (er) {
|
||
const fer = er;
|
||
if (fer?.path === path &&
|
||
fer?.code &&
|
||
codes.has(fer.code) &&
|
||
retries < max) {
|
||
retries++;
|
||
continue;
|
||
}
|
||
throw er;
|
||
}
|
||
}
|
||
};
|
||
return method;
|
||
};
|
||
|
||
// The default temporary folder location for use in the windows algorithm.
|
||
// It's TEMPting to use dirname(path), since that's guaranteed to be on the
|
||
// same device. However, this means that:
|
||
// rimraf(path).then(() => rimraf(dirname(path)))
|
||
// will often fail with EBUSY, because the parent dir contains
|
||
// marked-for-deletion directory entries (which do not show up in readdir).
|
||
// The approach here is to use os.tmpdir() if it's on the same drive letter,
|
||
// or resolve(path, '\\temp') if it exists, or the root of the drive if not.
|
||
// On Posix (not that you'd be likely to use the windows algorithm there),
|
||
// it uses os.tmpdir() always.
|
||
const { stat: stat$1 } = promises;
|
||
const isDirSync = (path) => {
|
||
try {
|
||
return statSync$1(path).isDirectory();
|
||
}
|
||
catch (er) {
|
||
return false;
|
||
}
|
||
};
|
||
const isDir = (path) => stat$1(path).then(st => st.isDirectory(), () => false);
|
||
const win32DefaultTmp = async (path) => {
|
||
const { root } = parse$d(path);
|
||
const tmp = tmpdir();
|
||
const { root: tmpRoot } = parse$d(tmp);
|
||
if (root.toLowerCase() === tmpRoot.toLowerCase()) {
|
||
return tmp;
|
||
}
|
||
const driveTmp = resolve$1(root, '/temp');
|
||
if (await isDir(driveTmp)) {
|
||
return driveTmp;
|
||
}
|
||
return root;
|
||
};
|
||
const win32DefaultTmpSync = (path) => {
|
||
const { root } = parse$d(path);
|
||
const tmp = tmpdir();
|
||
const { root: tmpRoot } = parse$d(tmp);
|
||
if (root.toLowerCase() === tmpRoot.toLowerCase()) {
|
||
return tmp;
|
||
}
|
||
const driveTmp = resolve$1(root, '/temp');
|
||
if (isDirSync(driveTmp)) {
|
||
return driveTmp;
|
||
}
|
||
return root;
|
||
};
|
||
const posixDefaultTmp = async () => tmpdir();
|
||
const posixDefaultTmpSync = () => tmpdir();
|
||
const defaultTmp = platform === 'win32' ? win32DefaultTmp : posixDefaultTmp;
|
||
const defaultTmpSync = platform === 'win32' ? win32DefaultTmpSync : posixDefaultTmpSync;
|
||
|
||
// https://youtu.be/uhRWMGBjlO8?t=537
|
||
//
|
||
// 1. readdir
|
||
// 2. for each entry
|
||
// a. if a non-empty directory, recurse
|
||
// b. if an empty directory, move to random hidden file name in $TEMP
|
||
// c. unlink/rmdir $TEMP
|
||
//
|
||
// This works around the fact that unlink/rmdir is non-atomic and takes
|
||
// a non-deterministic amount of time to complete.
|
||
//
|
||
// However, it is HELLA SLOW, like 2-10x slower than a naive recursive rm.
|
||
const { lstat: lstat$1, rename, unlink: unlink$1, rmdir: rmdir$1, chmod } = promises;
|
||
// crypto.randomBytes is much slower, and Math.random() is enough here
|
||
const uniqueFilename = (path) => `.${basename(path)}.${Math.random()}`;
|
||
const unlinkFixEPERM = async (path) => unlink$1(path).catch((er) => {
|
||
if (er.code === 'EPERM') {
|
||
return chmod(path, 0o666).then(() => unlink$1(path), er2 => {
|
||
if (er2.code === 'ENOENT') {
|
||
return;
|
||
}
|
||
throw er;
|
||
});
|
||
}
|
||
else if (er.code === 'ENOENT') {
|
||
return;
|
||
}
|
||
throw er;
|
||
});
|
||
const unlinkFixEPERMSync = (path) => {
|
||
try {
|
||
unlinkSync(path);
|
||
}
|
||
catch (er) {
|
||
if (er?.code === 'EPERM') {
|
||
try {
|
||
return chmodSync(path, 0o666);
|
||
}
|
||
catch (er2) {
|
||
if (er2?.code === 'ENOENT') {
|
||
return;
|
||
}
|
||
throw er;
|
||
}
|
||
}
|
||
else if (er?.code === 'ENOENT') {
|
||
return;
|
||
}
|
||
throw er;
|
||
}
|
||
};
|
||
const rimrafMoveRemove = async (path, opt) => {
|
||
if (opt?.signal?.aborted) {
|
||
throw opt.signal.reason;
|
||
}
|
||
try {
|
||
return await rimrafMoveRemoveDir(path, opt, await lstat$1(path));
|
||
}
|
||
catch (er) {
|
||
if (er?.code === 'ENOENT')
|
||
return true;
|
||
throw er;
|
||
}
|
||
};
|
||
const rimrafMoveRemoveDir = async (path, opt, ent) => {
|
||
if (opt?.signal?.aborted) {
|
||
throw opt.signal.reason;
|
||
}
|
||
if (!opt.tmp) {
|
||
return rimrafMoveRemoveDir(path, { ...opt, tmp: await defaultTmp(path) }, ent);
|
||
}
|
||
if (path === opt.tmp && parse$d(path).root !== path) {
|
||
throw new Error('cannot delete temp directory used for deletion');
|
||
}
|
||
const entries = ent.isDirectory() ? await readdirOrError(path) : null;
|
||
if (!Array.isArray(entries)) {
|
||
// this can only happen if lstat/readdir lied, or if the dir was
|
||
// swapped out with a file at just the right moment.
|
||
/* c8 ignore start */
|
||
if (entries) {
|
||
if (entries.code === 'ENOENT') {
|
||
return true;
|
||
}
|
||
if (entries.code !== 'ENOTDIR') {
|
||
throw entries;
|
||
}
|
||
}
|
||
/* c8 ignore stop */
|
||
if (opt.filter && !(await opt.filter(path, ent))) {
|
||
return false;
|
||
}
|
||
await ignoreENOENT(tmpUnlink(path, opt.tmp, unlinkFixEPERM));
|
||
return true;
|
||
}
|
||
const removedAll = (await Promise.all(entries.map(ent => rimrafMoveRemoveDir(resolve$1(path, ent.name), opt, ent)))).reduce((a, b) => a && b, true);
|
||
if (!removedAll) {
|
||
return false;
|
||
}
|
||
// we don't ever ACTUALLY try to unlink /, because that can never work
|
||
// but when preserveRoot is false, we could be operating on it.
|
||
// No need to check if preserveRoot is not false.
|
||
if (opt.preserveRoot === false && path === parse$d(path).root) {
|
||
return false;
|
||
}
|
||
if (opt.filter && !(await opt.filter(path, ent))) {
|
||
return false;
|
||
}
|
||
await ignoreENOENT(tmpUnlink(path, opt.tmp, rmdir$1));
|
||
return true;
|
||
};
|
||
const tmpUnlink = async (path, tmp, rm) => {
|
||
const tmpFile = resolve$1(tmp, uniqueFilename(path));
|
||
await rename(path, tmpFile);
|
||
return await rm(tmpFile);
|
||
};
|
||
const rimrafMoveRemoveSync = (path, opt) => {
|
||
if (opt?.signal?.aborted) {
|
||
throw opt.signal.reason;
|
||
}
|
||
try {
|
||
return rimrafMoveRemoveDirSync(path, opt, lstatSync(path));
|
||
}
|
||
catch (er) {
|
||
if (er?.code === 'ENOENT')
|
||
return true;
|
||
throw er;
|
||
}
|
||
};
|
||
const rimrafMoveRemoveDirSync = (path, opt, ent) => {
|
||
if (opt?.signal?.aborted) {
|
||
throw opt.signal.reason;
|
||
}
|
||
if (!opt.tmp) {
|
||
return rimrafMoveRemoveDirSync(path, { ...opt, tmp: defaultTmpSync(path) }, ent);
|
||
}
|
||
const tmp = opt.tmp;
|
||
if (path === opt.tmp && parse$d(path).root !== path) {
|
||
throw new Error('cannot delete temp directory used for deletion');
|
||
}
|
||
const entries = ent.isDirectory() ? readdirOrErrorSync(path) : null;
|
||
if (!Array.isArray(entries)) {
|
||
// this can only happen if lstat/readdir lied, or if the dir was
|
||
// swapped out with a file at just the right moment.
|
||
/* c8 ignore start */
|
||
if (entries) {
|
||
if (entries.code === 'ENOENT') {
|
||
return true;
|
||
}
|
||
if (entries.code !== 'ENOTDIR') {
|
||
throw entries;
|
||
}
|
||
}
|
||
/* c8 ignore stop */
|
||
if (opt.filter && !opt.filter(path, ent)) {
|
||
return false;
|
||
}
|
||
ignoreENOENTSync(() => tmpUnlinkSync(path, tmp, unlinkFixEPERMSync));
|
||
return true;
|
||
}
|
||
let removedAll = true;
|
||
for (const ent of entries) {
|
||
const p = resolve$1(path, ent.name);
|
||
removedAll = rimrafMoveRemoveDirSync(p, opt, ent) && removedAll;
|
||
}
|
||
if (!removedAll) {
|
||
return false;
|
||
}
|
||
if (opt.preserveRoot === false && path === parse$d(path).root) {
|
||
return false;
|
||
}
|
||
if (opt.filter && !opt.filter(path, ent)) {
|
||
return false;
|
||
}
|
||
ignoreENOENTSync(() => tmpUnlinkSync(path, tmp, rmdirSync));
|
||
return true;
|
||
};
|
||
const tmpUnlinkSync = (path, tmp, rmSync) => {
|
||
const tmpFile = resolve$1(tmp, uniqueFilename(path));
|
||
renameSync(path, tmpFile);
|
||
return rmSync(tmpFile);
|
||
};
|
||
|
||
// This is the same as rimrafPosix, with the following changes:
|
||
//
|
||
// 1. EBUSY, ENFILE, EMFILE trigger retries and/or exponential backoff
|
||
// 2. All non-directories are removed first and then all directories are
|
||
// removed in a second sweep.
|
||
// 3. If we hit ENOTEMPTY in the second sweep, fall back to move-remove on
|
||
// the that folder.
|
||
//
|
||
// Note: "move then remove" is 2-10 times slower, and just as unreliable.
|
||
const { unlink, rmdir, lstat } = promises;
|
||
const rimrafWindowsFile = retryBusy(fixEPERM(unlink));
|
||
const rimrafWindowsFileSync = retryBusySync(fixEPERMSync(unlinkSync));
|
||
const rimrafWindowsDirRetry = retryBusy(fixEPERM(rmdir));
|
||
const rimrafWindowsDirRetrySync = retryBusySync(fixEPERMSync(rmdirSync));
|
||
const rimrafWindowsDirMoveRemoveFallback = async (path, opt) => {
|
||
/* c8 ignore start */
|
||
if (opt?.signal?.aborted) {
|
||
throw opt.signal.reason;
|
||
}
|
||
/* c8 ignore stop */
|
||
// already filtered, remove from options so we don't call unnecessarily
|
||
const { filter, ...options } = opt;
|
||
try {
|
||
return await rimrafWindowsDirRetry(path, options);
|
||
}
|
||
catch (er) {
|
||
if (er?.code === 'ENOTEMPTY') {
|
||
return await rimrafMoveRemove(path, options);
|
||
}
|
||
throw er;
|
||
}
|
||
};
|
||
const rimrafWindowsDirMoveRemoveFallbackSync = (path, opt) => {
|
||
if (opt?.signal?.aborted) {
|
||
throw opt.signal.reason;
|
||
}
|
||
// already filtered, remove from options so we don't call unnecessarily
|
||
const { filter, ...options } = opt;
|
||
try {
|
||
return rimrafWindowsDirRetrySync(path, options);
|
||
}
|
||
catch (er) {
|
||
const fer = er;
|
||
if (fer?.code === 'ENOTEMPTY') {
|
||
return rimrafMoveRemoveSync(path, options);
|
||
}
|
||
throw er;
|
||
}
|
||
};
|
||
const START = Symbol('start');
|
||
const CHILD = Symbol('child');
|
||
const FINISH = Symbol('finish');
|
||
const rimrafWindows = async (path, opt) => {
|
||
if (opt?.signal?.aborted) {
|
||
throw opt.signal.reason;
|
||
}
|
||
try {
|
||
return await rimrafWindowsDir(path, opt, await lstat(path), START);
|
||
}
|
||
catch (er) {
|
||
if (er?.code === 'ENOENT')
|
||
return true;
|
||
throw er;
|
||
}
|
||
};
|
||
const rimrafWindowsSync = (path, opt) => {
|
||
if (opt?.signal?.aborted) {
|
||
throw opt.signal.reason;
|
||
}
|
||
try {
|
||
return rimrafWindowsDirSync(path, opt, lstatSync(path), START);
|
||
}
|
||
catch (er) {
|
||
if (er?.code === 'ENOENT')
|
||
return true;
|
||
throw er;
|
||
}
|
||
};
|
||
const rimrafWindowsDir = async (path, opt, ent, state = START) => {
|
||
if (opt?.signal?.aborted) {
|
||
throw opt.signal.reason;
|
||
}
|
||
const entries = ent.isDirectory() ? await readdirOrError(path) : null;
|
||
if (!Array.isArray(entries)) {
|
||
// this can only happen if lstat/readdir lied, or if the dir was
|
||
// swapped out with a file at just the right moment.
|
||
/* c8 ignore start */
|
||
if (entries) {
|
||
if (entries.code === 'ENOENT') {
|
||
return true;
|
||
}
|
||
if (entries.code !== 'ENOTDIR') {
|
||
throw entries;
|
||
}
|
||
}
|
||
/* c8 ignore stop */
|
||
if (opt.filter && !(await opt.filter(path, ent))) {
|
||
return false;
|
||
}
|
||
// is a file
|
||
await ignoreENOENT(rimrafWindowsFile(path, opt));
|
||
return true;
|
||
}
|
||
const s = state === START ? CHILD : state;
|
||
const removedAll = (await Promise.all(entries.map(ent => rimrafWindowsDir(resolve$1(path, ent.name), opt, ent, s)))).reduce((a, b) => a && b, true);
|
||
if (state === START) {
|
||
return rimrafWindowsDir(path, opt, ent, FINISH);
|
||
}
|
||
else if (state === FINISH) {
|
||
if (opt.preserveRoot === false && path === parse$d(path).root) {
|
||
return false;
|
||
}
|
||
if (!removedAll) {
|
||
return false;
|
||
}
|
||
if (opt.filter && !(await opt.filter(path, ent))) {
|
||
return false;
|
||
}
|
||
await ignoreENOENT(rimrafWindowsDirMoveRemoveFallback(path, opt));
|
||
}
|
||
return true;
|
||
};
|
||
const rimrafWindowsDirSync = (path, opt, ent, state = START) => {
|
||
const entries = ent.isDirectory() ? readdirOrErrorSync(path) : null;
|
||
if (!Array.isArray(entries)) {
|
||
// this can only happen if lstat/readdir lied, or if the dir was
|
||
// swapped out with a file at just the right moment.
|
||
/* c8 ignore start */
|
||
if (entries) {
|
||
if (entries.code === 'ENOENT') {
|
||
return true;
|
||
}
|
||
if (entries.code !== 'ENOTDIR') {
|
||
throw entries;
|
||
}
|
||
}
|
||
/* c8 ignore stop */
|
||
if (opt.filter && !opt.filter(path, ent)) {
|
||
return false;
|
||
}
|
||
// is a file
|
||
ignoreENOENTSync(() => rimrafWindowsFileSync(path, opt));
|
||
return true;
|
||
}
|
||
let removedAll = true;
|
||
for (const ent of entries) {
|
||
const s = state === START ? CHILD : state;
|
||
const p = resolve$1(path, ent.name);
|
||
removedAll = rimrafWindowsDirSync(p, opt, ent, s) && removedAll;
|
||
}
|
||
if (state === START) {
|
||
return rimrafWindowsDirSync(path, opt, ent, FINISH);
|
||
}
|
||
else if (state === FINISH) {
|
||
if (opt.preserveRoot === false && path === parse$d(path).root) {
|
||
return false;
|
||
}
|
||
if (!removedAll) {
|
||
return false;
|
||
}
|
||
if (opt.filter && !opt.filter(path, ent)) {
|
||
return false;
|
||
}
|
||
ignoreENOENTSync(() => {
|
||
rimrafWindowsDirMoveRemoveFallbackSync(path, opt);
|
||
});
|
||
}
|
||
return true;
|
||
};
|
||
|
||
const rimrafManual = platform === 'win32' ? rimrafWindows : rimrafPosix;
|
||
const rimrafManualSync = platform === 'win32' ? rimrafWindowsSync : rimrafPosixSync;
|
||
|
||
const { rm } = promises;
|
||
const rimrafNative = async (path, opt) => {
|
||
await rm(path, {
|
||
...opt,
|
||
force: true,
|
||
recursive: true,
|
||
});
|
||
return true;
|
||
};
|
||
const rimrafNativeSync = (path, opt) => {
|
||
rmSync(path, {
|
||
...opt,
|
||
force: true,
|
||
recursive: true,
|
||
});
|
||
return true;
|
||
};
|
||
|
||
const version$1 = process.env.__TESTING_RIMRAF_NODE_VERSION__ || process.version;
|
||
const versArr = version$1.replace(/^v/, '').split('.');
|
||
/* c8 ignore start */
|
||
const [major = 0, minor = 0] = versArr.map(v => parseInt(v, 10));
|
||
/* c8 ignore stop */
|
||
const hasNative = major > 14 || (major === 14 && minor >= 14);
|
||
// we do NOT use native by default on Windows, because Node's native
|
||
// rm implementation is less advanced. Change this code if that changes.
|
||
const useNative = !hasNative || platform === 'win32'
|
||
? () => false
|
||
: opt => !opt?.signal && !opt?.filter;
|
||
const useNativeSync = !hasNative || platform === 'win32'
|
||
? () => false
|
||
: opt => !opt?.signal && !opt?.filter;
|
||
|
||
const wrap = (fn) => async (path, opt) => {
|
||
const options = optArg(opt);
|
||
if (options.glob) {
|
||
path = await glob$1(path, options.glob);
|
||
}
|
||
if (Array.isArray(path)) {
|
||
return !!(await Promise.all(path.map(p => fn(pathArg(p, options), options)))).reduce((a, b) => a && b, true);
|
||
}
|
||
else {
|
||
return !!(await fn(pathArg(path, options), options));
|
||
}
|
||
};
|
||
const wrapSync = (fn) => (path, opt) => {
|
||
const options = optArgSync(opt);
|
||
if (options.glob) {
|
||
path = globSync(path, options.glob);
|
||
}
|
||
if (Array.isArray(path)) {
|
||
return !!path
|
||
.map(p => fn(pathArg(p, options), options))
|
||
.reduce((a, b) => a && b, true);
|
||
}
|
||
else {
|
||
return !!fn(pathArg(path, options), options);
|
||
}
|
||
};
|
||
const nativeSync = wrapSync(rimrafNativeSync);
|
||
const native = Object.assign(wrap(rimrafNative), { sync: nativeSync });
|
||
const manualSync = wrapSync(rimrafManualSync);
|
||
const manual = Object.assign(wrap(rimrafManual), { sync: manualSync });
|
||
const windowsSync = wrapSync(rimrafWindowsSync);
|
||
const windows$1 = Object.assign(wrap(rimrafWindows), { sync: windowsSync });
|
||
const posixSync = wrapSync(rimrafPosixSync);
|
||
const posix = Object.assign(wrap(rimrafPosix), { sync: posixSync });
|
||
const moveRemoveSync = wrapSync(rimrafMoveRemoveSync);
|
||
const moveRemove = Object.assign(wrap(rimrafMoveRemove), {
|
||
sync: moveRemoveSync,
|
||
});
|
||
const rimrafSync = wrapSync((path, opt) => useNativeSync(opt) ? rimrafNativeSync(path, opt) : rimrafManualSync(path, opt));
|
||
const rimraf_ = wrap((path, opt) => useNative(opt) ? rimrafNative(path, opt) : rimrafManual(path, opt));
|
||
const rimraf = Object.assign(rimraf_, {
|
||
rimraf: rimraf_,
|
||
sync: rimrafSync,
|
||
rimrafSync: rimrafSync,
|
||
manual,
|
||
manualSync,
|
||
native,
|
||
nativeSync,
|
||
posix,
|
||
posixSync,
|
||
windows: windows$1,
|
||
windowsSync,
|
||
moveRemove,
|
||
moveRemoveSync,
|
||
});
|
||
rimraf.rimraf = rimraf;
|
||
|
||
var src$2 = {exports: {}};
|
||
|
||
var node$1 = {exports: {}};
|
||
|
||
/* eslint-env browser */
|
||
|
||
const level$1 = (() => {
|
||
|
||
if (/\b(Chrome|Chromium)\//.test(undefined)) {
|
||
return 1;
|
||
}
|
||
|
||
return 0;
|
||
})();
|
||
|
||
const colorSupport$1 = level$1 !== 0 && {
|
||
level: level$1,
|
||
hasBasic: true,
|
||
has256: level$1 >= 2,
|
||
has16m: level$1 >= 3,
|
||
};
|
||
|
||
const supportsColor$1 = {
|
||
stdout: colorSupport$1,
|
||
stderr: colorSupport$1,
|
||
};
|
||
|
||
var browser$2 = /*#__PURE__*/Object.freeze({
|
||
__proto__: null,
|
||
default: supportsColor$1
|
||
});
|
||
|
||
var require$$2 = /*@__PURE__*/getAugmentedNamespace(browser$2);
|
||
|
||
/**
|
||
* Helpers.
|
||
*/
|
||
|
||
var ms$1;
|
||
var hasRequiredMs$1;
|
||
|
||
function requireMs$1 () {
|
||
if (hasRequiredMs$1) return ms$1;
|
||
hasRequiredMs$1 = 1;
|
||
var s = 1000;
|
||
var m = s * 60;
|
||
var h = m * 60;
|
||
var d = h * 24;
|
||
var w = d * 7;
|
||
var y = d * 365.25;
|
||
|
||
/**
|
||
* Parse or format the given `val`.
|
||
*
|
||
* Options:
|
||
*
|
||
* - `long` verbose formatting [false]
|
||
*
|
||
* @param {String|Number} val
|
||
* @param {Object} [options]
|
||
* @throws {Error} throw an error if val is not a non-empty string or a number
|
||
* @return {String|Number}
|
||
* @api public
|
||
*/
|
||
|
||
ms$1 = function(val, options) {
|
||
options = options || {};
|
||
var type = typeof val;
|
||
if (type === 'string' && val.length > 0) {
|
||
return parse(val);
|
||
} else if (type === 'number' && isFinite(val)) {
|
||
return options.long ? fmtLong(val) : fmtShort(val);
|
||
}
|
||
throw new Error(
|
||
'val is not a non-empty string or a valid number. val=' +
|
||
JSON.stringify(val)
|
||
);
|
||
};
|
||
|
||
/**
|
||
* Parse the given `str` and return milliseconds.
|
||
*
|
||
* @param {String} str
|
||
* @return {Number}
|
||
* @api private
|
||
*/
|
||
|
||
function parse(str) {
|
||
str = String(str);
|
||
if (str.length > 100) {
|
||
return;
|
||
}
|
||
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
|
||
str
|
||
);
|
||
if (!match) {
|
||
return;
|
||
}
|
||
var n = parseFloat(match[1]);
|
||
var type = (match[2] || 'ms').toLowerCase();
|
||
switch (type) {
|
||
case 'years':
|
||
case 'year':
|
||
case 'yrs':
|
||
case 'yr':
|
||
case 'y':
|
||
return n * y;
|
||
case 'weeks':
|
||
case 'week':
|
||
case 'w':
|
||
return n * w;
|
||
case 'days':
|
||
case 'day':
|
||
case 'd':
|
||
return n * d;
|
||
case 'hours':
|
||
case 'hour':
|
||
case 'hrs':
|
||
case 'hr':
|
||
case 'h':
|
||
return n * h;
|
||
case 'minutes':
|
||
case 'minute':
|
||
case 'mins':
|
||
case 'min':
|
||
case 'm':
|
||
return n * m;
|
||
case 'seconds':
|
||
case 'second':
|
||
case 'secs':
|
||
case 'sec':
|
||
case 's':
|
||
return n * s;
|
||
case 'milliseconds':
|
||
case 'millisecond':
|
||
case 'msecs':
|
||
case 'msec':
|
||
case 'ms':
|
||
return n;
|
||
default:
|
||
return undefined;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Short format for `ms`.
|
||
*
|
||
* @param {Number} ms
|
||
* @return {String}
|
||
* @api private
|
||
*/
|
||
|
||
function fmtShort(ms) {
|
||
var msAbs = Math.abs(ms);
|
||
if (msAbs >= d) {
|
||
return Math.round(ms / d) + 'd';
|
||
}
|
||
if (msAbs >= h) {
|
||
return Math.round(ms / h) + 'h';
|
||
}
|
||
if (msAbs >= m) {
|
||
return Math.round(ms / m) + 'm';
|
||
}
|
||
if (msAbs >= s) {
|
||
return Math.round(ms / s) + 's';
|
||
}
|
||
return ms + 'ms';
|
||
}
|
||
|
||
/**
|
||
* Long format for `ms`.
|
||
*
|
||
* @param {Number} ms
|
||
* @return {String}
|
||
* @api private
|
||
*/
|
||
|
||
function fmtLong(ms) {
|
||
var msAbs = Math.abs(ms);
|
||
if (msAbs >= d) {
|
||
return plural(ms, msAbs, d, 'day');
|
||
}
|
||
if (msAbs >= h) {
|
||
return plural(ms, msAbs, h, 'hour');
|
||
}
|
||
if (msAbs >= m) {
|
||
return plural(ms, msAbs, m, 'minute');
|
||
}
|
||
if (msAbs >= s) {
|
||
return plural(ms, msAbs, s, 'second');
|
||
}
|
||
return ms + ' ms';
|
||
}
|
||
|
||
/**
|
||
* Pluralization helper.
|
||
*/
|
||
|
||
function plural(ms, msAbs, n, name) {
|
||
var isPlural = msAbs >= n * 1.5;
|
||
return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
|
||
}
|
||
return ms$1;
|
||
}
|
||
|
||
var common$e;
|
||
var hasRequiredCommon;
|
||
|
||
function requireCommon () {
|
||
if (hasRequiredCommon) return common$e;
|
||
hasRequiredCommon = 1;
|
||
/**
|
||
* This is the common logic for both the Node.js and web browser
|
||
* implementations of `debug()`.
|
||
*/
|
||
|
||
function setup(env) {
|
||
createDebug.debug = createDebug;
|
||
createDebug.default = createDebug;
|
||
createDebug.coerce = coerce;
|
||
createDebug.disable = disable;
|
||
createDebug.enable = enable;
|
||
createDebug.enabled = enabled;
|
||
createDebug.humanize = requireMs$1();
|
||
createDebug.destroy = destroy;
|
||
|
||
Object.keys(env).forEach(key => {
|
||
createDebug[key] = env[key];
|
||
});
|
||
|
||
/**
|
||
* The currently active debug mode names, and names to skip.
|
||
*/
|
||
|
||
createDebug.names = [];
|
||
createDebug.skips = [];
|
||
|
||
/**
|
||
* Map of special "%n" handling functions, for the debug "format" argument.
|
||
*
|
||
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
|
||
*/
|
||
createDebug.formatters = {};
|
||
|
||
/**
|
||
* Selects a color for a debug namespace
|
||
* @param {String} namespace The namespace string for the debug instance to be colored
|
||
* @return {Number|String} An ANSI color code for the given namespace
|
||
* @api private
|
||
*/
|
||
function selectColor(namespace) {
|
||
let hash = 0;
|
||
|
||
for (let i = 0; i < namespace.length; i++) {
|
||
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
|
||
hash |= 0; // Convert to 32bit integer
|
||
}
|
||
|
||
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
|
||
}
|
||
createDebug.selectColor = selectColor;
|
||
|
||
/**
|
||
* Create a debugger with the given `namespace`.
|
||
*
|
||
* @param {String} namespace
|
||
* @return {Function}
|
||
* @api public
|
||
*/
|
||
function createDebug(namespace) {
|
||
let prevTime;
|
||
let enableOverride = null;
|
||
let namespacesCache;
|
||
let enabledCache;
|
||
|
||
function debug(...args) {
|
||
// Disabled?
|
||
if (!debug.enabled) {
|
||
return;
|
||
}
|
||
|
||
const self = debug;
|
||
|
||
// Set `diff` timestamp
|
||
const curr = Number(new Date());
|
||
const ms = curr - (prevTime || curr);
|
||
self.diff = ms;
|
||
self.prev = prevTime;
|
||
self.curr = curr;
|
||
prevTime = curr;
|
||
|
||
args[0] = createDebug.coerce(args[0]);
|
||
|
||
if (typeof args[0] !== 'string') {
|
||
// Anything else let's inspect with %O
|
||
args.unshift('%O');
|
||
}
|
||
|
||
// Apply any `formatters` transformations
|
||
let index = 0;
|
||
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
|
||
// If we encounter an escaped % then don't increase the array index
|
||
if (match === '%%') {
|
||
return '%';
|
||
}
|
||
index++;
|
||
const formatter = createDebug.formatters[format];
|
||
if (typeof formatter === 'function') {
|
||
const val = args[index];
|
||
match = formatter.call(self, val);
|
||
|
||
// Now we need to remove `args[index]` since it's inlined in the `format`
|
||
args.splice(index, 1);
|
||
index--;
|
||
}
|
||
return match;
|
||
});
|
||
|
||
// Apply env-specific formatting (colors, etc.)
|
||
createDebug.formatArgs.call(self, args);
|
||
|
||
const logFn = self.log || createDebug.log;
|
||
logFn.apply(self, args);
|
||
}
|
||
|
||
debug.namespace = namespace;
|
||
debug.useColors = createDebug.useColors();
|
||
debug.color = createDebug.selectColor(namespace);
|
||
debug.extend = extend;
|
||
debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.
|
||
|
||
Object.defineProperty(debug, 'enabled', {
|
||
enumerable: true,
|
||
configurable: false,
|
||
get: () => {
|
||
if (enableOverride !== null) {
|
||
return enableOverride;
|
||
}
|
||
if (namespacesCache !== createDebug.namespaces) {
|
||
namespacesCache = createDebug.namespaces;
|
||
enabledCache = createDebug.enabled(namespace);
|
||
}
|
||
|
||
return enabledCache;
|
||
},
|
||
set: v => {
|
||
enableOverride = v;
|
||
}
|
||
});
|
||
|
||
// Env-specific initialization logic for debug instances
|
||
if (typeof createDebug.init === 'function') {
|
||
createDebug.init(debug);
|
||
}
|
||
|
||
return debug;
|
||
}
|
||
|
||
function extend(namespace, delimiter) {
|
||
const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
|
||
newDebug.log = this.log;
|
||
return newDebug;
|
||
}
|
||
|
||
/**
|
||
* Enables a debug mode by namespaces. This can include modes
|
||
* separated by a colon and wildcards.
|
||
*
|
||
* @param {String} namespaces
|
||
* @api public
|
||
*/
|
||
function enable(namespaces) {
|
||
createDebug.save(namespaces);
|
||
createDebug.namespaces = namespaces;
|
||
|
||
createDebug.names = [];
|
||
createDebug.skips = [];
|
||
|
||
let i;
|
||
const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
|
||
const len = split.length;
|
||
|
||
for (i = 0; i < len; i++) {
|
||
if (!split[i]) {
|
||
// ignore empty strings
|
||
continue;
|
||
}
|
||
|
||
namespaces = split[i].replace(/\*/g, '.*?');
|
||
|
||
if (namespaces[0] === '-') {
|
||
createDebug.skips.push(new RegExp('^' + namespaces.slice(1) + '$'));
|
||
} else {
|
||
createDebug.names.push(new RegExp('^' + namespaces + '$'));
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Disable debug output.
|
||
*
|
||
* @return {String} namespaces
|
||
* @api public
|
||
*/
|
||
function disable() {
|
||
const namespaces = [
|
||
...createDebug.names.map(toNamespace),
|
||
...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace)
|
||
].join(',');
|
||
createDebug.enable('');
|
||
return namespaces;
|
||
}
|
||
|
||
/**
|
||
* Returns true if the given mode name is enabled, false otherwise.
|
||
*
|
||
* @param {String} name
|
||
* @return {Boolean}
|
||
* @api public
|
||
*/
|
||
function enabled(name) {
|
||
if (name[name.length - 1] === '*') {
|
||
return true;
|
||
}
|
||
|
||
let i;
|
||
let len;
|
||
|
||
for (i = 0, len = createDebug.skips.length; i < len; i++) {
|
||
if (createDebug.skips[i].test(name)) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
for (i = 0, len = createDebug.names.length; i < len; i++) {
|
||
if (createDebug.names[i].test(name)) {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Convert regexp to namespace
|
||
*
|
||
* @param {RegExp} regxep
|
||
* @return {String} namespace
|
||
* @api private
|
||
*/
|
||
function toNamespace(regexp) {
|
||
return regexp.toString()
|
||
.substring(2, regexp.toString().length - 2)
|
||
.replace(/\.\*\?$/, '*');
|
||
}
|
||
|
||
/**
|
||
* Coerce `val`.
|
||
*
|
||
* @param {Mixed} val
|
||
* @return {Mixed}
|
||
* @api private
|
||
*/
|
||
function coerce(val) {
|
||
if (val instanceof Error) {
|
||
return val.stack || val.message;
|
||
}
|
||
return val;
|
||
}
|
||
|
||
/**
|
||
* XXX DO NOT USE. This is a temporary stub function.
|
||
* XXX It WILL be removed in the next major release.
|
||
*/
|
||
function destroy() {
|
||
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
|
||
}
|
||
|
||
createDebug.enable(createDebug.load());
|
||
|
||
return createDebug;
|
||
}
|
||
|
||
common$e = setup;
|
||
return common$e;
|
||
}
|
||
|
||
/**
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var hasRequiredNode$1;
|
||
|
||
function requireNode$1 () {
|
||
if (hasRequiredNode$1) return node$1.exports;
|
||
hasRequiredNode$1 = 1;
|
||
(function (module, exports) {
|
||
const tty = require$$0$5;
|
||
const util = require$$0$4;
|
||
|
||
/**
|
||
* This is the Node.js implementation of `debug()`.
|
||
*/
|
||
|
||
exports.init = init;
|
||
exports.log = log;
|
||
exports.formatArgs = formatArgs;
|
||
exports.save = save;
|
||
exports.load = load;
|
||
exports.useColors = useColors;
|
||
exports.destroy = util.deprecate(
|
||
() => {},
|
||
'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'
|
||
);
|
||
|
||
/**
|
||
* Colors.
|
||
*/
|
||
|
||
exports.colors = [6, 2, 3, 4, 5, 1];
|
||
|
||
try {
|
||
// Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
|
||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||
const supportsColor = require$$2;
|
||
|
||
if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
|
||
exports.colors = [
|
||
20,
|
||
21,
|
||
26,
|
||
27,
|
||
32,
|
||
33,
|
||
38,
|
||
39,
|
||
40,
|
||
41,
|
||
42,
|
||
43,
|
||
44,
|
||
45,
|
||
56,
|
||
57,
|
||
62,
|
||
63,
|
||
68,
|
||
69,
|
||
74,
|
||
75,
|
||
76,
|
||
77,
|
||
78,
|
||
79,
|
||
80,
|
||
81,
|
||
92,
|
||
93,
|
||
98,
|
||
99,
|
||
112,
|
||
113,
|
||
128,
|
||
129,
|
||
134,
|
||
135,
|
||
148,
|
||
149,
|
||
160,
|
||
161,
|
||
162,
|
||
163,
|
||
164,
|
||
165,
|
||
166,
|
||
167,
|
||
168,
|
||
169,
|
||
170,
|
||
171,
|
||
172,
|
||
173,
|
||
178,
|
||
179,
|
||
184,
|
||
185,
|
||
196,
|
||
197,
|
||
198,
|
||
199,
|
||
200,
|
||
201,
|
||
202,
|
||
203,
|
||
204,
|
||
205,
|
||
206,
|
||
207,
|
||
208,
|
||
209,
|
||
214,
|
||
215,
|
||
220,
|
||
221
|
||
];
|
||
}
|
||
} catch (error) {
|
||
// Swallow - we only care if `supports-color` is available; it doesn't have to be.
|
||
}
|
||
|
||
/**
|
||
* Build up the default `inspectOpts` object from the environment variables.
|
||
*
|
||
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
|
||
*/
|
||
|
||
exports.inspectOpts = Object.keys(process.env).filter(key => {
|
||
return /^debug_/i.test(key);
|
||
}).reduce((obj, key) => {
|
||
// Camel-case
|
||
const prop = key
|
||
.substring(6)
|
||
.toLowerCase()
|
||
.replace(/_([a-z])/g, (_, k) => {
|
||
return k.toUpperCase();
|
||
});
|
||
|
||
// Coerce string value into JS value
|
||
let val = process.env[key];
|
||
if (/^(yes|on|true|enabled)$/i.test(val)) {
|
||
val = true;
|
||
} else if (/^(no|off|false|disabled)$/i.test(val)) {
|
||
val = false;
|
||
} else if (val === 'null') {
|
||
val = null;
|
||
} else {
|
||
val = Number(val);
|
||
}
|
||
|
||
obj[prop] = val;
|
||
return obj;
|
||
}, {});
|
||
|
||
/**
|
||
* Is stdout a TTY? Colored output is enabled when `true`.
|
||
*/
|
||
|
||
function useColors() {
|
||
return 'colors' in exports.inspectOpts ?
|
||
Boolean(exports.inspectOpts.colors) :
|
||
tty.isatty(process.stderr.fd);
|
||
}
|
||
|
||
/**
|
||
* Adds ANSI color escape codes if enabled.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
function formatArgs(args) {
|
||
const {namespace: name, useColors} = this;
|
||
|
||
if (useColors) {
|
||
const c = this.color;
|
||
const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c);
|
||
const prefix = ` ${colorCode};1m${name} \u001B[0m`;
|
||
|
||
args[0] = prefix + args[0].split('\n').join('\n' + prefix);
|
||
args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m');
|
||
} else {
|
||
args[0] = getDate() + name + ' ' + args[0];
|
||
}
|
||
}
|
||
|
||
function getDate() {
|
||
if (exports.inspectOpts.hideDate) {
|
||
return '';
|
||
}
|
||
return new Date().toISOString() + ' ';
|
||
}
|
||
|
||
/**
|
||
* Invokes `util.format()` with the specified arguments and writes to stderr.
|
||
*/
|
||
|
||
function log(...args) {
|
||
return process.stderr.write(util.format(...args) + '\n');
|
||
}
|
||
|
||
/**
|
||
* Save `namespaces`.
|
||
*
|
||
* @param {String} namespaces
|
||
* @api private
|
||
*/
|
||
function save(namespaces) {
|
||
if (namespaces) {
|
||
process.env.DEBUG = namespaces;
|
||
} else {
|
||
// If you set a process.env field to null or undefined, it gets cast to the
|
||
// string 'null' or 'undefined'. Just delete instead.
|
||
delete process.env.DEBUG;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Load `namespaces`.
|
||
*
|
||
* @return {String} returns the previously persisted debug modes
|
||
* @api private
|
||
*/
|
||
|
||
function load() {
|
||
return process.env.DEBUG;
|
||
}
|
||
|
||
/**
|
||
* Init logic for `debug` instances.
|
||
*
|
||
* Create a new `inspectOpts` object in case `useColors` is set
|
||
* differently for a particular `debug` instance.
|
||
*/
|
||
|
||
function init(debug) {
|
||
debug.inspectOpts = {};
|
||
|
||
const keys = Object.keys(exports.inspectOpts);
|
||
for (let i = 0; i < keys.length; i++) {
|
||
debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
|
||
}
|
||
}
|
||
|
||
module.exports = requireCommon()(exports);
|
||
|
||
const {formatters} = module.exports;
|
||
|
||
/**
|
||
* Map %o to `util.inspect()`, all on a single line.
|
||
*/
|
||
|
||
formatters.o = function (v) {
|
||
this.inspectOpts.colors = this.useColors;
|
||
return util.inspect(v, this.inspectOpts)
|
||
.split('\n')
|
||
.map(str => str.trim())
|
||
.join(' ');
|
||
};
|
||
|
||
/**
|
||
* Map %O to `util.inspect()`, allowing multiple lines if needed.
|
||
*/
|
||
|
||
formatters.O = function (v) {
|
||
this.inspectOpts.colors = this.useColors;
|
||
return util.inspect(v, this.inspectOpts);
|
||
};
|
||
} (node$1, node$1.exports));
|
||
return node$1.exports;
|
||
}
|
||
|
||
var browser$1 = {exports: {}};
|
||
|
||
/* eslint-env browser */
|
||
|
||
var hasRequiredBrowser$1;
|
||
|
||
function requireBrowser$1 () {
|
||
if (hasRequiredBrowser$1) return browser$1.exports;
|
||
hasRequiredBrowser$1 = 1;
|
||
(function (module, exports) {
|
||
/**
|
||
* This is the web browser implementation of `debug()`.
|
||
*/
|
||
|
||
exports.formatArgs = formatArgs;
|
||
exports.save = save;
|
||
exports.load = load;
|
||
exports.useColors = useColors;
|
||
exports.storage = localstorage();
|
||
exports.destroy = (() => {
|
||
let warned = false;
|
||
|
||
return () => {
|
||
if (!warned) {
|
||
warned = true;
|
||
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
|
||
}
|
||
};
|
||
})();
|
||
|
||
/**
|
||
* Colors.
|
||
*/
|
||
|
||
exports.colors = [
|
||
'#0000CC',
|
||
'#0000FF',
|
||
'#0033CC',
|
||
'#0033FF',
|
||
'#0066CC',
|
||
'#0066FF',
|
||
'#0099CC',
|
||
'#0099FF',
|
||
'#00CC00',
|
||
'#00CC33',
|
||
'#00CC66',
|
||
'#00CC99',
|
||
'#00CCCC',
|
||
'#00CCFF',
|
||
'#3300CC',
|
||
'#3300FF',
|
||
'#3333CC',
|
||
'#3333FF',
|
||
'#3366CC',
|
||
'#3366FF',
|
||
'#3399CC',
|
||
'#3399FF',
|
||
'#33CC00',
|
||
'#33CC33',
|
||
'#33CC66',
|
||
'#33CC99',
|
||
'#33CCCC',
|
||
'#33CCFF',
|
||
'#6600CC',
|
||
'#6600FF',
|
||
'#6633CC',
|
||
'#6633FF',
|
||
'#66CC00',
|
||
'#66CC33',
|
||
'#9900CC',
|
||
'#9900FF',
|
||
'#9933CC',
|
||
'#9933FF',
|
||
'#99CC00',
|
||
'#99CC33',
|
||
'#CC0000',
|
||
'#CC0033',
|
||
'#CC0066',
|
||
'#CC0099',
|
||
'#CC00CC',
|
||
'#CC00FF',
|
||
'#CC3300',
|
||
'#CC3333',
|
||
'#CC3366',
|
||
'#CC3399',
|
||
'#CC33CC',
|
||
'#CC33FF',
|
||
'#CC6600',
|
||
'#CC6633',
|
||
'#CC9900',
|
||
'#CC9933',
|
||
'#CCCC00',
|
||
'#CCCC33',
|
||
'#FF0000',
|
||
'#FF0033',
|
||
'#FF0066',
|
||
'#FF0099',
|
||
'#FF00CC',
|
||
'#FF00FF',
|
||
'#FF3300',
|
||
'#FF3333',
|
||
'#FF3366',
|
||
'#FF3399',
|
||
'#FF33CC',
|
||
'#FF33FF',
|
||
'#FF6600',
|
||
'#FF6633',
|
||
'#FF9900',
|
||
'#FF9933',
|
||
'#FFCC00',
|
||
'#FFCC33'
|
||
];
|
||
|
||
/**
|
||
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
|
||
* and the Firebug extension (any Firefox version) are known
|
||
* to support "%c" CSS customizations.
|
||
*
|
||
* TODO: add a `localStorage` variable to explicitly enable/disable colors
|
||
*/
|
||
|
||
// eslint-disable-next-line complexity
|
||
function useColors() {
|
||
// NB: In an Electron preload script, document will be defined but not fully
|
||
// initialized. Since we know we're in Chrome, we'll just detect this case
|
||
// explicitly
|
||
if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
|
||
return true;
|
||
}
|
||
|
||
// Internet Explorer and Edge do not support colors.
|
||
if (typeof navigator !== 'undefined' && undefined && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
|
||
return false;
|
||
}
|
||
|
||
// Is webkit? http://stackoverflow.com/a/16459606/376773
|
||
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
|
||
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
|
||
// Is firebug? http://stackoverflow.com/a/398120/376773
|
||
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
|
||
// Is firefox >= v31?
|
||
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
||
(typeof navigator !== 'undefined' && undefined && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
|
||
// Double check webkit in userAgent just in case we are in a worker
|
||
(typeof navigator !== 'undefined' && undefined && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
|
||
}
|
||
|
||
/**
|
||
* Colorize log arguments if enabled.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
function formatArgs(args) {
|
||
args[0] = (this.useColors ? '%c' : '') +
|
||
this.namespace +
|
||
(this.useColors ? ' %c' : ' ') +
|
||
args[0] +
|
||
(this.useColors ? '%c ' : ' ') +
|
||
'+' + module.exports.humanize(this.diff);
|
||
|
||
if (!this.useColors) {
|
||
return;
|
||
}
|
||
|
||
const c = 'color: ' + this.color;
|
||
args.splice(1, 0, c, 'color: inherit');
|
||
|
||
// The final "%c" is somewhat tricky, because there could be other
|
||
// arguments passed either before or after the %c, so we need to
|
||
// figure out the correct index to insert the CSS into
|
||
let index = 0;
|
||
let lastC = 0;
|
||
args[0].replace(/%[a-zA-Z%]/g, match => {
|
||
if (match === '%%') {
|
||
return;
|
||
}
|
||
index++;
|
||
if (match === '%c') {
|
||
// We only are interested in the *last* %c
|
||
// (the user may have provided their own)
|
||
lastC = index;
|
||
}
|
||
});
|
||
|
||
args.splice(lastC, 0, c);
|
||
}
|
||
|
||
/**
|
||
* Invokes `console.debug()` when available.
|
||
* No-op when `console.debug` is not a "function".
|
||
* If `console.debug` is not available, falls back
|
||
* to `console.log`.
|
||
*
|
||
* @api public
|
||
*/
|
||
exports.log = console.debug || console.log || (() => {});
|
||
|
||
/**
|
||
* Save `namespaces`.
|
||
*
|
||
* @param {String} namespaces
|
||
* @api private
|
||
*/
|
||
function save(namespaces) {
|
||
try {
|
||
if (namespaces) {
|
||
exports.storage.setItem('debug', namespaces);
|
||
} else {
|
||
exports.storage.removeItem('debug');
|
||
}
|
||
} catch (error) {
|
||
// Swallow
|
||
// XXX (@Qix-) should we be logging these?
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Load `namespaces`.
|
||
*
|
||
* @return {String} returns the previously persisted debug modes
|
||
* @api private
|
||
*/
|
||
function load() {
|
||
let r;
|
||
try {
|
||
r = exports.storage.getItem('debug');
|
||
} catch (error) {
|
||
// Swallow
|
||
// XXX (@Qix-) should we be logging these?
|
||
}
|
||
|
||
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
|
||
if (!r && typeof process !== 'undefined' && 'env' in process) {
|
||
r = process.env.DEBUG;
|
||
}
|
||
|
||
return r;
|
||
}
|
||
|
||
/**
|
||
* Localstorage attempts to return the localstorage.
|
||
*
|
||
* This is necessary because safari throws
|
||
* when a user disables cookies/localstorage
|
||
* and you attempt to access it.
|
||
*
|
||
* @return {LocalStorage}
|
||
* @api private
|
||
*/
|
||
|
||
function localstorage() {
|
||
try {
|
||
// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
|
||
// The Browser also has localStorage in the global context.
|
||
return localStorage;
|
||
} catch (error) {
|
||
// Swallow
|
||
// XXX (@Qix-) should we be logging these?
|
||
}
|
||
}
|
||
|
||
module.exports = requireCommon()(exports);
|
||
|
||
const {formatters} = module.exports;
|
||
|
||
/**
|
||
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
|
||
*/
|
||
|
||
formatters.j = function (v) {
|
||
try {
|
||
return JSON.stringify(v);
|
||
} catch (error) {
|
||
return '[UnexpectedJSONParseError]: ' + error.message;
|
||
}
|
||
};
|
||
} (browser$1, browser$1.exports));
|
||
return browser$1.exports;
|
||
}
|
||
|
||
/**
|
||
* Detect Electron renderer / nwjs process, which is node, but we should
|
||
* treat as a browser.
|
||
*/
|
||
|
||
if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {
|
||
src$2.exports = requireBrowser$1();
|
||
} else {
|
||
src$2.exports = requireNode$1();
|
||
}
|
||
|
||
var srcExports$1 = src$2.exports;
|
||
var _debug = /*@__PURE__*/getDefaultExportFromCjs(srcExports$1);
|
||
|
||
var picocolors = {exports: {}};
|
||
|
||
let tty = require$$0$5;
|
||
|
||
let isColorSupported =
|
||
!("NO_COLOR" in process.env || process.argv.includes("--no-color")) &&
|
||
("FORCE_COLOR" in process.env ||
|
||
process.argv.includes("--color") ||
|
||
process.platform === "win32" ||
|
||
(tty.isatty(1) && process.env.TERM !== "dumb") ||
|
||
"CI" in process.env);
|
||
|
||
let formatter =
|
||
(open, close, replace = open) =>
|
||
input => {
|
||
let string = "" + input;
|
||
let index = string.indexOf(close, open.length);
|
||
return ~index
|
||
? open + replaceClose(string, close, replace, index) + close
|
||
: open + string + close
|
||
};
|
||
|
||
let replaceClose = (string, close, replace, index) => {
|
||
let start = string.substring(0, index) + replace;
|
||
let end = string.substring(index + close.length);
|
||
let nextIndex = end.indexOf(close);
|
||
return ~nextIndex ? start + replaceClose(end, close, replace, nextIndex) : start + end
|
||
};
|
||
|
||
let createColors = (enabled = isColorSupported) => ({
|
||
isColorSupported: enabled,
|
||
reset: enabled ? s => `\x1b[0m${s}\x1b[0m` : String,
|
||
bold: enabled ? formatter("\x1b[1m", "\x1b[22m", "\x1b[22m\x1b[1m") : String,
|
||
dim: enabled ? formatter("\x1b[2m", "\x1b[22m", "\x1b[22m\x1b[2m") : String,
|
||
italic: enabled ? formatter("\x1b[3m", "\x1b[23m") : String,
|
||
underline: enabled ? formatter("\x1b[4m", "\x1b[24m") : String,
|
||
inverse: enabled ? formatter("\x1b[7m", "\x1b[27m") : String,
|
||
hidden: enabled ? formatter("\x1b[8m", "\x1b[28m") : String,
|
||
strikethrough: enabled ? formatter("\x1b[9m", "\x1b[29m") : String,
|
||
black: enabled ? formatter("\x1b[30m", "\x1b[39m") : String,
|
||
red: enabled ? formatter("\x1b[31m", "\x1b[39m") : String,
|
||
green: enabled ? formatter("\x1b[32m", "\x1b[39m") : String,
|
||
yellow: enabled ? formatter("\x1b[33m", "\x1b[39m") : String,
|
||
blue: enabled ? formatter("\x1b[34m", "\x1b[39m") : String,
|
||
magenta: enabled ? formatter("\x1b[35m", "\x1b[39m") : String,
|
||
cyan: enabled ? formatter("\x1b[36m", "\x1b[39m") : String,
|
||
white: enabled ? formatter("\x1b[37m", "\x1b[39m") : String,
|
||
gray: enabled ? formatter("\x1b[90m", "\x1b[39m") : String,
|
||
bgBlack: enabled ? formatter("\x1b[40m", "\x1b[49m") : String,
|
||
bgRed: enabled ? formatter("\x1b[41m", "\x1b[49m") : String,
|
||
bgGreen: enabled ? formatter("\x1b[42m", "\x1b[49m") : String,
|
||
bgYellow: enabled ? formatter("\x1b[43m", "\x1b[49m") : String,
|
||
bgBlue: enabled ? formatter("\x1b[44m", "\x1b[49m") : String,
|
||
bgMagenta: enabled ? formatter("\x1b[45m", "\x1b[49m") : String,
|
||
bgCyan: enabled ? formatter("\x1b[46m", "\x1b[49m") : String,
|
||
bgWhite: enabled ? formatter("\x1b[47m", "\x1b[49m") : String,
|
||
});
|
||
|
||
picocolors.exports = createColors();
|
||
picocolors.exports.createColors = createColors;
|
||
|
||
var picocolorsExports = picocolors.exports;
|
||
var c$2 = /*@__PURE__*/getDefaultExportFromCjs(picocolorsExports);
|
||
|
||
const require$1 = createRequire(import.meta.url);
|
||
const PKG_ROOT = resolve$1(fileURLToPath$1(import.meta.url), "../..");
|
||
const DIST_CLIENT_PATH = resolve$1(PKG_ROOT, "client");
|
||
const APP_PATH = join(DIST_CLIENT_PATH, "app");
|
||
join(DIST_CLIENT_PATH, "shared");
|
||
const DEFAULT_THEME_PATH = join(DIST_CLIENT_PATH, "theme-default");
|
||
const SITE_DATA_ID = "@siteData";
|
||
const SITE_DATA_REQUEST_PATH = "/" + SITE_DATA_ID;
|
||
const vueRuntimePath = "vue/dist/vue.runtime.esm-bundler.js";
|
||
function resolveAliases({ root, themeDir }, ssr) {
|
||
const paths = {
|
||
"@theme": themeDir,
|
||
[SITE_DATA_ID]: SITE_DATA_REQUEST_PATH
|
||
};
|
||
const aliases = [
|
||
...Object.keys(paths).map((p) => ({
|
||
find: p,
|
||
replacement: paths[p]
|
||
})),
|
||
{
|
||
find: /^vitepress$/,
|
||
replacement: join(DIST_CLIENT_PATH, "/index.js")
|
||
},
|
||
{
|
||
find: /^vitepress\/theme$/,
|
||
replacement: join(DIST_CLIENT_PATH, "/theme-default/index.js")
|
||
}
|
||
];
|
||
if (!ssr) {
|
||
let vuePath;
|
||
try {
|
||
vuePath = require$1.resolve(vueRuntimePath, { paths: [root] });
|
||
} catch (e) {
|
||
vuePath = require$1.resolve(vueRuntimePath);
|
||
}
|
||
aliases.push({
|
||
find: /^vue$/,
|
||
replacement: vuePath
|
||
});
|
||
}
|
||
return aliases;
|
||
}
|
||
|
||
var tasks = {};
|
||
|
||
var utils$s = {};
|
||
|
||
var array$1 = {};
|
||
|
||
Object.defineProperty(array$1, "__esModule", { value: true });
|
||
array$1.splitWhen = array$1.flatten = void 0;
|
||
function flatten(items) {
|
||
return items.reduce((collection, item) => [].concat(collection, item), []);
|
||
}
|
||
array$1.flatten = flatten;
|
||
function splitWhen(items, predicate) {
|
||
const result = [[]];
|
||
let groupIndex = 0;
|
||
for (const item of items) {
|
||
if (predicate(item)) {
|
||
groupIndex++;
|
||
result[groupIndex] = [];
|
||
}
|
||
else {
|
||
result[groupIndex].push(item);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
array$1.splitWhen = splitWhen;
|
||
|
||
var errno$1 = {};
|
||
|
||
Object.defineProperty(errno$1, "__esModule", { value: true });
|
||
errno$1.isEnoentCodeError = void 0;
|
||
function isEnoentCodeError(error) {
|
||
return error.code === 'ENOENT';
|
||
}
|
||
errno$1.isEnoentCodeError = isEnoentCodeError;
|
||
|
||
var fs$9 = {};
|
||
|
||
Object.defineProperty(fs$9, "__esModule", { value: true });
|
||
fs$9.createDirentFromStats = void 0;
|
||
let DirentFromStats$1 = class DirentFromStats {
|
||
constructor(name, stats) {
|
||
this.name = name;
|
||
this.isBlockDevice = stats.isBlockDevice.bind(stats);
|
||
this.isCharacterDevice = stats.isCharacterDevice.bind(stats);
|
||
this.isDirectory = stats.isDirectory.bind(stats);
|
||
this.isFIFO = stats.isFIFO.bind(stats);
|
||
this.isFile = stats.isFile.bind(stats);
|
||
this.isSocket = stats.isSocket.bind(stats);
|
||
this.isSymbolicLink = stats.isSymbolicLink.bind(stats);
|
||
}
|
||
};
|
||
function createDirentFromStats$1(name, stats) {
|
||
return new DirentFromStats$1(name, stats);
|
||
}
|
||
fs$9.createDirentFromStats = createDirentFromStats$1;
|
||
|
||
var path$c = {};
|
||
|
||
Object.defineProperty(path$c, "__esModule", { value: true });
|
||
path$c.convertPosixPathToPattern = path$c.convertWindowsPathToPattern = path$c.convertPathToPattern = path$c.escapePosixPath = path$c.escapeWindowsPath = path$c.escape = path$c.removeLeadingDotSegment = path$c.makeAbsolute = path$c.unixify = void 0;
|
||
const os = require$$0$6;
|
||
const path$b = path$q;
|
||
const IS_WINDOWS_PLATFORM = os.platform() === 'win32';
|
||
const LEADING_DOT_SEGMENT_CHARACTERS_COUNT = 2; // ./ or .\\
|
||
/**
|
||
* All non-escaped special characters.
|
||
* Posix: ()*?[]{|}, !+@ before (, ! at the beginning, \\ before non-special characters.
|
||
* Windows: (){}[], !+@ before (, ! at the beginning.
|
||
*/
|
||
const POSIX_UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()*?[\]{|}]|^!|[!+@](?=\()|\\(?![!()*+?@[\]{|}]))/g;
|
||
const WINDOWS_UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()[\]{}]|^!|[!+@](?=\())/g;
|
||
/**
|
||
* The device path (\\.\ or \\?\).
|
||
* https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#dos-device-paths
|
||
*/
|
||
const DOS_DEVICE_PATH_RE = /^\\\\([.?])/;
|
||
/**
|
||
* All backslashes except those escaping special characters.
|
||
* Windows: !()+@{}
|
||
* https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions
|
||
*/
|
||
const WINDOWS_BACKSLASHES_RE = /\\(?![!()+@[\]{}])/g;
|
||
/**
|
||
* Designed to work only with simple paths: `dir\\file`.
|
||
*/
|
||
function unixify(filepath) {
|
||
return filepath.replace(/\\/g, '/');
|
||
}
|
||
path$c.unixify = unixify;
|
||
function makeAbsolute(cwd, filepath) {
|
||
return path$b.resolve(cwd, filepath);
|
||
}
|
||
path$c.makeAbsolute = makeAbsolute;
|
||
function removeLeadingDotSegment(entry) {
|
||
// We do not use `startsWith` because this is 10x slower than current implementation for some cases.
|
||
// eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
|
||
if (entry.charAt(0) === '.') {
|
||
const secondCharactery = entry.charAt(1);
|
||
if (secondCharactery === '/' || secondCharactery === '\\') {
|
||
return entry.slice(LEADING_DOT_SEGMENT_CHARACTERS_COUNT);
|
||
}
|
||
}
|
||
return entry;
|
||
}
|
||
path$c.removeLeadingDotSegment = removeLeadingDotSegment;
|
||
path$c.escape = IS_WINDOWS_PLATFORM ? escapeWindowsPath : escapePosixPath;
|
||
function escapeWindowsPath(pattern) {
|
||
return pattern.replace(WINDOWS_UNESCAPED_GLOB_SYMBOLS_RE, '\\$2');
|
||
}
|
||
path$c.escapeWindowsPath = escapeWindowsPath;
|
||
function escapePosixPath(pattern) {
|
||
return pattern.replace(POSIX_UNESCAPED_GLOB_SYMBOLS_RE, '\\$2');
|
||
}
|
||
path$c.escapePosixPath = escapePosixPath;
|
||
path$c.convertPathToPattern = IS_WINDOWS_PLATFORM ? convertWindowsPathToPattern : convertPosixPathToPattern;
|
||
function convertWindowsPathToPattern(filepath) {
|
||
return escapeWindowsPath(filepath)
|
||
.replace(DOS_DEVICE_PATH_RE, '//$1')
|
||
.replace(WINDOWS_BACKSLASHES_RE, '/');
|
||
}
|
||
path$c.convertWindowsPathToPattern = convertWindowsPathToPattern;
|
||
function convertPosixPathToPattern(filepath) {
|
||
return escapePosixPath(filepath);
|
||
}
|
||
path$c.convertPosixPathToPattern = convertPosixPathToPattern;
|
||
|
||
var pattern$1 = {};
|
||
|
||
/*!
|
||
* is-extglob <https://github.com/jonschlinkert/is-extglob>
|
||
*
|
||
* Copyright (c) 2014-2016, Jon Schlinkert.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
|
||
var isExtglob$1 = function isExtglob(str) {
|
||
if (typeof str !== 'string' || str === '') {
|
||
return false;
|
||
}
|
||
|
||
var match;
|
||
while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) {
|
||
if (match[2]) return true;
|
||
str = str.slice(match.index + match[0].length);
|
||
}
|
||
|
||
return false;
|
||
};
|
||
|
||
/*!
|
||
* is-glob <https://github.com/jonschlinkert/is-glob>
|
||
*
|
||
* Copyright (c) 2014-2017, Jon Schlinkert.
|
||
* Released under the MIT License.
|
||
*/
|
||
|
||
var isExtglob = isExtglob$1;
|
||
var chars = { '{': '}', '(': ')', '[': ']'};
|
||
var strictCheck = function(str) {
|
||
if (str[0] === '!') {
|
||
return true;
|
||
}
|
||
var index = 0;
|
||
var pipeIndex = -2;
|
||
var closeSquareIndex = -2;
|
||
var closeCurlyIndex = -2;
|
||
var closeParenIndex = -2;
|
||
var backSlashIndex = -2;
|
||
while (index < str.length) {
|
||
if (str[index] === '*') {
|
||
return true;
|
||
}
|
||
|
||
if (str[index + 1] === '?' && /[\].+)]/.test(str[index])) {
|
||
return true;
|
||
}
|
||
|
||
if (closeSquareIndex !== -1 && str[index] === '[' && str[index + 1] !== ']') {
|
||
if (closeSquareIndex < index) {
|
||
closeSquareIndex = str.indexOf(']', index);
|
||
}
|
||
if (closeSquareIndex > index) {
|
||
if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) {
|
||
return true;
|
||
}
|
||
backSlashIndex = str.indexOf('\\', index);
|
||
if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (closeCurlyIndex !== -1 && str[index] === '{' && str[index + 1] !== '}') {
|
||
closeCurlyIndex = str.indexOf('}', index);
|
||
if (closeCurlyIndex > index) {
|
||
backSlashIndex = str.indexOf('\\', index);
|
||
if (backSlashIndex === -1 || backSlashIndex > closeCurlyIndex) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (closeParenIndex !== -1 && str[index] === '(' && str[index + 1] === '?' && /[:!=]/.test(str[index + 2]) && str[index + 3] !== ')') {
|
||
closeParenIndex = str.indexOf(')', index);
|
||
if (closeParenIndex > index) {
|
||
backSlashIndex = str.indexOf('\\', index);
|
||
if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pipeIndex !== -1 && str[index] === '(' && str[index + 1] !== '|') {
|
||
if (pipeIndex < index) {
|
||
pipeIndex = str.indexOf('|', index);
|
||
}
|
||
if (pipeIndex !== -1 && str[pipeIndex + 1] !== ')') {
|
||
closeParenIndex = str.indexOf(')', pipeIndex);
|
||
if (closeParenIndex > pipeIndex) {
|
||
backSlashIndex = str.indexOf('\\', pipeIndex);
|
||
if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (str[index] === '\\') {
|
||
var open = str[index + 1];
|
||
index += 2;
|
||
var close = chars[open];
|
||
|
||
if (close) {
|
||
var n = str.indexOf(close, index);
|
||
if (n !== -1) {
|
||
index = n + 1;
|
||
}
|
||
}
|
||
|
||
if (str[index] === '!') {
|
||
return true;
|
||
}
|
||
} else {
|
||
index++;
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
|
||
var relaxedCheck = function(str) {
|
||
if (str[0] === '!') {
|
||
return true;
|
||
}
|
||
var index = 0;
|
||
while (index < str.length) {
|
||
if (/[*?{}()[\]]/.test(str[index])) {
|
||
return true;
|
||
}
|
||
|
||
if (str[index] === '\\') {
|
||
var open = str[index + 1];
|
||
index += 2;
|
||
var close = chars[open];
|
||
|
||
if (close) {
|
||
var n = str.indexOf(close, index);
|
||
if (n !== -1) {
|
||
index = n + 1;
|
||
}
|
||
}
|
||
|
||
if (str[index] === '!') {
|
||
return true;
|
||
}
|
||
} else {
|
||
index++;
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
|
||
var isGlob$1 = function isGlob(str, options) {
|
||
if (typeof str !== 'string' || str === '') {
|
||
return false;
|
||
}
|
||
|
||
if (isExtglob(str)) {
|
||
return true;
|
||
}
|
||
|
||
var check = strictCheck;
|
||
|
||
// optionally relax check
|
||
if (options && options.strict === false) {
|
||
check = relaxedCheck;
|
||
}
|
||
|
||
return check(str);
|
||
};
|
||
|
||
var isGlob = isGlob$1;
|
||
var pathPosixDirname = path$q.posix.dirname;
|
||
var isWin32 = require$$0$6.platform() === 'win32';
|
||
|
||
var slash$1 = '/';
|
||
var backslash = /\\/g;
|
||
var enclosure = /[\{\[].*[\}\]]$/;
|
||
var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/;
|
||
var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g;
|
||
|
||
/**
|
||
* @param {string} str
|
||
* @param {Object} opts
|
||
* @param {boolean} [opts.flipBackslashes=true]
|
||
* @returns {string}
|
||
*/
|
||
var globParent$1 = function globParent(str, opts) {
|
||
var options = Object.assign({ flipBackslashes: true }, opts);
|
||
|
||
// flip windows path separators
|
||
if (options.flipBackslashes && isWin32 && str.indexOf(slash$1) < 0) {
|
||
str = str.replace(backslash, slash$1);
|
||
}
|
||
|
||
// special case for strings ending in enclosure containing path separator
|
||
if (enclosure.test(str)) {
|
||
str += slash$1;
|
||
}
|
||
|
||
// preserves full path in case of trailing path separator
|
||
str += 'a';
|
||
|
||
// remove path parts that are globby
|
||
do {
|
||
str = pathPosixDirname(str);
|
||
} while (isGlob(str) || globby.test(str));
|
||
|
||
// remove escape chars and return result
|
||
return str.replace(escaped, '$1');
|
||
};
|
||
|
||
var utils$r = {};
|
||
|
||
(function (exports) {
|
||
|
||
exports.isInteger = num => {
|
||
if (typeof num === 'number') {
|
||
return Number.isInteger(num);
|
||
}
|
||
if (typeof num === 'string' && num.trim() !== '') {
|
||
return Number.isInteger(Number(num));
|
||
}
|
||
return false;
|
||
};
|
||
|
||
/**
|
||
* Find a node of the given type
|
||
*/
|
||
|
||
exports.find = (node, type) => node.nodes.find(node => node.type === type);
|
||
|
||
/**
|
||
* Find a node of the given type
|
||
*/
|
||
|
||
exports.exceedsLimit = (min, max, step = 1, limit) => {
|
||
if (limit === false) return false;
|
||
if (!exports.isInteger(min) || !exports.isInteger(max)) return false;
|
||
return ((Number(max) - Number(min)) / Number(step)) >= limit;
|
||
};
|
||
|
||
/**
|
||
* Escape the given node with '\\' before node.value
|
||
*/
|
||
|
||
exports.escapeNode = (block, n = 0, type) => {
|
||
let node = block.nodes[n];
|
||
if (!node) return;
|
||
|
||
if ((type && node.type === type) || node.type === 'open' || node.type === 'close') {
|
||
if (node.escaped !== true) {
|
||
node.value = '\\' + node.value;
|
||
node.escaped = true;
|
||
}
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Returns true if the given brace node should be enclosed in literal braces
|
||
*/
|
||
|
||
exports.encloseBrace = node => {
|
||
if (node.type !== 'brace') return false;
|
||
if ((node.commas >> 0 + node.ranges >> 0) === 0) {
|
||
node.invalid = true;
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
/**
|
||
* Returns true if a brace node is invalid.
|
||
*/
|
||
|
||
exports.isInvalidBrace = block => {
|
||
if (block.type !== 'brace') return false;
|
||
if (block.invalid === true || block.dollar) return true;
|
||
if ((block.commas >> 0 + block.ranges >> 0) === 0) {
|
||
block.invalid = true;
|
||
return true;
|
||
}
|
||
if (block.open !== true || block.close !== true) {
|
||
block.invalid = true;
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
/**
|
||
* Returns true if a node is an open or close node
|
||
*/
|
||
|
||
exports.isOpenOrClose = node => {
|
||
if (node.type === 'open' || node.type === 'close') {
|
||
return true;
|
||
}
|
||
return node.open === true || node.close === true;
|
||
};
|
||
|
||
/**
|
||
* Reduce an array of text nodes.
|
||
*/
|
||
|
||
exports.reduce = nodes => nodes.reduce((acc, node) => {
|
||
if (node.type === 'text') acc.push(node.value);
|
||
if (node.type === 'range') node.type = 'text';
|
||
return acc;
|
||
}, []);
|
||
|
||
/**
|
||
* Flatten an array
|
||
*/
|
||
|
||
exports.flatten = (...args) => {
|
||
const result = [];
|
||
const flat = arr => {
|
||
for (let i = 0; i < arr.length; i++) {
|
||
let ele = arr[i];
|
||
Array.isArray(ele) ? flat(ele) : ele !== void 0 && result.push(ele);
|
||
}
|
||
return result;
|
||
};
|
||
flat(args);
|
||
return result;
|
||
};
|
||
} (utils$r));
|
||
|
||
const utils$q = utils$r;
|
||
|
||
var stringify$7 = (ast, options = {}) => {
|
||
let stringify = (node, parent = {}) => {
|
||
let invalidBlock = options.escapeInvalid && utils$q.isInvalidBrace(parent);
|
||
let invalidNode = node.invalid === true && options.escapeInvalid === true;
|
||
let output = '';
|
||
|
||
if (node.value) {
|
||
if ((invalidBlock || invalidNode) && utils$q.isOpenOrClose(node)) {
|
||
return '\\' + node.value;
|
||
}
|
||
return node.value;
|
||
}
|
||
|
||
if (node.value) {
|
||
return node.value;
|
||
}
|
||
|
||
if (node.nodes) {
|
||
for (let child of node.nodes) {
|
||
output += stringify(child);
|
||
}
|
||
}
|
||
return output;
|
||
};
|
||
|
||
return stringify(ast);
|
||
};
|
||
|
||
/*!
|
||
* is-number <https://github.com/jonschlinkert/is-number>
|
||
*
|
||
* Copyright (c) 2014-present, Jon Schlinkert.
|
||
* Released under the MIT License.
|
||
*/
|
||
|
||
var isNumber$3 = function(num) {
|
||
if (typeof num === 'number') {
|
||
return num - num === 0;
|
||
}
|
||
if (typeof num === 'string' && num.trim() !== '') {
|
||
return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
|
||
}
|
||
return false;
|
||
};
|
||
|
||
/*!
|
||
* to-regex-range <https://github.com/micromatch/to-regex-range>
|
||
*
|
||
* Copyright (c) 2015-present, Jon Schlinkert.
|
||
* Released under the MIT License.
|
||
*/
|
||
|
||
const isNumber$2 = isNumber$3;
|
||
|
||
const toRegexRange$1 = (min, max, options) => {
|
||
if (isNumber$2(min) === false) {
|
||
throw new TypeError('toRegexRange: expected the first argument to be a number');
|
||
}
|
||
|
||
if (max === void 0 || min === max) {
|
||
return String(min);
|
||
}
|
||
|
||
if (isNumber$2(max) === false) {
|
||
throw new TypeError('toRegexRange: expected the second argument to be a number.');
|
||
}
|
||
|
||
let opts = { relaxZeros: true, ...options };
|
||
if (typeof opts.strictZeros === 'boolean') {
|
||
opts.relaxZeros = opts.strictZeros === false;
|
||
}
|
||
|
||
let relax = String(opts.relaxZeros);
|
||
let shorthand = String(opts.shorthand);
|
||
let capture = String(opts.capture);
|
||
let wrap = String(opts.wrap);
|
||
let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap;
|
||
|
||
if (toRegexRange$1.cache.hasOwnProperty(cacheKey)) {
|
||
return toRegexRange$1.cache[cacheKey].result;
|
||
}
|
||
|
||
let a = Math.min(min, max);
|
||
let b = Math.max(min, max);
|
||
|
||
if (Math.abs(a - b) === 1) {
|
||
let result = min + '|' + max;
|
||
if (opts.capture) {
|
||
return `(${result})`;
|
||
}
|
||
if (opts.wrap === false) {
|
||
return result;
|
||
}
|
||
return `(?:${result})`;
|
||
}
|
||
|
||
let isPadded = hasPadding(min) || hasPadding(max);
|
||
let state = { min, max, a, b };
|
||
let positives = [];
|
||
let negatives = [];
|
||
|
||
if (isPadded) {
|
||
state.isPadded = isPadded;
|
||
state.maxLen = String(state.max).length;
|
||
}
|
||
|
||
if (a < 0) {
|
||
let newMin = b < 0 ? Math.abs(b) : 1;
|
||
negatives = splitToPatterns(newMin, Math.abs(a), state, opts);
|
||
a = state.a = 0;
|
||
}
|
||
|
||
if (b >= 0) {
|
||
positives = splitToPatterns(a, b, state, opts);
|
||
}
|
||
|
||
state.negatives = negatives;
|
||
state.positives = positives;
|
||
state.result = collatePatterns(negatives, positives);
|
||
|
||
if (opts.capture === true) {
|
||
state.result = `(${state.result})`;
|
||
} else if (opts.wrap !== false && (positives.length + negatives.length) > 1) {
|
||
state.result = `(?:${state.result})`;
|
||
}
|
||
|
||
toRegexRange$1.cache[cacheKey] = state;
|
||
return state.result;
|
||
};
|
||
|
||
function collatePatterns(neg, pos, options) {
|
||
let onlyNegative = filterPatterns(neg, pos, '-', false) || [];
|
||
let onlyPositive = filterPatterns(pos, neg, '', false) || [];
|
||
let intersected = filterPatterns(neg, pos, '-?', true) || [];
|
||
let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive);
|
||
return subpatterns.join('|');
|
||
}
|
||
|
||
function splitToRanges(min, max) {
|
||
let nines = 1;
|
||
let zeros = 1;
|
||
|
||
let stop = countNines(min, nines);
|
||
let stops = new Set([max]);
|
||
|
||
while (min <= stop && stop <= max) {
|
||
stops.add(stop);
|
||
nines += 1;
|
||
stop = countNines(min, nines);
|
||
}
|
||
|
||
stop = countZeros(max + 1, zeros) - 1;
|
||
|
||
while (min < stop && stop <= max) {
|
||
stops.add(stop);
|
||
zeros += 1;
|
||
stop = countZeros(max + 1, zeros) - 1;
|
||
}
|
||
|
||
stops = [...stops];
|
||
stops.sort(compare);
|
||
return stops;
|
||
}
|
||
|
||
/**
|
||
* Convert a range to a regex pattern
|
||
* @param {Number} `start`
|
||
* @param {Number} `stop`
|
||
* @return {String}
|
||
*/
|
||
|
||
function rangeToPattern(start, stop, options) {
|
||
if (start === stop) {
|
||
return { pattern: start, count: [], digits: 0 };
|
||
}
|
||
|
||
let zipped = zip(start, stop);
|
||
let digits = zipped.length;
|
||
let pattern = '';
|
||
let count = 0;
|
||
|
||
for (let i = 0; i < digits; i++) {
|
||
let [startDigit, stopDigit] = zipped[i];
|
||
|
||
if (startDigit === stopDigit) {
|
||
pattern += startDigit;
|
||
|
||
} else if (startDigit !== '0' || stopDigit !== '9') {
|
||
pattern += toCharacterClass(startDigit, stopDigit);
|
||
|
||
} else {
|
||
count++;
|
||
}
|
||
}
|
||
|
||
if (count) {
|
||
pattern += options.shorthand === true ? '\\d' : '[0-9]';
|
||
}
|
||
|
||
return { pattern, count: [count], digits };
|
||
}
|
||
|
||
function splitToPatterns(min, max, tok, options) {
|
||
let ranges = splitToRanges(min, max);
|
||
let tokens = [];
|
||
let start = min;
|
||
let prev;
|
||
|
||
for (let i = 0; i < ranges.length; i++) {
|
||
let max = ranges[i];
|
||
let obj = rangeToPattern(String(start), String(max), options);
|
||
let zeros = '';
|
||
|
||
if (!tok.isPadded && prev && prev.pattern === obj.pattern) {
|
||
if (prev.count.length > 1) {
|
||
prev.count.pop();
|
||
}
|
||
|
||
prev.count.push(obj.count[0]);
|
||
prev.string = prev.pattern + toQuantifier(prev.count);
|
||
start = max + 1;
|
||
continue;
|
||
}
|
||
|
||
if (tok.isPadded) {
|
||
zeros = padZeros(max, tok, options);
|
||
}
|
||
|
||
obj.string = zeros + obj.pattern + toQuantifier(obj.count);
|
||
tokens.push(obj);
|
||
start = max + 1;
|
||
prev = obj;
|
||
}
|
||
|
||
return tokens;
|
||
}
|
||
|
||
function filterPatterns(arr, comparison, prefix, intersection, options) {
|
||
let result = [];
|
||
|
||
for (let ele of arr) {
|
||
let { string } = ele;
|
||
|
||
// only push if _both_ are negative...
|
||
if (!intersection && !contains(comparison, 'string', string)) {
|
||
result.push(prefix + string);
|
||
}
|
||
|
||
// or _both_ are positive
|
||
if (intersection && contains(comparison, 'string', string)) {
|
||
result.push(prefix + string);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Zip strings
|
||
*/
|
||
|
||
function zip(a, b) {
|
||
let arr = [];
|
||
for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]);
|
||
return arr;
|
||
}
|
||
|
||
function compare(a, b) {
|
||
return a > b ? 1 : b > a ? -1 : 0;
|
||
}
|
||
|
||
function contains(arr, key, val) {
|
||
return arr.some(ele => ele[key] === val);
|
||
}
|
||
|
||
function countNines(min, len) {
|
||
return Number(String(min).slice(0, -len) + '9'.repeat(len));
|
||
}
|
||
|
||
function countZeros(integer, zeros) {
|
||
return integer - (integer % Math.pow(10, zeros));
|
||
}
|
||
|
||
function toQuantifier(digits) {
|
||
let [start = 0, stop = ''] = digits;
|
||
if (stop || start > 1) {
|
||
return `{${start + (stop ? ',' + stop : '')}}`;
|
||
}
|
||
return '';
|
||
}
|
||
|
||
function toCharacterClass(a, b, options) {
|
||
return `[${a}${(b - a === 1) ? '' : '-'}${b}]`;
|
||
}
|
||
|
||
function hasPadding(str) {
|
||
return /^-?(0+)\d/.test(str);
|
||
}
|
||
|
||
function padZeros(value, tok, options) {
|
||
if (!tok.isPadded) {
|
||
return value;
|
||
}
|
||
|
||
let diff = Math.abs(tok.maxLen - String(value).length);
|
||
let relax = options.relaxZeros !== false;
|
||
|
||
switch (diff) {
|
||
case 0:
|
||
return '';
|
||
case 1:
|
||
return relax ? '0?' : '0';
|
||
case 2:
|
||
return relax ? '0{0,2}' : '00';
|
||
default: {
|
||
return relax ? `0{0,${diff}}` : `0{${diff}}`;
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Cache
|
||
*/
|
||
|
||
toRegexRange$1.cache = {};
|
||
toRegexRange$1.clearCache = () => (toRegexRange$1.cache = {});
|
||
|
||
/**
|
||
* Expose `toRegexRange`
|
||
*/
|
||
|
||
var toRegexRange_1 = toRegexRange$1;
|
||
|
||
/*!
|
||
* fill-range <https://github.com/jonschlinkert/fill-range>
|
||
*
|
||
* Copyright (c) 2014-present, Jon Schlinkert.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
|
||
const util$1 = require$$0$4;
|
||
const toRegexRange = toRegexRange_1;
|
||
|
||
const isObject$5 = val => val !== null && typeof val === 'object' && !Array.isArray(val);
|
||
|
||
const transform = toNumber => {
|
||
return value => toNumber === true ? Number(value) : String(value);
|
||
};
|
||
|
||
const isValidValue = value => {
|
||
return typeof value === 'number' || (typeof value === 'string' && value !== '');
|
||
};
|
||
|
||
const isNumber$1 = num => Number.isInteger(+num);
|
||
|
||
const zeros = input => {
|
||
let value = `${input}`;
|
||
let index = -1;
|
||
if (value[0] === '-') value = value.slice(1);
|
||
if (value === '0') return false;
|
||
while (value[++index] === '0');
|
||
return index > 0;
|
||
};
|
||
|
||
const stringify$6 = (start, end, options) => {
|
||
if (typeof start === 'string' || typeof end === 'string') {
|
||
return true;
|
||
}
|
||
return options.stringify === true;
|
||
};
|
||
|
||
const pad = (input, maxLength, toNumber) => {
|
||
if (maxLength > 0) {
|
||
let dash = input[0] === '-' ? '-' : '';
|
||
if (dash) input = input.slice(1);
|
||
input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0'));
|
||
}
|
||
if (toNumber === false) {
|
||
return String(input);
|
||
}
|
||
return input;
|
||
};
|
||
|
||
const toMaxLen = (input, maxLength) => {
|
||
let negative = input[0] === '-' ? '-' : '';
|
||
if (negative) {
|
||
input = input.slice(1);
|
||
maxLength--;
|
||
}
|
||
while (input.length < maxLength) input = '0' + input;
|
||
return negative ? ('-' + input) : input;
|
||
};
|
||
|
||
const toSequence = (parts, options) => {
|
||
parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
||
parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
||
|
||
let prefix = options.capture ? '' : '?:';
|
||
let positives = '';
|
||
let negatives = '';
|
||
let result;
|
||
|
||
if (parts.positives.length) {
|
||
positives = parts.positives.join('|');
|
||
}
|
||
|
||
if (parts.negatives.length) {
|
||
negatives = `-(${prefix}${parts.negatives.join('|')})`;
|
||
}
|
||
|
||
if (positives && negatives) {
|
||
result = `${positives}|${negatives}`;
|
||
} else {
|
||
result = positives || negatives;
|
||
}
|
||
|
||
if (options.wrap) {
|
||
return `(${prefix}${result})`;
|
||
}
|
||
|
||
return result;
|
||
};
|
||
|
||
const toRange = (a, b, isNumbers, options) => {
|
||
if (isNumbers) {
|
||
return toRegexRange(a, b, { wrap: false, ...options });
|
||
}
|
||
|
||
let start = String.fromCharCode(a);
|
||
if (a === b) return start;
|
||
|
||
let stop = String.fromCharCode(b);
|
||
return `[${start}-${stop}]`;
|
||
};
|
||
|
||
const toRegex = (start, end, options) => {
|
||
if (Array.isArray(start)) {
|
||
let wrap = options.wrap === true;
|
||
let prefix = options.capture ? '' : '?:';
|
||
return wrap ? `(${prefix}${start.join('|')})` : start.join('|');
|
||
}
|
||
return toRegexRange(start, end, options);
|
||
};
|
||
|
||
const rangeError = (...args) => {
|
||
return new RangeError('Invalid range arguments: ' + util$1.inspect(...args));
|
||
};
|
||
|
||
const invalidRange = (start, end, options) => {
|
||
if (options.strictRanges === true) throw rangeError([start, end]);
|
||
return [];
|
||
};
|
||
|
||
const invalidStep = (step, options) => {
|
||
if (options.strictRanges === true) {
|
||
throw new TypeError(`Expected step "${step}" to be a number`);
|
||
}
|
||
return [];
|
||
};
|
||
|
||
const fillNumbers = (start, end, step = 1, options = {}) => {
|
||
let a = Number(start);
|
||
let b = Number(end);
|
||
|
||
if (!Number.isInteger(a) || !Number.isInteger(b)) {
|
||
if (options.strictRanges === true) throw rangeError([start, end]);
|
||
return [];
|
||
}
|
||
|
||
// fix negative zero
|
||
if (a === 0) a = 0;
|
||
if (b === 0) b = 0;
|
||
|
||
let descending = a > b;
|
||
let startString = String(start);
|
||
let endString = String(end);
|
||
let stepString = String(step);
|
||
step = Math.max(Math.abs(step), 1);
|
||
|
||
let padded = zeros(startString) || zeros(endString) || zeros(stepString);
|
||
let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0;
|
||
let toNumber = padded === false && stringify$6(start, end, options) === false;
|
||
let format = options.transform || transform(toNumber);
|
||
|
||
if (options.toRegex && step === 1) {
|
||
return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options);
|
||
}
|
||
|
||
let parts = { negatives: [], positives: [] };
|
||
let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num));
|
||
let range = [];
|
||
let index = 0;
|
||
|
||
while (descending ? a >= b : a <= b) {
|
||
if (options.toRegex === true && step > 1) {
|
||
push(a);
|
||
} else {
|
||
range.push(pad(format(a, index), maxLen, toNumber));
|
||
}
|
||
a = descending ? a - step : a + step;
|
||
index++;
|
||
}
|
||
|
||
if (options.toRegex === true) {
|
||
return step > 1
|
||
? toSequence(parts, options)
|
||
: toRegex(range, null, { wrap: false, ...options });
|
||
}
|
||
|
||
return range;
|
||
};
|
||
|
||
const fillLetters = (start, end, step = 1, options = {}) => {
|
||
if ((!isNumber$1(start) && start.length > 1) || (!isNumber$1(end) && end.length > 1)) {
|
||
return invalidRange(start, end, options);
|
||
}
|
||
|
||
|
||
let format = options.transform || (val => String.fromCharCode(val));
|
||
let a = `${start}`.charCodeAt(0);
|
||
let b = `${end}`.charCodeAt(0);
|
||
|
||
let descending = a > b;
|
||
let min = Math.min(a, b);
|
||
let max = Math.max(a, b);
|
||
|
||
if (options.toRegex && step === 1) {
|
||
return toRange(min, max, false, options);
|
||
}
|
||
|
||
let range = [];
|
||
let index = 0;
|
||
|
||
while (descending ? a >= b : a <= b) {
|
||
range.push(format(a, index));
|
||
a = descending ? a - step : a + step;
|
||
index++;
|
||
}
|
||
|
||
if (options.toRegex === true) {
|
||
return toRegex(range, null, { wrap: false, options });
|
||
}
|
||
|
||
return range;
|
||
};
|
||
|
||
const fill$2 = (start, end, step, options = {}) => {
|
||
if (end == null && isValidValue(start)) {
|
||
return [start];
|
||
}
|
||
|
||
if (!isValidValue(start) || !isValidValue(end)) {
|
||
return invalidRange(start, end, options);
|
||
}
|
||
|
||
if (typeof step === 'function') {
|
||
return fill$2(start, end, 1, { transform: step });
|
||
}
|
||
|
||
if (isObject$5(step)) {
|
||
return fill$2(start, end, 0, step);
|
||
}
|
||
|
||
let opts = { ...options };
|
||
if (opts.capture === true) opts.wrap = true;
|
||
step = step || opts.step || 1;
|
||
|
||
if (!isNumber$1(step)) {
|
||
if (step != null && !isObject$5(step)) return invalidStep(step, opts);
|
||
return fill$2(start, end, 1, step);
|
||
}
|
||
|
||
if (isNumber$1(start) && isNumber$1(end)) {
|
||
return fillNumbers(start, end, step, opts);
|
||
}
|
||
|
||
return fillLetters(start, end, Math.max(Math.abs(step), 1), opts);
|
||
};
|
||
|
||
var fillRange = fill$2;
|
||
|
||
const fill$1 = fillRange;
|
||
const utils$p = utils$r;
|
||
|
||
const compile$3 = (ast, options = {}) => {
|
||
let walk = (node, parent = {}) => {
|
||
let invalidBlock = utils$p.isInvalidBrace(parent);
|
||
let invalidNode = node.invalid === true && options.escapeInvalid === true;
|
||
let invalid = invalidBlock === true || invalidNode === true;
|
||
let prefix = options.escapeInvalid === true ? '\\' : '';
|
||
let output = '';
|
||
|
||
if (node.isOpen === true) {
|
||
return prefix + node.value;
|
||
}
|
||
if (node.isClose === true) {
|
||
return prefix + node.value;
|
||
}
|
||
|
||
if (node.type === 'open') {
|
||
return invalid ? (prefix + node.value) : '(';
|
||
}
|
||
|
||
if (node.type === 'close') {
|
||
return invalid ? (prefix + node.value) : ')';
|
||
}
|
||
|
||
if (node.type === 'comma') {
|
||
return node.prev.type === 'comma' ? '' : (invalid ? node.value : '|');
|
||
}
|
||
|
||
if (node.value) {
|
||
return node.value;
|
||
}
|
||
|
||
if (node.nodes && node.ranges > 0) {
|
||
let args = utils$p.reduce(node.nodes);
|
||
let range = fill$1(...args, { ...options, wrap: false, toRegex: true });
|
||
|
||
if (range.length !== 0) {
|
||
return args.length > 1 && range.length > 1 ? `(${range})` : range;
|
||
}
|
||
}
|
||
|
||
if (node.nodes) {
|
||
for (let child of node.nodes) {
|
||
output += walk(child, node);
|
||
}
|
||
}
|
||
return output;
|
||
};
|
||
|
||
return walk(ast);
|
||
};
|
||
|
||
var compile_1 = compile$3;
|
||
|
||
const fill = fillRange;
|
||
const stringify$5 = stringify$7;
|
||
const utils$o = utils$r;
|
||
|
||
const append$1 = (queue = '', stash = '', enclose = false) => {
|
||
let result = [];
|
||
|
||
queue = [].concat(queue);
|
||
stash = [].concat(stash);
|
||
|
||
if (!stash.length) return queue;
|
||
if (!queue.length) {
|
||
return enclose ? utils$o.flatten(stash).map(ele => `{${ele}}`) : stash;
|
||
}
|
||
|
||
for (let item of queue) {
|
||
if (Array.isArray(item)) {
|
||
for (let value of item) {
|
||
result.push(append$1(value, stash, enclose));
|
||
}
|
||
} else {
|
||
for (let ele of stash) {
|
||
if (enclose === true && typeof ele === 'string') ele = `{${ele}}`;
|
||
result.push(Array.isArray(ele) ? append$1(item, ele, enclose) : (item + ele));
|
||
}
|
||
}
|
||
}
|
||
return utils$o.flatten(result);
|
||
};
|
||
|
||
const expand$1 = (ast, options = {}) => {
|
||
let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit;
|
||
|
||
let walk = (node, parent = {}) => {
|
||
node.queue = [];
|
||
|
||
let p = parent;
|
||
let q = parent.queue;
|
||
|
||
while (p.type !== 'brace' && p.type !== 'root' && p.parent) {
|
||
p = p.parent;
|
||
q = p.queue;
|
||
}
|
||
|
||
if (node.invalid || node.dollar) {
|
||
q.push(append$1(q.pop(), stringify$5(node, options)));
|
||
return;
|
||
}
|
||
|
||
if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) {
|
||
q.push(append$1(q.pop(), ['{}']));
|
||
return;
|
||
}
|
||
|
||
if (node.nodes && node.ranges > 0) {
|
||
let args = utils$o.reduce(node.nodes);
|
||
|
||
if (utils$o.exceedsLimit(...args, options.step, rangeLimit)) {
|
||
throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.');
|
||
}
|
||
|
||
let range = fill(...args, options);
|
||
if (range.length === 0) {
|
||
range = stringify$5(node, options);
|
||
}
|
||
|
||
q.push(append$1(q.pop(), range));
|
||
node.nodes = [];
|
||
return;
|
||
}
|
||
|
||
let enclose = utils$o.encloseBrace(node);
|
||
let queue = node.queue;
|
||
let block = node;
|
||
|
||
while (block.type !== 'brace' && block.type !== 'root' && block.parent) {
|
||
block = block.parent;
|
||
queue = block.queue;
|
||
}
|
||
|
||
for (let i = 0; i < node.nodes.length; i++) {
|
||
let child = node.nodes[i];
|
||
|
||
if (child.type === 'comma' && node.type === 'brace') {
|
||
if (i === 1) queue.push('');
|
||
queue.push('');
|
||
continue;
|
||
}
|
||
|
||
if (child.type === 'close') {
|
||
q.push(append$1(q.pop(), queue, enclose));
|
||
continue;
|
||
}
|
||
|
||
if (child.value && child.type !== 'open') {
|
||
queue.push(append$1(queue.pop(), child.value));
|
||
continue;
|
||
}
|
||
|
||
if (child.nodes) {
|
||
walk(child, node);
|
||
}
|
||
}
|
||
|
||
return queue;
|
||
};
|
||
|
||
return utils$o.flatten(walk(ast));
|
||
};
|
||
|
||
var expand_1 = expand$1;
|
||
|
||
var constants$4 = {
|
||
MAX_LENGTH: 1024 * 64,
|
||
|
||
// Digits
|
||
CHAR_0: '0', /* 0 */
|
||
CHAR_9: '9', /* 9 */
|
||
|
||
// Alphabet chars.
|
||
CHAR_UPPERCASE_A: 'A', /* A */
|
||
CHAR_LOWERCASE_A: 'a', /* a */
|
||
CHAR_UPPERCASE_Z: 'Z', /* Z */
|
||
CHAR_LOWERCASE_Z: 'z', /* z */
|
||
|
||
CHAR_LEFT_PARENTHESES: '(', /* ( */
|
||
CHAR_RIGHT_PARENTHESES: ')', /* ) */
|
||
|
||
CHAR_ASTERISK: '*', /* * */
|
||
|
||
// Non-alphabetic chars.
|
||
CHAR_AMPERSAND: '&', /* & */
|
||
CHAR_AT: '@', /* @ */
|
||
CHAR_BACKSLASH: '\\', /* \ */
|
||
CHAR_BACKTICK: '`', /* ` */
|
||
CHAR_CARRIAGE_RETURN: '\r', /* \r */
|
||
CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */
|
||
CHAR_COLON: ':', /* : */
|
||
CHAR_COMMA: ',', /* , */
|
||
CHAR_DOLLAR: '$', /* . */
|
||
CHAR_DOT: '.', /* . */
|
||
CHAR_DOUBLE_QUOTE: '"', /* " */
|
||
CHAR_EQUAL: '=', /* = */
|
||
CHAR_EXCLAMATION_MARK: '!', /* ! */
|
||
CHAR_FORM_FEED: '\f', /* \f */
|
||
CHAR_FORWARD_SLASH: '/', /* / */
|
||
CHAR_HASH: '#', /* # */
|
||
CHAR_HYPHEN_MINUS: '-', /* - */
|
||
CHAR_LEFT_ANGLE_BRACKET: '<', /* < */
|
||
CHAR_LEFT_CURLY_BRACE: '{', /* { */
|
||
CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */
|
||
CHAR_LINE_FEED: '\n', /* \n */
|
||
CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */
|
||
CHAR_PERCENT: '%', /* % */
|
||
CHAR_PLUS: '+', /* + */
|
||
CHAR_QUESTION_MARK: '?', /* ? */
|
||
CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */
|
||
CHAR_RIGHT_CURLY_BRACE: '}', /* } */
|
||
CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */
|
||
CHAR_SEMICOLON: ';', /* ; */
|
||
CHAR_SINGLE_QUOTE: '\'', /* ' */
|
||
CHAR_SPACE: ' ', /* */
|
||
CHAR_TAB: '\t', /* \t */
|
||
CHAR_UNDERSCORE: '_', /* _ */
|
||
CHAR_VERTICAL_LINE: '|', /* | */
|
||
CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */
|
||
};
|
||
|
||
const stringify$4 = stringify$7;
|
||
|
||
/**
|
||
* Constants
|
||
*/
|
||
|
||
const {
|
||
MAX_LENGTH: MAX_LENGTH$1,
|
||
CHAR_BACKSLASH, /* \ */
|
||
CHAR_BACKTICK, /* ` */
|
||
CHAR_COMMA: CHAR_COMMA$2, /* , */
|
||
CHAR_DOT: CHAR_DOT$1, /* . */
|
||
CHAR_LEFT_PARENTHESES: CHAR_LEFT_PARENTHESES$1, /* ( */
|
||
CHAR_RIGHT_PARENTHESES: CHAR_RIGHT_PARENTHESES$1, /* ) */
|
||
CHAR_LEFT_CURLY_BRACE: CHAR_LEFT_CURLY_BRACE$1, /* { */
|
||
CHAR_RIGHT_CURLY_BRACE: CHAR_RIGHT_CURLY_BRACE$1, /* } */
|
||
CHAR_LEFT_SQUARE_BRACKET: CHAR_LEFT_SQUARE_BRACKET$2, /* [ */
|
||
CHAR_RIGHT_SQUARE_BRACKET: CHAR_RIGHT_SQUARE_BRACKET$2, /* ] */
|
||
CHAR_DOUBLE_QUOTE: CHAR_DOUBLE_QUOTE$1, /* " */
|
||
CHAR_SINGLE_QUOTE: CHAR_SINGLE_QUOTE$1, /* ' */
|
||
CHAR_NO_BREAK_SPACE,
|
||
CHAR_ZERO_WIDTH_NOBREAK_SPACE
|
||
} = constants$4;
|
||
|
||
/**
|
||
* parse
|
||
*/
|
||
|
||
const parse$c = (input, options = {}) => {
|
||
if (typeof input !== 'string') {
|
||
throw new TypeError('Expected a string');
|
||
}
|
||
|
||
let opts = options || {};
|
||
let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH$1, opts.maxLength) : MAX_LENGTH$1;
|
||
if (input.length > max) {
|
||
throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`);
|
||
}
|
||
|
||
let ast = { type: 'root', input, nodes: [] };
|
||
let stack = [ast];
|
||
let block = ast;
|
||
let prev = ast;
|
||
let brackets = 0;
|
||
let length = input.length;
|
||
let index = 0;
|
||
let depth = 0;
|
||
let value;
|
||
|
||
/**
|
||
* Helpers
|
||
*/
|
||
|
||
const advance = () => input[index++];
|
||
const push = node => {
|
||
if (node.type === 'text' && prev.type === 'dot') {
|
||
prev.type = 'text';
|
||
}
|
||
|
||
if (prev && prev.type === 'text' && node.type === 'text') {
|
||
prev.value += node.value;
|
||
return;
|
||
}
|
||
|
||
block.nodes.push(node);
|
||
node.parent = block;
|
||
node.prev = prev;
|
||
prev = node;
|
||
return node;
|
||
};
|
||
|
||
push({ type: 'bos' });
|
||
|
||
while (index < length) {
|
||
block = stack[stack.length - 1];
|
||
value = advance();
|
||
|
||
/**
|
||
* Invalid chars
|
||
*/
|
||
|
||
if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) {
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Escaped chars
|
||
*/
|
||
|
||
if (value === CHAR_BACKSLASH) {
|
||
push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Right square bracket (literal): ']'
|
||
*/
|
||
|
||
if (value === CHAR_RIGHT_SQUARE_BRACKET$2) {
|
||
push({ type: 'text', value: '\\' + value });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Left square bracket: '['
|
||
*/
|
||
|
||
if (value === CHAR_LEFT_SQUARE_BRACKET$2) {
|
||
brackets++;
|
||
let next;
|
||
|
||
while (index < length && (next = advance())) {
|
||
value += next;
|
||
|
||
if (next === CHAR_LEFT_SQUARE_BRACKET$2) {
|
||
brackets++;
|
||
continue;
|
||
}
|
||
|
||
if (next === CHAR_BACKSLASH) {
|
||
value += advance();
|
||
continue;
|
||
}
|
||
|
||
if (next === CHAR_RIGHT_SQUARE_BRACKET$2) {
|
||
brackets--;
|
||
|
||
if (brackets === 0) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
push({ type: 'text', value });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Parentheses
|
||
*/
|
||
|
||
if (value === CHAR_LEFT_PARENTHESES$1) {
|
||
block = push({ type: 'paren', nodes: [] });
|
||
stack.push(block);
|
||
push({ type: 'text', value });
|
||
continue;
|
||
}
|
||
|
||
if (value === CHAR_RIGHT_PARENTHESES$1) {
|
||
if (block.type !== 'paren') {
|
||
push({ type: 'text', value });
|
||
continue;
|
||
}
|
||
block = stack.pop();
|
||
push({ type: 'text', value });
|
||
block = stack[stack.length - 1];
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Quotes: '|"|`
|
||
*/
|
||
|
||
if (value === CHAR_DOUBLE_QUOTE$1 || value === CHAR_SINGLE_QUOTE$1 || value === CHAR_BACKTICK) {
|
||
let open = value;
|
||
let next;
|
||
|
||
if (options.keepQuotes !== true) {
|
||
value = '';
|
||
}
|
||
|
||
while (index < length && (next = advance())) {
|
||
if (next === CHAR_BACKSLASH) {
|
||
value += next + advance();
|
||
continue;
|
||
}
|
||
|
||
if (next === open) {
|
||
if (options.keepQuotes === true) value += next;
|
||
break;
|
||
}
|
||
|
||
value += next;
|
||
}
|
||
|
||
push({ type: 'text', value });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Left curly brace: '{'
|
||
*/
|
||
|
||
if (value === CHAR_LEFT_CURLY_BRACE$1) {
|
||
depth++;
|
||
|
||
let dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true;
|
||
let brace = {
|
||
type: 'brace',
|
||
open: true,
|
||
close: false,
|
||
dollar,
|
||
depth,
|
||
commas: 0,
|
||
ranges: 0,
|
||
nodes: []
|
||
};
|
||
|
||
block = push(brace);
|
||
stack.push(block);
|
||
push({ type: 'open', value });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Right curly brace: '}'
|
||
*/
|
||
|
||
if (value === CHAR_RIGHT_CURLY_BRACE$1) {
|
||
if (block.type !== 'brace') {
|
||
push({ type: 'text', value });
|
||
continue;
|
||
}
|
||
|
||
let type = 'close';
|
||
block = stack.pop();
|
||
block.close = true;
|
||
|
||
push({ type, value });
|
||
depth--;
|
||
|
||
block = stack[stack.length - 1];
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Comma: ','
|
||
*/
|
||
|
||
if (value === CHAR_COMMA$2 && depth > 0) {
|
||
if (block.ranges > 0) {
|
||
block.ranges = 0;
|
||
let open = block.nodes.shift();
|
||
block.nodes = [open, { type: 'text', value: stringify$4(block) }];
|
||
}
|
||
|
||
push({ type: 'comma', value });
|
||
block.commas++;
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Dot: '.'
|
||
*/
|
||
|
||
if (value === CHAR_DOT$1 && depth > 0 && block.commas === 0) {
|
||
let siblings = block.nodes;
|
||
|
||
if (depth === 0 || siblings.length === 0) {
|
||
push({ type: 'text', value });
|
||
continue;
|
||
}
|
||
|
||
if (prev.type === 'dot') {
|
||
block.range = [];
|
||
prev.value += value;
|
||
prev.type = 'range';
|
||
|
||
if (block.nodes.length !== 3 && block.nodes.length !== 5) {
|
||
block.invalid = true;
|
||
block.ranges = 0;
|
||
prev.type = 'text';
|
||
continue;
|
||
}
|
||
|
||
block.ranges++;
|
||
block.args = [];
|
||
continue;
|
||
}
|
||
|
||
if (prev.type === 'range') {
|
||
siblings.pop();
|
||
|
||
let before = siblings[siblings.length - 1];
|
||
before.value += prev.value + value;
|
||
prev = before;
|
||
block.ranges--;
|
||
continue;
|
||
}
|
||
|
||
push({ type: 'dot', value });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Text
|
||
*/
|
||
|
||
push({ type: 'text', value });
|
||
}
|
||
|
||
// Mark imbalanced braces and brackets as invalid
|
||
do {
|
||
block = stack.pop();
|
||
|
||
if (block.type !== 'root') {
|
||
block.nodes.forEach(node => {
|
||
if (!node.nodes) {
|
||
if (node.type === 'open') node.isOpen = true;
|
||
if (node.type === 'close') node.isClose = true;
|
||
if (!node.nodes) node.type = 'text';
|
||
node.invalid = true;
|
||
}
|
||
});
|
||
|
||
// get the location of the block on parent.nodes (block's siblings)
|
||
let parent = stack[stack.length - 1];
|
||
let index = parent.nodes.indexOf(block);
|
||
// replace the (invalid) block with it's nodes
|
||
parent.nodes.splice(index, 1, ...block.nodes);
|
||
}
|
||
} while (stack.length > 0);
|
||
|
||
push({ type: 'eos' });
|
||
return ast;
|
||
};
|
||
|
||
var parse_1$2 = parse$c;
|
||
|
||
const stringify$3 = stringify$7;
|
||
const compile$2 = compile_1;
|
||
const expand = expand_1;
|
||
const parse$b = parse_1$2;
|
||
|
||
/**
|
||
* Expand the given pattern or create a regex-compatible string.
|
||
*
|
||
* ```js
|
||
* const braces = require('braces');
|
||
* console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)']
|
||
* console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c']
|
||
* ```
|
||
* @param {String} `str`
|
||
* @param {Object} `options`
|
||
* @return {String}
|
||
* @api public
|
||
*/
|
||
|
||
const braces$1 = (input, options = {}) => {
|
||
let output = [];
|
||
|
||
if (Array.isArray(input)) {
|
||
for (let pattern of input) {
|
||
let result = braces$1.create(pattern, options);
|
||
if (Array.isArray(result)) {
|
||
output.push(...result);
|
||
} else {
|
||
output.push(result);
|
||
}
|
||
}
|
||
} else {
|
||
output = [].concat(braces$1.create(input, options));
|
||
}
|
||
|
||
if (options && options.expand === true && options.nodupes === true) {
|
||
output = [...new Set(output)];
|
||
}
|
||
return output;
|
||
};
|
||
|
||
/**
|
||
* Parse the given `str` with the given `options`.
|
||
*
|
||
* ```js
|
||
* // braces.parse(pattern, [, options]);
|
||
* const ast = braces.parse('a/{b,c}/d');
|
||
* console.log(ast);
|
||
* ```
|
||
* @param {String} pattern Brace pattern to parse
|
||
* @param {Object} options
|
||
* @return {Object} Returns an AST
|
||
* @api public
|
||
*/
|
||
|
||
braces$1.parse = (input, options = {}) => parse$b(input, options);
|
||
|
||
/**
|
||
* Creates a braces string from an AST, or an AST node.
|
||
*
|
||
* ```js
|
||
* const braces = require('braces');
|
||
* let ast = braces.parse('foo/{a,b}/bar');
|
||
* console.log(stringify(ast.nodes[2])); //=> '{a,b}'
|
||
* ```
|
||
* @param {String} `input` Brace pattern or AST.
|
||
* @param {Object} `options`
|
||
* @return {Array} Returns an array of expanded values.
|
||
* @api public
|
||
*/
|
||
|
||
braces$1.stringify = (input, options = {}) => {
|
||
if (typeof input === 'string') {
|
||
return stringify$3(braces$1.parse(input, options), options);
|
||
}
|
||
return stringify$3(input, options);
|
||
};
|
||
|
||
/**
|
||
* Compiles a brace pattern into a regex-compatible, optimized string.
|
||
* This method is called by the main [braces](#braces) function by default.
|
||
*
|
||
* ```js
|
||
* const braces = require('braces');
|
||
* console.log(braces.compile('a/{b,c}/d'));
|
||
* //=> ['a/(b|c)/d']
|
||
* ```
|
||
* @param {String} `input` Brace pattern or AST.
|
||
* @param {Object} `options`
|
||
* @return {Array} Returns an array of expanded values.
|
||
* @api public
|
||
*/
|
||
|
||
braces$1.compile = (input, options = {}) => {
|
||
if (typeof input === 'string') {
|
||
input = braces$1.parse(input, options);
|
||
}
|
||
return compile$2(input, options);
|
||
};
|
||
|
||
/**
|
||
* Expands a brace pattern into an array. This method is called by the
|
||
* main [braces](#braces) function when `options.expand` is true. Before
|
||
* using this method it's recommended that you read the [performance notes](#performance))
|
||
* and advantages of using [.compile](#compile) instead.
|
||
*
|
||
* ```js
|
||
* const braces = require('braces');
|
||
* console.log(braces.expand('a/{b,c}/d'));
|
||
* //=> ['a/b/d', 'a/c/d'];
|
||
* ```
|
||
* @param {String} `pattern` Brace pattern
|
||
* @param {Object} `options`
|
||
* @return {Array} Returns an array of expanded values.
|
||
* @api public
|
||
*/
|
||
|
||
braces$1.expand = (input, options = {}) => {
|
||
if (typeof input === 'string') {
|
||
input = braces$1.parse(input, options);
|
||
}
|
||
|
||
let result = expand(input, options);
|
||
|
||
// filter out empty strings if specified
|
||
if (options.noempty === true) {
|
||
result = result.filter(Boolean);
|
||
}
|
||
|
||
// filter out duplicates if specified
|
||
if (options.nodupes === true) {
|
||
result = [...new Set(result)];
|
||
}
|
||
|
||
return result;
|
||
};
|
||
|
||
/**
|
||
* Processes a brace pattern and returns either an expanded array
|
||
* (if `options.expand` is true), a highly optimized regex-compatible string.
|
||
* This method is called by the main [braces](#braces) function.
|
||
*
|
||
* ```js
|
||
* const braces = require('braces');
|
||
* console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}'))
|
||
* //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)'
|
||
* ```
|
||
* @param {String} `pattern` Brace pattern
|
||
* @param {Object} `options`
|
||
* @return {Array} Returns an array of expanded values.
|
||
* @api public
|
||
*/
|
||
|
||
braces$1.create = (input, options = {}) => {
|
||
if (input === '' || input.length < 3) {
|
||
return [input];
|
||
}
|
||
|
||
return options.expand !== true
|
||
? braces$1.compile(input, options)
|
||
: braces$1.expand(input, options);
|
||
};
|
||
|
||
/**
|
||
* Expose "braces"
|
||
*/
|
||
|
||
var braces_1 = braces$1;
|
||
|
||
var utils$n = {};
|
||
|
||
const path$a = path$q;
|
||
const WIN_SLASH = '\\\\/';
|
||
const WIN_NO_SLASH = `[^${WIN_SLASH}]`;
|
||
|
||
/**
|
||
* Posix glob regex
|
||
*/
|
||
|
||
const DOT_LITERAL = '\\.';
|
||
const PLUS_LITERAL = '\\+';
|
||
const QMARK_LITERAL = '\\?';
|
||
const SLASH_LITERAL = '\\/';
|
||
const ONE_CHAR = '(?=.)';
|
||
const QMARK = '[^/]';
|
||
const END_ANCHOR = `(?:${SLASH_LITERAL}|$)`;
|
||
const START_ANCHOR = `(?:^|${SLASH_LITERAL})`;
|
||
const DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`;
|
||
const NO_DOT = `(?!${DOT_LITERAL})`;
|
||
const NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`;
|
||
const NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`;
|
||
const NO_DOTS_SLASH = `(?!${DOTS_SLASH})`;
|
||
const QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`;
|
||
const STAR = `${QMARK}*?`;
|
||
|
||
const POSIX_CHARS = {
|
||
DOT_LITERAL,
|
||
PLUS_LITERAL,
|
||
QMARK_LITERAL,
|
||
SLASH_LITERAL,
|
||
ONE_CHAR,
|
||
QMARK,
|
||
END_ANCHOR,
|
||
DOTS_SLASH,
|
||
NO_DOT,
|
||
NO_DOTS,
|
||
NO_DOT_SLASH,
|
||
NO_DOTS_SLASH,
|
||
QMARK_NO_DOT,
|
||
STAR,
|
||
START_ANCHOR
|
||
};
|
||
|
||
/**
|
||
* Windows glob regex
|
||
*/
|
||
|
||
const WINDOWS_CHARS = {
|
||
...POSIX_CHARS,
|
||
|
||
SLASH_LITERAL: `[${WIN_SLASH}]`,
|
||
QMARK: WIN_NO_SLASH,
|
||
STAR: `${WIN_NO_SLASH}*?`,
|
||
DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`,
|
||
NO_DOT: `(?!${DOT_LITERAL})`,
|
||
NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`,
|
||
NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`,
|
||
NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`,
|
||
QMARK_NO_DOT: `[^.${WIN_SLASH}]`,
|
||
START_ANCHOR: `(?:^|[${WIN_SLASH}])`,
|
||
END_ANCHOR: `(?:[${WIN_SLASH}]|$)`
|
||
};
|
||
|
||
/**
|
||
* POSIX Bracket Regex
|
||
*/
|
||
|
||
const POSIX_REGEX_SOURCE$1 = {
|
||
alnum: 'a-zA-Z0-9',
|
||
alpha: 'a-zA-Z',
|
||
ascii: '\\x00-\\x7F',
|
||
blank: ' \\t',
|
||
cntrl: '\\x00-\\x1F\\x7F',
|
||
digit: '0-9',
|
||
graph: '\\x21-\\x7E',
|
||
lower: 'a-z',
|
||
print: '\\x20-\\x7E ',
|
||
punct: '\\-!"#$%&\'()\\*+,./:;<=>?@[\\]^_`{|}~',
|
||
space: ' \\t\\r\\n\\v\\f',
|
||
upper: 'A-Z',
|
||
word: 'A-Za-z0-9_',
|
||
xdigit: 'A-Fa-f0-9'
|
||
};
|
||
|
||
var constants$3 = {
|
||
MAX_LENGTH: 1024 * 64,
|
||
POSIX_REGEX_SOURCE: POSIX_REGEX_SOURCE$1,
|
||
|
||
// regular expressions
|
||
REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g,
|
||
REGEX_NON_SPECIAL_CHARS: /^[^@![\].,$*+?^{}()|\\/]+/,
|
||
REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/,
|
||
REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g,
|
||
REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g,
|
||
REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g,
|
||
|
||
// Replace globs with equivalent patterns to reduce parsing time.
|
||
REPLACEMENTS: {
|
||
'***': '*',
|
||
'**/**': '**',
|
||
'**/**/**': '**'
|
||
},
|
||
|
||
// Digits
|
||
CHAR_0: 48, /* 0 */
|
||
CHAR_9: 57, /* 9 */
|
||
|
||
// Alphabet chars.
|
||
CHAR_UPPERCASE_A: 65, /* A */
|
||
CHAR_LOWERCASE_A: 97, /* a */
|
||
CHAR_UPPERCASE_Z: 90, /* Z */
|
||
CHAR_LOWERCASE_Z: 122, /* z */
|
||
|
||
CHAR_LEFT_PARENTHESES: 40, /* ( */
|
||
CHAR_RIGHT_PARENTHESES: 41, /* ) */
|
||
|
||
CHAR_ASTERISK: 42, /* * */
|
||
|
||
// Non-alphabetic chars.
|
||
CHAR_AMPERSAND: 38, /* & */
|
||
CHAR_AT: 64, /* @ */
|
||
CHAR_BACKWARD_SLASH: 92, /* \ */
|
||
CHAR_CARRIAGE_RETURN: 13, /* \r */
|
||
CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */
|
||
CHAR_COLON: 58, /* : */
|
||
CHAR_COMMA: 44, /* , */
|
||
CHAR_DOT: 46, /* . */
|
||
CHAR_DOUBLE_QUOTE: 34, /* " */
|
||
CHAR_EQUAL: 61, /* = */
|
||
CHAR_EXCLAMATION_MARK: 33, /* ! */
|
||
CHAR_FORM_FEED: 12, /* \f */
|
||
CHAR_FORWARD_SLASH: 47, /* / */
|
||
CHAR_GRAVE_ACCENT: 96, /* ` */
|
||
CHAR_HASH: 35, /* # */
|
||
CHAR_HYPHEN_MINUS: 45, /* - */
|
||
CHAR_LEFT_ANGLE_BRACKET: 60, /* < */
|
||
CHAR_LEFT_CURLY_BRACE: 123, /* { */
|
||
CHAR_LEFT_SQUARE_BRACKET: 91, /* [ */
|
||
CHAR_LINE_FEED: 10, /* \n */
|
||
CHAR_NO_BREAK_SPACE: 160, /* \u00A0 */
|
||
CHAR_PERCENT: 37, /* % */
|
||
CHAR_PLUS: 43, /* + */
|
||
CHAR_QUESTION_MARK: 63, /* ? */
|
||
CHAR_RIGHT_ANGLE_BRACKET: 62, /* > */
|
||
CHAR_RIGHT_CURLY_BRACE: 125, /* } */
|
||
CHAR_RIGHT_SQUARE_BRACKET: 93, /* ] */
|
||
CHAR_SEMICOLON: 59, /* ; */
|
||
CHAR_SINGLE_QUOTE: 39, /* ' */
|
||
CHAR_SPACE: 32, /* */
|
||
CHAR_TAB: 9, /* \t */
|
||
CHAR_UNDERSCORE: 95, /* _ */
|
||
CHAR_VERTICAL_LINE: 124, /* | */
|
||
CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, /* \uFEFF */
|
||
|
||
SEP: path$a.sep,
|
||
|
||
/**
|
||
* Create EXTGLOB_CHARS
|
||
*/
|
||
|
||
extglobChars(chars) {
|
||
return {
|
||
'!': { type: 'negate', open: '(?:(?!(?:', close: `))${chars.STAR})` },
|
||
'?': { type: 'qmark', open: '(?:', close: ')?' },
|
||
'+': { type: 'plus', open: '(?:', close: ')+' },
|
||
'*': { type: 'star', open: '(?:', close: ')*' },
|
||
'@': { type: 'at', open: '(?:', close: ')' }
|
||
};
|
||
},
|
||
|
||
/**
|
||
* Create GLOB_CHARS
|
||
*/
|
||
|
||
globChars(win32) {
|
||
return win32 === true ? WINDOWS_CHARS : POSIX_CHARS;
|
||
}
|
||
};
|
||
|
||
(function (exports) {
|
||
|
||
const path = path$q;
|
||
const win32 = process.platform === 'win32';
|
||
const {
|
||
REGEX_BACKSLASH,
|
||
REGEX_REMOVE_BACKSLASH,
|
||
REGEX_SPECIAL_CHARS,
|
||
REGEX_SPECIAL_CHARS_GLOBAL
|
||
} = constants$3;
|
||
|
||
exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val);
|
||
exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str);
|
||
exports.isRegexChar = str => str.length === 1 && exports.hasRegexChars(str);
|
||
exports.escapeRegex = str => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, '\\$1');
|
||
exports.toPosixSlashes = str => str.replace(REGEX_BACKSLASH, '/');
|
||
|
||
exports.removeBackslashes = str => {
|
||
return str.replace(REGEX_REMOVE_BACKSLASH, match => {
|
||
return match === '\\' ? '' : match;
|
||
});
|
||
};
|
||
|
||
exports.supportsLookbehinds = () => {
|
||
const segs = process.version.slice(1).split('.').map(Number);
|
||
if (segs.length === 3 && segs[0] >= 9 || (segs[0] === 8 && segs[1] >= 10)) {
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
exports.isWindows = options => {
|
||
if (options && typeof options.windows === 'boolean') {
|
||
return options.windows;
|
||
}
|
||
return win32 === true || path.sep === '\\';
|
||
};
|
||
|
||
exports.escapeLast = (input, char, lastIdx) => {
|
||
const idx = input.lastIndexOf(char, lastIdx);
|
||
if (idx === -1) return input;
|
||
if (input[idx - 1] === '\\') return exports.escapeLast(input, char, idx - 1);
|
||
return `${input.slice(0, idx)}\\${input.slice(idx)}`;
|
||
};
|
||
|
||
exports.removePrefix = (input, state = {}) => {
|
||
let output = input;
|
||
if (output.startsWith('./')) {
|
||
output = output.slice(2);
|
||
state.prefix = './';
|
||
}
|
||
return output;
|
||
};
|
||
|
||
exports.wrapOutput = (input, state = {}, options = {}) => {
|
||
const prepend = options.contains ? '' : '^';
|
||
const append = options.contains ? '' : '$';
|
||
|
||
let output = `${prepend}(?:${input})${append}`;
|
||
if (state.negated === true) {
|
||
output = `(?:^(?!${output}).*$)`;
|
||
}
|
||
return output;
|
||
};
|
||
} (utils$n));
|
||
|
||
const utils$m = utils$n;
|
||
const {
|
||
CHAR_ASTERISK: CHAR_ASTERISK$1, /* * */
|
||
CHAR_AT, /* @ */
|
||
CHAR_BACKWARD_SLASH, /* \ */
|
||
CHAR_COMMA: CHAR_COMMA$1, /* , */
|
||
CHAR_DOT, /* . */
|
||
CHAR_EXCLAMATION_MARK, /* ! */
|
||
CHAR_FORWARD_SLASH, /* / */
|
||
CHAR_LEFT_CURLY_BRACE, /* { */
|
||
CHAR_LEFT_PARENTHESES, /* ( */
|
||
CHAR_LEFT_SQUARE_BRACKET: CHAR_LEFT_SQUARE_BRACKET$1, /* [ */
|
||
CHAR_PLUS, /* + */
|
||
CHAR_QUESTION_MARK, /* ? */
|
||
CHAR_RIGHT_CURLY_BRACE, /* } */
|
||
CHAR_RIGHT_PARENTHESES, /* ) */
|
||
CHAR_RIGHT_SQUARE_BRACKET: CHAR_RIGHT_SQUARE_BRACKET$1 /* ] */
|
||
} = constants$3;
|
||
|
||
const isPathSeparator = code => {
|
||
return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
|
||
};
|
||
|
||
const depth = token => {
|
||
if (token.isPrefix !== true) {
|
||
token.depth = token.isGlobstar ? Infinity : 1;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Quickly scans a glob pattern and returns an object with a handful of
|
||
* useful properties, like `isGlob`, `path` (the leading non-glob, if it exists),
|
||
* `glob` (the actual pattern), `negated` (true if the path starts with `!` but not
|
||
* with `!(`) and `negatedExtglob` (true if the path starts with `!(`).
|
||
*
|
||
* ```js
|
||
* const pm = require('picomatch');
|
||
* console.log(pm.scan('foo/bar/*.js'));
|
||
* { isGlob: true, input: 'foo/bar/*.js', base: 'foo/bar', glob: '*.js' }
|
||
* ```
|
||
* @param {String} `str`
|
||
* @param {Object} `options`
|
||
* @return {Object} Returns an object with tokens and regex source string.
|
||
* @api public
|
||
*/
|
||
|
||
const scan$1 = (input, options) => {
|
||
const opts = options || {};
|
||
|
||
const length = input.length - 1;
|
||
const scanToEnd = opts.parts === true || opts.scanToEnd === true;
|
||
const slashes = [];
|
||
const tokens = [];
|
||
const parts = [];
|
||
|
||
let str = input;
|
||
let index = -1;
|
||
let start = 0;
|
||
let lastIndex = 0;
|
||
let isBrace = false;
|
||
let isBracket = false;
|
||
let isGlob = false;
|
||
let isExtglob = false;
|
||
let isGlobstar = false;
|
||
let braceEscaped = false;
|
||
let backslashes = false;
|
||
let negated = false;
|
||
let negatedExtglob = false;
|
||
let finished = false;
|
||
let braces = 0;
|
||
let prev;
|
||
let code;
|
||
let token = { value: '', depth: 0, isGlob: false };
|
||
|
||
const eos = () => index >= length;
|
||
const peek = () => str.charCodeAt(index + 1);
|
||
const advance = () => {
|
||
prev = code;
|
||
return str.charCodeAt(++index);
|
||
};
|
||
|
||
while (index < length) {
|
||
code = advance();
|
||
let next;
|
||
|
||
if (code === CHAR_BACKWARD_SLASH) {
|
||
backslashes = token.backslashes = true;
|
||
code = advance();
|
||
|
||
if (code === CHAR_LEFT_CURLY_BRACE) {
|
||
braceEscaped = true;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE) {
|
||
braces++;
|
||
|
||
while (eos() !== true && (code = advance())) {
|
||
if (code === CHAR_BACKWARD_SLASH) {
|
||
backslashes = token.backslashes = true;
|
||
advance();
|
||
continue;
|
||
}
|
||
|
||
if (code === CHAR_LEFT_CURLY_BRACE) {
|
||
braces++;
|
||
continue;
|
||
}
|
||
|
||
if (braceEscaped !== true && code === CHAR_DOT && (code = advance()) === CHAR_DOT) {
|
||
isBrace = token.isBrace = true;
|
||
isGlob = token.isGlob = true;
|
||
finished = true;
|
||
|
||
if (scanToEnd === true) {
|
||
continue;
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
if (braceEscaped !== true && code === CHAR_COMMA$1) {
|
||
isBrace = token.isBrace = true;
|
||
isGlob = token.isGlob = true;
|
||
finished = true;
|
||
|
||
if (scanToEnd === true) {
|
||
continue;
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
if (code === CHAR_RIGHT_CURLY_BRACE) {
|
||
braces--;
|
||
|
||
if (braces === 0) {
|
||
braceEscaped = false;
|
||
isBrace = token.isBrace = true;
|
||
finished = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (scanToEnd === true) {
|
||
continue;
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
if (code === CHAR_FORWARD_SLASH) {
|
||
slashes.push(index);
|
||
tokens.push(token);
|
||
token = { value: '', depth: 0, isGlob: false };
|
||
|
||
if (finished === true) continue;
|
||
if (prev === CHAR_DOT && index === (start + 1)) {
|
||
start += 2;
|
||
continue;
|
||
}
|
||
|
||
lastIndex = index + 1;
|
||
continue;
|
||
}
|
||
|
||
if (opts.noext !== true) {
|
||
const isExtglobChar = code === CHAR_PLUS
|
||
|| code === CHAR_AT
|
||
|| code === CHAR_ASTERISK$1
|
||
|| code === CHAR_QUESTION_MARK
|
||
|| code === CHAR_EXCLAMATION_MARK;
|
||
|
||
if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES) {
|
||
isGlob = token.isGlob = true;
|
||
isExtglob = token.isExtglob = true;
|
||
finished = true;
|
||
if (code === CHAR_EXCLAMATION_MARK && index === start) {
|
||
negatedExtglob = true;
|
||
}
|
||
|
||
if (scanToEnd === true) {
|
||
while (eos() !== true && (code = advance())) {
|
||
if (code === CHAR_BACKWARD_SLASH) {
|
||
backslashes = token.backslashes = true;
|
||
code = advance();
|
||
continue;
|
||
}
|
||
|
||
if (code === CHAR_RIGHT_PARENTHESES) {
|
||
isGlob = token.isGlob = true;
|
||
finished = true;
|
||
break;
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (code === CHAR_ASTERISK$1) {
|
||
if (prev === CHAR_ASTERISK$1) isGlobstar = token.isGlobstar = true;
|
||
isGlob = token.isGlob = true;
|
||
finished = true;
|
||
|
||
if (scanToEnd === true) {
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
|
||
if (code === CHAR_QUESTION_MARK) {
|
||
isGlob = token.isGlob = true;
|
||
finished = true;
|
||
|
||
if (scanToEnd === true) {
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
|
||
if (code === CHAR_LEFT_SQUARE_BRACKET$1) {
|
||
while (eos() !== true && (next = advance())) {
|
||
if (next === CHAR_BACKWARD_SLASH) {
|
||
backslashes = token.backslashes = true;
|
||
advance();
|
||
continue;
|
||
}
|
||
|
||
if (next === CHAR_RIGHT_SQUARE_BRACKET$1) {
|
||
isBracket = token.isBracket = true;
|
||
isGlob = token.isGlob = true;
|
||
finished = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (scanToEnd === true) {
|
||
continue;
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) {
|
||
negated = token.negated = true;
|
||
start++;
|
||
continue;
|
||
}
|
||
|
||
if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES) {
|
||
isGlob = token.isGlob = true;
|
||
|
||
if (scanToEnd === true) {
|
||
while (eos() !== true && (code = advance())) {
|
||
if (code === CHAR_LEFT_PARENTHESES) {
|
||
backslashes = token.backslashes = true;
|
||
code = advance();
|
||
continue;
|
||
}
|
||
|
||
if (code === CHAR_RIGHT_PARENTHESES) {
|
||
finished = true;
|
||
break;
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
|
||
if (isGlob === true) {
|
||
finished = true;
|
||
|
||
if (scanToEnd === true) {
|
||
continue;
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (opts.noext === true) {
|
||
isExtglob = false;
|
||
isGlob = false;
|
||
}
|
||
|
||
let base = str;
|
||
let prefix = '';
|
||
let glob = '';
|
||
|
||
if (start > 0) {
|
||
prefix = str.slice(0, start);
|
||
str = str.slice(start);
|
||
lastIndex -= start;
|
||
}
|
||
|
||
if (base && isGlob === true && lastIndex > 0) {
|
||
base = str.slice(0, lastIndex);
|
||
glob = str.slice(lastIndex);
|
||
} else if (isGlob === true) {
|
||
base = '';
|
||
glob = str;
|
||
} else {
|
||
base = str;
|
||
}
|
||
|
||
if (base && base !== '' && base !== '/' && base !== str) {
|
||
if (isPathSeparator(base.charCodeAt(base.length - 1))) {
|
||
base = base.slice(0, -1);
|
||
}
|
||
}
|
||
|
||
if (opts.unescape === true) {
|
||
if (glob) glob = utils$m.removeBackslashes(glob);
|
||
|
||
if (base && backslashes === true) {
|
||
base = utils$m.removeBackslashes(base);
|
||
}
|
||
}
|
||
|
||
const state = {
|
||
prefix,
|
||
input,
|
||
start,
|
||
base,
|
||
glob,
|
||
isBrace,
|
||
isBracket,
|
||
isGlob,
|
||
isExtglob,
|
||
isGlobstar,
|
||
negated,
|
||
negatedExtglob
|
||
};
|
||
|
||
if (opts.tokens === true) {
|
||
state.maxDepth = 0;
|
||
if (!isPathSeparator(code)) {
|
||
tokens.push(token);
|
||
}
|
||
state.tokens = tokens;
|
||
}
|
||
|
||
if (opts.parts === true || opts.tokens === true) {
|
||
let prevIndex;
|
||
|
||
for (let idx = 0; idx < slashes.length; idx++) {
|
||
const n = prevIndex ? prevIndex + 1 : start;
|
||
const i = slashes[idx];
|
||
const value = input.slice(n, i);
|
||
if (opts.tokens) {
|
||
if (idx === 0 && start !== 0) {
|
||
tokens[idx].isPrefix = true;
|
||
tokens[idx].value = prefix;
|
||
} else {
|
||
tokens[idx].value = value;
|
||
}
|
||
depth(tokens[idx]);
|
||
state.maxDepth += tokens[idx].depth;
|
||
}
|
||
if (idx !== 0 || value !== '') {
|
||
parts.push(value);
|
||
}
|
||
prevIndex = i;
|
||
}
|
||
|
||
if (prevIndex && prevIndex + 1 < input.length) {
|
||
const value = input.slice(prevIndex + 1);
|
||
parts.push(value);
|
||
|
||
if (opts.tokens) {
|
||
tokens[tokens.length - 1].value = value;
|
||
depth(tokens[tokens.length - 1]);
|
||
state.maxDepth += tokens[tokens.length - 1].depth;
|
||
}
|
||
}
|
||
|
||
state.slashes = slashes;
|
||
state.parts = parts;
|
||
}
|
||
|
||
return state;
|
||
};
|
||
|
||
var scan_1 = scan$1;
|
||
|
||
const constants$2 = constants$3;
|
||
const utils$l = utils$n;
|
||
|
||
/**
|
||
* Constants
|
||
*/
|
||
|
||
const {
|
||
MAX_LENGTH,
|
||
POSIX_REGEX_SOURCE,
|
||
REGEX_NON_SPECIAL_CHARS,
|
||
REGEX_SPECIAL_CHARS_BACKREF,
|
||
REPLACEMENTS
|
||
} = constants$2;
|
||
|
||
/**
|
||
* Helpers
|
||
*/
|
||
|
||
const expandRange = (args, options) => {
|
||
if (typeof options.expandRange === 'function') {
|
||
return options.expandRange(...args, options);
|
||
}
|
||
|
||
args.sort();
|
||
const value = `[${args.join('-')}]`;
|
||
|
||
try {
|
||
/* eslint-disable-next-line no-new */
|
||
new RegExp(value);
|
||
} catch (ex) {
|
||
return args.map(v => utils$l.escapeRegex(v)).join('..');
|
||
}
|
||
|
||
return value;
|
||
};
|
||
|
||
/**
|
||
* Create the message for a syntax error
|
||
*/
|
||
|
||
const syntaxError = (type, char) => {
|
||
return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`;
|
||
};
|
||
|
||
/**
|
||
* Parse the given input string.
|
||
* @param {String} input
|
||
* @param {Object} options
|
||
* @return {Object}
|
||
*/
|
||
|
||
const parse$a = (input, options) => {
|
||
if (typeof input !== 'string') {
|
||
throw new TypeError('Expected a string');
|
||
}
|
||
|
||
input = REPLACEMENTS[input] || input;
|
||
|
||
const opts = { ...options };
|
||
const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
|
||
|
||
let len = input.length;
|
||
if (len > max) {
|
||
throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);
|
||
}
|
||
|
||
const bos = { type: 'bos', value: '', output: opts.prepend || '' };
|
||
const tokens = [bos];
|
||
|
||
const capture = opts.capture ? '' : '?:';
|
||
const win32 = utils$l.isWindows(options);
|
||
|
||
// create constants based on platform, for windows or posix
|
||
const PLATFORM_CHARS = constants$2.globChars(win32);
|
||
const EXTGLOB_CHARS = constants$2.extglobChars(PLATFORM_CHARS);
|
||
|
||
const {
|
||
DOT_LITERAL,
|
||
PLUS_LITERAL,
|
||
SLASH_LITERAL,
|
||
ONE_CHAR,
|
||
DOTS_SLASH,
|
||
NO_DOT,
|
||
NO_DOT_SLASH,
|
||
NO_DOTS_SLASH,
|
||
QMARK,
|
||
QMARK_NO_DOT,
|
||
STAR,
|
||
START_ANCHOR
|
||
} = PLATFORM_CHARS;
|
||
|
||
const globstar = opts => {
|
||
return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`;
|
||
};
|
||
|
||
const nodot = opts.dot ? '' : NO_DOT;
|
||
const qmarkNoDot = opts.dot ? QMARK : QMARK_NO_DOT;
|
||
let star = opts.bash === true ? globstar(opts) : STAR;
|
||
|
||
if (opts.capture) {
|
||
star = `(${star})`;
|
||
}
|
||
|
||
// minimatch options support
|
||
if (typeof opts.noext === 'boolean') {
|
||
opts.noextglob = opts.noext;
|
||
}
|
||
|
||
const state = {
|
||
input,
|
||
index: -1,
|
||
start: 0,
|
||
dot: opts.dot === true,
|
||
consumed: '',
|
||
output: '',
|
||
prefix: '',
|
||
backtrack: false,
|
||
negated: false,
|
||
brackets: 0,
|
||
braces: 0,
|
||
parens: 0,
|
||
quotes: 0,
|
||
globstar: false,
|
||
tokens
|
||
};
|
||
|
||
input = utils$l.removePrefix(input, state);
|
||
len = input.length;
|
||
|
||
const extglobs = [];
|
||
const braces = [];
|
||
const stack = [];
|
||
let prev = bos;
|
||
let value;
|
||
|
||
/**
|
||
* Tokenizing helpers
|
||
*/
|
||
|
||
const eos = () => state.index === len - 1;
|
||
const peek = state.peek = (n = 1) => input[state.index + n];
|
||
const advance = state.advance = () => input[++state.index] || '';
|
||
const remaining = () => input.slice(state.index + 1);
|
||
const consume = (value = '', num = 0) => {
|
||
state.consumed += value;
|
||
state.index += num;
|
||
};
|
||
|
||
const append = token => {
|
||
state.output += token.output != null ? token.output : token.value;
|
||
consume(token.value);
|
||
};
|
||
|
||
const negate = () => {
|
||
let count = 1;
|
||
|
||
while (peek() === '!' && (peek(2) !== '(' || peek(3) === '?')) {
|
||
advance();
|
||
state.start++;
|
||
count++;
|
||
}
|
||
|
||
if (count % 2 === 0) {
|
||
return false;
|
||
}
|
||
|
||
state.negated = true;
|
||
state.start++;
|
||
return true;
|
||
};
|
||
|
||
const increment = type => {
|
||
state[type]++;
|
||
stack.push(type);
|
||
};
|
||
|
||
const decrement = type => {
|
||
state[type]--;
|
||
stack.pop();
|
||
};
|
||
|
||
/**
|
||
* Push tokens onto the tokens array. This helper speeds up
|
||
* tokenizing by 1) helping us avoid backtracking as much as possible,
|
||
* and 2) helping us avoid creating extra tokens when consecutive
|
||
* characters are plain text. This improves performance and simplifies
|
||
* lookbehinds.
|
||
*/
|
||
|
||
const push = tok => {
|
||
if (prev.type === 'globstar') {
|
||
const isBrace = state.braces > 0 && (tok.type === 'comma' || tok.type === 'brace');
|
||
const isExtglob = tok.extglob === true || (extglobs.length && (tok.type === 'pipe' || tok.type === 'paren'));
|
||
|
||
if (tok.type !== 'slash' && tok.type !== 'paren' && !isBrace && !isExtglob) {
|
||
state.output = state.output.slice(0, -prev.output.length);
|
||
prev.type = 'star';
|
||
prev.value = '*';
|
||
prev.output = star;
|
||
state.output += prev.output;
|
||
}
|
||
}
|
||
|
||
if (extglobs.length && tok.type !== 'paren') {
|
||
extglobs[extglobs.length - 1].inner += tok.value;
|
||
}
|
||
|
||
if (tok.value || tok.output) append(tok);
|
||
if (prev && prev.type === 'text' && tok.type === 'text') {
|
||
prev.value += tok.value;
|
||
prev.output = (prev.output || '') + tok.value;
|
||
return;
|
||
}
|
||
|
||
tok.prev = prev;
|
||
tokens.push(tok);
|
||
prev = tok;
|
||
};
|
||
|
||
const extglobOpen = (type, value) => {
|
||
const token = { ...EXTGLOB_CHARS[value], conditions: 1, inner: '' };
|
||
|
||
token.prev = prev;
|
||
token.parens = state.parens;
|
||
token.output = state.output;
|
||
const output = (opts.capture ? '(' : '') + token.open;
|
||
|
||
increment('parens');
|
||
push({ type, value, output: state.output ? '' : ONE_CHAR });
|
||
push({ type: 'paren', extglob: true, value: advance(), output });
|
||
extglobs.push(token);
|
||
};
|
||
|
||
const extglobClose = token => {
|
||
let output = token.close + (opts.capture ? ')' : '');
|
||
let rest;
|
||
|
||
if (token.type === 'negate') {
|
||
let extglobStar = star;
|
||
|
||
if (token.inner && token.inner.length > 1 && token.inner.includes('/')) {
|
||
extglobStar = globstar(opts);
|
||
}
|
||
|
||
if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) {
|
||
output = token.close = `)$))${extglobStar}`;
|
||
}
|
||
|
||
if (token.inner.includes('*') && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) {
|
||
// Any non-magical string (`.ts`) or even nested expression (`.{ts,tsx}`) can follow after the closing parenthesis.
|
||
// In this case, we need to parse the string and use it in the output of the original pattern.
|
||
// Suitable patterns: `/!(*.d).ts`, `/!(*.d).{ts,tsx}`, `**/!(*-dbg).@(js)`.
|
||
//
|
||
// Disabling the `fastpaths` option due to a problem with parsing strings as `.ts` in the pattern like `**/!(*.d).ts`.
|
||
const expression = parse$a(rest, { ...options, fastpaths: false }).output;
|
||
|
||
output = token.close = `)${expression})${extglobStar})`;
|
||
}
|
||
|
||
if (token.prev.type === 'bos') {
|
||
state.negatedExtglob = true;
|
||
}
|
||
}
|
||
|
||
push({ type: 'paren', extglob: true, value, output });
|
||
decrement('parens');
|
||
};
|
||
|
||
/**
|
||
* Fast paths
|
||
*/
|
||
|
||
if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) {
|
||
let backslashes = false;
|
||
|
||
let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => {
|
||
if (first === '\\') {
|
||
backslashes = true;
|
||
return m;
|
||
}
|
||
|
||
if (first === '?') {
|
||
if (esc) {
|
||
return esc + first + (rest ? QMARK.repeat(rest.length) : '');
|
||
}
|
||
if (index === 0) {
|
||
return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : '');
|
||
}
|
||
return QMARK.repeat(chars.length);
|
||
}
|
||
|
||
if (first === '.') {
|
||
return DOT_LITERAL.repeat(chars.length);
|
||
}
|
||
|
||
if (first === '*') {
|
||
if (esc) {
|
||
return esc + first + (rest ? star : '');
|
||
}
|
||
return star;
|
||
}
|
||
return esc ? m : `\\${m}`;
|
||
});
|
||
|
||
if (backslashes === true) {
|
||
if (opts.unescape === true) {
|
||
output = output.replace(/\\/g, '');
|
||
} else {
|
||
output = output.replace(/\\+/g, m => {
|
||
return m.length % 2 === 0 ? '\\\\' : (m ? '\\' : '');
|
||
});
|
||
}
|
||
}
|
||
|
||
if (output === input && opts.contains === true) {
|
||
state.output = input;
|
||
return state;
|
||
}
|
||
|
||
state.output = utils$l.wrapOutput(output, state, options);
|
||
return state;
|
||
}
|
||
|
||
/**
|
||
* Tokenize input until we reach end-of-string
|
||
*/
|
||
|
||
while (!eos()) {
|
||
value = advance();
|
||
|
||
if (value === '\u0000') {
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Escaped characters
|
||
*/
|
||
|
||
if (value === '\\') {
|
||
const next = peek();
|
||
|
||
if (next === '/' && opts.bash !== true) {
|
||
continue;
|
||
}
|
||
|
||
if (next === '.' || next === ';') {
|
||
continue;
|
||
}
|
||
|
||
if (!next) {
|
||
value += '\\';
|
||
push({ type: 'text', value });
|
||
continue;
|
||
}
|
||
|
||
// collapse slashes to reduce potential for exploits
|
||
const match = /^\\+/.exec(remaining());
|
||
let slashes = 0;
|
||
|
||
if (match && match[0].length > 2) {
|
||
slashes = match[0].length;
|
||
state.index += slashes;
|
||
if (slashes % 2 !== 0) {
|
||
value += '\\';
|
||
}
|
||
}
|
||
|
||
if (opts.unescape === true) {
|
||
value = advance();
|
||
} else {
|
||
value += advance();
|
||
}
|
||
|
||
if (state.brackets === 0) {
|
||
push({ type: 'text', value });
|
||
continue;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* If we're inside a regex character class, continue
|
||
* until we reach the closing bracket.
|
||
*/
|
||
|
||
if (state.brackets > 0 && (value !== ']' || prev.value === '[' || prev.value === '[^')) {
|
||
if (opts.posix !== false && value === ':') {
|
||
const inner = prev.value.slice(1);
|
||
if (inner.includes('[')) {
|
||
prev.posix = true;
|
||
|
||
if (inner.includes(':')) {
|
||
const idx = prev.value.lastIndexOf('[');
|
||
const pre = prev.value.slice(0, idx);
|
||
const rest = prev.value.slice(idx + 2);
|
||
const posix = POSIX_REGEX_SOURCE[rest];
|
||
if (posix) {
|
||
prev.value = pre + posix;
|
||
state.backtrack = true;
|
||
advance();
|
||
|
||
if (!bos.output && tokens.indexOf(prev) === 1) {
|
||
bos.output = ONE_CHAR;
|
||
}
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if ((value === '[' && peek() !== ':') || (value === '-' && peek() === ']')) {
|
||
value = `\\${value}`;
|
||
}
|
||
|
||
if (value === ']' && (prev.value === '[' || prev.value === '[^')) {
|
||
value = `\\${value}`;
|
||
}
|
||
|
||
if (opts.posix === true && value === '!' && prev.value === '[') {
|
||
value = '^';
|
||
}
|
||
|
||
prev.value += value;
|
||
append({ value });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* If we're inside a quoted string, continue
|
||
* until we reach the closing double quote.
|
||
*/
|
||
|
||
if (state.quotes === 1 && value !== '"') {
|
||
value = utils$l.escapeRegex(value);
|
||
prev.value += value;
|
||
append({ value });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Double quotes
|
||
*/
|
||
|
||
if (value === '"') {
|
||
state.quotes = state.quotes === 1 ? 0 : 1;
|
||
if (opts.keepQuotes === true) {
|
||
push({ type: 'text', value });
|
||
}
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Parentheses
|
||
*/
|
||
|
||
if (value === '(') {
|
||
increment('parens');
|
||
push({ type: 'paren', value });
|
||
continue;
|
||
}
|
||
|
||
if (value === ')') {
|
||
if (state.parens === 0 && opts.strictBrackets === true) {
|
||
throw new SyntaxError(syntaxError('opening', '('));
|
||
}
|
||
|
||
const extglob = extglobs[extglobs.length - 1];
|
||
if (extglob && state.parens === extglob.parens + 1) {
|
||
extglobClose(extglobs.pop());
|
||
continue;
|
||
}
|
||
|
||
push({ type: 'paren', value, output: state.parens ? ')' : '\\)' });
|
||
decrement('parens');
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Square brackets
|
||
*/
|
||
|
||
if (value === '[') {
|
||
if (opts.nobracket === true || !remaining().includes(']')) {
|
||
if (opts.nobracket !== true && opts.strictBrackets === true) {
|
||
throw new SyntaxError(syntaxError('closing', ']'));
|
||
}
|
||
|
||
value = `\\${value}`;
|
||
} else {
|
||
increment('brackets');
|
||
}
|
||
|
||
push({ type: 'bracket', value });
|
||
continue;
|
||
}
|
||
|
||
if (value === ']') {
|
||
if (opts.nobracket === true || (prev && prev.type === 'bracket' && prev.value.length === 1)) {
|
||
push({ type: 'text', value, output: `\\${value}` });
|
||
continue;
|
||
}
|
||
|
||
if (state.brackets === 0) {
|
||
if (opts.strictBrackets === true) {
|
||
throw new SyntaxError(syntaxError('opening', '['));
|
||
}
|
||
|
||
push({ type: 'text', value, output: `\\${value}` });
|
||
continue;
|
||
}
|
||
|
||
decrement('brackets');
|
||
|
||
const prevValue = prev.value.slice(1);
|
||
if (prev.posix !== true && prevValue[0] === '^' && !prevValue.includes('/')) {
|
||
value = `/${value}`;
|
||
}
|
||
|
||
prev.value += value;
|
||
append({ value });
|
||
|
||
// when literal brackets are explicitly disabled
|
||
// assume we should match with a regex character class
|
||
if (opts.literalBrackets === false || utils$l.hasRegexChars(prevValue)) {
|
||
continue;
|
||
}
|
||
|
||
const escaped = utils$l.escapeRegex(prev.value);
|
||
state.output = state.output.slice(0, -prev.value.length);
|
||
|
||
// when literal brackets are explicitly enabled
|
||
// assume we should escape the brackets to match literal characters
|
||
if (opts.literalBrackets === true) {
|
||
state.output += escaped;
|
||
prev.value = escaped;
|
||
continue;
|
||
}
|
||
|
||
// when the user specifies nothing, try to match both
|
||
prev.value = `(${capture}${escaped}|${prev.value})`;
|
||
state.output += prev.value;
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Braces
|
||
*/
|
||
|
||
if (value === '{' && opts.nobrace !== true) {
|
||
increment('braces');
|
||
|
||
const open = {
|
||
type: 'brace',
|
||
value,
|
||
output: '(',
|
||
outputIndex: state.output.length,
|
||
tokensIndex: state.tokens.length
|
||
};
|
||
|
||
braces.push(open);
|
||
push(open);
|
||
continue;
|
||
}
|
||
|
||
if (value === '}') {
|
||
const brace = braces[braces.length - 1];
|
||
|
||
if (opts.nobrace === true || !brace) {
|
||
push({ type: 'text', value, output: value });
|
||
continue;
|
||
}
|
||
|
||
let output = ')';
|
||
|
||
if (brace.dots === true) {
|
||
const arr = tokens.slice();
|
||
const range = [];
|
||
|
||
for (let i = arr.length - 1; i >= 0; i--) {
|
||
tokens.pop();
|
||
if (arr[i].type === 'brace') {
|
||
break;
|
||
}
|
||
if (arr[i].type !== 'dots') {
|
||
range.unshift(arr[i].value);
|
||
}
|
||
}
|
||
|
||
output = expandRange(range, opts);
|
||
state.backtrack = true;
|
||
}
|
||
|
||
if (brace.comma !== true && brace.dots !== true) {
|
||
const out = state.output.slice(0, brace.outputIndex);
|
||
const toks = state.tokens.slice(brace.tokensIndex);
|
||
brace.value = brace.output = '\\{';
|
||
value = output = '\\}';
|
||
state.output = out;
|
||
for (const t of toks) {
|
||
state.output += (t.output || t.value);
|
||
}
|
||
}
|
||
|
||
push({ type: 'brace', value, output });
|
||
decrement('braces');
|
||
braces.pop();
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Pipes
|
||
*/
|
||
|
||
if (value === '|') {
|
||
if (extglobs.length > 0) {
|
||
extglobs[extglobs.length - 1].conditions++;
|
||
}
|
||
push({ type: 'text', value });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Commas
|
||
*/
|
||
|
||
if (value === ',') {
|
||
let output = value;
|
||
|
||
const brace = braces[braces.length - 1];
|
||
if (brace && stack[stack.length - 1] === 'braces') {
|
||
brace.comma = true;
|
||
output = '|';
|
||
}
|
||
|
||
push({ type: 'comma', value, output });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Slashes
|
||
*/
|
||
|
||
if (value === '/') {
|
||
// if the beginning of the glob is "./", advance the start
|
||
// to the current index, and don't add the "./" characters
|
||
// to the state. This greatly simplifies lookbehinds when
|
||
// checking for BOS characters like "!" and "." (not "./")
|
||
if (prev.type === 'dot' && state.index === state.start + 1) {
|
||
state.start = state.index + 1;
|
||
state.consumed = '';
|
||
state.output = '';
|
||
tokens.pop();
|
||
prev = bos; // reset "prev" to the first token
|
||
continue;
|
||
}
|
||
|
||
push({ type: 'slash', value, output: SLASH_LITERAL });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Dots
|
||
*/
|
||
|
||
if (value === '.') {
|
||
if (state.braces > 0 && prev.type === 'dot') {
|
||
if (prev.value === '.') prev.output = DOT_LITERAL;
|
||
const brace = braces[braces.length - 1];
|
||
prev.type = 'dots';
|
||
prev.output += value;
|
||
prev.value += value;
|
||
brace.dots = true;
|
||
continue;
|
||
}
|
||
|
||
if ((state.braces + state.parens) === 0 && prev.type !== 'bos' && prev.type !== 'slash') {
|
||
push({ type: 'text', value, output: DOT_LITERAL });
|
||
continue;
|
||
}
|
||
|
||
push({ type: 'dot', value, output: DOT_LITERAL });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Question marks
|
||
*/
|
||
|
||
if (value === '?') {
|
||
const isGroup = prev && prev.value === '(';
|
||
if (!isGroup && opts.noextglob !== true && peek() === '(' && peek(2) !== '?') {
|
||
extglobOpen('qmark', value);
|
||
continue;
|
||
}
|
||
|
||
if (prev && prev.type === 'paren') {
|
||
const next = peek();
|
||
let output = value;
|
||
|
||
if (next === '<' && !utils$l.supportsLookbehinds()) {
|
||
throw new Error('Node.js v10 or higher is required for regex lookbehinds');
|
||
}
|
||
|
||
if ((prev.value === '(' && !/[!=<:]/.test(next)) || (next === '<' && !/<([!=]|\w+>)/.test(remaining()))) {
|
||
output = `\\${value}`;
|
||
}
|
||
|
||
push({ type: 'text', value, output });
|
||
continue;
|
||
}
|
||
|
||
if (opts.dot !== true && (prev.type === 'slash' || prev.type === 'bos')) {
|
||
push({ type: 'qmark', value, output: QMARK_NO_DOT });
|
||
continue;
|
||
}
|
||
|
||
push({ type: 'qmark', value, output: QMARK });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Exclamation
|
||
*/
|
||
|
||
if (value === '!') {
|
||
if (opts.noextglob !== true && peek() === '(') {
|
||
if (peek(2) !== '?' || !/[!=<:]/.test(peek(3))) {
|
||
extglobOpen('negate', value);
|
||
continue;
|
||
}
|
||
}
|
||
|
||
if (opts.nonegate !== true && state.index === 0) {
|
||
negate();
|
||
continue;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Plus
|
||
*/
|
||
|
||
if (value === '+') {
|
||
if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') {
|
||
extglobOpen('plus', value);
|
||
continue;
|
||
}
|
||
|
||
if ((prev && prev.value === '(') || opts.regex === false) {
|
||
push({ type: 'plus', value, output: PLUS_LITERAL });
|
||
continue;
|
||
}
|
||
|
||
if ((prev && (prev.type === 'bracket' || prev.type === 'paren' || prev.type === 'brace')) || state.parens > 0) {
|
||
push({ type: 'plus', value });
|
||
continue;
|
||
}
|
||
|
||
push({ type: 'plus', value: PLUS_LITERAL });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Plain text
|
||
*/
|
||
|
||
if (value === '@') {
|
||
if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') {
|
||
push({ type: 'at', extglob: true, value, output: '' });
|
||
continue;
|
||
}
|
||
|
||
push({ type: 'text', value });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Plain text
|
||
*/
|
||
|
||
if (value !== '*') {
|
||
if (value === '$' || value === '^') {
|
||
value = `\\${value}`;
|
||
}
|
||
|
||
const match = REGEX_NON_SPECIAL_CHARS.exec(remaining());
|
||
if (match) {
|
||
value += match[0];
|
||
state.index += match[0].length;
|
||
}
|
||
|
||
push({ type: 'text', value });
|
||
continue;
|
||
}
|
||
|
||
/**
|
||
* Stars
|
||
*/
|
||
|
||
if (prev && (prev.type === 'globstar' || prev.star === true)) {
|
||
prev.type = 'star';
|
||
prev.star = true;
|
||
prev.value += value;
|
||
prev.output = star;
|
||
state.backtrack = true;
|
||
state.globstar = true;
|
||
consume(value);
|
||
continue;
|
||
}
|
||
|
||
let rest = remaining();
|
||
if (opts.noextglob !== true && /^\([^?]/.test(rest)) {
|
||
extglobOpen('star', value);
|
||
continue;
|
||
}
|
||
|
||
if (prev.type === 'star') {
|
||
if (opts.noglobstar === true) {
|
||
consume(value);
|
||
continue;
|
||
}
|
||
|
||
const prior = prev.prev;
|
||
const before = prior.prev;
|
||
const isStart = prior.type === 'slash' || prior.type === 'bos';
|
||
const afterStar = before && (before.type === 'star' || before.type === 'globstar');
|
||
|
||
if (opts.bash === true && (!isStart || (rest[0] && rest[0] !== '/'))) {
|
||
push({ type: 'star', value, output: '' });
|
||
continue;
|
||
}
|
||
|
||
const isBrace = state.braces > 0 && (prior.type === 'comma' || prior.type === 'brace');
|
||
const isExtglob = extglobs.length && (prior.type === 'pipe' || prior.type === 'paren');
|
||
if (!isStart && prior.type !== 'paren' && !isBrace && !isExtglob) {
|
||
push({ type: 'star', value, output: '' });
|
||
continue;
|
||
}
|
||
|
||
// strip consecutive `/**/`
|
||
while (rest.slice(0, 3) === '/**') {
|
||
const after = input[state.index + 4];
|
||
if (after && after !== '/') {
|
||
break;
|
||
}
|
||
rest = rest.slice(3);
|
||
consume('/**', 3);
|
||
}
|
||
|
||
if (prior.type === 'bos' && eos()) {
|
||
prev.type = 'globstar';
|
||
prev.value += value;
|
||
prev.output = globstar(opts);
|
||
state.output = prev.output;
|
||
state.globstar = true;
|
||
consume(value);
|
||
continue;
|
||
}
|
||
|
||
if (prior.type === 'slash' && prior.prev.type !== 'bos' && !afterStar && eos()) {
|
||
state.output = state.output.slice(0, -(prior.output + prev.output).length);
|
||
prior.output = `(?:${prior.output}`;
|
||
|
||
prev.type = 'globstar';
|
||
prev.output = globstar(opts) + (opts.strictSlashes ? ')' : '|$)');
|
||
prev.value += value;
|
||
state.globstar = true;
|
||
state.output += prior.output + prev.output;
|
||
consume(value);
|
||
continue;
|
||
}
|
||
|
||
if (prior.type === 'slash' && prior.prev.type !== 'bos' && rest[0] === '/') {
|
||
const end = rest[1] !== void 0 ? '|$' : '';
|
||
|
||
state.output = state.output.slice(0, -(prior.output + prev.output).length);
|
||
prior.output = `(?:${prior.output}`;
|
||
|
||
prev.type = 'globstar';
|
||
prev.output = `${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`;
|
||
prev.value += value;
|
||
|
||
state.output += prior.output + prev.output;
|
||
state.globstar = true;
|
||
|
||
consume(value + advance());
|
||
|
||
push({ type: 'slash', value: '/', output: '' });
|
||
continue;
|
||
}
|
||
|
||
if (prior.type === 'bos' && rest[0] === '/') {
|
||
prev.type = 'globstar';
|
||
prev.value += value;
|
||
prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`;
|
||
state.output = prev.output;
|
||
state.globstar = true;
|
||
consume(value + advance());
|
||
push({ type: 'slash', value: '/', output: '' });
|
||
continue;
|
||
}
|
||
|
||
// remove single star from output
|
||
state.output = state.output.slice(0, -prev.output.length);
|
||
|
||
// reset previous token to globstar
|
||
prev.type = 'globstar';
|
||
prev.output = globstar(opts);
|
||
prev.value += value;
|
||
|
||
// reset output with globstar
|
||
state.output += prev.output;
|
||
state.globstar = true;
|
||
consume(value);
|
||
continue;
|
||
}
|
||
|
||
const token = { type: 'star', value, output: star };
|
||
|
||
if (opts.bash === true) {
|
||
token.output = '.*?';
|
||
if (prev.type === 'bos' || prev.type === 'slash') {
|
||
token.output = nodot + token.output;
|
||
}
|
||
push(token);
|
||
continue;
|
||
}
|
||
|
||
if (prev && (prev.type === 'bracket' || prev.type === 'paren') && opts.regex === true) {
|
||
token.output = value;
|
||
push(token);
|
||
continue;
|
||
}
|
||
|
||
if (state.index === state.start || prev.type === 'slash' || prev.type === 'dot') {
|
||
if (prev.type === 'dot') {
|
||
state.output += NO_DOT_SLASH;
|
||
prev.output += NO_DOT_SLASH;
|
||
|
||
} else if (opts.dot === true) {
|
||
state.output += NO_DOTS_SLASH;
|
||
prev.output += NO_DOTS_SLASH;
|
||
|
||
} else {
|
||
state.output += nodot;
|
||
prev.output += nodot;
|
||
}
|
||
|
||
if (peek() !== '*') {
|
||
state.output += ONE_CHAR;
|
||
prev.output += ONE_CHAR;
|
||
}
|
||
}
|
||
|
||
push(token);
|
||
}
|
||
|
||
while (state.brackets > 0) {
|
||
if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ']'));
|
||
state.output = utils$l.escapeLast(state.output, '[');
|
||
decrement('brackets');
|
||
}
|
||
|
||
while (state.parens > 0) {
|
||
if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ')'));
|
||
state.output = utils$l.escapeLast(state.output, '(');
|
||
decrement('parens');
|
||
}
|
||
|
||
while (state.braces > 0) {
|
||
if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', '}'));
|
||
state.output = utils$l.escapeLast(state.output, '{');
|
||
decrement('braces');
|
||
}
|
||
|
||
if (opts.strictSlashes !== true && (prev.type === 'star' || prev.type === 'bracket')) {
|
||
push({ type: 'maybe_slash', value: '', output: `${SLASH_LITERAL}?` });
|
||
}
|
||
|
||
// rebuild the output if we had to backtrack at any point
|
||
if (state.backtrack === true) {
|
||
state.output = '';
|
||
|
||
for (const token of state.tokens) {
|
||
state.output += token.output != null ? token.output : token.value;
|
||
|
||
if (token.suffix) {
|
||
state.output += token.suffix;
|
||
}
|
||
}
|
||
}
|
||
|
||
return state;
|
||
};
|
||
|
||
/**
|
||
* Fast paths for creating regular expressions for common glob patterns.
|
||
* This can significantly speed up processing and has very little downside
|
||
* impact when none of the fast paths match.
|
||
*/
|
||
|
||
parse$a.fastpaths = (input, options) => {
|
||
const opts = { ...options };
|
||
const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
|
||
const len = input.length;
|
||
if (len > max) {
|
||
throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);
|
||
}
|
||
|
||
input = REPLACEMENTS[input] || input;
|
||
const win32 = utils$l.isWindows(options);
|
||
|
||
// create constants based on platform, for windows or posix
|
||
const {
|
||
DOT_LITERAL,
|
||
SLASH_LITERAL,
|
||
ONE_CHAR,
|
||
DOTS_SLASH,
|
||
NO_DOT,
|
||
NO_DOTS,
|
||
NO_DOTS_SLASH,
|
||
STAR,
|
||
START_ANCHOR
|
||
} = constants$2.globChars(win32);
|
||
|
||
const nodot = opts.dot ? NO_DOTS : NO_DOT;
|
||
const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT;
|
||
const capture = opts.capture ? '' : '?:';
|
||
const state = { negated: false, prefix: '' };
|
||
let star = opts.bash === true ? '.*?' : STAR;
|
||
|
||
if (opts.capture) {
|
||
star = `(${star})`;
|
||
}
|
||
|
||
const globstar = opts => {
|
||
if (opts.noglobstar === true) return star;
|
||
return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`;
|
||
};
|
||
|
||
const create = str => {
|
||
switch (str) {
|
||
case '*':
|
||
return `${nodot}${ONE_CHAR}${star}`;
|
||
|
||
case '.*':
|
||
return `${DOT_LITERAL}${ONE_CHAR}${star}`;
|
||
|
||
case '*.*':
|
||
return `${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`;
|
||
|
||
case '*/*':
|
||
return `${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`;
|
||
|
||
case '**':
|
||
return nodot + globstar(opts);
|
||
|
||
case '**/*':
|
||
return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`;
|
||
|
||
case '**/*.*':
|
||
return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`;
|
||
|
||
case '**/.*':
|
||
return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`;
|
||
|
||
default: {
|
||
const match = /^(.*?)\.(\w+)$/.exec(str);
|
||
if (!match) return;
|
||
|
||
const source = create(match[1]);
|
||
if (!source) return;
|
||
|
||
return source + DOT_LITERAL + match[2];
|
||
}
|
||
}
|
||
};
|
||
|
||
const output = utils$l.removePrefix(input, state);
|
||
let source = create(output);
|
||
|
||
if (source && opts.strictSlashes !== true) {
|
||
source += `${SLASH_LITERAL}?`;
|
||
}
|
||
|
||
return source;
|
||
};
|
||
|
||
var parse_1$1 = parse$a;
|
||
|
||
const path$9 = path$q;
|
||
const scan = scan_1;
|
||
const parse$9 = parse_1$1;
|
||
const utils$k = utils$n;
|
||
const constants$1 = constants$3;
|
||
const isObject$4 = val => val && typeof val === 'object' && !Array.isArray(val);
|
||
|
||
/**
|
||
* Creates a matcher function from one or more glob patterns. The
|
||
* returned function takes a string to match as its first argument,
|
||
* and returns true if the string is a match. The returned matcher
|
||
* function also takes a boolean as the second argument that, when true,
|
||
* returns an object with additional information.
|
||
*
|
||
* ```js
|
||
* const picomatch = require('picomatch');
|
||
* // picomatch(glob[, options]);
|
||
*
|
||
* const isMatch = picomatch('*.!(*a)');
|
||
* console.log(isMatch('a.a')); //=> false
|
||
* console.log(isMatch('a.b')); //=> true
|
||
* ```
|
||
* @name picomatch
|
||
* @param {String|Array} `globs` One or more glob patterns.
|
||
* @param {Object=} `options`
|
||
* @return {Function=} Returns a matcher function.
|
||
* @api public
|
||
*/
|
||
|
||
const picomatch$2 = (glob, options, returnState = false) => {
|
||
if (Array.isArray(glob)) {
|
||
const fns = glob.map(input => picomatch$2(input, options, returnState));
|
||
const arrayMatcher = str => {
|
||
for (const isMatch of fns) {
|
||
const state = isMatch(str);
|
||
if (state) return state;
|
||
}
|
||
return false;
|
||
};
|
||
return arrayMatcher;
|
||
}
|
||
|
||
const isState = isObject$4(glob) && glob.tokens && glob.input;
|
||
|
||
if (glob === '' || (typeof glob !== 'string' && !isState)) {
|
||
throw new TypeError('Expected pattern to be a non-empty string');
|
||
}
|
||
|
||
const opts = options || {};
|
||
const posix = utils$k.isWindows(options);
|
||
const regex = isState
|
||
? picomatch$2.compileRe(glob, options)
|
||
: picomatch$2.makeRe(glob, options, false, true);
|
||
|
||
const state = regex.state;
|
||
delete regex.state;
|
||
|
||
let isIgnored = () => false;
|
||
if (opts.ignore) {
|
||
const ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null };
|
||
isIgnored = picomatch$2(opts.ignore, ignoreOpts, returnState);
|
||
}
|
||
|
||
const matcher = (input, returnObject = false) => {
|
||
const { isMatch, match, output } = picomatch$2.test(input, regex, options, { glob, posix });
|
||
const result = { glob, state, regex, posix, input, output, match, isMatch };
|
||
|
||
if (typeof opts.onResult === 'function') {
|
||
opts.onResult(result);
|
||
}
|
||
|
||
if (isMatch === false) {
|
||
result.isMatch = false;
|
||
return returnObject ? result : false;
|
||
}
|
||
|
||
if (isIgnored(input)) {
|
||
if (typeof opts.onIgnore === 'function') {
|
||
opts.onIgnore(result);
|
||
}
|
||
result.isMatch = false;
|
||
return returnObject ? result : false;
|
||
}
|
||
|
||
if (typeof opts.onMatch === 'function') {
|
||
opts.onMatch(result);
|
||
}
|
||
return returnObject ? result : true;
|
||
};
|
||
|
||
if (returnState) {
|
||
matcher.state = state;
|
||
}
|
||
|
||
return matcher;
|
||
};
|
||
|
||
/**
|
||
* Test `input` with the given `regex`. This is used by the main
|
||
* `picomatch()` function to test the input string.
|
||
*
|
||
* ```js
|
||
* const picomatch = require('picomatch');
|
||
* // picomatch.test(input, regex[, options]);
|
||
*
|
||
* console.log(picomatch.test('foo/bar', /^(?:([^/]*?)\/([^/]*?))$/));
|
||
* // { isMatch: true, match: [ 'foo/', 'foo', 'bar' ], output: 'foo/bar' }
|
||
* ```
|
||
* @param {String} `input` String to test.
|
||
* @param {RegExp} `regex`
|
||
* @return {Object} Returns an object with matching info.
|
||
* @api public
|
||
*/
|
||
|
||
picomatch$2.test = (input, regex, options, { glob, posix } = {}) => {
|
||
if (typeof input !== 'string') {
|
||
throw new TypeError('Expected input to be a string');
|
||
}
|
||
|
||
if (input === '') {
|
||
return { isMatch: false, output: '' };
|
||
}
|
||
|
||
const opts = options || {};
|
||
const format = opts.format || (posix ? utils$k.toPosixSlashes : null);
|
||
let match = input === glob;
|
||
let output = (match && format) ? format(input) : input;
|
||
|
||
if (match === false) {
|
||
output = format ? format(input) : input;
|
||
match = output === glob;
|
||
}
|
||
|
||
if (match === false || opts.capture === true) {
|
||
if (opts.matchBase === true || opts.basename === true) {
|
||
match = picomatch$2.matchBase(input, regex, options, posix);
|
||
} else {
|
||
match = regex.exec(output);
|
||
}
|
||
}
|
||
|
||
return { isMatch: Boolean(match), match, output };
|
||
};
|
||
|
||
/**
|
||
* Match the basename of a filepath.
|
||
*
|
||
* ```js
|
||
* const picomatch = require('picomatch');
|
||
* // picomatch.matchBase(input, glob[, options]);
|
||
* console.log(picomatch.matchBase('foo/bar.js', '*.js'); // true
|
||
* ```
|
||
* @param {String} `input` String to test.
|
||
* @param {RegExp|String} `glob` Glob pattern or regex created by [.makeRe](#makeRe).
|
||
* @return {Boolean}
|
||
* @api public
|
||
*/
|
||
|
||
picomatch$2.matchBase = (input, glob, options, posix = utils$k.isWindows(options)) => {
|
||
const regex = glob instanceof RegExp ? glob : picomatch$2.makeRe(glob, options);
|
||
return regex.test(path$9.basename(input));
|
||
};
|
||
|
||
/**
|
||
* Returns true if **any** of the given glob `patterns` match the specified `string`.
|
||
*
|
||
* ```js
|
||
* const picomatch = require('picomatch');
|
||
* // picomatch.isMatch(string, patterns[, options]);
|
||
*
|
||
* console.log(picomatch.isMatch('a.a', ['b.*', '*.a'])); //=> true
|
||
* console.log(picomatch.isMatch('a.a', 'b.*')); //=> false
|
||
* ```
|
||
* @param {String|Array} str The string to test.
|
||
* @param {String|Array} patterns One or more glob patterns to use for matching.
|
||
* @param {Object} [options] See available [options](#options).
|
||
* @return {Boolean} Returns true if any patterns match `str`
|
||
* @api public
|
||
*/
|
||
|
||
picomatch$2.isMatch = (str, patterns, options) => picomatch$2(patterns, options)(str);
|
||
|
||
/**
|
||
* Parse a glob pattern to create the source string for a regular
|
||
* expression.
|
||
*
|
||
* ```js
|
||
* const picomatch = require('picomatch');
|
||
* const result = picomatch.parse(pattern[, options]);
|
||
* ```
|
||
* @param {String} `pattern`
|
||
* @param {Object} `options`
|
||
* @return {Object} Returns an object with useful properties and output to be used as a regex source string.
|
||
* @api public
|
||
*/
|
||
|
||
picomatch$2.parse = (pattern, options) => {
|
||
if (Array.isArray(pattern)) return pattern.map(p => picomatch$2.parse(p, options));
|
||
return parse$9(pattern, { ...options, fastpaths: false });
|
||
};
|
||
|
||
/**
|
||
* Scan a glob pattern to separate the pattern into segments.
|
||
*
|
||
* ```js
|
||
* const picomatch = require('picomatch');
|
||
* // picomatch.scan(input[, options]);
|
||
*
|
||
* const result = picomatch.scan('!./foo/*.js');
|
||
* console.log(result);
|
||
* { prefix: '!./',
|
||
* input: '!./foo/*.js',
|
||
* start: 3,
|
||
* base: 'foo',
|
||
* glob: '*.js',
|
||
* isBrace: false,
|
||
* isBracket: false,
|
||
* isGlob: true,
|
||
* isExtglob: false,
|
||
* isGlobstar: false,
|
||
* negated: true }
|
||
* ```
|
||
* @param {String} `input` Glob pattern to scan.
|
||
* @param {Object} `options`
|
||
* @return {Object} Returns an object with
|
||
* @api public
|
||
*/
|
||
|
||
picomatch$2.scan = (input, options) => scan(input, options);
|
||
|
||
/**
|
||
* Compile a regular expression from the `state` object returned by the
|
||
* [parse()](#parse) method.
|
||
*
|
||
* @param {Object} `state`
|
||
* @param {Object} `options`
|
||
* @param {Boolean} `returnOutput` Intended for implementors, this argument allows you to return the raw output from the parser.
|
||
* @param {Boolean} `returnState` Adds the state to a `state` property on the returned regex. Useful for implementors and debugging.
|
||
* @return {RegExp}
|
||
* @api public
|
||
*/
|
||
|
||
picomatch$2.compileRe = (state, options, returnOutput = false, returnState = false) => {
|
||
if (returnOutput === true) {
|
||
return state.output;
|
||
}
|
||
|
||
const opts = options || {};
|
||
const prepend = opts.contains ? '' : '^';
|
||
const append = opts.contains ? '' : '$';
|
||
|
||
let source = `${prepend}(?:${state.output})${append}`;
|
||
if (state && state.negated === true) {
|
||
source = `^(?!${source}).*$`;
|
||
}
|
||
|
||
const regex = picomatch$2.toRegex(source, options);
|
||
if (returnState === true) {
|
||
regex.state = state;
|
||
}
|
||
|
||
return regex;
|
||
};
|
||
|
||
/**
|
||
* Create a regular expression from a parsed glob pattern.
|
||
*
|
||
* ```js
|
||
* const picomatch = require('picomatch');
|
||
* const state = picomatch.parse('*.js');
|
||
* // picomatch.compileRe(state[, options]);
|
||
*
|
||
* console.log(picomatch.compileRe(state));
|
||
* //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
|
||
* ```
|
||
* @param {String} `state` The object returned from the `.parse` method.
|
||
* @param {Object} `options`
|
||
* @param {Boolean} `returnOutput` Implementors may use this argument to return the compiled output, instead of a regular expression. This is not exposed on the options to prevent end-users from mutating the result.
|
||
* @param {Boolean} `returnState` Implementors may use this argument to return the state from the parsed glob with the returned regular expression.
|
||
* @return {RegExp} Returns a regex created from the given pattern.
|
||
* @api public
|
||
*/
|
||
|
||
picomatch$2.makeRe = (input, options = {}, returnOutput = false, returnState = false) => {
|
||
if (!input || typeof input !== 'string') {
|
||
throw new TypeError('Expected a non-empty string');
|
||
}
|
||
|
||
let parsed = { negated: false, fastpaths: true };
|
||
|
||
if (options.fastpaths !== false && (input[0] === '.' || input[0] === '*')) {
|
||
parsed.output = parse$9.fastpaths(input, options);
|
||
}
|
||
|
||
if (!parsed.output) {
|
||
parsed = parse$9(input, options);
|
||
}
|
||
|
||
return picomatch$2.compileRe(parsed, options, returnOutput, returnState);
|
||
};
|
||
|
||
/**
|
||
* Create a regular expression from the given regex source string.
|
||
*
|
||
* ```js
|
||
* const picomatch = require('picomatch');
|
||
* // picomatch.toRegex(source[, options]);
|
||
*
|
||
* const { output } = picomatch.parse('*.js');
|
||
* console.log(picomatch.toRegex(output));
|
||
* //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
|
||
* ```
|
||
* @param {String} `source` Regular expression source string.
|
||
* @param {Object} `options`
|
||
* @return {RegExp}
|
||
* @api public
|
||
*/
|
||
|
||
picomatch$2.toRegex = (source, options) => {
|
||
try {
|
||
const opts = options || {};
|
||
return new RegExp(source, opts.flags || (opts.nocase ? 'i' : ''));
|
||
} catch (err) {
|
||
if (options && options.debug === true) throw err;
|
||
return /$^/;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Picomatch constants.
|
||
* @return {Object}
|
||
*/
|
||
|
||
picomatch$2.constants = constants$1;
|
||
|
||
/**
|
||
* Expose "picomatch"
|
||
*/
|
||
|
||
var picomatch_1 = picomatch$2;
|
||
|
||
var picomatch$1 = picomatch_1;
|
||
|
||
const util = require$$0$4;
|
||
const braces = braces_1;
|
||
const picomatch = picomatch$1;
|
||
const utils$j = utils$n;
|
||
const isEmptyString = val => val === '' || val === './';
|
||
|
||
/**
|
||
* Returns an array of strings that match one or more glob patterns.
|
||
*
|
||
* ```js
|
||
* const mm = require('micromatch');
|
||
* // mm(list, patterns[, options]);
|
||
*
|
||
* console.log(mm(['a.js', 'a.txt'], ['*.js']));
|
||
* //=> [ 'a.js' ]
|
||
* ```
|
||
* @param {String|Array<string>} `list` List of strings to match.
|
||
* @param {String|Array<string>} `patterns` One or more glob patterns to use for matching.
|
||
* @param {Object} `options` See available [options](#options)
|
||
* @return {Array} Returns an array of matches
|
||
* @summary false
|
||
* @api public
|
||
*/
|
||
|
||
const micromatch$1 = (list, patterns, options) => {
|
||
patterns = [].concat(patterns);
|
||
list = [].concat(list);
|
||
|
||
let omit = new Set();
|
||
let keep = new Set();
|
||
let items = new Set();
|
||
let negatives = 0;
|
||
|
||
let onResult = state => {
|
||
items.add(state.output);
|
||
if (options && options.onResult) {
|
||
options.onResult(state);
|
||
}
|
||
};
|
||
|
||
for (let i = 0; i < patterns.length; i++) {
|
||
let isMatch = picomatch(String(patterns[i]), { ...options, onResult }, true);
|
||
let negated = isMatch.state.negated || isMatch.state.negatedExtglob;
|
||
if (negated) negatives++;
|
||
|
||
for (let item of list) {
|
||
let matched = isMatch(item, true);
|
||
|
||
let match = negated ? !matched.isMatch : matched.isMatch;
|
||
if (!match) continue;
|
||
|
||
if (negated) {
|
||
omit.add(matched.output);
|
||
} else {
|
||
omit.delete(matched.output);
|
||
keep.add(matched.output);
|
||
}
|
||
}
|
||
}
|
||
|
||
let result = negatives === patterns.length ? [...items] : [...keep];
|
||
let matches = result.filter(item => !omit.has(item));
|
||
|
||
if (options && matches.length === 0) {
|
||
if (options.failglob === true) {
|
||
throw new Error(`No matches found for "${patterns.join(', ')}"`);
|
||
}
|
||
|
||
if (options.nonull === true || options.nullglob === true) {
|
||
return options.unescape ? patterns.map(p => p.replace(/\\/g, '')) : patterns;
|
||
}
|
||
}
|
||
|
||
return matches;
|
||
};
|
||
|
||
/**
|
||
* Backwards compatibility
|
||
*/
|
||
|
||
micromatch$1.match = micromatch$1;
|
||
|
||
/**
|
||
* Returns a matcher function from the given glob `pattern` and `options`.
|
||
* The returned function takes a string to match as its only argument and returns
|
||
* true if the string is a match.
|
||
*
|
||
* ```js
|
||
* const mm = require('micromatch');
|
||
* // mm.matcher(pattern[, options]);
|
||
*
|
||
* const isMatch = mm.matcher('*.!(*a)');
|
||
* console.log(isMatch('a.a')); //=> false
|
||
* console.log(isMatch('a.b')); //=> true
|
||
* ```
|
||
* @param {String} `pattern` Glob pattern
|
||
* @param {Object} `options`
|
||
* @return {Function} Returns a matcher function.
|
||
* @api public
|
||
*/
|
||
|
||
micromatch$1.matcher = (pattern, options) => picomatch(pattern, options);
|
||
|
||
/**
|
||
* Returns true if **any** of the given glob `patterns` match the specified `string`.
|
||
*
|
||
* ```js
|
||
* const mm = require('micromatch');
|
||
* // mm.isMatch(string, patterns[, options]);
|
||
*
|
||
* console.log(mm.isMatch('a.a', ['b.*', '*.a'])); //=> true
|
||
* console.log(mm.isMatch('a.a', 'b.*')); //=> false
|
||
* ```
|
||
* @param {String} `str` The string to test.
|
||
* @param {String|Array} `patterns` One or more glob patterns to use for matching.
|
||
* @param {Object} `[options]` See available [options](#options).
|
||
* @return {Boolean} Returns true if any patterns match `str`
|
||
* @api public
|
||
*/
|
||
|
||
micromatch$1.isMatch = (str, patterns, options) => picomatch(patterns, options)(str);
|
||
|
||
/**
|
||
* Backwards compatibility
|
||
*/
|
||
|
||
micromatch$1.any = micromatch$1.isMatch;
|
||
|
||
/**
|
||
* Returns a list of strings that _**do not match any**_ of the given `patterns`.
|
||
*
|
||
* ```js
|
||
* const mm = require('micromatch');
|
||
* // mm.not(list, patterns[, options]);
|
||
*
|
||
* console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a'));
|
||
* //=> ['b.b', 'c.c']
|
||
* ```
|
||
* @param {Array} `list` Array of strings to match.
|
||
* @param {String|Array} `patterns` One or more glob pattern to use for matching.
|
||
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
||
* @return {Array} Returns an array of strings that **do not match** the given patterns.
|
||
* @api public
|
||
*/
|
||
|
||
micromatch$1.not = (list, patterns, options = {}) => {
|
||
patterns = [].concat(patterns).map(String);
|
||
let result = new Set();
|
||
let items = [];
|
||
|
||
let onResult = state => {
|
||
if (options.onResult) options.onResult(state);
|
||
items.push(state.output);
|
||
};
|
||
|
||
let matches = new Set(micromatch$1(list, patterns, { ...options, onResult }));
|
||
|
||
for (let item of items) {
|
||
if (!matches.has(item)) {
|
||
result.add(item);
|
||
}
|
||
}
|
||
return [...result];
|
||
};
|
||
|
||
/**
|
||
* Returns true if the given `string` contains the given pattern. Similar
|
||
* to [.isMatch](#isMatch) but the pattern can match any part of the string.
|
||
*
|
||
* ```js
|
||
* var mm = require('micromatch');
|
||
* // mm.contains(string, pattern[, options]);
|
||
*
|
||
* console.log(mm.contains('aa/bb/cc', '*b'));
|
||
* //=> true
|
||
* console.log(mm.contains('aa/bb/cc', '*d'));
|
||
* //=> false
|
||
* ```
|
||
* @param {String} `str` The string to match.
|
||
* @param {String|Array} `patterns` Glob pattern to use for matching.
|
||
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
||
* @return {Boolean} Returns true if any of the patterns matches any part of `str`.
|
||
* @api public
|
||
*/
|
||
|
||
micromatch$1.contains = (str, pattern, options) => {
|
||
if (typeof str !== 'string') {
|
||
throw new TypeError(`Expected a string: "${util.inspect(str)}"`);
|
||
}
|
||
|
||
if (Array.isArray(pattern)) {
|
||
return pattern.some(p => micromatch$1.contains(str, p, options));
|
||
}
|
||
|
||
if (typeof pattern === 'string') {
|
||
if (isEmptyString(str) || isEmptyString(pattern)) {
|
||
return false;
|
||
}
|
||
|
||
if (str.includes(pattern) || (str.startsWith('./') && str.slice(2).includes(pattern))) {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return micromatch$1.isMatch(str, pattern, { ...options, contains: true });
|
||
};
|
||
|
||
/**
|
||
* Filter the keys of the given object with the given `glob` pattern
|
||
* and `options`. Does not attempt to match nested keys. If you need this feature,
|
||
* use [glob-object][] instead.
|
||
*
|
||
* ```js
|
||
* const mm = require('micromatch');
|
||
* // mm.matchKeys(object, patterns[, options]);
|
||
*
|
||
* const obj = { aa: 'a', ab: 'b', ac: 'c' };
|
||
* console.log(mm.matchKeys(obj, '*b'));
|
||
* //=> { ab: 'b' }
|
||
* ```
|
||
* @param {Object} `object` The object with keys to filter.
|
||
* @param {String|Array} `patterns` One or more glob patterns to use for matching.
|
||
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
||
* @return {Object} Returns an object with only keys that match the given patterns.
|
||
* @api public
|
||
*/
|
||
|
||
micromatch$1.matchKeys = (obj, patterns, options) => {
|
||
if (!utils$j.isObject(obj)) {
|
||
throw new TypeError('Expected the first argument to be an object');
|
||
}
|
||
let keys = micromatch$1(Object.keys(obj), patterns, options);
|
||
let res = {};
|
||
for (let key of keys) res[key] = obj[key];
|
||
return res;
|
||
};
|
||
|
||
/**
|
||
* Returns true if some of the strings in the given `list` match any of the given glob `patterns`.
|
||
*
|
||
* ```js
|
||
* const mm = require('micromatch');
|
||
* // mm.some(list, patterns[, options]);
|
||
*
|
||
* console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js']));
|
||
* // true
|
||
* console.log(mm.some(['foo.js'], ['*.js', '!foo.js']));
|
||
* // false
|
||
* ```
|
||
* @param {String|Array} `list` The string or array of strings to test. Returns as soon as the first match is found.
|
||
* @param {String|Array} `patterns` One or more glob patterns to use for matching.
|
||
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
||
* @return {Boolean} Returns true if any `patterns` matches any of the strings in `list`
|
||
* @api public
|
||
*/
|
||
|
||
micromatch$1.some = (list, patterns, options) => {
|
||
let items = [].concat(list);
|
||
|
||
for (let pattern of [].concat(patterns)) {
|
||
let isMatch = picomatch(String(pattern), options);
|
||
if (items.some(item => isMatch(item))) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
|
||
/**
|
||
* Returns true if every string in the given `list` matches
|
||
* any of the given glob `patterns`.
|
||
*
|
||
* ```js
|
||
* const mm = require('micromatch');
|
||
* // mm.every(list, patterns[, options]);
|
||
*
|
||
* console.log(mm.every('foo.js', ['foo.js']));
|
||
* // true
|
||
* console.log(mm.every(['foo.js', 'bar.js'], ['*.js']));
|
||
* // true
|
||
* console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js']));
|
||
* // false
|
||
* console.log(mm.every(['foo.js'], ['*.js', '!foo.js']));
|
||
* // false
|
||
* ```
|
||
* @param {String|Array} `list` The string or array of strings to test.
|
||
* @param {String|Array} `patterns` One or more glob patterns to use for matching.
|
||
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
||
* @return {Boolean} Returns true if all `patterns` matches all of the strings in `list`
|
||
* @api public
|
||
*/
|
||
|
||
micromatch$1.every = (list, patterns, options) => {
|
||
let items = [].concat(list);
|
||
|
||
for (let pattern of [].concat(patterns)) {
|
||
let isMatch = picomatch(String(pattern), options);
|
||
if (!items.every(item => isMatch(item))) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
};
|
||
|
||
/**
|
||
* Returns true if **all** of the given `patterns` match
|
||
* the specified string.
|
||
*
|
||
* ```js
|
||
* const mm = require('micromatch');
|
||
* // mm.all(string, patterns[, options]);
|
||
*
|
||
* console.log(mm.all('foo.js', ['foo.js']));
|
||
* // true
|
||
*
|
||
* console.log(mm.all('foo.js', ['*.js', '!foo.js']));
|
||
* // false
|
||
*
|
||
* console.log(mm.all('foo.js', ['*.js', 'foo.js']));
|
||
* // true
|
||
*
|
||
* console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js']));
|
||
* // true
|
||
* ```
|
||
* @param {String|Array} `str` The string to test.
|
||
* @param {String|Array} `patterns` One or more glob patterns to use for matching.
|
||
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
||
* @return {Boolean} Returns true if any patterns match `str`
|
||
* @api public
|
||
*/
|
||
|
||
micromatch$1.all = (str, patterns, options) => {
|
||
if (typeof str !== 'string') {
|
||
throw new TypeError(`Expected a string: "${util.inspect(str)}"`);
|
||
}
|
||
|
||
return [].concat(patterns).every(p => picomatch(p, options)(str));
|
||
};
|
||
|
||
/**
|
||
* Returns an array of matches captured by `pattern` in `string, or `null` if the pattern did not match.
|
||
*
|
||
* ```js
|
||
* const mm = require('micromatch');
|
||
* // mm.capture(pattern, string[, options]);
|
||
*
|
||
* console.log(mm.capture('test/*.js', 'test/foo.js'));
|
||
* //=> ['foo']
|
||
* console.log(mm.capture('test/*.js', 'foo/bar.css'));
|
||
* //=> null
|
||
* ```
|
||
* @param {String} `glob` Glob pattern to use for matching.
|
||
* @param {String} `input` String to match
|
||
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
||
* @return {Array|null} Returns an array of captures if the input matches the glob pattern, otherwise `null`.
|
||
* @api public
|
||
*/
|
||
|
||
micromatch$1.capture = (glob, input, options) => {
|
||
let posix = utils$j.isWindows(options);
|
||
let regex = picomatch.makeRe(String(glob), { ...options, capture: true });
|
||
let match = regex.exec(posix ? utils$j.toPosixSlashes(input) : input);
|
||
|
||
if (match) {
|
||
return match.slice(1).map(v => v === void 0 ? '' : v);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Create a regular expression from the given glob `pattern`.
|
||
*
|
||
* ```js
|
||
* const mm = require('micromatch');
|
||
* // mm.makeRe(pattern[, options]);
|
||
*
|
||
* console.log(mm.makeRe('*.js'));
|
||
* //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/
|
||
* ```
|
||
* @param {String} `pattern` A glob pattern to convert to regex.
|
||
* @param {Object} `options`
|
||
* @return {RegExp} Returns a regex created from the given pattern.
|
||
* @api public
|
||
*/
|
||
|
||
micromatch$1.makeRe = (...args) => picomatch.makeRe(...args);
|
||
|
||
/**
|
||
* Scan a glob pattern to separate the pattern into segments. Used
|
||
* by the [split](#split) method.
|
||
*
|
||
* ```js
|
||
* const mm = require('micromatch');
|
||
* const state = mm.scan(pattern[, options]);
|
||
* ```
|
||
* @param {String} `pattern`
|
||
* @param {Object} `options`
|
||
* @return {Object} Returns an object with
|
||
* @api public
|
||
*/
|
||
|
||
micromatch$1.scan = (...args) => picomatch.scan(...args);
|
||
|
||
/**
|
||
* Parse a glob pattern to create the source string for a regular
|
||
* expression.
|
||
*
|
||
* ```js
|
||
* const mm = require('micromatch');
|
||
* const state = mm.parse(pattern[, options]);
|
||
* ```
|
||
* @param {String} `glob`
|
||
* @param {Object} `options`
|
||
* @return {Object} Returns an object with useful properties and output to be used as regex source string.
|
||
* @api public
|
||
*/
|
||
|
||
micromatch$1.parse = (patterns, options) => {
|
||
let res = [];
|
||
for (let pattern of [].concat(patterns || [])) {
|
||
for (let str of braces(String(pattern), options)) {
|
||
res.push(picomatch.parse(str, options));
|
||
}
|
||
}
|
||
return res;
|
||
};
|
||
|
||
/**
|
||
* Process the given brace `pattern`.
|
||
*
|
||
* ```js
|
||
* const { braces } = require('micromatch');
|
||
* console.log(braces('foo/{a,b,c}/bar'));
|
||
* //=> [ 'foo/(a|b|c)/bar' ]
|
||
*
|
||
* console.log(braces('foo/{a,b,c}/bar', { expand: true }));
|
||
* //=> [ 'foo/a/bar', 'foo/b/bar', 'foo/c/bar' ]
|
||
* ```
|
||
* @param {String} `pattern` String with brace pattern to process.
|
||
* @param {Object} `options` Any [options](#options) to change how expansion is performed. See the [braces][] library for all available options.
|
||
* @return {Array}
|
||
* @api public
|
||
*/
|
||
|
||
micromatch$1.braces = (pattern, options) => {
|
||
if (typeof pattern !== 'string') throw new TypeError('Expected a string');
|
||
if ((options && options.nobrace === true) || !/\{.*\}/.test(pattern)) {
|
||
return [pattern];
|
||
}
|
||
return braces(pattern, options);
|
||
};
|
||
|
||
/**
|
||
* Expand braces
|
||
*/
|
||
|
||
micromatch$1.braceExpand = (pattern, options) => {
|
||
if (typeof pattern !== 'string') throw new TypeError('Expected a string');
|
||
return micromatch$1.braces(pattern, { ...options, expand: true });
|
||
};
|
||
|
||
/**
|
||
* Expose micromatch
|
||
*/
|
||
|
||
var micromatch_1 = micromatch$1;
|
||
|
||
Object.defineProperty(pattern$1, "__esModule", { value: true });
|
||
pattern$1.removeDuplicateSlashes = pattern$1.matchAny = pattern$1.convertPatternsToRe = pattern$1.makeRe = pattern$1.getPatternParts = pattern$1.expandBraceExpansion = pattern$1.expandPatternsWithBraceExpansion = pattern$1.isAffectDepthOfReadingPattern = pattern$1.endsWithSlashGlobStar = pattern$1.hasGlobStar = pattern$1.getBaseDirectory = pattern$1.isPatternRelatedToParentDirectory = pattern$1.getPatternsOutsideCurrentDirectory = pattern$1.getPatternsInsideCurrentDirectory = pattern$1.getPositivePatterns = pattern$1.getNegativePatterns = pattern$1.isPositivePattern = pattern$1.isNegativePattern = pattern$1.convertToNegativePattern = pattern$1.convertToPositivePattern = pattern$1.isDynamicPattern = pattern$1.isStaticPattern = void 0;
|
||
const path$8 = path$q;
|
||
const globParent = globParent$1;
|
||
const micromatch = micromatch_1;
|
||
const GLOBSTAR = '**';
|
||
const ESCAPE_SYMBOL = '\\';
|
||
const COMMON_GLOB_SYMBOLS_RE = /[*?]|^!/;
|
||
const REGEX_CHARACTER_CLASS_SYMBOLS_RE = /\[[^[]*]/;
|
||
const REGEX_GROUP_SYMBOLS_RE = /(?:^|[^!*+?@])\([^(]*\|[^|]*\)/;
|
||
const GLOB_EXTENSION_SYMBOLS_RE = /[!*+?@]\([^(]*\)/;
|
||
const BRACE_EXPANSION_SEPARATORS_RE = /,|\.\./;
|
||
/**
|
||
* Matches a sequence of two or more consecutive slashes, excluding the first two slashes at the beginning of the string.
|
||
* The latter is due to the presence of the device path at the beginning of the UNC path.
|
||
*/
|
||
const DOUBLE_SLASH_RE = /(?!^)\/{2,}/g;
|
||
function isStaticPattern(pattern, options = {}) {
|
||
return !isDynamicPattern(pattern, options);
|
||
}
|
||
pattern$1.isStaticPattern = isStaticPattern;
|
||
function isDynamicPattern(pattern, options = {}) {
|
||
/**
|
||
* A special case with an empty string is necessary for matching patterns that start with a forward slash.
|
||
* An empty string cannot be a dynamic pattern.
|
||
* For example, the pattern `/lib/*` will be spread into parts: '', 'lib', '*'.
|
||
*/
|
||
if (pattern === '') {
|
||
return false;
|
||
}
|
||
/**
|
||
* When the `caseSensitiveMatch` option is disabled, all patterns must be marked as dynamic, because we cannot check
|
||
* filepath directly (without read directory).
|
||
*/
|
||
if (options.caseSensitiveMatch === false || pattern.includes(ESCAPE_SYMBOL)) {
|
||
return true;
|
||
}
|
||
if (COMMON_GLOB_SYMBOLS_RE.test(pattern) || REGEX_CHARACTER_CLASS_SYMBOLS_RE.test(pattern) || REGEX_GROUP_SYMBOLS_RE.test(pattern)) {
|
||
return true;
|
||
}
|
||
if (options.extglob !== false && GLOB_EXTENSION_SYMBOLS_RE.test(pattern)) {
|
||
return true;
|
||
}
|
||
if (options.braceExpansion !== false && hasBraceExpansion(pattern)) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
pattern$1.isDynamicPattern = isDynamicPattern;
|
||
function hasBraceExpansion(pattern) {
|
||
const openingBraceIndex = pattern.indexOf('{');
|
||
if (openingBraceIndex === -1) {
|
||
return false;
|
||
}
|
||
const closingBraceIndex = pattern.indexOf('}', openingBraceIndex + 1);
|
||
if (closingBraceIndex === -1) {
|
||
return false;
|
||
}
|
||
const braceContent = pattern.slice(openingBraceIndex, closingBraceIndex);
|
||
return BRACE_EXPANSION_SEPARATORS_RE.test(braceContent);
|
||
}
|
||
function convertToPositivePattern(pattern) {
|
||
return isNegativePattern(pattern) ? pattern.slice(1) : pattern;
|
||
}
|
||
pattern$1.convertToPositivePattern = convertToPositivePattern;
|
||
function convertToNegativePattern(pattern) {
|
||
return '!' + pattern;
|
||
}
|
||
pattern$1.convertToNegativePattern = convertToNegativePattern;
|
||
function isNegativePattern(pattern) {
|
||
return pattern.startsWith('!') && pattern[1] !== '(';
|
||
}
|
||
pattern$1.isNegativePattern = isNegativePattern;
|
||
function isPositivePattern(pattern) {
|
||
return !isNegativePattern(pattern);
|
||
}
|
||
pattern$1.isPositivePattern = isPositivePattern;
|
||
function getNegativePatterns(patterns) {
|
||
return patterns.filter(isNegativePattern);
|
||
}
|
||
pattern$1.getNegativePatterns = getNegativePatterns;
|
||
function getPositivePatterns$1(patterns) {
|
||
return patterns.filter(isPositivePattern);
|
||
}
|
||
pattern$1.getPositivePatterns = getPositivePatterns$1;
|
||
/**
|
||
* Returns patterns that can be applied inside the current directory.
|
||
*
|
||
* @example
|
||
* // ['./*', '*', 'a/*']
|
||
* getPatternsInsideCurrentDirectory(['./*', '*', 'a/*', '../*', './../*'])
|
||
*/
|
||
function getPatternsInsideCurrentDirectory(patterns) {
|
||
return patterns.filter((pattern) => !isPatternRelatedToParentDirectory(pattern));
|
||
}
|
||
pattern$1.getPatternsInsideCurrentDirectory = getPatternsInsideCurrentDirectory;
|
||
/**
|
||
* Returns patterns to be expanded relative to (outside) the current directory.
|
||
*
|
||
* @example
|
||
* // ['../*', './../*']
|
||
* getPatternsInsideCurrentDirectory(['./*', '*', 'a/*', '../*', './../*'])
|
||
*/
|
||
function getPatternsOutsideCurrentDirectory(patterns) {
|
||
return patterns.filter(isPatternRelatedToParentDirectory);
|
||
}
|
||
pattern$1.getPatternsOutsideCurrentDirectory = getPatternsOutsideCurrentDirectory;
|
||
function isPatternRelatedToParentDirectory(pattern) {
|
||
return pattern.startsWith('..') || pattern.startsWith('./..');
|
||
}
|
||
pattern$1.isPatternRelatedToParentDirectory = isPatternRelatedToParentDirectory;
|
||
function getBaseDirectory(pattern) {
|
||
return globParent(pattern, { flipBackslashes: false });
|
||
}
|
||
pattern$1.getBaseDirectory = getBaseDirectory;
|
||
function hasGlobStar(pattern) {
|
||
return pattern.includes(GLOBSTAR);
|
||
}
|
||
pattern$1.hasGlobStar = hasGlobStar;
|
||
function endsWithSlashGlobStar(pattern) {
|
||
return pattern.endsWith('/' + GLOBSTAR);
|
||
}
|
||
pattern$1.endsWithSlashGlobStar = endsWithSlashGlobStar;
|
||
function isAffectDepthOfReadingPattern(pattern) {
|
||
const basename = path$8.basename(pattern);
|
||
return endsWithSlashGlobStar(pattern) || isStaticPattern(basename);
|
||
}
|
||
pattern$1.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern;
|
||
function expandPatternsWithBraceExpansion(patterns) {
|
||
return patterns.reduce((collection, pattern) => {
|
||
return collection.concat(expandBraceExpansion(pattern));
|
||
}, []);
|
||
}
|
||
pattern$1.expandPatternsWithBraceExpansion = expandPatternsWithBraceExpansion;
|
||
function expandBraceExpansion(pattern) {
|
||
const patterns = micromatch.braces(pattern, { expand: true, nodupes: true, keepEscaping: true });
|
||
/**
|
||
* Sort the patterns by length so that the same depth patterns are processed side by side.
|
||
* `a/{b,}/{c,}/*` – `['a///*', 'a/b//*', 'a//c/*', 'a/b/c/*']`
|
||
*/
|
||
patterns.sort((a, b) => a.length - b.length);
|
||
/**
|
||
* Micromatch can return an empty string in the case of patterns like `{a,}`.
|
||
*/
|
||
return patterns.filter((pattern) => pattern !== '');
|
||
}
|
||
pattern$1.expandBraceExpansion = expandBraceExpansion;
|
||
function getPatternParts(pattern, options) {
|
||
let { parts } = micromatch.scan(pattern, Object.assign(Object.assign({}, options), { parts: true }));
|
||
/**
|
||
* The scan method returns an empty array in some cases.
|
||
* See micromatch/picomatch#58 for more details.
|
||
*/
|
||
if (parts.length === 0) {
|
||
parts = [pattern];
|
||
}
|
||
/**
|
||
* The scan method does not return an empty part for the pattern with a forward slash.
|
||
* This is another part of micromatch/picomatch#58.
|
||
*/
|
||
if (parts[0].startsWith('/')) {
|
||
parts[0] = parts[0].slice(1);
|
||
parts.unshift('');
|
||
}
|
||
return parts;
|
||
}
|
||
pattern$1.getPatternParts = getPatternParts;
|
||
function makeRe(pattern, options) {
|
||
return micromatch.makeRe(pattern, options);
|
||
}
|
||
pattern$1.makeRe = makeRe;
|
||
function convertPatternsToRe(patterns, options) {
|
||
return patterns.map((pattern) => makeRe(pattern, options));
|
||
}
|
||
pattern$1.convertPatternsToRe = convertPatternsToRe;
|
||
function matchAny(entry, patternsRe) {
|
||
return patternsRe.some((patternRe) => patternRe.test(entry));
|
||
}
|
||
pattern$1.matchAny = matchAny;
|
||
/**
|
||
* This package only works with forward slashes as a path separator.
|
||
* Because of this, we cannot use the standard `path.normalize` method, because on Windows platform it will use of backslashes.
|
||
*/
|
||
function removeDuplicateSlashes(pattern) {
|
||
return pattern.replace(DOUBLE_SLASH_RE, '/');
|
||
}
|
||
pattern$1.removeDuplicateSlashes = removeDuplicateSlashes;
|
||
|
||
var stream$4 = {};
|
||
|
||
/*
|
||
* merge2
|
||
* https://github.com/teambition/merge2
|
||
*
|
||
* Copyright (c) 2014-2020 Teambition
|
||
* Licensed under the MIT license.
|
||
*/
|
||
const Stream = require$$0$3;
|
||
const PassThrough = Stream.PassThrough;
|
||
const slice = Array.prototype.slice;
|
||
|
||
var merge2_1 = merge2$1;
|
||
|
||
function merge2$1 () {
|
||
const streamsQueue = [];
|
||
const args = slice.call(arguments);
|
||
let merging = false;
|
||
let options = args[args.length - 1];
|
||
|
||
if (options && !Array.isArray(options) && options.pipe == null) {
|
||
args.pop();
|
||
} else {
|
||
options = {};
|
||
}
|
||
|
||
const doEnd = options.end !== false;
|
||
const doPipeError = options.pipeError === true;
|
||
if (options.objectMode == null) {
|
||
options.objectMode = true;
|
||
}
|
||
if (options.highWaterMark == null) {
|
||
options.highWaterMark = 64 * 1024;
|
||
}
|
||
const mergedStream = PassThrough(options);
|
||
|
||
function addStream () {
|
||
for (let i = 0, len = arguments.length; i < len; i++) {
|
||
streamsQueue.push(pauseStreams(arguments[i], options));
|
||
}
|
||
mergeStream();
|
||
return this
|
||
}
|
||
|
||
function mergeStream () {
|
||
if (merging) {
|
||
return
|
||
}
|
||
merging = true;
|
||
|
||
let streams = streamsQueue.shift();
|
||
if (!streams) {
|
||
process.nextTick(endStream);
|
||
return
|
||
}
|
||
if (!Array.isArray(streams)) {
|
||
streams = [streams];
|
||
}
|
||
|
||
let pipesCount = streams.length + 1;
|
||
|
||
function next () {
|
||
if (--pipesCount > 0) {
|
||
return
|
||
}
|
||
merging = false;
|
||
mergeStream();
|
||
}
|
||
|
||
function pipe (stream) {
|
||
function onend () {
|
||
stream.removeListener('merge2UnpipeEnd', onend);
|
||
stream.removeListener('end', onend);
|
||
if (doPipeError) {
|
||
stream.removeListener('error', onerror);
|
||
}
|
||
next();
|
||
}
|
||
function onerror (err) {
|
||
mergedStream.emit('error', err);
|
||
}
|
||
// skip ended stream
|
||
if (stream._readableState.endEmitted) {
|
||
return next()
|
||
}
|
||
|
||
stream.on('merge2UnpipeEnd', onend);
|
||
stream.on('end', onend);
|
||
|
||
if (doPipeError) {
|
||
stream.on('error', onerror);
|
||
}
|
||
|
||
stream.pipe(mergedStream, { end: false });
|
||
// compatible for old stream
|
||
stream.resume();
|
||
}
|
||
|
||
for (let i = 0; i < streams.length; i++) {
|
||
pipe(streams[i]);
|
||
}
|
||
|
||
next();
|
||
}
|
||
|
||
function endStream () {
|
||
merging = false;
|
||
// emit 'queueDrain' when all streams merged.
|
||
mergedStream.emit('queueDrain');
|
||
if (doEnd) {
|
||
mergedStream.end();
|
||
}
|
||
}
|
||
|
||
mergedStream.setMaxListeners(0);
|
||
mergedStream.add = addStream;
|
||
mergedStream.on('unpipe', function (stream) {
|
||
stream.emit('merge2UnpipeEnd');
|
||
});
|
||
|
||
if (args.length) {
|
||
addStream.apply(null, args);
|
||
}
|
||
return mergedStream
|
||
}
|
||
|
||
// check and pause streams for pipe.
|
||
function pauseStreams (streams, options) {
|
||
if (!Array.isArray(streams)) {
|
||
// Backwards-compat with old-style streams
|
||
if (!streams._readableState && streams.pipe) {
|
||
streams = streams.pipe(PassThrough(options));
|
||
}
|
||
if (!streams._readableState || !streams.pause || !streams.pipe) {
|
||
throw new Error('Only readable stream can be merged.')
|
||
}
|
||
streams.pause();
|
||
} else {
|
||
for (let i = 0, len = streams.length; i < len; i++) {
|
||
streams[i] = pauseStreams(streams[i], options);
|
||
}
|
||
}
|
||
return streams
|
||
}
|
||
|
||
Object.defineProperty(stream$4, "__esModule", { value: true });
|
||
stream$4.merge = void 0;
|
||
const merge2 = merge2_1;
|
||
function merge$1(streams) {
|
||
const mergedStream = merge2(streams);
|
||
streams.forEach((stream) => {
|
||
stream.once('error', (error) => mergedStream.emit('error', error));
|
||
});
|
||
mergedStream.once('close', () => propagateCloseEventToSources(streams));
|
||
mergedStream.once('end', () => propagateCloseEventToSources(streams));
|
||
return mergedStream;
|
||
}
|
||
stream$4.merge = merge$1;
|
||
function propagateCloseEventToSources(streams) {
|
||
streams.forEach((stream) => stream.emit('close'));
|
||
}
|
||
|
||
var string$1 = {};
|
||
|
||
Object.defineProperty(string$1, "__esModule", { value: true });
|
||
string$1.isEmpty = string$1.isString = void 0;
|
||
function isString$2(input) {
|
||
return typeof input === 'string';
|
||
}
|
||
string$1.isString = isString$2;
|
||
function isEmpty(input) {
|
||
return input === '';
|
||
}
|
||
string$1.isEmpty = isEmpty;
|
||
|
||
Object.defineProperty(utils$s, "__esModule", { value: true });
|
||
utils$s.string = utils$s.stream = utils$s.pattern = utils$s.path = utils$s.fs = utils$s.errno = utils$s.array = void 0;
|
||
const array = array$1;
|
||
utils$s.array = array;
|
||
const errno = errno$1;
|
||
utils$s.errno = errno;
|
||
const fs$8 = fs$9;
|
||
utils$s.fs = fs$8;
|
||
const path$7 = path$c;
|
||
utils$s.path = path$7;
|
||
const pattern = pattern$1;
|
||
utils$s.pattern = pattern;
|
||
const stream$3 = stream$4;
|
||
utils$s.stream = stream$3;
|
||
const string = string$1;
|
||
utils$s.string = string;
|
||
|
||
Object.defineProperty(tasks, "__esModule", { value: true });
|
||
tasks.convertPatternGroupToTask = tasks.convertPatternGroupsToTasks = tasks.groupPatternsByBaseDirectory = tasks.getNegativePatternsAsPositive = tasks.getPositivePatterns = tasks.convertPatternsToTasks = tasks.generate = void 0;
|
||
const utils$i = utils$s;
|
||
function generate(input, settings) {
|
||
const patterns = processPatterns(input, settings);
|
||
const ignore = processPatterns(settings.ignore, settings);
|
||
const positivePatterns = getPositivePatterns(patterns);
|
||
const negativePatterns = getNegativePatternsAsPositive(patterns, ignore);
|
||
const staticPatterns = positivePatterns.filter((pattern) => utils$i.pattern.isStaticPattern(pattern, settings));
|
||
const dynamicPatterns = positivePatterns.filter((pattern) => utils$i.pattern.isDynamicPattern(pattern, settings));
|
||
const staticTasks = convertPatternsToTasks(staticPatterns, negativePatterns, /* dynamic */ false);
|
||
const dynamicTasks = convertPatternsToTasks(dynamicPatterns, negativePatterns, /* dynamic */ true);
|
||
return staticTasks.concat(dynamicTasks);
|
||
}
|
||
tasks.generate = generate;
|
||
function processPatterns(input, settings) {
|
||
let patterns = input;
|
||
/**
|
||
* The original pattern like `{,*,**,a/*}` can lead to problems checking the depth when matching entry
|
||
* and some problems with the micromatch package (see fast-glob issues: #365, #394).
|
||
*
|
||
* To solve this problem, we expand all patterns containing brace expansion. This can lead to a slight slowdown
|
||
* in matching in the case of a large set of patterns after expansion.
|
||
*/
|
||
if (settings.braceExpansion) {
|
||
patterns = utils$i.pattern.expandPatternsWithBraceExpansion(patterns);
|
||
}
|
||
/**
|
||
* If the `baseNameMatch` option is enabled, we must add globstar to patterns, so that they can be used
|
||
* at any nesting level.
|
||
*
|
||
* We do this here, because otherwise we have to complicate the filtering logic. For example, we need to change
|
||
* the pattern in the filter before creating a regular expression. There is no need to change the patterns
|
||
* in the application. Only on the input.
|
||
*/
|
||
if (settings.baseNameMatch) {
|
||
patterns = patterns.map((pattern) => pattern.includes('/') ? pattern : `**/${pattern}`);
|
||
}
|
||
/**
|
||
* This method also removes duplicate slashes that may have been in the pattern or formed as a result of expansion.
|
||
*/
|
||
return patterns.map((pattern) => utils$i.pattern.removeDuplicateSlashes(pattern));
|
||
}
|
||
/**
|
||
* Returns tasks grouped by basic pattern directories.
|
||
*
|
||
* Patterns that can be found inside (`./`) and outside (`../`) the current directory are handled separately.
|
||
* This is necessary because directory traversal starts at the base directory and goes deeper.
|
||
*/
|
||
function convertPatternsToTasks(positive, negative, dynamic) {
|
||
const tasks = [];
|
||
const patternsOutsideCurrentDirectory = utils$i.pattern.getPatternsOutsideCurrentDirectory(positive);
|
||
const patternsInsideCurrentDirectory = utils$i.pattern.getPatternsInsideCurrentDirectory(positive);
|
||
const outsideCurrentDirectoryGroup = groupPatternsByBaseDirectory(patternsOutsideCurrentDirectory);
|
||
const insideCurrentDirectoryGroup = groupPatternsByBaseDirectory(patternsInsideCurrentDirectory);
|
||
tasks.push(...convertPatternGroupsToTasks(outsideCurrentDirectoryGroup, negative, dynamic));
|
||
/*
|
||
* For the sake of reducing future accesses to the file system, we merge all tasks within the current directory
|
||
* into a global task, if at least one pattern refers to the root (`.`). In this case, the global task covers the rest.
|
||
*/
|
||
if ('.' in insideCurrentDirectoryGroup) {
|
||
tasks.push(convertPatternGroupToTask('.', patternsInsideCurrentDirectory, negative, dynamic));
|
||
}
|
||
else {
|
||
tasks.push(...convertPatternGroupsToTasks(insideCurrentDirectoryGroup, negative, dynamic));
|
||
}
|
||
return tasks;
|
||
}
|
||
tasks.convertPatternsToTasks = convertPatternsToTasks;
|
||
function getPositivePatterns(patterns) {
|
||
return utils$i.pattern.getPositivePatterns(patterns);
|
||
}
|
||
tasks.getPositivePatterns = getPositivePatterns;
|
||
function getNegativePatternsAsPositive(patterns, ignore) {
|
||
const negative = utils$i.pattern.getNegativePatterns(patterns).concat(ignore);
|
||
const positive = negative.map(utils$i.pattern.convertToPositivePattern);
|
||
return positive;
|
||
}
|
||
tasks.getNegativePatternsAsPositive = getNegativePatternsAsPositive;
|
||
function groupPatternsByBaseDirectory(patterns) {
|
||
const group = {};
|
||
return patterns.reduce((collection, pattern) => {
|
||
const base = utils$i.pattern.getBaseDirectory(pattern);
|
||
if (base in collection) {
|
||
collection[base].push(pattern);
|
||
}
|
||
else {
|
||
collection[base] = [pattern];
|
||
}
|
||
return collection;
|
||
}, group);
|
||
}
|
||
tasks.groupPatternsByBaseDirectory = groupPatternsByBaseDirectory;
|
||
function convertPatternGroupsToTasks(positive, negative, dynamic) {
|
||
return Object.keys(positive).map((base) => {
|
||
return convertPatternGroupToTask(base, positive[base], negative, dynamic);
|
||
});
|
||
}
|
||
tasks.convertPatternGroupsToTasks = convertPatternGroupsToTasks;
|
||
function convertPatternGroupToTask(base, positive, negative, dynamic) {
|
||
return {
|
||
dynamic,
|
||
positive,
|
||
negative,
|
||
base,
|
||
patterns: [].concat(positive, negative.map(utils$i.pattern.convertToNegativePattern))
|
||
};
|
||
}
|
||
tasks.convertPatternGroupToTask = convertPatternGroupToTask;
|
||
|
||
var async$7 = {};
|
||
|
||
var async$6 = {};
|
||
|
||
var out$3 = {};
|
||
|
||
var async$5 = {};
|
||
|
||
var async$4 = {};
|
||
|
||
var out$2 = {};
|
||
|
||
var async$3 = {};
|
||
|
||
var out$1 = {};
|
||
|
||
var async$2 = {};
|
||
|
||
Object.defineProperty(async$2, "__esModule", { value: true });
|
||
async$2.read = void 0;
|
||
function read$3(path, settings, callback) {
|
||
settings.fs.lstat(path, (lstatError, lstat) => {
|
||
if (lstatError !== null) {
|
||
callFailureCallback$2(callback, lstatError);
|
||
return;
|
||
}
|
||
if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) {
|
||
callSuccessCallback$2(callback, lstat);
|
||
return;
|
||
}
|
||
settings.fs.stat(path, (statError, stat) => {
|
||
if (statError !== null) {
|
||
if (settings.throwErrorOnBrokenSymbolicLink) {
|
||
callFailureCallback$2(callback, statError);
|
||
return;
|
||
}
|
||
callSuccessCallback$2(callback, lstat);
|
||
return;
|
||
}
|
||
if (settings.markSymbolicLink) {
|
||
stat.isSymbolicLink = () => true;
|
||
}
|
||
callSuccessCallback$2(callback, stat);
|
||
});
|
||
});
|
||
}
|
||
async$2.read = read$3;
|
||
function callFailureCallback$2(callback, error) {
|
||
callback(error);
|
||
}
|
||
function callSuccessCallback$2(callback, result) {
|
||
callback(null, result);
|
||
}
|
||
|
||
var sync$8 = {};
|
||
|
||
Object.defineProperty(sync$8, "__esModule", { value: true });
|
||
sync$8.read = void 0;
|
||
function read$2(path, settings) {
|
||
const lstat = settings.fs.lstatSync(path);
|
||
if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) {
|
||
return lstat;
|
||
}
|
||
try {
|
||
const stat = settings.fs.statSync(path);
|
||
if (settings.markSymbolicLink) {
|
||
stat.isSymbolicLink = () => true;
|
||
}
|
||
return stat;
|
||
}
|
||
catch (error) {
|
||
if (!settings.throwErrorOnBrokenSymbolicLink) {
|
||
return lstat;
|
||
}
|
||
throw error;
|
||
}
|
||
}
|
||
sync$8.read = read$2;
|
||
|
||
var settings$3 = {};
|
||
|
||
var fs$7 = {};
|
||
|
||
(function (exports) {
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.createFileSystemAdapter = exports.FILE_SYSTEM_ADAPTER = void 0;
|
||
const fs = fs__default;
|
||
exports.FILE_SYSTEM_ADAPTER = {
|
||
lstat: fs.lstat,
|
||
stat: fs.stat,
|
||
lstatSync: fs.lstatSync,
|
||
statSync: fs.statSync
|
||
};
|
||
function createFileSystemAdapter(fsMethods) {
|
||
if (fsMethods === undefined) {
|
||
return exports.FILE_SYSTEM_ADAPTER;
|
||
}
|
||
return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods);
|
||
}
|
||
exports.createFileSystemAdapter = createFileSystemAdapter;
|
||
} (fs$7));
|
||
|
||
Object.defineProperty(settings$3, "__esModule", { value: true });
|
||
const fs$6 = fs$7;
|
||
let Settings$2 = class Settings {
|
||
constructor(_options = {}) {
|
||
this._options = _options;
|
||
this.followSymbolicLink = this._getValue(this._options.followSymbolicLink, true);
|
||
this.fs = fs$6.createFileSystemAdapter(this._options.fs);
|
||
this.markSymbolicLink = this._getValue(this._options.markSymbolicLink, false);
|
||
this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
|
||
}
|
||
_getValue(option, value) {
|
||
return option !== null && option !== void 0 ? option : value;
|
||
}
|
||
};
|
||
settings$3.default = Settings$2;
|
||
|
||
Object.defineProperty(out$1, "__esModule", { value: true });
|
||
out$1.statSync = out$1.stat = out$1.Settings = void 0;
|
||
const async$1 = async$2;
|
||
const sync$7 = sync$8;
|
||
const settings_1$3 = settings$3;
|
||
out$1.Settings = settings_1$3.default;
|
||
function stat(path, optionsOrSettingsOrCallback, callback) {
|
||
if (typeof optionsOrSettingsOrCallback === 'function') {
|
||
async$1.read(path, getSettings$2(), optionsOrSettingsOrCallback);
|
||
return;
|
||
}
|
||
async$1.read(path, getSettings$2(optionsOrSettingsOrCallback), callback);
|
||
}
|
||
out$1.stat = stat;
|
||
function statSync(path, optionsOrSettings) {
|
||
const settings = getSettings$2(optionsOrSettings);
|
||
return sync$7.read(path, settings);
|
||
}
|
||
out$1.statSync = statSync;
|
||
function getSettings$2(settingsOrOptions = {}) {
|
||
if (settingsOrOptions instanceof settings_1$3.default) {
|
||
return settingsOrOptions;
|
||
}
|
||
return new settings_1$3.default(settingsOrOptions);
|
||
}
|
||
|
||
/*! queue-microtask. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||
|
||
let promise;
|
||
|
||
var queueMicrotask_1 = typeof queueMicrotask === 'function'
|
||
? queueMicrotask.bind(typeof window !== 'undefined' ? window : commonjsGlobal)
|
||
// reuse resolved promise, and allocate it lazily
|
||
: cb => (promise || (promise = Promise.resolve()))
|
||
.then(cb)
|
||
.catch(err => setTimeout(() => { throw err }, 0));
|
||
|
||
/*! run-parallel. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||
|
||
var runParallel_1 = runParallel;
|
||
|
||
const queueMicrotask$1 = queueMicrotask_1;
|
||
|
||
function runParallel (tasks, cb) {
|
||
let results, pending, keys;
|
||
let isSync = true;
|
||
|
||
if (Array.isArray(tasks)) {
|
||
results = [];
|
||
pending = tasks.length;
|
||
} else {
|
||
keys = Object.keys(tasks);
|
||
results = {};
|
||
pending = keys.length;
|
||
}
|
||
|
||
function done (err) {
|
||
function end () {
|
||
if (cb) cb(err, results);
|
||
cb = null;
|
||
}
|
||
if (isSync) queueMicrotask$1(end);
|
||
else end();
|
||
}
|
||
|
||
function each (i, err, result) {
|
||
results[i] = result;
|
||
if (--pending === 0 || err) {
|
||
done(err);
|
||
}
|
||
}
|
||
|
||
if (!pending) {
|
||
// empty
|
||
done(null);
|
||
} else if (keys) {
|
||
// object
|
||
keys.forEach(function (key) {
|
||
tasks[key](function (err, result) { each(key, err, result); });
|
||
});
|
||
} else {
|
||
// array
|
||
tasks.forEach(function (task, i) {
|
||
task(function (err, result) { each(i, err, result); });
|
||
});
|
||
}
|
||
|
||
isSync = false;
|
||
}
|
||
|
||
var constants = {};
|
||
|
||
Object.defineProperty(constants, "__esModule", { value: true });
|
||
constants.IS_SUPPORT_READDIR_WITH_FILE_TYPES = void 0;
|
||
const NODE_PROCESS_VERSION_PARTS = process.versions.node.split('.');
|
||
if (NODE_PROCESS_VERSION_PARTS[0] === undefined || NODE_PROCESS_VERSION_PARTS[1] === undefined) {
|
||
throw new Error(`Unexpected behavior. The 'process.versions.node' variable has invalid value: ${process.versions.node}`);
|
||
}
|
||
const MAJOR_VERSION = Number.parseInt(NODE_PROCESS_VERSION_PARTS[0], 10);
|
||
const MINOR_VERSION = Number.parseInt(NODE_PROCESS_VERSION_PARTS[1], 10);
|
||
const SUPPORTED_MAJOR_VERSION = 10;
|
||
const SUPPORTED_MINOR_VERSION = 10;
|
||
const IS_MATCHED_BY_MAJOR = MAJOR_VERSION > SUPPORTED_MAJOR_VERSION;
|
||
const IS_MATCHED_BY_MAJOR_AND_MINOR = MAJOR_VERSION === SUPPORTED_MAJOR_VERSION && MINOR_VERSION >= SUPPORTED_MINOR_VERSION;
|
||
/**
|
||
* IS `true` for Node.js 10.10 and greater.
|
||
*/
|
||
constants.IS_SUPPORT_READDIR_WITH_FILE_TYPES = IS_MATCHED_BY_MAJOR || IS_MATCHED_BY_MAJOR_AND_MINOR;
|
||
|
||
var utils$h = {};
|
||
|
||
var fs$5 = {};
|
||
|
||
Object.defineProperty(fs$5, "__esModule", { value: true });
|
||
fs$5.createDirentFromStats = void 0;
|
||
class DirentFromStats {
|
||
constructor(name, stats) {
|
||
this.name = name;
|
||
this.isBlockDevice = stats.isBlockDevice.bind(stats);
|
||
this.isCharacterDevice = stats.isCharacterDevice.bind(stats);
|
||
this.isDirectory = stats.isDirectory.bind(stats);
|
||
this.isFIFO = stats.isFIFO.bind(stats);
|
||
this.isFile = stats.isFile.bind(stats);
|
||
this.isSocket = stats.isSocket.bind(stats);
|
||
this.isSymbolicLink = stats.isSymbolicLink.bind(stats);
|
||
}
|
||
}
|
||
function createDirentFromStats(name, stats) {
|
||
return new DirentFromStats(name, stats);
|
||
}
|
||
fs$5.createDirentFromStats = createDirentFromStats;
|
||
|
||
Object.defineProperty(utils$h, "__esModule", { value: true });
|
||
utils$h.fs = void 0;
|
||
const fs$4 = fs$5;
|
||
utils$h.fs = fs$4;
|
||
|
||
var common$d = {};
|
||
|
||
Object.defineProperty(common$d, "__esModule", { value: true });
|
||
common$d.joinPathSegments = void 0;
|
||
function joinPathSegments$1(a, b, separator) {
|
||
/**
|
||
* The correct handling of cases when the first segment is a root (`/`, `C:/`) or UNC path (`//?/C:/`).
|
||
*/
|
||
if (a.endsWith(separator)) {
|
||
return a + b;
|
||
}
|
||
return a + separator + b;
|
||
}
|
||
common$d.joinPathSegments = joinPathSegments$1;
|
||
|
||
Object.defineProperty(async$3, "__esModule", { value: true });
|
||
async$3.readdir = async$3.readdirWithFileTypes = async$3.read = void 0;
|
||
const fsStat$5 = out$1;
|
||
const rpl = runParallel_1;
|
||
const constants_1$1 = constants;
|
||
const utils$g = utils$h;
|
||
const common$c = common$d;
|
||
function read$1(directory, settings, callback) {
|
||
if (!settings.stats && constants_1$1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) {
|
||
readdirWithFileTypes$1(directory, settings, callback);
|
||
return;
|
||
}
|
||
readdir$1(directory, settings, callback);
|
||
}
|
||
async$3.read = read$1;
|
||
function readdirWithFileTypes$1(directory, settings, callback) {
|
||
settings.fs.readdir(directory, { withFileTypes: true }, (readdirError, dirents) => {
|
||
if (readdirError !== null) {
|
||
callFailureCallback$1(callback, readdirError);
|
||
return;
|
||
}
|
||
const entries = dirents.map((dirent) => ({
|
||
dirent,
|
||
name: dirent.name,
|
||
path: common$c.joinPathSegments(directory, dirent.name, settings.pathSegmentSeparator)
|
||
}));
|
||
if (!settings.followSymbolicLinks) {
|
||
callSuccessCallback$1(callback, entries);
|
||
return;
|
||
}
|
||
const tasks = entries.map((entry) => makeRplTaskEntry(entry, settings));
|
||
rpl(tasks, (rplError, rplEntries) => {
|
||
if (rplError !== null) {
|
||
callFailureCallback$1(callback, rplError);
|
||
return;
|
||
}
|
||
callSuccessCallback$1(callback, rplEntries);
|
||
});
|
||
});
|
||
}
|
||
async$3.readdirWithFileTypes = readdirWithFileTypes$1;
|
||
function makeRplTaskEntry(entry, settings) {
|
||
return (done) => {
|
||
if (!entry.dirent.isSymbolicLink()) {
|
||
done(null, entry);
|
||
return;
|
||
}
|
||
settings.fs.stat(entry.path, (statError, stats) => {
|
||
if (statError !== null) {
|
||
if (settings.throwErrorOnBrokenSymbolicLink) {
|
||
done(statError);
|
||
return;
|
||
}
|
||
done(null, entry);
|
||
return;
|
||
}
|
||
entry.dirent = utils$g.fs.createDirentFromStats(entry.name, stats);
|
||
done(null, entry);
|
||
});
|
||
};
|
||
}
|
||
function readdir$1(directory, settings, callback) {
|
||
settings.fs.readdir(directory, (readdirError, names) => {
|
||
if (readdirError !== null) {
|
||
callFailureCallback$1(callback, readdirError);
|
||
return;
|
||
}
|
||
const tasks = names.map((name) => {
|
||
const path = common$c.joinPathSegments(directory, name, settings.pathSegmentSeparator);
|
||
return (done) => {
|
||
fsStat$5.stat(path, settings.fsStatSettings, (error, stats) => {
|
||
if (error !== null) {
|
||
done(error);
|
||
return;
|
||
}
|
||
const entry = {
|
||
name,
|
||
path,
|
||
dirent: utils$g.fs.createDirentFromStats(name, stats)
|
||
};
|
||
if (settings.stats) {
|
||
entry.stats = stats;
|
||
}
|
||
done(null, entry);
|
||
});
|
||
};
|
||
});
|
||
rpl(tasks, (rplError, entries) => {
|
||
if (rplError !== null) {
|
||
callFailureCallback$1(callback, rplError);
|
||
return;
|
||
}
|
||
callSuccessCallback$1(callback, entries);
|
||
});
|
||
});
|
||
}
|
||
async$3.readdir = readdir$1;
|
||
function callFailureCallback$1(callback, error) {
|
||
callback(error);
|
||
}
|
||
function callSuccessCallback$1(callback, result) {
|
||
callback(null, result);
|
||
}
|
||
|
||
var sync$6 = {};
|
||
|
||
Object.defineProperty(sync$6, "__esModule", { value: true });
|
||
sync$6.readdir = sync$6.readdirWithFileTypes = sync$6.read = void 0;
|
||
const fsStat$4 = out$1;
|
||
const constants_1 = constants;
|
||
const utils$f = utils$h;
|
||
const common$b = common$d;
|
||
function read(directory, settings) {
|
||
if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) {
|
||
return readdirWithFileTypes(directory, settings);
|
||
}
|
||
return readdir(directory, settings);
|
||
}
|
||
sync$6.read = read;
|
||
function readdirWithFileTypes(directory, settings) {
|
||
const dirents = settings.fs.readdirSync(directory, { withFileTypes: true });
|
||
return dirents.map((dirent) => {
|
||
const entry = {
|
||
dirent,
|
||
name: dirent.name,
|
||
path: common$b.joinPathSegments(directory, dirent.name, settings.pathSegmentSeparator)
|
||
};
|
||
if (entry.dirent.isSymbolicLink() && settings.followSymbolicLinks) {
|
||
try {
|
||
const stats = settings.fs.statSync(entry.path);
|
||
entry.dirent = utils$f.fs.createDirentFromStats(entry.name, stats);
|
||
}
|
||
catch (error) {
|
||
if (settings.throwErrorOnBrokenSymbolicLink) {
|
||
throw error;
|
||
}
|
||
}
|
||
}
|
||
return entry;
|
||
});
|
||
}
|
||
sync$6.readdirWithFileTypes = readdirWithFileTypes;
|
||
function readdir(directory, settings) {
|
||
const names = settings.fs.readdirSync(directory);
|
||
return names.map((name) => {
|
||
const entryPath = common$b.joinPathSegments(directory, name, settings.pathSegmentSeparator);
|
||
const stats = fsStat$4.statSync(entryPath, settings.fsStatSettings);
|
||
const entry = {
|
||
name,
|
||
path: entryPath,
|
||
dirent: utils$f.fs.createDirentFromStats(name, stats)
|
||
};
|
||
if (settings.stats) {
|
||
entry.stats = stats;
|
||
}
|
||
return entry;
|
||
});
|
||
}
|
||
sync$6.readdir = readdir;
|
||
|
||
var settings$2 = {};
|
||
|
||
var fs$3 = {};
|
||
|
||
(function (exports) {
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.createFileSystemAdapter = exports.FILE_SYSTEM_ADAPTER = void 0;
|
||
const fs = fs__default;
|
||
exports.FILE_SYSTEM_ADAPTER = {
|
||
lstat: fs.lstat,
|
||
stat: fs.stat,
|
||
lstatSync: fs.lstatSync,
|
||
statSync: fs.statSync,
|
||
readdir: fs.readdir,
|
||
readdirSync: fs.readdirSync
|
||
};
|
||
function createFileSystemAdapter(fsMethods) {
|
||
if (fsMethods === undefined) {
|
||
return exports.FILE_SYSTEM_ADAPTER;
|
||
}
|
||
return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods);
|
||
}
|
||
exports.createFileSystemAdapter = createFileSystemAdapter;
|
||
} (fs$3));
|
||
|
||
Object.defineProperty(settings$2, "__esModule", { value: true });
|
||
const path$6 = path$q;
|
||
const fsStat$3 = out$1;
|
||
const fs$2 = fs$3;
|
||
let Settings$1 = class Settings {
|
||
constructor(_options = {}) {
|
||
this._options = _options;
|
||
this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false);
|
||
this.fs = fs$2.createFileSystemAdapter(this._options.fs);
|
||
this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path$6.sep);
|
||
this.stats = this._getValue(this._options.stats, false);
|
||
this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
|
||
this.fsStatSettings = new fsStat$3.Settings({
|
||
followSymbolicLink: this.followSymbolicLinks,
|
||
fs: this.fs,
|
||
throwErrorOnBrokenSymbolicLink: this.throwErrorOnBrokenSymbolicLink
|
||
});
|
||
}
|
||
_getValue(option, value) {
|
||
return option !== null && option !== void 0 ? option : value;
|
||
}
|
||
};
|
||
settings$2.default = Settings$1;
|
||
|
||
Object.defineProperty(out$2, "__esModule", { value: true });
|
||
out$2.Settings = out$2.scandirSync = out$2.scandir = void 0;
|
||
const async = async$3;
|
||
const sync$5 = sync$6;
|
||
const settings_1$2 = settings$2;
|
||
out$2.Settings = settings_1$2.default;
|
||
function scandir(path, optionsOrSettingsOrCallback, callback) {
|
||
if (typeof optionsOrSettingsOrCallback === 'function') {
|
||
async.read(path, getSettings$1(), optionsOrSettingsOrCallback);
|
||
return;
|
||
}
|
||
async.read(path, getSettings$1(optionsOrSettingsOrCallback), callback);
|
||
}
|
||
out$2.scandir = scandir;
|
||
function scandirSync(path, optionsOrSettings) {
|
||
const settings = getSettings$1(optionsOrSettings);
|
||
return sync$5.read(path, settings);
|
||
}
|
||
out$2.scandirSync = scandirSync;
|
||
function getSettings$1(settingsOrOptions = {}) {
|
||
if (settingsOrOptions instanceof settings_1$2.default) {
|
||
return settingsOrOptions;
|
||
}
|
||
return new settings_1$2.default(settingsOrOptions);
|
||
}
|
||
|
||
var queue = {exports: {}};
|
||
|
||
function reusify$1 (Constructor) {
|
||
var head = new Constructor();
|
||
var tail = head;
|
||
|
||
function get () {
|
||
var current = head;
|
||
|
||
if (current.next) {
|
||
head = current.next;
|
||
} else {
|
||
head = new Constructor();
|
||
tail = head;
|
||
}
|
||
|
||
current.next = null;
|
||
|
||
return current
|
||
}
|
||
|
||
function release (obj) {
|
||
tail.next = obj;
|
||
tail = obj;
|
||
}
|
||
|
||
return {
|
||
get: get,
|
||
release: release
|
||
}
|
||
}
|
||
|
||
var reusify_1 = reusify$1;
|
||
|
||
/* eslint-disable no-var */
|
||
|
||
var reusify = reusify_1;
|
||
|
||
function fastqueue (context, worker, concurrency) {
|
||
if (typeof context === 'function') {
|
||
concurrency = worker;
|
||
worker = context;
|
||
context = null;
|
||
}
|
||
|
||
if (concurrency < 1) {
|
||
throw new Error('fastqueue concurrency must be greater than 1')
|
||
}
|
||
|
||
var cache = reusify(Task);
|
||
var queueHead = null;
|
||
var queueTail = null;
|
||
var _running = 0;
|
||
var errorHandler = null;
|
||
|
||
var self = {
|
||
push: push,
|
||
drain: noop$1,
|
||
saturated: noop$1,
|
||
pause: pause,
|
||
paused: false,
|
||
concurrency: concurrency,
|
||
running: running,
|
||
resume: resume,
|
||
idle: idle,
|
||
length: length,
|
||
getQueue: getQueue,
|
||
unshift: unshift,
|
||
empty: noop$1,
|
||
kill: kill,
|
||
killAndDrain: killAndDrain,
|
||
error: error
|
||
};
|
||
|
||
return self
|
||
|
||
function running () {
|
||
return _running
|
||
}
|
||
|
||
function pause () {
|
||
self.paused = true;
|
||
}
|
||
|
||
function length () {
|
||
var current = queueHead;
|
||
var counter = 0;
|
||
|
||
while (current) {
|
||
current = current.next;
|
||
counter++;
|
||
}
|
||
|
||
return counter
|
||
}
|
||
|
||
function getQueue () {
|
||
var current = queueHead;
|
||
var tasks = [];
|
||
|
||
while (current) {
|
||
tasks.push(current.value);
|
||
current = current.next;
|
||
}
|
||
|
||
return tasks
|
||
}
|
||
|
||
function resume () {
|
||
if (!self.paused) return
|
||
self.paused = false;
|
||
for (var i = 0; i < self.concurrency; i++) {
|
||
_running++;
|
||
release();
|
||
}
|
||
}
|
||
|
||
function idle () {
|
||
return _running === 0 && self.length() === 0
|
||
}
|
||
|
||
function push (value, done) {
|
||
var current = cache.get();
|
||
|
||
current.context = context;
|
||
current.release = release;
|
||
current.value = value;
|
||
current.callback = done || noop$1;
|
||
current.errorHandler = errorHandler;
|
||
|
||
if (_running === self.concurrency || self.paused) {
|
||
if (queueTail) {
|
||
queueTail.next = current;
|
||
queueTail = current;
|
||
} else {
|
||
queueHead = current;
|
||
queueTail = current;
|
||
self.saturated();
|
||
}
|
||
} else {
|
||
_running++;
|
||
worker.call(context, current.value, current.worked);
|
||
}
|
||
}
|
||
|
||
function unshift (value, done) {
|
||
var current = cache.get();
|
||
|
||
current.context = context;
|
||
current.release = release;
|
||
current.value = value;
|
||
current.callback = done || noop$1;
|
||
current.errorHandler = errorHandler;
|
||
|
||
if (_running === self.concurrency || self.paused) {
|
||
if (queueHead) {
|
||
current.next = queueHead;
|
||
queueHead = current;
|
||
} else {
|
||
queueHead = current;
|
||
queueTail = current;
|
||
self.saturated();
|
||
}
|
||
} else {
|
||
_running++;
|
||
worker.call(context, current.value, current.worked);
|
||
}
|
||
}
|
||
|
||
function release (holder) {
|
||
if (holder) {
|
||
cache.release(holder);
|
||
}
|
||
var next = queueHead;
|
||
if (next) {
|
||
if (!self.paused) {
|
||
if (queueTail === queueHead) {
|
||
queueTail = null;
|
||
}
|
||
queueHead = next.next;
|
||
next.next = null;
|
||
worker.call(context, next.value, next.worked);
|
||
if (queueTail === null) {
|
||
self.empty();
|
||
}
|
||
} else {
|
||
_running--;
|
||
}
|
||
} else if (--_running === 0) {
|
||
self.drain();
|
||
}
|
||
}
|
||
|
||
function kill () {
|
||
queueHead = null;
|
||
queueTail = null;
|
||
self.drain = noop$1;
|
||
}
|
||
|
||
function killAndDrain () {
|
||
queueHead = null;
|
||
queueTail = null;
|
||
self.drain();
|
||
self.drain = noop$1;
|
||
}
|
||
|
||
function error (handler) {
|
||
errorHandler = handler;
|
||
}
|
||
}
|
||
|
||
function noop$1 () {}
|
||
|
||
function Task () {
|
||
this.value = null;
|
||
this.callback = noop$1;
|
||
this.next = null;
|
||
this.release = noop$1;
|
||
this.context = null;
|
||
this.errorHandler = null;
|
||
|
||
var self = this;
|
||
|
||
this.worked = function worked (err, result) {
|
||
var callback = self.callback;
|
||
var errorHandler = self.errorHandler;
|
||
var val = self.value;
|
||
self.value = null;
|
||
self.callback = noop$1;
|
||
if (self.errorHandler) {
|
||
errorHandler(err, val);
|
||
}
|
||
callback.call(self.context, err, result);
|
||
self.release(self);
|
||
};
|
||
}
|
||
|
||
function queueAsPromised (context, worker, concurrency) {
|
||
if (typeof context === 'function') {
|
||
concurrency = worker;
|
||
worker = context;
|
||
context = null;
|
||
}
|
||
|
||
function asyncWrapper (arg, cb) {
|
||
worker.call(this, arg)
|
||
.then(function (res) {
|
||
cb(null, res);
|
||
}, cb);
|
||
}
|
||
|
||
var queue = fastqueue(context, asyncWrapper, concurrency);
|
||
|
||
var pushCb = queue.push;
|
||
var unshiftCb = queue.unshift;
|
||
|
||
queue.push = push;
|
||
queue.unshift = unshift;
|
||
queue.drained = drained;
|
||
|
||
return queue
|
||
|
||
function push (value) {
|
||
var p = new Promise(function (resolve, reject) {
|
||
pushCb(value, function (err, result) {
|
||
if (err) {
|
||
reject(err);
|
||
return
|
||
}
|
||
resolve(result);
|
||
});
|
||
});
|
||
|
||
// Let's fork the promise chain to
|
||
// make the error bubble up to the user but
|
||
// not lead to a unhandledRejection
|
||
p.catch(noop$1);
|
||
|
||
return p
|
||
}
|
||
|
||
function unshift (value) {
|
||
var p = new Promise(function (resolve, reject) {
|
||
unshiftCb(value, function (err, result) {
|
||
if (err) {
|
||
reject(err);
|
||
return
|
||
}
|
||
resolve(result);
|
||
});
|
||
});
|
||
|
||
// Let's fork the promise chain to
|
||
// make the error bubble up to the user but
|
||
// not lead to a unhandledRejection
|
||
p.catch(noop$1);
|
||
|
||
return p
|
||
}
|
||
|
||
function drained () {
|
||
if (queue.idle()) {
|
||
return new Promise(function (resolve) {
|
||
resolve();
|
||
})
|
||
}
|
||
|
||
var previousDrain = queue.drain;
|
||
|
||
var p = new Promise(function (resolve) {
|
||
queue.drain = function () {
|
||
previousDrain();
|
||
resolve();
|
||
};
|
||
});
|
||
|
||
return p
|
||
}
|
||
}
|
||
|
||
queue.exports = fastqueue;
|
||
queue.exports.promise = queueAsPromised;
|
||
|
||
var queueExports = queue.exports;
|
||
|
||
var common$a = {};
|
||
|
||
Object.defineProperty(common$a, "__esModule", { value: true });
|
||
common$a.joinPathSegments = common$a.replacePathSegmentSeparator = common$a.isAppliedFilter = common$a.isFatalError = void 0;
|
||
function isFatalError(settings, error) {
|
||
if (settings.errorFilter === null) {
|
||
return true;
|
||
}
|
||
return !settings.errorFilter(error);
|
||
}
|
||
common$a.isFatalError = isFatalError;
|
||
function isAppliedFilter(filter, value) {
|
||
return filter === null || filter(value);
|
||
}
|
||
common$a.isAppliedFilter = isAppliedFilter;
|
||
function replacePathSegmentSeparator(filepath, separator) {
|
||
return filepath.split(/[/\\]/).join(separator);
|
||
}
|
||
common$a.replacePathSegmentSeparator = replacePathSegmentSeparator;
|
||
function joinPathSegments(a, b, separator) {
|
||
if (a === '') {
|
||
return b;
|
||
}
|
||
/**
|
||
* The correct handling of cases when the first segment is a root (`/`, `C:/`) or UNC path (`//?/C:/`).
|
||
*/
|
||
if (a.endsWith(separator)) {
|
||
return a + b;
|
||
}
|
||
return a + separator + b;
|
||
}
|
||
common$a.joinPathSegments = joinPathSegments;
|
||
|
||
var reader$1 = {};
|
||
|
||
Object.defineProperty(reader$1, "__esModule", { value: true });
|
||
const common$9 = common$a;
|
||
let Reader$1 = class Reader {
|
||
constructor(_root, _settings) {
|
||
this._root = _root;
|
||
this._settings = _settings;
|
||
this._root = common$9.replacePathSegmentSeparator(_root, _settings.pathSegmentSeparator);
|
||
}
|
||
};
|
||
reader$1.default = Reader$1;
|
||
|
||
Object.defineProperty(async$4, "__esModule", { value: true });
|
||
const events_1 = require$$0$7;
|
||
const fsScandir$2 = out$2;
|
||
const fastq = queueExports;
|
||
const common$8 = common$a;
|
||
const reader_1$4 = reader$1;
|
||
class AsyncReader extends reader_1$4.default {
|
||
constructor(_root, _settings) {
|
||
super(_root, _settings);
|
||
this._settings = _settings;
|
||
this._scandir = fsScandir$2.scandir;
|
||
this._emitter = new events_1.EventEmitter();
|
||
this._queue = fastq(this._worker.bind(this), this._settings.concurrency);
|
||
this._isFatalError = false;
|
||
this._isDestroyed = false;
|
||
this._queue.drain = () => {
|
||
if (!this._isFatalError) {
|
||
this._emitter.emit('end');
|
||
}
|
||
};
|
||
}
|
||
read() {
|
||
this._isFatalError = false;
|
||
this._isDestroyed = false;
|
||
setImmediate(() => {
|
||
this._pushToQueue(this._root, this._settings.basePath);
|
||
});
|
||
return this._emitter;
|
||
}
|
||
get isDestroyed() {
|
||
return this._isDestroyed;
|
||
}
|
||
destroy() {
|
||
if (this._isDestroyed) {
|
||
throw new Error('The reader is already destroyed');
|
||
}
|
||
this._isDestroyed = true;
|
||
this._queue.killAndDrain();
|
||
}
|
||
onEntry(callback) {
|
||
this._emitter.on('entry', callback);
|
||
}
|
||
onError(callback) {
|
||
this._emitter.once('error', callback);
|
||
}
|
||
onEnd(callback) {
|
||
this._emitter.once('end', callback);
|
||
}
|
||
_pushToQueue(directory, base) {
|
||
const queueItem = { directory, base };
|
||
this._queue.push(queueItem, (error) => {
|
||
if (error !== null) {
|
||
this._handleError(error);
|
||
}
|
||
});
|
||
}
|
||
_worker(item, done) {
|
||
this._scandir(item.directory, this._settings.fsScandirSettings, (error, entries) => {
|
||
if (error !== null) {
|
||
done(error, undefined);
|
||
return;
|
||
}
|
||
for (const entry of entries) {
|
||
this._handleEntry(entry, item.base);
|
||
}
|
||
done(null, undefined);
|
||
});
|
||
}
|
||
_handleError(error) {
|
||
if (this._isDestroyed || !common$8.isFatalError(this._settings, error)) {
|
||
return;
|
||
}
|
||
this._isFatalError = true;
|
||
this._isDestroyed = true;
|
||
this._emitter.emit('error', error);
|
||
}
|
||
_handleEntry(entry, base) {
|
||
if (this._isDestroyed || this._isFatalError) {
|
||
return;
|
||
}
|
||
const fullpath = entry.path;
|
||
if (base !== undefined) {
|
||
entry.path = common$8.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator);
|
||
}
|
||
if (common$8.isAppliedFilter(this._settings.entryFilter, entry)) {
|
||
this._emitEntry(entry);
|
||
}
|
||
if (entry.dirent.isDirectory() && common$8.isAppliedFilter(this._settings.deepFilter, entry)) {
|
||
this._pushToQueue(fullpath, base === undefined ? undefined : entry.path);
|
||
}
|
||
}
|
||
_emitEntry(entry) {
|
||
this._emitter.emit('entry', entry);
|
||
}
|
||
}
|
||
async$4.default = AsyncReader;
|
||
|
||
Object.defineProperty(async$5, "__esModule", { value: true });
|
||
const async_1$4 = async$4;
|
||
class AsyncProvider {
|
||
constructor(_root, _settings) {
|
||
this._root = _root;
|
||
this._settings = _settings;
|
||
this._reader = new async_1$4.default(this._root, this._settings);
|
||
this._storage = [];
|
||
}
|
||
read(callback) {
|
||
this._reader.onError((error) => {
|
||
callFailureCallback(callback, error);
|
||
});
|
||
this._reader.onEntry((entry) => {
|
||
this._storage.push(entry);
|
||
});
|
||
this._reader.onEnd(() => {
|
||
callSuccessCallback(callback, this._storage);
|
||
});
|
||
this._reader.read();
|
||
}
|
||
}
|
||
async$5.default = AsyncProvider;
|
||
function callFailureCallback(callback, error) {
|
||
callback(error);
|
||
}
|
||
function callSuccessCallback(callback, entries) {
|
||
callback(null, entries);
|
||
}
|
||
|
||
var stream$2 = {};
|
||
|
||
Object.defineProperty(stream$2, "__esModule", { value: true });
|
||
const stream_1$9 = require$$0$3;
|
||
const async_1$3 = async$4;
|
||
class StreamProvider {
|
||
constructor(_root, _settings) {
|
||
this._root = _root;
|
||
this._settings = _settings;
|
||
this._reader = new async_1$3.default(this._root, this._settings);
|
||
this._stream = new stream_1$9.Readable({
|
||
objectMode: true,
|
||
read: () => { },
|
||
destroy: () => {
|
||
if (!this._reader.isDestroyed) {
|
||
this._reader.destroy();
|
||
}
|
||
}
|
||
});
|
||
}
|
||
read() {
|
||
this._reader.onError((error) => {
|
||
this._stream.emit('error', error);
|
||
});
|
||
this._reader.onEntry((entry) => {
|
||
this._stream.push(entry);
|
||
});
|
||
this._reader.onEnd(() => {
|
||
this._stream.push(null);
|
||
});
|
||
this._reader.read();
|
||
return this._stream;
|
||
}
|
||
}
|
||
stream$2.default = StreamProvider;
|
||
|
||
var sync$4 = {};
|
||
|
||
var sync$3 = {};
|
||
|
||
Object.defineProperty(sync$3, "__esModule", { value: true });
|
||
const fsScandir$1 = out$2;
|
||
const common$7 = common$a;
|
||
const reader_1$3 = reader$1;
|
||
class SyncReader extends reader_1$3.default {
|
||
constructor() {
|
||
super(...arguments);
|
||
this._scandir = fsScandir$1.scandirSync;
|
||
this._storage = [];
|
||
this._queue = new Set();
|
||
}
|
||
read() {
|
||
this._pushToQueue(this._root, this._settings.basePath);
|
||
this._handleQueue();
|
||
return this._storage;
|
||
}
|
||
_pushToQueue(directory, base) {
|
||
this._queue.add({ directory, base });
|
||
}
|
||
_handleQueue() {
|
||
for (const item of this._queue.values()) {
|
||
this._handleDirectory(item.directory, item.base);
|
||
}
|
||
}
|
||
_handleDirectory(directory, base) {
|
||
try {
|
||
const entries = this._scandir(directory, this._settings.fsScandirSettings);
|
||
for (const entry of entries) {
|
||
this._handleEntry(entry, base);
|
||
}
|
||
}
|
||
catch (error) {
|
||
this._handleError(error);
|
||
}
|
||
}
|
||
_handleError(error) {
|
||
if (!common$7.isFatalError(this._settings, error)) {
|
||
return;
|
||
}
|
||
throw error;
|
||
}
|
||
_handleEntry(entry, base) {
|
||
const fullpath = entry.path;
|
||
if (base !== undefined) {
|
||
entry.path = common$7.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator);
|
||
}
|
||
if (common$7.isAppliedFilter(this._settings.entryFilter, entry)) {
|
||
this._pushToStorage(entry);
|
||
}
|
||
if (entry.dirent.isDirectory() && common$7.isAppliedFilter(this._settings.deepFilter, entry)) {
|
||
this._pushToQueue(fullpath, base === undefined ? undefined : entry.path);
|
||
}
|
||
}
|
||
_pushToStorage(entry) {
|
||
this._storage.push(entry);
|
||
}
|
||
}
|
||
sync$3.default = SyncReader;
|
||
|
||
Object.defineProperty(sync$4, "__esModule", { value: true });
|
||
const sync_1$3 = sync$3;
|
||
class SyncProvider {
|
||
constructor(_root, _settings) {
|
||
this._root = _root;
|
||
this._settings = _settings;
|
||
this._reader = new sync_1$3.default(this._root, this._settings);
|
||
}
|
||
read() {
|
||
return this._reader.read();
|
||
}
|
||
}
|
||
sync$4.default = SyncProvider;
|
||
|
||
var settings$1 = {};
|
||
|
||
Object.defineProperty(settings$1, "__esModule", { value: true });
|
||
const path$5 = path$q;
|
||
const fsScandir = out$2;
|
||
class Settings {
|
||
constructor(_options = {}) {
|
||
this._options = _options;
|
||
this.basePath = this._getValue(this._options.basePath, undefined);
|
||
this.concurrency = this._getValue(this._options.concurrency, Number.POSITIVE_INFINITY);
|
||
this.deepFilter = this._getValue(this._options.deepFilter, null);
|
||
this.entryFilter = this._getValue(this._options.entryFilter, null);
|
||
this.errorFilter = this._getValue(this._options.errorFilter, null);
|
||
this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path$5.sep);
|
||
this.fsScandirSettings = new fsScandir.Settings({
|
||
followSymbolicLinks: this._options.followSymbolicLinks,
|
||
fs: this._options.fs,
|
||
pathSegmentSeparator: this._options.pathSegmentSeparator,
|
||
stats: this._options.stats,
|
||
throwErrorOnBrokenSymbolicLink: this._options.throwErrorOnBrokenSymbolicLink
|
||
});
|
||
}
|
||
_getValue(option, value) {
|
||
return option !== null && option !== void 0 ? option : value;
|
||
}
|
||
}
|
||
settings$1.default = Settings;
|
||
|
||
Object.defineProperty(out$3, "__esModule", { value: true });
|
||
out$3.Settings = out$3.walkStream = out$3.walkSync = out$3.walk = void 0;
|
||
const async_1$2 = async$5;
|
||
const stream_1$8 = stream$2;
|
||
const sync_1$2 = sync$4;
|
||
const settings_1$1 = settings$1;
|
||
out$3.Settings = settings_1$1.default;
|
||
function walk(directory, optionsOrSettingsOrCallback, callback) {
|
||
if (typeof optionsOrSettingsOrCallback === 'function') {
|
||
new async_1$2.default(directory, getSettings()).read(optionsOrSettingsOrCallback);
|
||
return;
|
||
}
|
||
new async_1$2.default(directory, getSettings(optionsOrSettingsOrCallback)).read(callback);
|
||
}
|
||
out$3.walk = walk;
|
||
function walkSync(directory, optionsOrSettings) {
|
||
const settings = getSettings(optionsOrSettings);
|
||
const provider = new sync_1$2.default(directory, settings);
|
||
return provider.read();
|
||
}
|
||
out$3.walkSync = walkSync;
|
||
function walkStream(directory, optionsOrSettings) {
|
||
const settings = getSettings(optionsOrSettings);
|
||
const provider = new stream_1$8.default(directory, settings);
|
||
return provider.read();
|
||
}
|
||
out$3.walkStream = walkStream;
|
||
function getSettings(settingsOrOptions = {}) {
|
||
if (settingsOrOptions instanceof settings_1$1.default) {
|
||
return settingsOrOptions;
|
||
}
|
||
return new settings_1$1.default(settingsOrOptions);
|
||
}
|
||
|
||
var reader = {};
|
||
|
||
Object.defineProperty(reader, "__esModule", { value: true });
|
||
const path$4 = path$q;
|
||
const fsStat$2 = out$1;
|
||
const utils$e = utils$s;
|
||
class Reader {
|
||
constructor(_settings) {
|
||
this._settings = _settings;
|
||
this._fsStatSettings = new fsStat$2.Settings({
|
||
followSymbolicLink: this._settings.followSymbolicLinks,
|
||
fs: this._settings.fs,
|
||
throwErrorOnBrokenSymbolicLink: this._settings.followSymbolicLinks
|
||
});
|
||
}
|
||
_getFullEntryPath(filepath) {
|
||
return path$4.resolve(this._settings.cwd, filepath);
|
||
}
|
||
_makeEntry(stats, pattern) {
|
||
const entry = {
|
||
name: pattern,
|
||
path: pattern,
|
||
dirent: utils$e.fs.createDirentFromStats(pattern, stats)
|
||
};
|
||
if (this._settings.stats) {
|
||
entry.stats = stats;
|
||
}
|
||
return entry;
|
||
}
|
||
_isFatalError(error) {
|
||
return !utils$e.errno.isEnoentCodeError(error) && !this._settings.suppressErrors;
|
||
}
|
||
}
|
||
reader.default = Reader;
|
||
|
||
var stream$1 = {};
|
||
|
||
Object.defineProperty(stream$1, "__esModule", { value: true });
|
||
const stream_1$7 = require$$0$3;
|
||
const fsStat$1 = out$1;
|
||
const fsWalk$2 = out$3;
|
||
const reader_1$2 = reader;
|
||
class ReaderStream extends reader_1$2.default {
|
||
constructor() {
|
||
super(...arguments);
|
||
this._walkStream = fsWalk$2.walkStream;
|
||
this._stat = fsStat$1.stat;
|
||
}
|
||
dynamic(root, options) {
|
||
return this._walkStream(root, options);
|
||
}
|
||
static(patterns, options) {
|
||
const filepaths = patterns.map(this._getFullEntryPath, this);
|
||
const stream = new stream_1$7.PassThrough({ objectMode: true });
|
||
stream._write = (index, _enc, done) => {
|
||
return this._getEntry(filepaths[index], patterns[index], options)
|
||
.then((entry) => {
|
||
if (entry !== null && options.entryFilter(entry)) {
|
||
stream.push(entry);
|
||
}
|
||
if (index === filepaths.length - 1) {
|
||
stream.end();
|
||
}
|
||
done();
|
||
})
|
||
.catch(done);
|
||
};
|
||
for (let i = 0; i < filepaths.length; i++) {
|
||
stream.write(i);
|
||
}
|
||
return stream;
|
||
}
|
||
_getEntry(filepath, pattern, options) {
|
||
return this._getStat(filepath)
|
||
.then((stats) => this._makeEntry(stats, pattern))
|
||
.catch((error) => {
|
||
if (options.errorFilter(error)) {
|
||
return null;
|
||
}
|
||
throw error;
|
||
});
|
||
}
|
||
_getStat(filepath) {
|
||
return new Promise((resolve, reject) => {
|
||
this._stat(filepath, this._fsStatSettings, (error, stats) => {
|
||
return error === null ? resolve(stats) : reject(error);
|
||
});
|
||
});
|
||
}
|
||
}
|
||
stream$1.default = ReaderStream;
|
||
|
||
Object.defineProperty(async$6, "__esModule", { value: true });
|
||
const fsWalk$1 = out$3;
|
||
const reader_1$1 = reader;
|
||
const stream_1$6 = stream$1;
|
||
class ReaderAsync extends reader_1$1.default {
|
||
constructor() {
|
||
super(...arguments);
|
||
this._walkAsync = fsWalk$1.walk;
|
||
this._readerStream = new stream_1$6.default(this._settings);
|
||
}
|
||
dynamic(root, options) {
|
||
return new Promise((resolve, reject) => {
|
||
this._walkAsync(root, options, (error, entries) => {
|
||
if (error === null) {
|
||
resolve(entries);
|
||
}
|
||
else {
|
||
reject(error);
|
||
}
|
||
});
|
||
});
|
||
}
|
||
async static(patterns, options) {
|
||
const entries = [];
|
||
const stream = this._readerStream.static(patterns, options);
|
||
// After #235, replace it with an asynchronous iterator.
|
||
return new Promise((resolve, reject) => {
|
||
stream.once('error', reject);
|
||
stream.on('data', (entry) => entries.push(entry));
|
||
stream.once('end', () => resolve(entries));
|
||
});
|
||
}
|
||
}
|
||
async$6.default = ReaderAsync;
|
||
|
||
var provider = {};
|
||
|
||
var deep = {};
|
||
|
||
var partial = {};
|
||
|
||
var matcher = {};
|
||
|
||
Object.defineProperty(matcher, "__esModule", { value: true });
|
||
const utils$d = utils$s;
|
||
class Matcher {
|
||
constructor(_patterns, _settings, _micromatchOptions) {
|
||
this._patterns = _patterns;
|
||
this._settings = _settings;
|
||
this._micromatchOptions = _micromatchOptions;
|
||
this._storage = [];
|
||
this._fillStorage();
|
||
}
|
||
_fillStorage() {
|
||
for (const pattern of this._patterns) {
|
||
const segments = this._getPatternSegments(pattern);
|
||
const sections = this._splitSegmentsIntoSections(segments);
|
||
this._storage.push({
|
||
complete: sections.length <= 1,
|
||
pattern,
|
||
segments,
|
||
sections
|
||
});
|
||
}
|
||
}
|
||
_getPatternSegments(pattern) {
|
||
const parts = utils$d.pattern.getPatternParts(pattern, this._micromatchOptions);
|
||
return parts.map((part) => {
|
||
const dynamic = utils$d.pattern.isDynamicPattern(part, this._settings);
|
||
if (!dynamic) {
|
||
return {
|
||
dynamic: false,
|
||
pattern: part
|
||
};
|
||
}
|
||
return {
|
||
dynamic: true,
|
||
pattern: part,
|
||
patternRe: utils$d.pattern.makeRe(part, this._micromatchOptions)
|
||
};
|
||
});
|
||
}
|
||
_splitSegmentsIntoSections(segments) {
|
||
return utils$d.array.splitWhen(segments, (segment) => segment.dynamic && utils$d.pattern.hasGlobStar(segment.pattern));
|
||
}
|
||
}
|
||
matcher.default = Matcher;
|
||
|
||
Object.defineProperty(partial, "__esModule", { value: true });
|
||
const matcher_1 = matcher;
|
||
class PartialMatcher extends matcher_1.default {
|
||
match(filepath) {
|
||
const parts = filepath.split('/');
|
||
const levels = parts.length;
|
||
const patterns = this._storage.filter((info) => !info.complete || info.segments.length > levels);
|
||
for (const pattern of patterns) {
|
||
const section = pattern.sections[0];
|
||
/**
|
||
* In this case, the pattern has a globstar and we must read all directories unconditionally,
|
||
* but only if the level has reached the end of the first group.
|
||
*
|
||
* fixtures/{a,b}/**
|
||
* ^ true/false ^ always true
|
||
*/
|
||
if (!pattern.complete && levels > section.length) {
|
||
return true;
|
||
}
|
||
const match = parts.every((part, index) => {
|
||
const segment = pattern.segments[index];
|
||
if (segment.dynamic && segment.patternRe.test(part)) {
|
||
return true;
|
||
}
|
||
if (!segment.dynamic && segment.pattern === part) {
|
||
return true;
|
||
}
|
||
return false;
|
||
});
|
||
if (match) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
partial.default = PartialMatcher;
|
||
|
||
Object.defineProperty(deep, "__esModule", { value: true });
|
||
const utils$c = utils$s;
|
||
const partial_1 = partial;
|
||
class DeepFilter {
|
||
constructor(_settings, _micromatchOptions) {
|
||
this._settings = _settings;
|
||
this._micromatchOptions = _micromatchOptions;
|
||
}
|
||
getFilter(basePath, positive, negative) {
|
||
const matcher = this._getMatcher(positive);
|
||
const negativeRe = this._getNegativePatternsRe(negative);
|
||
return (entry) => this._filter(basePath, entry, matcher, negativeRe);
|
||
}
|
||
_getMatcher(patterns) {
|
||
return new partial_1.default(patterns, this._settings, this._micromatchOptions);
|
||
}
|
||
_getNegativePatternsRe(patterns) {
|
||
const affectDepthOfReadingPatterns = patterns.filter(utils$c.pattern.isAffectDepthOfReadingPattern);
|
||
return utils$c.pattern.convertPatternsToRe(affectDepthOfReadingPatterns, this._micromatchOptions);
|
||
}
|
||
_filter(basePath, entry, matcher, negativeRe) {
|
||
if (this._isSkippedByDeep(basePath, entry.path)) {
|
||
return false;
|
||
}
|
||
if (this._isSkippedSymbolicLink(entry)) {
|
||
return false;
|
||
}
|
||
const filepath = utils$c.path.removeLeadingDotSegment(entry.path);
|
||
if (this._isSkippedByPositivePatterns(filepath, matcher)) {
|
||
return false;
|
||
}
|
||
return this._isSkippedByNegativePatterns(filepath, negativeRe);
|
||
}
|
||
_isSkippedByDeep(basePath, entryPath) {
|
||
/**
|
||
* Avoid unnecessary depth calculations when it doesn't matter.
|
||
*/
|
||
if (this._settings.deep === Infinity) {
|
||
return false;
|
||
}
|
||
return this._getEntryLevel(basePath, entryPath) >= this._settings.deep;
|
||
}
|
||
_getEntryLevel(basePath, entryPath) {
|
||
const entryPathDepth = entryPath.split('/').length;
|
||
if (basePath === '') {
|
||
return entryPathDepth;
|
||
}
|
||
const basePathDepth = basePath.split('/').length;
|
||
return entryPathDepth - basePathDepth;
|
||
}
|
||
_isSkippedSymbolicLink(entry) {
|
||
return !this._settings.followSymbolicLinks && entry.dirent.isSymbolicLink();
|
||
}
|
||
_isSkippedByPositivePatterns(entryPath, matcher) {
|
||
return !this._settings.baseNameMatch && !matcher.match(entryPath);
|
||
}
|
||
_isSkippedByNegativePatterns(entryPath, patternsRe) {
|
||
return !utils$c.pattern.matchAny(entryPath, patternsRe);
|
||
}
|
||
}
|
||
deep.default = DeepFilter;
|
||
|
||
var entry$1 = {};
|
||
|
||
Object.defineProperty(entry$1, "__esModule", { value: true });
|
||
const utils$b = utils$s;
|
||
class EntryFilter {
|
||
constructor(_settings, _micromatchOptions) {
|
||
this._settings = _settings;
|
||
this._micromatchOptions = _micromatchOptions;
|
||
this.index = new Map();
|
||
}
|
||
getFilter(positive, negative) {
|
||
const positiveRe = utils$b.pattern.convertPatternsToRe(positive, this._micromatchOptions);
|
||
const negativeRe = utils$b.pattern.convertPatternsToRe(negative, Object.assign(Object.assign({}, this._micromatchOptions), { dot: true }));
|
||
return (entry) => this._filter(entry, positiveRe, negativeRe);
|
||
}
|
||
_filter(entry, positiveRe, negativeRe) {
|
||
const filepath = utils$b.path.removeLeadingDotSegment(entry.path);
|
||
if (this._settings.unique && this._isDuplicateEntry(filepath)) {
|
||
return false;
|
||
}
|
||
if (this._onlyFileFilter(entry) || this._onlyDirectoryFilter(entry)) {
|
||
return false;
|
||
}
|
||
if (this._isSkippedByAbsoluteNegativePatterns(filepath, negativeRe)) {
|
||
return false;
|
||
}
|
||
const isDirectory = entry.dirent.isDirectory();
|
||
const isMatched = this._isMatchToPatterns(filepath, positiveRe, isDirectory) && !this._isMatchToPatterns(filepath, negativeRe, isDirectory);
|
||
if (this._settings.unique && isMatched) {
|
||
this._createIndexRecord(filepath);
|
||
}
|
||
return isMatched;
|
||
}
|
||
_isDuplicateEntry(filepath) {
|
||
return this.index.has(filepath);
|
||
}
|
||
_createIndexRecord(filepath) {
|
||
this.index.set(filepath, undefined);
|
||
}
|
||
_onlyFileFilter(entry) {
|
||
return this._settings.onlyFiles && !entry.dirent.isFile();
|
||
}
|
||
_onlyDirectoryFilter(entry) {
|
||
return this._settings.onlyDirectories && !entry.dirent.isDirectory();
|
||
}
|
||
_isSkippedByAbsoluteNegativePatterns(entryPath, patternsRe) {
|
||
if (!this._settings.absolute) {
|
||
return false;
|
||
}
|
||
const fullpath = utils$b.path.makeAbsolute(this._settings.cwd, entryPath);
|
||
return utils$b.pattern.matchAny(fullpath, patternsRe);
|
||
}
|
||
_isMatchToPatterns(filepath, patternsRe, isDirectory) {
|
||
// Trying to match files and directories by patterns.
|
||
const isMatched = utils$b.pattern.matchAny(filepath, patternsRe);
|
||
// A pattern with a trailling slash can be used for directory matching.
|
||
// To apply such pattern, we need to add a tralling slash to the path.
|
||
if (!isMatched && isDirectory) {
|
||
return utils$b.pattern.matchAny(filepath + '/', patternsRe);
|
||
}
|
||
return isMatched;
|
||
}
|
||
}
|
||
entry$1.default = EntryFilter;
|
||
|
||
var error$1 = {};
|
||
|
||
Object.defineProperty(error$1, "__esModule", { value: true });
|
||
const utils$a = utils$s;
|
||
class ErrorFilter {
|
||
constructor(_settings) {
|
||
this._settings = _settings;
|
||
}
|
||
getFilter() {
|
||
return (error) => this._isNonFatalError(error);
|
||
}
|
||
_isNonFatalError(error) {
|
||
return utils$a.errno.isEnoentCodeError(error) || this._settings.suppressErrors;
|
||
}
|
||
}
|
||
error$1.default = ErrorFilter;
|
||
|
||
var entry = {};
|
||
|
||
Object.defineProperty(entry, "__esModule", { value: true });
|
||
const utils$9 = utils$s;
|
||
class EntryTransformer {
|
||
constructor(_settings) {
|
||
this._settings = _settings;
|
||
}
|
||
getTransformer() {
|
||
return (entry) => this._transform(entry);
|
||
}
|
||
_transform(entry) {
|
||
let filepath = entry.path;
|
||
if (this._settings.absolute) {
|
||
filepath = utils$9.path.makeAbsolute(this._settings.cwd, filepath);
|
||
filepath = utils$9.path.unixify(filepath);
|
||
}
|
||
if (this._settings.markDirectories && entry.dirent.isDirectory()) {
|
||
filepath += '/';
|
||
}
|
||
if (!this._settings.objectMode) {
|
||
return filepath;
|
||
}
|
||
return Object.assign(Object.assign({}, entry), { path: filepath });
|
||
}
|
||
}
|
||
entry.default = EntryTransformer;
|
||
|
||
Object.defineProperty(provider, "__esModule", { value: true });
|
||
const path$3 = path$q;
|
||
const deep_1 = deep;
|
||
const entry_1 = entry$1;
|
||
const error_1 = error$1;
|
||
const entry_2 = entry;
|
||
class Provider {
|
||
constructor(_settings) {
|
||
this._settings = _settings;
|
||
this.errorFilter = new error_1.default(this._settings);
|
||
this.entryFilter = new entry_1.default(this._settings, this._getMicromatchOptions());
|
||
this.deepFilter = new deep_1.default(this._settings, this._getMicromatchOptions());
|
||
this.entryTransformer = new entry_2.default(this._settings);
|
||
}
|
||
_getRootDirectory(task) {
|
||
return path$3.resolve(this._settings.cwd, task.base);
|
||
}
|
||
_getReaderOptions(task) {
|
||
const basePath = task.base === '.' ? '' : task.base;
|
||
return {
|
||
basePath,
|
||
pathSegmentSeparator: '/',
|
||
concurrency: this._settings.concurrency,
|
||
deepFilter: this.deepFilter.getFilter(basePath, task.positive, task.negative),
|
||
entryFilter: this.entryFilter.getFilter(task.positive, task.negative),
|
||
errorFilter: this.errorFilter.getFilter(),
|
||
followSymbolicLinks: this._settings.followSymbolicLinks,
|
||
fs: this._settings.fs,
|
||
stats: this._settings.stats,
|
||
throwErrorOnBrokenSymbolicLink: this._settings.throwErrorOnBrokenSymbolicLink,
|
||
transform: this.entryTransformer.getTransformer()
|
||
};
|
||
}
|
||
_getMicromatchOptions() {
|
||
return {
|
||
dot: this._settings.dot,
|
||
matchBase: this._settings.baseNameMatch,
|
||
nobrace: !this._settings.braceExpansion,
|
||
nocase: !this._settings.caseSensitiveMatch,
|
||
noext: !this._settings.extglob,
|
||
noglobstar: !this._settings.globstar,
|
||
posix: true,
|
||
strictSlashes: false
|
||
};
|
||
}
|
||
}
|
||
provider.default = Provider;
|
||
|
||
Object.defineProperty(async$7, "__esModule", { value: true });
|
||
const async_1$1 = async$6;
|
||
const provider_1$2 = provider;
|
||
class ProviderAsync extends provider_1$2.default {
|
||
constructor() {
|
||
super(...arguments);
|
||
this._reader = new async_1$1.default(this._settings);
|
||
}
|
||
async read(task) {
|
||
const root = this._getRootDirectory(task);
|
||
const options = this._getReaderOptions(task);
|
||
const entries = await this.api(root, task, options);
|
||
return entries.map((entry) => options.transform(entry));
|
||
}
|
||
api(root, task, options) {
|
||
if (task.dynamic) {
|
||
return this._reader.dynamic(root, options);
|
||
}
|
||
return this._reader.static(task.patterns, options);
|
||
}
|
||
}
|
||
async$7.default = ProviderAsync;
|
||
|
||
var stream = {};
|
||
|
||
Object.defineProperty(stream, "__esModule", { value: true });
|
||
const stream_1$5 = require$$0$3;
|
||
const stream_2 = stream$1;
|
||
const provider_1$1 = provider;
|
||
class ProviderStream extends provider_1$1.default {
|
||
constructor() {
|
||
super(...arguments);
|
||
this._reader = new stream_2.default(this._settings);
|
||
}
|
||
read(task) {
|
||
const root = this._getRootDirectory(task);
|
||
const options = this._getReaderOptions(task);
|
||
const source = this.api(root, task, options);
|
||
const destination = new stream_1$5.Readable({ objectMode: true, read: () => { } });
|
||
source
|
||
.once('error', (error) => destination.emit('error', error))
|
||
.on('data', (entry) => destination.emit('data', options.transform(entry)))
|
||
.once('end', () => destination.emit('end'));
|
||
destination
|
||
.once('close', () => source.destroy());
|
||
return destination;
|
||
}
|
||
api(root, task, options) {
|
||
if (task.dynamic) {
|
||
return this._reader.dynamic(root, options);
|
||
}
|
||
return this._reader.static(task.patterns, options);
|
||
}
|
||
}
|
||
stream.default = ProviderStream;
|
||
|
||
var sync$2 = {};
|
||
|
||
var sync$1 = {};
|
||
|
||
Object.defineProperty(sync$1, "__esModule", { value: true });
|
||
const fsStat = out$1;
|
||
const fsWalk = out$3;
|
||
const reader_1 = reader;
|
||
class ReaderSync extends reader_1.default {
|
||
constructor() {
|
||
super(...arguments);
|
||
this._walkSync = fsWalk.walkSync;
|
||
this._statSync = fsStat.statSync;
|
||
}
|
||
dynamic(root, options) {
|
||
return this._walkSync(root, options);
|
||
}
|
||
static(patterns, options) {
|
||
const entries = [];
|
||
for (const pattern of patterns) {
|
||
const filepath = this._getFullEntryPath(pattern);
|
||
const entry = this._getEntry(filepath, pattern, options);
|
||
if (entry === null || !options.entryFilter(entry)) {
|
||
continue;
|
||
}
|
||
entries.push(entry);
|
||
}
|
||
return entries;
|
||
}
|
||
_getEntry(filepath, pattern, options) {
|
||
try {
|
||
const stats = this._getStat(filepath);
|
||
return this._makeEntry(stats, pattern);
|
||
}
|
||
catch (error) {
|
||
if (options.errorFilter(error)) {
|
||
return null;
|
||
}
|
||
throw error;
|
||
}
|
||
}
|
||
_getStat(filepath) {
|
||
return this._statSync(filepath, this._fsStatSettings);
|
||
}
|
||
}
|
||
sync$1.default = ReaderSync;
|
||
|
||
Object.defineProperty(sync$2, "__esModule", { value: true });
|
||
const sync_1$1 = sync$1;
|
||
const provider_1 = provider;
|
||
class ProviderSync extends provider_1.default {
|
||
constructor() {
|
||
super(...arguments);
|
||
this._reader = new sync_1$1.default(this._settings);
|
||
}
|
||
read(task) {
|
||
const root = this._getRootDirectory(task);
|
||
const options = this._getReaderOptions(task);
|
||
const entries = this.api(root, task, options);
|
||
return entries.map(options.transform);
|
||
}
|
||
api(root, task, options) {
|
||
if (task.dynamic) {
|
||
return this._reader.dynamic(root, options);
|
||
}
|
||
return this._reader.static(task.patterns, options);
|
||
}
|
||
}
|
||
sync$2.default = ProviderSync;
|
||
|
||
var settings = {};
|
||
|
||
(function (exports) {
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.DEFAULT_FILE_SYSTEM_ADAPTER = void 0;
|
||
const fs = fs__default;
|
||
const os = require$$0$6;
|
||
/**
|
||
* The `os.cpus` method can return zero. We expect the number of cores to be greater than zero.
|
||
* https://github.com/nodejs/node/blob/7faeddf23a98c53896f8b574a6e66589e8fb1eb8/lib/os.js#L106-L107
|
||
*/
|
||
const CPU_COUNT = Math.max(os.cpus().length, 1);
|
||
exports.DEFAULT_FILE_SYSTEM_ADAPTER = {
|
||
lstat: fs.lstat,
|
||
lstatSync: fs.lstatSync,
|
||
stat: fs.stat,
|
||
statSync: fs.statSync,
|
||
readdir: fs.readdir,
|
||
readdirSync: fs.readdirSync
|
||
};
|
||
class Settings {
|
||
constructor(_options = {}) {
|
||
this._options = _options;
|
||
this.absolute = this._getValue(this._options.absolute, false);
|
||
this.baseNameMatch = this._getValue(this._options.baseNameMatch, false);
|
||
this.braceExpansion = this._getValue(this._options.braceExpansion, true);
|
||
this.caseSensitiveMatch = this._getValue(this._options.caseSensitiveMatch, true);
|
||
this.concurrency = this._getValue(this._options.concurrency, CPU_COUNT);
|
||
this.cwd = this._getValue(this._options.cwd, process.cwd());
|
||
this.deep = this._getValue(this._options.deep, Infinity);
|
||
this.dot = this._getValue(this._options.dot, false);
|
||
this.extglob = this._getValue(this._options.extglob, true);
|
||
this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, true);
|
||
this.fs = this._getFileSystemMethods(this._options.fs);
|
||
this.globstar = this._getValue(this._options.globstar, true);
|
||
this.ignore = this._getValue(this._options.ignore, []);
|
||
this.markDirectories = this._getValue(this._options.markDirectories, false);
|
||
this.objectMode = this._getValue(this._options.objectMode, false);
|
||
this.onlyDirectories = this._getValue(this._options.onlyDirectories, false);
|
||
this.onlyFiles = this._getValue(this._options.onlyFiles, true);
|
||
this.stats = this._getValue(this._options.stats, false);
|
||
this.suppressErrors = this._getValue(this._options.suppressErrors, false);
|
||
this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, false);
|
||
this.unique = this._getValue(this._options.unique, true);
|
||
if (this.onlyDirectories) {
|
||
this.onlyFiles = false;
|
||
}
|
||
if (this.stats) {
|
||
this.objectMode = true;
|
||
}
|
||
// Remove the cast to the array in the next major (#404).
|
||
this.ignore = [].concat(this.ignore);
|
||
}
|
||
_getValue(option, value) {
|
||
return option === undefined ? value : option;
|
||
}
|
||
_getFileSystemMethods(methods = {}) {
|
||
return Object.assign(Object.assign({}, exports.DEFAULT_FILE_SYSTEM_ADAPTER), methods);
|
||
}
|
||
}
|
||
exports.default = Settings;
|
||
} (settings));
|
||
|
||
const taskManager = tasks;
|
||
const async_1 = async$7;
|
||
const stream_1$4 = stream;
|
||
const sync_1 = sync$2;
|
||
const settings_1 = settings;
|
||
const utils$8 = utils$s;
|
||
async function FastGlob(source, options) {
|
||
assertPatternsInput(source);
|
||
const works = getWorks(source, async_1.default, options);
|
||
const result = await Promise.all(works);
|
||
return utils$8.array.flatten(result);
|
||
}
|
||
// https://github.com/typescript-eslint/typescript-eslint/issues/60
|
||
// eslint-disable-next-line no-redeclare
|
||
(function (FastGlob) {
|
||
FastGlob.glob = FastGlob;
|
||
FastGlob.globSync = sync;
|
||
FastGlob.globStream = stream;
|
||
FastGlob.async = FastGlob;
|
||
function sync(source, options) {
|
||
assertPatternsInput(source);
|
||
const works = getWorks(source, sync_1.default, options);
|
||
return utils$8.array.flatten(works);
|
||
}
|
||
FastGlob.sync = sync;
|
||
function stream(source, options) {
|
||
assertPatternsInput(source);
|
||
const works = getWorks(source, stream_1$4.default, options);
|
||
/**
|
||
* The stream returned by the provider cannot work with an asynchronous iterator.
|
||
* To support asynchronous iterators, regardless of the number of tasks, we always multiplex streams.
|
||
* This affects performance (+25%). I don't see best solution right now.
|
||
*/
|
||
return utils$8.stream.merge(works);
|
||
}
|
||
FastGlob.stream = stream;
|
||
function generateTasks(source, options) {
|
||
assertPatternsInput(source);
|
||
const patterns = [].concat(source);
|
||
const settings = new settings_1.default(options);
|
||
return taskManager.generate(patterns, settings);
|
||
}
|
||
FastGlob.generateTasks = generateTasks;
|
||
function isDynamicPattern(source, options) {
|
||
assertPatternsInput(source);
|
||
const settings = new settings_1.default(options);
|
||
return utils$8.pattern.isDynamicPattern(source, settings);
|
||
}
|
||
FastGlob.isDynamicPattern = isDynamicPattern;
|
||
function escapePath(source) {
|
||
assertPatternsInput(source);
|
||
return utils$8.path.escape(source);
|
||
}
|
||
FastGlob.escapePath = escapePath;
|
||
function convertPathToPattern(source) {
|
||
assertPatternsInput(source);
|
||
return utils$8.path.convertPathToPattern(source);
|
||
}
|
||
FastGlob.convertPathToPattern = convertPathToPattern;
|
||
(function (posix) {
|
||
function escapePath(source) {
|
||
assertPatternsInput(source);
|
||
return utils$8.path.escapePosixPath(source);
|
||
}
|
||
posix.escapePath = escapePath;
|
||
function convertPathToPattern(source) {
|
||
assertPatternsInput(source);
|
||
return utils$8.path.convertPosixPathToPattern(source);
|
||
}
|
||
posix.convertPathToPattern = convertPathToPattern;
|
||
})(FastGlob.posix || (FastGlob.posix = {}));
|
||
(function (win32) {
|
||
function escapePath(source) {
|
||
assertPatternsInput(source);
|
||
return utils$8.path.escapeWindowsPath(source);
|
||
}
|
||
win32.escapePath = escapePath;
|
||
function convertPathToPattern(source) {
|
||
assertPatternsInput(source);
|
||
return utils$8.path.convertWindowsPathToPattern(source);
|
||
}
|
||
win32.convertPathToPattern = convertPathToPattern;
|
||
})(FastGlob.win32 || (FastGlob.win32 = {}));
|
||
})(FastGlob || (FastGlob = {}));
|
||
function getWorks(source, _Provider, options) {
|
||
const patterns = [].concat(source);
|
||
const settings = new settings_1.default(options);
|
||
const tasks = taskManager.generate(patterns, settings);
|
||
const provider = new _Provider(settings);
|
||
return tasks.map(provider.read, provider);
|
||
}
|
||
function assertPatternsInput(input) {
|
||
const source = [].concat(input);
|
||
const isValidSource = source.every((item) => utils$8.string.isString(item) && !utils$8.string.isEmpty(item));
|
||
if (!isValidSource) {
|
||
throw new TypeError('Patterns must be a string (non empty) or an array of strings');
|
||
}
|
||
}
|
||
var out = FastGlob;
|
||
|
||
var glob = /*@__PURE__*/getDefaultExportFromCjs(out);
|
||
|
||
/**
|
||
* Tokenize input string.
|
||
*/
|
||
function lexer(str) {
|
||
var tokens = [];
|
||
var i = 0;
|
||
while (i < str.length) {
|
||
var char = str[i];
|
||
if (char === "*" || char === "+" || char === "?") {
|
||
tokens.push({ type: "MODIFIER", index: i, value: str[i++] });
|
||
continue;
|
||
}
|
||
if (char === "\\") {
|
||
tokens.push({ type: "ESCAPED_CHAR", index: i++, value: str[i++] });
|
||
continue;
|
||
}
|
||
if (char === "{") {
|
||
tokens.push({ type: "OPEN", index: i, value: str[i++] });
|
||
continue;
|
||
}
|
||
if (char === "}") {
|
||
tokens.push({ type: "CLOSE", index: i, value: str[i++] });
|
||
continue;
|
||
}
|
||
if (char === ":") {
|
||
var name = "";
|
||
var j = i + 1;
|
||
while (j < str.length) {
|
||
var code = str.charCodeAt(j);
|
||
if (
|
||
// `0-9`
|
||
(code >= 48 && code <= 57) ||
|
||
// `A-Z`
|
||
(code >= 65 && code <= 90) ||
|
||
// `a-z`
|
||
(code >= 97 && code <= 122) ||
|
||
// `_`
|
||
code === 95) {
|
||
name += str[j++];
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
if (!name)
|
||
throw new TypeError("Missing parameter name at ".concat(i));
|
||
tokens.push({ type: "NAME", index: i, value: name });
|
||
i = j;
|
||
continue;
|
||
}
|
||
if (char === "(") {
|
||
var count = 1;
|
||
var pattern = "";
|
||
var j = i + 1;
|
||
if (str[j] === "?") {
|
||
throw new TypeError("Pattern cannot start with \"?\" at ".concat(j));
|
||
}
|
||
while (j < str.length) {
|
||
if (str[j] === "\\") {
|
||
pattern += str[j++] + str[j++];
|
||
continue;
|
||
}
|
||
if (str[j] === ")") {
|
||
count--;
|
||
if (count === 0) {
|
||
j++;
|
||
break;
|
||
}
|
||
}
|
||
else if (str[j] === "(") {
|
||
count++;
|
||
if (str[j + 1] !== "?") {
|
||
throw new TypeError("Capturing groups are not allowed at ".concat(j));
|
||
}
|
||
}
|
||
pattern += str[j++];
|
||
}
|
||
if (count)
|
||
throw new TypeError("Unbalanced pattern at ".concat(i));
|
||
if (!pattern)
|
||
throw new TypeError("Missing pattern at ".concat(i));
|
||
tokens.push({ type: "PATTERN", index: i, value: pattern });
|
||
i = j;
|
||
continue;
|
||
}
|
||
tokens.push({ type: "CHAR", index: i, value: str[i++] });
|
||
}
|
||
tokens.push({ type: "END", index: i, value: "" });
|
||
return tokens;
|
||
}
|
||
/**
|
||
* Parse a string for the raw tokens.
|
||
*/
|
||
function parse$8(str, options) {
|
||
if (options === void 0) { options = {}; }
|
||
var tokens = lexer(str);
|
||
var _a = options.prefixes, prefixes = _a === void 0 ? "./" : _a;
|
||
var defaultPattern = "[^".concat(escapeString$1(options.delimiter || "/#?"), "]+?");
|
||
var result = [];
|
||
var key = 0;
|
||
var i = 0;
|
||
var path = "";
|
||
var tryConsume = function (type) {
|
||
if (i < tokens.length && tokens[i].type === type)
|
||
return tokens[i++].value;
|
||
};
|
||
var mustConsume = function (type) {
|
||
var value = tryConsume(type);
|
||
if (value !== undefined)
|
||
return value;
|
||
var _a = tokens[i], nextType = _a.type, index = _a.index;
|
||
throw new TypeError("Unexpected ".concat(nextType, " at ").concat(index, ", expected ").concat(type));
|
||
};
|
||
var consumeText = function () {
|
||
var result = "";
|
||
var value;
|
||
while ((value = tryConsume("CHAR") || tryConsume("ESCAPED_CHAR"))) {
|
||
result += value;
|
||
}
|
||
return result;
|
||
};
|
||
while (i < tokens.length) {
|
||
var char = tryConsume("CHAR");
|
||
var name = tryConsume("NAME");
|
||
var pattern = tryConsume("PATTERN");
|
||
if (name || pattern) {
|
||
var prefix = char || "";
|
||
if (prefixes.indexOf(prefix) === -1) {
|
||
path += prefix;
|
||
prefix = "";
|
||
}
|
||
if (path) {
|
||
result.push(path);
|
||
path = "";
|
||
}
|
||
result.push({
|
||
name: name || key++,
|
||
prefix: prefix,
|
||
suffix: "",
|
||
pattern: pattern || defaultPattern,
|
||
modifier: tryConsume("MODIFIER") || "",
|
||
});
|
||
continue;
|
||
}
|
||
var value = char || tryConsume("ESCAPED_CHAR");
|
||
if (value) {
|
||
path += value;
|
||
continue;
|
||
}
|
||
if (path) {
|
||
result.push(path);
|
||
path = "";
|
||
}
|
||
var open = tryConsume("OPEN");
|
||
if (open) {
|
||
var prefix = consumeText();
|
||
var name_1 = tryConsume("NAME") || "";
|
||
var pattern_1 = tryConsume("PATTERN") || "";
|
||
var suffix = consumeText();
|
||
mustConsume("CLOSE");
|
||
result.push({
|
||
name: name_1 || (pattern_1 ? key++ : ""),
|
||
pattern: name_1 && !pattern_1 ? defaultPattern : pattern_1,
|
||
prefix: prefix,
|
||
suffix: suffix,
|
||
modifier: tryConsume("MODIFIER") || "",
|
||
});
|
||
continue;
|
||
}
|
||
mustConsume("END");
|
||
}
|
||
return result;
|
||
}
|
||
/**
|
||
* Compile a string to a template function for the path.
|
||
*/
|
||
function compile$1(str, options) {
|
||
return tokensToFunction(parse$8(str, options), options);
|
||
}
|
||
/**
|
||
* Expose a method for transforming tokens into the path function.
|
||
*/
|
||
function tokensToFunction(tokens, options) {
|
||
if (options === void 0) { options = {}; }
|
||
var reFlags = flags(options);
|
||
var _a = options.encode, encode = _a === void 0 ? function (x) { return x; } : _a, _b = options.validate, validate = _b === void 0 ? true : _b;
|
||
// Compile all the tokens into regexps.
|
||
var matches = tokens.map(function (token) {
|
||
if (typeof token === "object") {
|
||
return new RegExp("^(?:".concat(token.pattern, ")$"), reFlags);
|
||
}
|
||
});
|
||
return function (data) {
|
||
var path = "";
|
||
for (var i = 0; i < tokens.length; i++) {
|
||
var token = tokens[i];
|
||
if (typeof token === "string") {
|
||
path += token;
|
||
continue;
|
||
}
|
||
var value = data ? data[token.name] : undefined;
|
||
var optional = token.modifier === "?" || token.modifier === "*";
|
||
var repeat = token.modifier === "*" || token.modifier === "+";
|
||
if (Array.isArray(value)) {
|
||
if (!repeat) {
|
||
throw new TypeError("Expected \"".concat(token.name, "\" to not repeat, but got an array"));
|
||
}
|
||
if (value.length === 0) {
|
||
if (optional)
|
||
continue;
|
||
throw new TypeError("Expected \"".concat(token.name, "\" to not be empty"));
|
||
}
|
||
for (var j = 0; j < value.length; j++) {
|
||
var segment = encode(value[j], token);
|
||
if (validate && !matches[i].test(segment)) {
|
||
throw new TypeError("Expected all \"".concat(token.name, "\" to match \"").concat(token.pattern, "\", but got \"").concat(segment, "\""));
|
||
}
|
||
path += token.prefix + segment + token.suffix;
|
||
}
|
||
continue;
|
||
}
|
||
if (typeof value === "string" || typeof value === "number") {
|
||
var segment = encode(String(value), token);
|
||
if (validate && !matches[i].test(segment)) {
|
||
throw new TypeError("Expected \"".concat(token.name, "\" to match \"").concat(token.pattern, "\", but got \"").concat(segment, "\""));
|
||
}
|
||
path += token.prefix + segment + token.suffix;
|
||
continue;
|
||
}
|
||
if (optional)
|
||
continue;
|
||
var typeOfMessage = repeat ? "an array" : "a string";
|
||
throw new TypeError("Expected \"".concat(token.name, "\" to be ").concat(typeOfMessage));
|
||
}
|
||
return path;
|
||
};
|
||
}
|
||
/**
|
||
* Create path match function from `path-to-regexp` spec.
|
||
*/
|
||
function match(str, options) {
|
||
var keys = [];
|
||
var re = pathToRegexp(str, keys, options);
|
||
return regexpToFunction(re, keys, options);
|
||
}
|
||
/**
|
||
* Create a path match function from `path-to-regexp` output.
|
||
*/
|
||
function regexpToFunction(re, keys, options) {
|
||
if (options === void 0) { options = {}; }
|
||
var _a = options.decode, decode = _a === void 0 ? function (x) { return x; } : _a;
|
||
return function (pathname) {
|
||
var m = re.exec(pathname);
|
||
if (!m)
|
||
return false;
|
||
var path = m[0], index = m.index;
|
||
var params = Object.create(null);
|
||
var _loop_1 = function (i) {
|
||
if (m[i] === undefined)
|
||
return "continue";
|
||
var key = keys[i - 1];
|
||
if (key.modifier === "*" || key.modifier === "+") {
|
||
params[key.name] = m[i].split(key.prefix + key.suffix).map(function (value) {
|
||
return decode(value, key);
|
||
});
|
||
}
|
||
else {
|
||
params[key.name] = decode(m[i], key);
|
||
}
|
||
};
|
||
for (var i = 1; i < m.length; i++) {
|
||
_loop_1(i);
|
||
}
|
||
return { path: path, index: index, params: params };
|
||
};
|
||
}
|
||
/**
|
||
* Escape a regular expression string.
|
||
*/
|
||
function escapeString$1(str) {
|
||
return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, "\\$1");
|
||
}
|
||
/**
|
||
* Get the flags for a regexp from the options.
|
||
*/
|
||
function flags(options) {
|
||
return options && options.sensitive ? "" : "i";
|
||
}
|
||
/**
|
||
* Pull out keys from a regexp.
|
||
*/
|
||
function regexpToRegexp(path, keys) {
|
||
if (!keys)
|
||
return path;
|
||
var groupsRegex = /\((?:\?<(.*?)>)?(?!\?)/g;
|
||
var index = 0;
|
||
var execResult = groupsRegex.exec(path.source);
|
||
while (execResult) {
|
||
keys.push({
|
||
// Use parenthesized substring match if available, index otherwise
|
||
name: execResult[1] || index++,
|
||
prefix: "",
|
||
suffix: "",
|
||
modifier: "",
|
||
pattern: "",
|
||
});
|
||
execResult = groupsRegex.exec(path.source);
|
||
}
|
||
return path;
|
||
}
|
||
/**
|
||
* Transform an array into a regexp.
|
||
*/
|
||
function arrayToRegexp(paths, keys, options) {
|
||
var parts = paths.map(function (path) { return pathToRegexp(path, keys, options).source; });
|
||
return new RegExp("(?:".concat(parts.join("|"), ")"), flags(options));
|
||
}
|
||
/**
|
||
* Create a path regexp from string input.
|
||
*/
|
||
function stringToRegexp(path, keys, options) {
|
||
return tokensToRegexp(parse$8(path, options), keys, options);
|
||
}
|
||
/**
|
||
* Expose a function for taking tokens and returning a RegExp.
|
||
*/
|
||
function tokensToRegexp(tokens, keys, options) {
|
||
if (options === void 0) { options = {}; }
|
||
var _a = options.strict, strict = _a === void 0 ? false : _a, _b = options.start, start = _b === void 0 ? true : _b, _c = options.end, end = _c === void 0 ? true : _c, _d = options.encode, encode = _d === void 0 ? function (x) { return x; } : _d, _e = options.delimiter, delimiter = _e === void 0 ? "/#?" : _e, _f = options.endsWith, endsWith = _f === void 0 ? "" : _f;
|
||
var endsWithRe = "[".concat(escapeString$1(endsWith), "]|$");
|
||
var delimiterRe = "[".concat(escapeString$1(delimiter), "]");
|
||
var route = start ? "^" : "";
|
||
// Iterate over the tokens and create our regexp string.
|
||
for (var _i = 0, tokens_1 = tokens; _i < tokens_1.length; _i++) {
|
||
var token = tokens_1[_i];
|
||
if (typeof token === "string") {
|
||
route += escapeString$1(encode(token));
|
||
}
|
||
else {
|
||
var prefix = escapeString$1(encode(token.prefix));
|
||
var suffix = escapeString$1(encode(token.suffix));
|
||
if (token.pattern) {
|
||
if (keys)
|
||
keys.push(token);
|
||
if (prefix || suffix) {
|
||
if (token.modifier === "+" || token.modifier === "*") {
|
||
var mod = token.modifier === "*" ? "?" : "";
|
||
route += "(?:".concat(prefix, "((?:").concat(token.pattern, ")(?:").concat(suffix).concat(prefix, "(?:").concat(token.pattern, "))*)").concat(suffix, ")").concat(mod);
|
||
}
|
||
else {
|
||
route += "(?:".concat(prefix, "(").concat(token.pattern, ")").concat(suffix, ")").concat(token.modifier);
|
||
}
|
||
}
|
||
else {
|
||
if (token.modifier === "+" || token.modifier === "*") {
|
||
route += "((?:".concat(token.pattern, ")").concat(token.modifier, ")");
|
||
}
|
||
else {
|
||
route += "(".concat(token.pattern, ")").concat(token.modifier);
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
route += "(?:".concat(prefix).concat(suffix, ")").concat(token.modifier);
|
||
}
|
||
}
|
||
}
|
||
if (end) {
|
||
if (!strict)
|
||
route += "".concat(delimiterRe, "?");
|
||
route += !options.endsWith ? "$" : "(?=".concat(endsWithRe, ")");
|
||
}
|
||
else {
|
||
var endToken = tokens[tokens.length - 1];
|
||
var isEndDelimited = typeof endToken === "string"
|
||
? delimiterRe.indexOf(endToken[endToken.length - 1]) > -1
|
||
: endToken === undefined;
|
||
if (!strict) {
|
||
route += "(?:".concat(delimiterRe, "(?=").concat(endsWithRe, "))?");
|
||
}
|
||
if (!isEndDelimited) {
|
||
route += "(?=".concat(delimiterRe, "|").concat(endsWithRe, ")");
|
||
}
|
||
}
|
||
return new RegExp(route, flags(options));
|
||
}
|
||
/**
|
||
* Normalize the given path string, returning a regular expression.
|
||
*
|
||
* An empty array can be passed in for the keys, which will hold the
|
||
* placeholder key descriptions. For example, using `/user/:id`, `keys` will
|
||
* contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
|
||
*/
|
||
function pathToRegexp(path, keys, options) {
|
||
if (path instanceof RegExp)
|
||
return regexpToRegexp(path, keys);
|
||
if (Array.isArray(path))
|
||
return arrayToRegexp(path, keys, options);
|
||
return stringToRegexp(path, keys, options);
|
||
}
|
||
|
||
function resolveRewrites(pages, userRewrites) {
|
||
const rewriteRules = Object.entries(userRewrites || {}).map(([from, to]) => ({
|
||
toPath: compile$1(`/${to}`, { validate: false }),
|
||
matchUrl: match(from.startsWith("^") ? new RegExp(from) : from)
|
||
}));
|
||
const pageToRewrite = {};
|
||
const rewriteToPage = {};
|
||
if (rewriteRules.length) {
|
||
for (const page of pages) {
|
||
for (const { matchUrl, toPath } of rewriteRules) {
|
||
const res = matchUrl(page);
|
||
if (res) {
|
||
const dest = toPath(res.params).slice(1);
|
||
pageToRewrite[page] = dest;
|
||
rewriteToPage[dest] = page;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return {
|
||
map: pageToRewrite,
|
||
inv: rewriteToPage
|
||
};
|
||
}
|
||
const rewritesPlugin = (config) => {
|
||
return {
|
||
name: "vitepress:rewrites",
|
||
configureServer(server) {
|
||
server.middlewares.use((req, _res, next) => {
|
||
if (req.url) {
|
||
const page = decodeURI(req.url).replace(/[?#].*$/, "").slice(config.site.base.length);
|
||
if (config.rewrites.inv[page]) {
|
||
req.url = req.url.replace(
|
||
encodeURI(page),
|
||
encodeURI(config.rewrites.inv[page])
|
||
);
|
||
}
|
||
}
|
||
next();
|
||
});
|
||
}
|
||
};
|
||
};
|
||
|
||
const dynamicRouteRE = /\[(\w+?)\]/g;
|
||
async function resolvePages(srcDir, userConfig, logger) {
|
||
const allMarkdownFiles = (await glob(["**.md"], {
|
||
cwd: srcDir,
|
||
ignore: [
|
||
"**/node_modules/**",
|
||
"**/dist/**",
|
||
...userConfig.srcExclude || []
|
||
]
|
||
})).sort();
|
||
const pages = [];
|
||
const dynamicRouteFiles = [];
|
||
allMarkdownFiles.forEach((file) => {
|
||
dynamicRouteRE.lastIndex = 0;
|
||
(dynamicRouteRE.test(file) ? dynamicRouteFiles : pages).push(file);
|
||
});
|
||
const dynamicRoutes = await resolveDynamicRoutes(
|
||
srcDir,
|
||
dynamicRouteFiles,
|
||
logger
|
||
);
|
||
pages.push(...dynamicRoutes.routes.map((r) => r.path));
|
||
const rewrites = resolveRewrites(pages, userConfig.rewrites);
|
||
return {
|
||
pages,
|
||
dynamicRoutes,
|
||
rewrites
|
||
};
|
||
}
|
||
const routeModuleCache = /* @__PURE__ */ new Map();
|
||
const dynamicRoutesPlugin = async (config) => {
|
||
let server;
|
||
return {
|
||
name: "vitepress:dynamic-routes",
|
||
configureServer(_server) {
|
||
server = _server;
|
||
},
|
||
resolveId(id) {
|
||
if (!id.endsWith(".md"))
|
||
return;
|
||
const normalizedId = id.startsWith(config.srcDir) ? id : normalizePath(path$q.resolve(config.srcDir, id.replace(/^\//, "")));
|
||
const matched = config.dynamicRoutes.routes.find(
|
||
(r) => r.fullPath === normalizedId
|
||
);
|
||
if (matched) {
|
||
return normalizedId;
|
||
}
|
||
},
|
||
load(id) {
|
||
const matched = config.dynamicRoutes.routes.find((r) => r.fullPath === id);
|
||
if (matched) {
|
||
const { route, params, content } = matched;
|
||
const routeFile = normalizePath(path$q.resolve(config.srcDir, route));
|
||
config.dynamicRoutes.fileToModulesMap[routeFile].add(id);
|
||
let baseContent = fs$a.readFileSync(routeFile, "utf-8");
|
||
if (content) {
|
||
baseContent = baseContent.replace(/<!--\s*@content\s*-->/, content);
|
||
}
|
||
return `__VP_PARAMS_START${JSON.stringify(
|
||
params
|
||
)}__VP_PARAMS_END__${baseContent}`;
|
||
}
|
||
},
|
||
async handleHotUpdate(ctx) {
|
||
routeModuleCache.delete(ctx.file);
|
||
const mods = config.dynamicRoutes.fileToModulesMap[ctx.file];
|
||
if (mods) {
|
||
if (!/\.md$/.test(ctx.file)) {
|
||
Object.assign(
|
||
config,
|
||
await resolvePages(config.srcDir, config.userConfig, config.logger)
|
||
);
|
||
}
|
||
for (const id of mods) {
|
||
ctx.modules.push(server.moduleGraph.getModuleById(id));
|
||
}
|
||
}
|
||
}
|
||
};
|
||
};
|
||
async function resolveDynamicRoutes(srcDir, routes, logger) {
|
||
const pendingResolveRoutes = [];
|
||
const routeFileToModulesMap = {};
|
||
for (const route of routes) {
|
||
const fullPath = normalizePath(path$q.resolve(srcDir, route));
|
||
const paths = ["js", "ts", "mjs", "mts"].map(
|
||
(ext) => fullPath.replace(/\.md$/, `.paths.${ext}`)
|
||
);
|
||
const pathsFile = paths.find((p) => fs$a.existsSync(p));
|
||
if (pathsFile == null) {
|
||
logger.warn(
|
||
c$2.yellow(
|
||
`Missing paths file for dynamic route ${route}: a corresponding ${paths[0]} (or .ts/.mjs/.mts) file is needed.`
|
||
)
|
||
);
|
||
continue;
|
||
}
|
||
let mod = routeModuleCache.get(pathsFile);
|
||
if (!mod) {
|
||
try {
|
||
mod = await loadConfigFromFile(
|
||
{},
|
||
pathsFile,
|
||
void 0,
|
||
"silent"
|
||
);
|
||
routeModuleCache.set(pathsFile, mod);
|
||
} catch (e) {
|
||
logger.warn(`${c$2.yellow(`Failed to load ${pathsFile}:`)}
|
||
${e.stack}`);
|
||
continue;
|
||
}
|
||
}
|
||
const matchedModuleIds = routeFileToModulesMap[normalizePath(path$q.resolve(srcDir, route))] = /* @__PURE__ */ new Set();
|
||
for (const dep of mod.dependencies) {
|
||
routeFileToModulesMap[normalizePath(path$q.resolve(dep))] = matchedModuleIds;
|
||
}
|
||
const loader = mod.config.paths;
|
||
if (!loader) {
|
||
logger.warn(
|
||
c$2.yellow(
|
||
`Invalid paths file export in ${pathsFile}. Missing "paths" property from default export.`
|
||
)
|
||
);
|
||
continue;
|
||
}
|
||
const resolveRoute = async () => {
|
||
const paths2 = await (typeof loader === "function" ? loader() : loader);
|
||
return paths2.map((userConfig) => {
|
||
const resolvedPath = route.replace(
|
||
dynamicRouteRE,
|
||
(_, key) => userConfig.params[key]
|
||
);
|
||
return {
|
||
path: resolvedPath,
|
||
fullPath: normalizePath(path$q.resolve(srcDir, resolvedPath)),
|
||
route,
|
||
...userConfig
|
||
};
|
||
});
|
||
};
|
||
pendingResolveRoutes.push(resolveRoute());
|
||
}
|
||
return {
|
||
routes: (await Promise.all(pendingResolveRoutes)).flat(),
|
||
fileToModulesMap: routeFileToModulesMap
|
||
};
|
||
}
|
||
|
||
const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i;
|
||
const APPEARANCE_KEY = "vitepress-theme-appearance";
|
||
const HASH_RE = /#.*$/;
|
||
const EXT_RE = /(index)?\.(md|html)$/;
|
||
const inBrowser = typeof document !== "undefined";
|
||
const notFoundPageData = {
|
||
relativePath: "",
|
||
filePath: "",
|
||
title: "404",
|
||
description: "Not Found",
|
||
headers: [],
|
||
frontmatter: { sidebar: false, layout: "page" },
|
||
lastUpdated: 0,
|
||
isNotFound: true
|
||
};
|
||
function isActive(currentPath, matchPath, asRegex = false) {
|
||
if (matchPath === void 0) {
|
||
return false;
|
||
}
|
||
currentPath = normalize$1(`/${currentPath}`);
|
||
if (asRegex) {
|
||
return new RegExp(matchPath).test(currentPath);
|
||
}
|
||
if (normalize$1(matchPath) !== currentPath) {
|
||
return false;
|
||
}
|
||
const hashMatch = matchPath.match(HASH_RE);
|
||
if (hashMatch) {
|
||
return (inBrowser ? location.hash : "") === hashMatch[0];
|
||
}
|
||
return true;
|
||
}
|
||
function normalize$1(path) {
|
||
return decodeURI(path).replace(HASH_RE, "").replace(EXT_RE, "");
|
||
}
|
||
function isExternal(path) {
|
||
return EXTERNAL_URL_RE.test(path);
|
||
}
|
||
function resolveSiteDataByRoute(siteData, relativePath) {
|
||
const localeIndex = Object.keys(siteData.locales).find(
|
||
(key) => key !== "root" && !isExternal(key) && isActive(relativePath, `/${key}/`, true)
|
||
) || "root";
|
||
return Object.assign({}, siteData, {
|
||
localeIndex,
|
||
lang: siteData.locales[localeIndex]?.lang ?? siteData.lang,
|
||
dir: siteData.locales[localeIndex]?.dir ?? siteData.dir,
|
||
title: siteData.locales[localeIndex]?.title ?? siteData.title,
|
||
titleTemplate: siteData.locales[localeIndex]?.titleTemplate ?? siteData.titleTemplate,
|
||
description: siteData.locales[localeIndex]?.description ?? siteData.description,
|
||
head: mergeHead(siteData.head, siteData.locales[localeIndex]?.head ?? []),
|
||
themeConfig: {
|
||
...siteData.themeConfig,
|
||
...siteData.locales[localeIndex]?.themeConfig
|
||
}
|
||
});
|
||
}
|
||
function createTitle(siteData, pageData) {
|
||
const title = pageData.title || siteData.title;
|
||
const template = pageData.titleTemplate ?? siteData.titleTemplate;
|
||
if (typeof template === "string" && template.includes(":title")) {
|
||
return template.replace(/:title/g, title);
|
||
}
|
||
const templateString = createTitleTemplate(siteData.title, template);
|
||
if (title === templateString.slice(3)) {
|
||
return title;
|
||
}
|
||
return `${title}${templateString}`;
|
||
}
|
||
function createTitleTemplate(siteTitle, template) {
|
||
if (template === false) {
|
||
return "";
|
||
}
|
||
if (template === true || template === void 0) {
|
||
return ` | ${siteTitle}`;
|
||
}
|
||
if (siteTitle === template) {
|
||
return "";
|
||
}
|
||
return ` | ${template}`;
|
||
}
|
||
function hasTag(head, tag) {
|
||
const [tagType, tagAttrs] = tag;
|
||
if (tagType !== "meta")
|
||
return false;
|
||
const keyAttr = Object.entries(tagAttrs)[0];
|
||
if (keyAttr == null)
|
||
return false;
|
||
return head.some(
|
||
([type, attrs]) => type === tagType && attrs[keyAttr[0]] === keyAttr[1]
|
||
);
|
||
}
|
||
function mergeHead(prev, curr) {
|
||
return [...prev.filter((tagAttrs) => !hasTag(curr, tagAttrs)), ...curr];
|
||
}
|
||
const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g;
|
||
const DRIVE_LETTER_REGEX = /^[a-z]:/i;
|
||
function sanitizeFileName(name) {
|
||
const match = DRIVE_LETTER_REGEX.exec(name);
|
||
const driveLetter = match ? match[0] : "";
|
||
return driveLetter + name.slice(driveLetter.length).replace(INVALID_CHAR_REGEX, "_").replace(/(^|\/)_+(?=[^/]*$)/, "$1");
|
||
}
|
||
function slash(p) {
|
||
return p.replace(/\\/g, "/");
|
||
}
|
||
const KNOWN_EXTENSIONS = new Set(
|
||
"3g2,3gp,7z,aac,abw,ai,aif,aifc,aiff,arc,asf,asr,asx,au,avi,avif,axs,azw,bin,bmp,bz,bz2,c,cda,cer,class,crl,crt,csh,css,csv,dcr,der,dll,doc,docx,eot,eps,epub,exe,gif,gtar,gz,gzip,ico,ics,ief,jar,jpe,jpeg,jpg,js,json,jsonld,latex,m3u,man,mdb,mht,mhtml,mid,midi,mjs,mov,mp2,mp3,mp4,mpa,mpe,mpeg,mpg,mpkg,mpp,odp,ods,odt,oga,ogv,ogx,opus,otf,p10,p12,p7b,p7c,p7m,p7r,p7s,pbm,pdf,pfx,php,png,ppt,pptx,ps,pub,qt,rar,roff,rtf,rtx,ser,sh,spc,svg,swf,t,tar,tcl,tex,texi,texinfo,tgz,tif,tiff,tr,ts,tsv,ttf,txt,ua,viv,vivo,vsd,wav,weba,webm,webp,woff,woff2,xbm,xhtml,xls,xlsx,xml,xul,zip".split(",")
|
||
);
|
||
function treatAsHtml(filename) {
|
||
const ext = filename.split(".").pop();
|
||
return ext == null || !KNOWN_EXTENSIONS.has(ext.toLowerCase());
|
||
}
|
||
function escapeRegExp$1(str) {
|
||
return str.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
|
||
}
|
||
|
||
const debug$4 = _debug("vitepress:config");
|
||
const resolve = (root, file) => normalizePath(path$q.resolve(root, `.vitepress`, file));
|
||
function defineConfig(config) {
|
||
return config;
|
||
}
|
||
function defineConfigWithTheme(config) {
|
||
return config;
|
||
}
|
||
async function resolveConfig(root = process.cwd(), command = "serve", mode = "development") {
|
||
root = normalizePath(path$q.resolve(root));
|
||
const [userConfig, configPath, configDeps] = await resolveUserConfig(
|
||
root,
|
||
command,
|
||
mode
|
||
);
|
||
const logger = userConfig.vite?.customLogger ?? createLogger(userConfig.vite?.logLevel, {
|
||
prefix: "[vitepress]",
|
||
allowClearScreen: userConfig.vite?.clearScreen
|
||
});
|
||
const site = await resolveSiteData(root, userConfig);
|
||
const srcDir = normalizePath(path$q.resolve(root, userConfig.srcDir || "."));
|
||
const assetsDir = userConfig.assetsDir ? slash(userConfig.assetsDir).replace(/^\.?\/|\/$/g, "") : "assets";
|
||
const outDir = userConfig.outDir ? normalizePath(path$q.resolve(root, userConfig.outDir)) : resolve(root, "dist");
|
||
const cacheDir = userConfig.cacheDir ? normalizePath(path$q.resolve(root, userConfig.cacheDir)) : resolve(root, "cache");
|
||
const resolvedAssetsDir = normalizePath(path$q.resolve(outDir, assetsDir));
|
||
if (!resolvedAssetsDir.startsWith(outDir)) {
|
||
throw new Error(
|
||
[
|
||
`assetsDir cannot be set to a location outside of the outDir.`,
|
||
`outDir: ${outDir}`,
|
||
`assetsDir: ${assetsDir}`,
|
||
`resolved: ${resolvedAssetsDir}`
|
||
].join("\n ")
|
||
);
|
||
}
|
||
const userThemeDir = resolve(root, "theme");
|
||
const themeDir = await fs$a.pathExists(userThemeDir) ? userThemeDir : DEFAULT_THEME_PATH;
|
||
const { pages, dynamicRoutes, rewrites } = await resolvePages(
|
||
srcDir,
|
||
userConfig,
|
||
logger
|
||
);
|
||
const config = {
|
||
root,
|
||
srcDir,
|
||
assetsDir,
|
||
site,
|
||
themeDir,
|
||
pages,
|
||
dynamicRoutes,
|
||
configPath,
|
||
configDeps,
|
||
outDir,
|
||
cacheDir,
|
||
logger,
|
||
tempDir: resolve(root, ".temp"),
|
||
markdown: userConfig.markdown,
|
||
lastUpdated: userConfig.lastUpdated ?? !!userConfig.themeConfig?.lastUpdated,
|
||
vue: userConfig.vue,
|
||
vite: userConfig.vite,
|
||
shouldPreload: userConfig.shouldPreload,
|
||
mpa: !!userConfig.mpa,
|
||
metaChunk: !!userConfig.metaChunk,
|
||
ignoreDeadLinks: userConfig.ignoreDeadLinks,
|
||
cleanUrls: !!userConfig.cleanUrls,
|
||
useWebFonts: userConfig.useWebFonts ?? typeof process.versions.webcontainer === "string",
|
||
postRender: userConfig.postRender,
|
||
buildEnd: userConfig.buildEnd,
|
||
transformHead: userConfig.transformHead,
|
||
transformHtml: userConfig.transformHtml,
|
||
transformPageData: userConfig.transformPageData,
|
||
rewrites,
|
||
userConfig,
|
||
sitemap: userConfig.sitemap,
|
||
buildConcurrency: userConfig.buildConcurrency ?? 64
|
||
};
|
||
global.VITEPRESS_CONFIG = config;
|
||
return config;
|
||
}
|
||
const supportedConfigExtensions = ["js", "ts", "mjs", "mts"];
|
||
async function resolveUserConfig(root, command, mode) {
|
||
const configPath = supportedConfigExtensions.flatMap((ext) => [
|
||
resolve(root, `config/index.${ext}`),
|
||
resolve(root, `config.${ext}`)
|
||
]).find(fs$a.pathExistsSync);
|
||
let userConfig = {};
|
||
let configDeps = [];
|
||
if (!configPath) {
|
||
debug$4(`no config file found.`);
|
||
} else {
|
||
const configExports = await loadConfigFromFile(
|
||
{ command, mode },
|
||
configPath,
|
||
root
|
||
);
|
||
if (configExports) {
|
||
userConfig = configExports.config;
|
||
configDeps = configExports.dependencies.map(
|
||
(file) => normalizePath(path$q.resolve(file))
|
||
);
|
||
}
|
||
debug$4(`loaded config at ${c$2.yellow(configPath)}`);
|
||
}
|
||
return [await resolveConfigExtends(userConfig), configPath, configDeps];
|
||
}
|
||
async function resolveConfigExtends(config) {
|
||
const resolved = await (typeof config === "function" ? config() : config);
|
||
if (resolved.extends) {
|
||
const base = await resolveConfigExtends(resolved.extends);
|
||
return mergeConfig(base, resolved);
|
||
}
|
||
return resolved;
|
||
}
|
||
function mergeConfig(a, b, isRoot = true) {
|
||
const merged = { ...a };
|
||
for (const key in b) {
|
||
const value = b[key];
|
||
if (value == null) {
|
||
continue;
|
||
}
|
||
const existing = merged[key];
|
||
if (Array.isArray(existing) && Array.isArray(value)) {
|
||
merged[key] = [...existing, ...value];
|
||
continue;
|
||
}
|
||
if (isObject$3(existing) && isObject$3(value)) {
|
||
if (isRoot && key === "vite") {
|
||
merged[key] = mergeConfig$1(existing, value);
|
||
} else {
|
||
merged[key] = mergeConfig(existing, value, false);
|
||
}
|
||
continue;
|
||
}
|
||
merged[key] = value;
|
||
}
|
||
return merged;
|
||
}
|
||
function isObject$3(value) {
|
||
return Object.prototype.toString.call(value) === "[object Object]";
|
||
}
|
||
async function resolveSiteData(root, userConfig, command = "serve", mode = "development") {
|
||
userConfig = userConfig || (await resolveUserConfig(root, command, mode))[0];
|
||
return {
|
||
lang: userConfig.lang || "en-US",
|
||
dir: userConfig.dir || "ltr",
|
||
title: userConfig.title || "VitePress",
|
||
titleTemplate: userConfig.titleTemplate,
|
||
description: userConfig.description || "A VitePress site",
|
||
base: userConfig.base ? userConfig.base.replace(/([^/])$/, "$1/") : "/",
|
||
head: resolveSiteDataHead(userConfig),
|
||
router: {
|
||
prefetchLinks: userConfig.router?.prefetchLinks ?? true
|
||
},
|
||
appearance: userConfig.appearance ?? true,
|
||
themeConfig: userConfig.themeConfig || {},
|
||
locales: userConfig.locales || {},
|
||
scrollOffset: userConfig.scrollOffset ?? 134,
|
||
cleanUrls: !!userConfig.cleanUrls,
|
||
contentProps: userConfig.contentProps
|
||
};
|
||
}
|
||
function resolveSiteDataHead(userConfig) {
|
||
const head = userConfig?.head ?? [];
|
||
if (userConfig?.appearance ?? true) {
|
||
const fallbackPreference = typeof userConfig?.appearance === "string" ? userConfig?.appearance : typeof userConfig?.appearance === "object" ? userConfig.appearance.initialValue ?? "auto" : "auto";
|
||
head.push([
|
||
"script",
|
||
{ id: "check-dark-mode" },
|
||
fallbackPreference === "force-dark" ? `document.documentElement.classList.add('dark')` : `;(() => {
|
||
const preference = localStorage.getItem('${APPEARANCE_KEY}') || '${fallbackPreference}'
|
||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
|
||
if (!preference || preference === 'auto' ? prefersDark : preference === 'dark')
|
||
document.documentElement.classList.add('dark')
|
||
})()`
|
||
]);
|
||
}
|
||
head.push([
|
||
"script",
|
||
{ id: "check-mac-os" },
|
||
`document.documentElement.classList.toggle('mac', /Mac|iPhone|iPod|iPad/i.test(navigator.platform))`
|
||
]);
|
||
return head;
|
||
}
|
||
|
||
const htmlEscapeMap = {
|
||
"&": "&",
|
||
"<": "<",
|
||
">": ">",
|
||
"'": "'",
|
||
'"': """
|
||
};
|
||
const htmlEscapeRegexp = /[&<>'"]/g;
|
||
const htmlEscape = (str) => str.replace(
|
||
htmlEscapeRegexp,
|
||
(char) => htmlEscapeMap[char]
|
||
);
|
||
|
||
const resolveTitleFromToken = (token, { shouldAllowHtml, shouldEscapeText }) => {
|
||
const children = token.children ?? [];
|
||
const titleTokenTypes = ["text", "emoji", "code_inline"];
|
||
if (shouldAllowHtml) {
|
||
titleTokenTypes.push("html_inline");
|
||
}
|
||
const titleTokens = children.filter(
|
||
(item) => titleTokenTypes.includes(item.type) && // filter permalink symbol that generated by markdown-it-anchor
|
||
!item.meta?.isPermalinkSymbol
|
||
);
|
||
return titleTokens.reduce((result, item) => {
|
||
if (shouldEscapeText) {
|
||
if (item.type === "code_inline" || item.type === "text") {
|
||
return `${result}${htmlEscape(item.content)}`;
|
||
}
|
||
}
|
||
return `${result}${item.content}`;
|
||
}, "").trim();
|
||
};
|
||
|
||
const resolveHeadersFromTokens = (tokens, {
|
||
level,
|
||
shouldAllowHtml,
|
||
shouldAllowNested,
|
||
shouldEscapeText,
|
||
slugify,
|
||
format
|
||
}) => {
|
||
const headers = [];
|
||
const stack = [];
|
||
const push = (header) => {
|
||
while (stack.length !== 0 && header.level <= stack[0].level) {
|
||
stack.shift();
|
||
}
|
||
if (stack.length === 0) {
|
||
headers.push(header);
|
||
stack.push(header);
|
||
} else {
|
||
stack[0].children.push(header);
|
||
stack.unshift(header);
|
||
}
|
||
};
|
||
for (let i = 0; i < tokens.length; i += 1) {
|
||
const token = tokens[i];
|
||
if (token?.type !== "heading_open") {
|
||
continue;
|
||
}
|
||
if (token?.level !== 0 && !shouldAllowNested) {
|
||
continue;
|
||
}
|
||
const headerLevel = Number.parseInt(token.tag.slice(1), 10);
|
||
if (!level.includes(headerLevel)) {
|
||
continue;
|
||
}
|
||
const nextToken = tokens[i + 1];
|
||
if (!nextToken) {
|
||
continue;
|
||
}
|
||
const title = resolveTitleFromToken(nextToken, {
|
||
shouldAllowHtml,
|
||
shouldEscapeText
|
||
});
|
||
const slug = token.attrGet("id") ?? slugify(title);
|
||
push({
|
||
level: headerLevel,
|
||
title: format?.(title) ?? title,
|
||
slug,
|
||
link: `#${slug}`,
|
||
children: []
|
||
});
|
||
}
|
||
return headers;
|
||
};
|
||
|
||
const rControl = /[\u0000-\u001f]/g;
|
||
const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'“”‘’<>,.?/]+/g;
|
||
const rCombining = /[\u0300-\u036F]/g;
|
||
const slugify = (str) => str.normalize("NFKD").replace(rCombining, "").replace(rControl, "").replace(rSpecial, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "").replace(/^(\d)/, "_$1").toLowerCase();
|
||
|
||
// List of valid html blocks names, according to commonmark spec
|
||
// https://spec.commonmark.org/0.30/#html-blocks
|
||
|
||
var block_names = [
|
||
'address',
|
||
'article',
|
||
'aside',
|
||
'base',
|
||
'basefont',
|
||
'blockquote',
|
||
'body',
|
||
'caption',
|
||
'center',
|
||
'col',
|
||
'colgroup',
|
||
'dd',
|
||
'details',
|
||
'dialog',
|
||
'dir',
|
||
'div',
|
||
'dl',
|
||
'dt',
|
||
'fieldset',
|
||
'figcaption',
|
||
'figure',
|
||
'footer',
|
||
'form',
|
||
'frame',
|
||
'frameset',
|
||
'h1',
|
||
'h2',
|
||
'h3',
|
||
'h4',
|
||
'h5',
|
||
'h6',
|
||
'head',
|
||
'header',
|
||
'hr',
|
||
'html',
|
||
'iframe',
|
||
'legend',
|
||
'li',
|
||
'link',
|
||
'main',
|
||
'menu',
|
||
'menuitem',
|
||
'nav',
|
||
'noframes',
|
||
'ol',
|
||
'optgroup',
|
||
'option',
|
||
'p',
|
||
'param',
|
||
'section',
|
||
'source',
|
||
'summary',
|
||
'table',
|
||
'tbody',
|
||
'td',
|
||
'tfoot',
|
||
'th',
|
||
'thead',
|
||
'title',
|
||
'tr',
|
||
'track',
|
||
'ul'
|
||
];
|
||
|
||
const attr_name$1 = "[a-zA-Z_:@][a-zA-Z0-9:._-]*";
|
||
const unquoted$1 = "[^\"'=<>`\\x00-\\x20]+";
|
||
const single_quoted$1 = "'[^']*'";
|
||
const double_quoted$1 = '"[^"]*"';
|
||
const attr_value$1 = "(?:" + unquoted$1 + "|" + single_quoted$1 + "|" + double_quoted$1 + ")";
|
||
const attribute$1 = "(?:\\s+" + attr_name$1 + "(?:\\s*=\\s*" + attr_value$1 + ")?)";
|
||
const open_tag$1 = "<[A-Za-z][A-Za-z0-9\\-]*" + attribute$1 + "*\\s*\\/?>";
|
||
const close_tag$1 = "<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>";
|
||
const comment$1 = "<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->";
|
||
const processing$1 = "<[?][\\s\\S]*?[?]>";
|
||
const declaration$1 = "<![A-Z]+\\s+[^>]*>";
|
||
const cdata$1 = "<!\\[CDATA\\[[\\s\\S]*?\\]\\]>";
|
||
const HTML_TAG_RE$1 = new RegExp(
|
||
"^(?:" + open_tag$1 + "|" + close_tag$1 + "|" + comment$1 + "|" + processing$1 + "|" + declaration$1 + "|" + cdata$1 + ")"
|
||
);
|
||
const HTML_OPEN_CLOSE_TAG_RE$1 = new RegExp(
|
||
"^(?:" + open_tag$1 + "|" + close_tag$1 + ")"
|
||
);
|
||
const HTML_SELF_CLOSING_TAG_RE = new RegExp(
|
||
"^<[A-Za-z][A-Za-z0-9\\-]*" + attribute$1 + "*\\s*\\/>"
|
||
);
|
||
const HTML_OPEN_AND_CLOSE_TAG_IN_THE_SAME_LINE_RE = new RegExp(
|
||
"^<([A-Za-z][A-Za-z0-9\\-]*)" + attribute$1 + "*\\s*>.*<\\/\\1\\s*>"
|
||
);
|
||
|
||
const TAGS_BLOCK = block_names;
|
||
const TAGS_INLINE = [
|
||
"a",
|
||
"abbr",
|
||
"acronym",
|
||
"audio",
|
||
"b",
|
||
"bdi",
|
||
"bdo",
|
||
"big",
|
||
"br",
|
||
"button",
|
||
"canvas",
|
||
"cite",
|
||
"code",
|
||
"data",
|
||
"datalist",
|
||
"del",
|
||
"dfn",
|
||
"em",
|
||
"embed",
|
||
"i",
|
||
"iframe",
|
||
"img",
|
||
"input",
|
||
"ins",
|
||
"kbd",
|
||
"label",
|
||
"map",
|
||
"mark",
|
||
"meter",
|
||
"noscript",
|
||
"object",
|
||
"output",
|
||
"picture",
|
||
"progress",
|
||
"q",
|
||
"ruby",
|
||
"s",
|
||
"samp",
|
||
"script",
|
||
"select",
|
||
"slot",
|
||
"small",
|
||
"span",
|
||
"strong",
|
||
"sub",
|
||
"sup",
|
||
"svg",
|
||
"template",
|
||
"textarea",
|
||
"time",
|
||
"u",
|
||
"tt",
|
||
"var",
|
||
"video",
|
||
"wbr"
|
||
];
|
||
const TAGS_VUE_RESERVED = [
|
||
"template",
|
||
"component",
|
||
"transition",
|
||
"transition-group",
|
||
"keep-alive",
|
||
"slot",
|
||
"teleport"
|
||
];
|
||
|
||
const createHtmlSequences = ({
|
||
blockTags,
|
||
inlineTags
|
||
}) => {
|
||
const forceBlockTags = [...blockTags, ...TAGS_BLOCK];
|
||
const forceInlineTags = [
|
||
...inlineTags,
|
||
...TAGS_INLINE.filter((item) => !TAGS_VUE_RESERVED.includes(item))
|
||
];
|
||
const HTML_SEQUENCES = [
|
||
[/^<(script|pre|style)(?=(\s|>|$))/i, /<\/(script|pre|style)>/i, true],
|
||
[/^<!--/, /-->/, true],
|
||
[/^<\?/, /\?>/, true],
|
||
[/^<![A-Z]/, />/, true],
|
||
[/^<!\[CDATA\[/, /\]\]>/, true],
|
||
// MODIFIED: Support extra block tags from user options
|
||
[
|
||
new RegExp("^</?(" + forceBlockTags.join("|") + ")(?=(\\s|/?>|$))", "i"),
|
||
/^$/,
|
||
true
|
||
],
|
||
// ADDED: Matching component tags (all unknown tags) (i = 6)
|
||
[
|
||
new RegExp(
|
||
"^</?(?!(" + forceInlineTags.join("|") + ")(?![\\w-]))[A-Za-z][A-Za-z0-9\\-]*(?=(\\s|/?>|$))"
|
||
),
|
||
/^$/,
|
||
true
|
||
],
|
||
// this line is to treat a line that only have a single self-closed html tag
|
||
// as html_block, even if it's a self-closed inline tag
|
||
// MODIFIED: Tweak the original HTML_OPEN_CLOSE_TAG_RE
|
||
[new RegExp(HTML_OPEN_CLOSE_TAG_RE$1.source + "\\s*$"), /^$/, false]
|
||
];
|
||
return HTML_SEQUENCES;
|
||
};
|
||
const createHtmlBlockRule = (options) => {
|
||
const HTML_SEQUENCES = createHtmlSequences(options);
|
||
return (state, startLine, endLine, silent) => {
|
||
let i;
|
||
let nextLine;
|
||
let lineText;
|
||
let pos = state.bMarks[startLine] + state.tShift[startLine];
|
||
let max = state.eMarks[startLine];
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) {
|
||
return false;
|
||
}
|
||
if (!state.md.options.html) {
|
||
return false;
|
||
}
|
||
if (state.src.charCodeAt(pos) !== 60) {
|
||
return false;
|
||
}
|
||
lineText = state.src.slice(pos, max);
|
||
for (i = 0; i < HTML_SEQUENCES.length; i++) {
|
||
if (HTML_SEQUENCES[i][0].test(lineText)) {
|
||
break;
|
||
}
|
||
}
|
||
if (i === HTML_SEQUENCES.length) {
|
||
return false;
|
||
}
|
||
if (silent) {
|
||
return HTML_SEQUENCES[i][2];
|
||
}
|
||
if (i === 6) {
|
||
const match = (
|
||
// if the component tag is self-closing
|
||
lineText.match(HTML_SELF_CLOSING_TAG_RE) ?? // or has open and close tag in the same line
|
||
lineText.match(HTML_OPEN_AND_CLOSE_TAG_IN_THE_SAME_LINE_RE)
|
||
);
|
||
if (match) {
|
||
state.line = startLine + 1;
|
||
let token2 = state.push("html_inline", "", 0);
|
||
token2.content = match[0];
|
||
token2.map = [startLine, state.line];
|
||
token2 = state.push("inline", "", 0);
|
||
token2.content = lineText.slice(match[0].length);
|
||
token2.map = [startLine, state.line];
|
||
token2.children = [];
|
||
return true;
|
||
}
|
||
}
|
||
nextLine = startLine + 1;
|
||
if (!HTML_SEQUENCES[i][1].test(lineText)) {
|
||
for (; nextLine < endLine; nextLine++) {
|
||
if (state.sCount[nextLine] < state.blkIndent) {
|
||
break;
|
||
}
|
||
pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
max = state.eMarks[nextLine];
|
||
lineText = state.src.slice(pos, max);
|
||
if (HTML_SEQUENCES[i][1].test(lineText)) {
|
||
if (lineText.length !== 0) {
|
||
nextLine++;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
state.line = nextLine;
|
||
const token = state.push("html_block", "", 0);
|
||
token.map = [startLine, nextLine];
|
||
token.content = state.getLines(startLine, nextLine, state.blkIndent, true);
|
||
return true;
|
||
};
|
||
};
|
||
|
||
const isLetter$1 = (ch) => {
|
||
const lc = ch | 32;
|
||
return lc >= 97 && lc <= 122;
|
||
};
|
||
const htmlInlineRule = (state, silent) => {
|
||
const { pos } = state;
|
||
if (!state.md.options.html) {
|
||
return false;
|
||
}
|
||
const max = state.posMax;
|
||
if (state.src.charCodeAt(pos) !== 60 || pos + 2 >= max) {
|
||
return false;
|
||
}
|
||
const ch = state.src.charCodeAt(pos + 1);
|
||
if (ch !== 33 && ch !== 63 && ch !== 47 && !isLetter$1(ch)) {
|
||
return false;
|
||
}
|
||
const match = state.src.slice(pos).match(HTML_TAG_RE$1);
|
||
if (!match) {
|
||
return false;
|
||
}
|
||
if (!silent) {
|
||
const token = state.push("html_inline", "", 0);
|
||
token.content = state.src.slice(pos, pos + match[0].length);
|
||
}
|
||
state.pos += match[0].length;
|
||
return true;
|
||
};
|
||
|
||
const componentPlugin = (md, { blockTags = [], inlineTags = [] } = {}) => {
|
||
const htmlBlockRule = createHtmlBlockRule({
|
||
blockTags,
|
||
inlineTags
|
||
});
|
||
md.block.ruler.at("html_block", htmlBlockRule, {
|
||
alt: ["paragraph", "reference", "blockquote"]
|
||
});
|
||
md.inline.ruler.at("html_inline", htmlInlineRule);
|
||
};
|
||
|
||
var toString$1 = Object.prototype.toString;
|
||
|
||
var kindOf = function kindOf(val) {
|
||
if (val === void 0) return 'undefined';
|
||
if (val === null) return 'null';
|
||
|
||
var type = typeof val;
|
||
if (type === 'boolean') return 'boolean';
|
||
if (type === 'string') return 'string';
|
||
if (type === 'number') return 'number';
|
||
if (type === 'symbol') return 'symbol';
|
||
if (type === 'function') {
|
||
return isGeneratorFn(val) ? 'generatorfunction' : 'function';
|
||
}
|
||
|
||
if (isArray$1(val)) return 'array';
|
||
if (isBuffer$1(val)) return 'buffer';
|
||
if (isArguments(val)) return 'arguments';
|
||
if (isDate(val)) return 'date';
|
||
if (isError(val)) return 'error';
|
||
if (isRegexp(val)) return 'regexp';
|
||
|
||
switch (ctorName(val)) {
|
||
case 'Symbol': return 'symbol';
|
||
case 'Promise': return 'promise';
|
||
|
||
// Set, Map, WeakSet, WeakMap
|
||
case 'WeakMap': return 'weakmap';
|
||
case 'WeakSet': return 'weakset';
|
||
case 'Map': return 'map';
|
||
case 'Set': return 'set';
|
||
|
||
// 8-bit typed arrays
|
||
case 'Int8Array': return 'int8array';
|
||
case 'Uint8Array': return 'uint8array';
|
||
case 'Uint8ClampedArray': return 'uint8clampedarray';
|
||
|
||
// 16-bit typed arrays
|
||
case 'Int16Array': return 'int16array';
|
||
case 'Uint16Array': return 'uint16array';
|
||
|
||
// 32-bit typed arrays
|
||
case 'Int32Array': return 'int32array';
|
||
case 'Uint32Array': return 'uint32array';
|
||
case 'Float32Array': return 'float32array';
|
||
case 'Float64Array': return 'float64array';
|
||
}
|
||
|
||
if (isGeneratorObj(val)) {
|
||
return 'generator';
|
||
}
|
||
|
||
// Non-plain objects
|
||
type = toString$1.call(val);
|
||
switch (type) {
|
||
case '[object Object]': return 'object';
|
||
// iterators
|
||
case '[object Map Iterator]': return 'mapiterator';
|
||
case '[object Set Iterator]': return 'setiterator';
|
||
case '[object String Iterator]': return 'stringiterator';
|
||
case '[object Array Iterator]': return 'arrayiterator';
|
||
}
|
||
|
||
// other
|
||
return type.slice(8, -1).toLowerCase().replace(/\s/g, '');
|
||
};
|
||
|
||
function ctorName(val) {
|
||
return typeof val.constructor === 'function' ? val.constructor.name : null;
|
||
}
|
||
|
||
function isArray$1(val) {
|
||
if (Array.isArray) return Array.isArray(val);
|
||
return val instanceof Array;
|
||
}
|
||
|
||
function isError(val) {
|
||
return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number');
|
||
}
|
||
|
||
function isDate(val) {
|
||
if (val instanceof Date) return true;
|
||
return typeof val.toDateString === 'function'
|
||
&& typeof val.getDate === 'function'
|
||
&& typeof val.setDate === 'function';
|
||
}
|
||
|
||
function isRegexp(val) {
|
||
if (val instanceof RegExp) return true;
|
||
return typeof val.flags === 'string'
|
||
&& typeof val.ignoreCase === 'boolean'
|
||
&& typeof val.multiline === 'boolean'
|
||
&& typeof val.global === 'boolean';
|
||
}
|
||
|
||
function isGeneratorFn(name, val) {
|
||
return ctorName(name) === 'GeneratorFunction';
|
||
}
|
||
|
||
function isGeneratorObj(val) {
|
||
return typeof val.throw === 'function'
|
||
&& typeof val.return === 'function'
|
||
&& typeof val.next === 'function';
|
||
}
|
||
|
||
function isArguments(val) {
|
||
try {
|
||
if (typeof val.length === 'number' && typeof val.callee === 'function') {
|
||
return true;
|
||
}
|
||
} catch (err) {
|
||
if (err.message.indexOf('callee') !== -1) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* If you need to support Safari 5-7 (8-10 yr-old browser),
|
||
* take a look at https://github.com/feross/is-buffer
|
||
*/
|
||
|
||
function isBuffer$1(val) {
|
||
if (val.constructor && typeof val.constructor.isBuffer === 'function') {
|
||
return val.constructor.isBuffer(val);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/*!
|
||
* is-extendable <https://github.com/jonschlinkert/is-extendable>
|
||
*
|
||
* Copyright (c) 2015, Jon Schlinkert.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
|
||
var isExtendable = function isExtendable(val) {
|
||
return typeof val !== 'undefined' && val !== null
|
||
&& (typeof val === 'object' || typeof val === 'function');
|
||
};
|
||
|
||
var isObject$2 = isExtendable;
|
||
|
||
var extendShallow = function extend(o/*, objects*/) {
|
||
if (!isObject$2(o)) { o = {}; }
|
||
|
||
var len = arguments.length;
|
||
for (var i = 1; i < len; i++) {
|
||
var obj = arguments[i];
|
||
|
||
if (isObject$2(obj)) {
|
||
assign$2(o, obj);
|
||
}
|
||
}
|
||
return o;
|
||
};
|
||
|
||
function assign$2(a, b) {
|
||
for (var key in b) {
|
||
if (hasOwn(b, key)) {
|
||
a[key] = b[key];
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Returns true if the given `key` is an own property of `obj`.
|
||
*/
|
||
|
||
function hasOwn(obj, key) {
|
||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||
}
|
||
|
||
var typeOf$2 = kindOf;
|
||
var extend$1 = extendShallow;
|
||
|
||
/**
|
||
* Parse sections in `input` with the given `options`.
|
||
*
|
||
* ```js
|
||
* var sections = require('{%= name %}');
|
||
* var result = sections(input, options);
|
||
* // { content: 'Content before sections', sections: [] }
|
||
* ```
|
||
* @param {String|Buffer|Object} `input` If input is an object, it's `content` property must be a string or buffer.
|
||
* @param {Object} options
|
||
* @return {Object} Returns an object with a `content` string and an array of `sections` objects.
|
||
* @api public
|
||
*/
|
||
|
||
var sectionMatter = function(input, options) {
|
||
if (typeof options === 'function') {
|
||
options = { parse: options };
|
||
}
|
||
|
||
var file = toObject(input);
|
||
var defaults = {section_delimiter: '---', parse: identity};
|
||
var opts = extend$1({}, defaults, options);
|
||
var delim = opts.section_delimiter;
|
||
var lines = file.content.split(/\r?\n/);
|
||
var sections = null;
|
||
var section = createSection();
|
||
var content = [];
|
||
var stack = [];
|
||
|
||
function initSections(val) {
|
||
file.content = val;
|
||
sections = [];
|
||
content = [];
|
||
}
|
||
|
||
function closeSection(val) {
|
||
if (stack.length) {
|
||
section.key = getKey(stack[0], delim);
|
||
section.content = val;
|
||
opts.parse(section, sections);
|
||
sections.push(section);
|
||
section = createSection();
|
||
content = [];
|
||
stack = [];
|
||
}
|
||
}
|
||
|
||
for (var i = 0; i < lines.length; i++) {
|
||
var line = lines[i];
|
||
var len = stack.length;
|
||
var ln = line.trim();
|
||
|
||
if (isDelimiter(ln, delim)) {
|
||
if (ln.length === 3 && i !== 0) {
|
||
if (len === 0 || len === 2) {
|
||
content.push(line);
|
||
continue;
|
||
}
|
||
stack.push(ln);
|
||
section.data = content.join('\n');
|
||
content = [];
|
||
continue;
|
||
}
|
||
|
||
if (sections === null) {
|
||
initSections(content.join('\n'));
|
||
}
|
||
|
||
if (len === 2) {
|
||
closeSection(content.join('\n'));
|
||
}
|
||
|
||
stack.push(ln);
|
||
continue;
|
||
}
|
||
|
||
content.push(line);
|
||
}
|
||
|
||
if (sections === null) {
|
||
initSections(content.join('\n'));
|
||
} else {
|
||
closeSection(content.join('\n'));
|
||
}
|
||
|
||
file.sections = sections;
|
||
return file;
|
||
};
|
||
|
||
function isDelimiter(line, delim) {
|
||
if (line.slice(0, delim.length) !== delim) {
|
||
return false;
|
||
}
|
||
if (line.charAt(delim.length + 1) === delim.slice(-1)) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
function toObject(input) {
|
||
if (typeOf$2(input) !== 'object') {
|
||
input = { content: input };
|
||
}
|
||
|
||
if (typeof input.content !== 'string' && !isBuffer(input.content)) {
|
||
throw new TypeError('expected a buffer or string');
|
||
}
|
||
|
||
input.content = input.content.toString();
|
||
input.sections = [];
|
||
return input;
|
||
}
|
||
|
||
function getKey(val, delim) {
|
||
return val ? val.slice(delim.length).trim() : '';
|
||
}
|
||
|
||
function createSection() {
|
||
return { key: '', data: '', content: '' };
|
||
}
|
||
|
||
function identity(val) {
|
||
return val;
|
||
}
|
||
|
||
function isBuffer(val) {
|
||
if (val && val.constructor && typeof val.constructor.isBuffer === 'function') {
|
||
return val.constructor.isBuffer(val);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
var engines$2 = {exports: {}};
|
||
|
||
var jsYaml$1 = {};
|
||
|
||
var loader$1 = {};
|
||
|
||
var common$6 = {};
|
||
|
||
function isNothing(subject) {
|
||
return (typeof subject === 'undefined') || (subject === null);
|
||
}
|
||
|
||
|
||
function isObject$1(subject) {
|
||
return (typeof subject === 'object') && (subject !== null);
|
||
}
|
||
|
||
|
||
function toArray(sequence) {
|
||
if (Array.isArray(sequence)) return sequence;
|
||
else if (isNothing(sequence)) return [];
|
||
|
||
return [ sequence ];
|
||
}
|
||
|
||
|
||
function extend(target, source) {
|
||
var index, length, key, sourceKeys;
|
||
|
||
if (source) {
|
||
sourceKeys = Object.keys(source);
|
||
|
||
for (index = 0, length = sourceKeys.length; index < length; index += 1) {
|
||
key = sourceKeys[index];
|
||
target[key] = source[key];
|
||
}
|
||
}
|
||
|
||
return target;
|
||
}
|
||
|
||
|
||
function repeat(string, count) {
|
||
var result = '', cycle;
|
||
|
||
for (cycle = 0; cycle < count; cycle += 1) {
|
||
result += string;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
function isNegativeZero(number) {
|
||
return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number);
|
||
}
|
||
|
||
|
||
common$6.isNothing = isNothing;
|
||
common$6.isObject = isObject$1;
|
||
common$6.toArray = toArray;
|
||
common$6.repeat = repeat;
|
||
common$6.isNegativeZero = isNegativeZero;
|
||
common$6.extend = extend;
|
||
|
||
function YAMLException$4(reason, mark) {
|
||
// Super constructor
|
||
Error.call(this);
|
||
|
||
this.name = 'YAMLException';
|
||
this.reason = reason;
|
||
this.mark = mark;
|
||
this.message = (this.reason || '(unknown reason)') + (this.mark ? ' ' + this.mark.toString() : '');
|
||
|
||
// Include stack trace in error object
|
||
if (Error.captureStackTrace) {
|
||
// Chrome and NodeJS
|
||
Error.captureStackTrace(this, this.constructor);
|
||
} else {
|
||
// FF, IE 10+ and Safari 6+. Fallback for others
|
||
this.stack = (new Error()).stack || '';
|
||
}
|
||
}
|
||
|
||
|
||
// Inherit from Error
|
||
YAMLException$4.prototype = Object.create(Error.prototype);
|
||
YAMLException$4.prototype.constructor = YAMLException$4;
|
||
|
||
|
||
YAMLException$4.prototype.toString = function toString(compact) {
|
||
var result = this.name + ': ';
|
||
|
||
result += this.reason || '(unknown reason)';
|
||
|
||
if (!compact && this.mark) {
|
||
result += ' ' + this.mark.toString();
|
||
}
|
||
|
||
return result;
|
||
};
|
||
|
||
|
||
var exception = YAMLException$4;
|
||
|
||
var common$5 = common$6;
|
||
|
||
|
||
function Mark$1(name, buffer, position, line, column) {
|
||
this.name = name;
|
||
this.buffer = buffer;
|
||
this.position = position;
|
||
this.line = line;
|
||
this.column = column;
|
||
}
|
||
|
||
|
||
Mark$1.prototype.getSnippet = function getSnippet(indent, maxLength) {
|
||
var head, start, tail, end, snippet;
|
||
|
||
if (!this.buffer) return null;
|
||
|
||
indent = indent || 4;
|
||
maxLength = maxLength || 75;
|
||
|
||
head = '';
|
||
start = this.position;
|
||
|
||
while (start > 0 && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(start - 1)) === -1) {
|
||
start -= 1;
|
||
if (this.position - start > (maxLength / 2 - 1)) {
|
||
head = ' ... ';
|
||
start += 5;
|
||
break;
|
||
}
|
||
}
|
||
|
||
tail = '';
|
||
end = this.position;
|
||
|
||
while (end < this.buffer.length && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(end)) === -1) {
|
||
end += 1;
|
||
if (end - this.position > (maxLength / 2 - 1)) {
|
||
tail = ' ... ';
|
||
end -= 5;
|
||
break;
|
||
}
|
||
}
|
||
|
||
snippet = this.buffer.slice(start, end);
|
||
|
||
return common$5.repeat(' ', indent) + head + snippet + tail + '\n' +
|
||
common$5.repeat(' ', indent + this.position - start + head.length) + '^';
|
||
};
|
||
|
||
|
||
Mark$1.prototype.toString = function toString(compact) {
|
||
var snippet, where = '';
|
||
|
||
if (this.name) {
|
||
where += 'in "' + this.name + '" ';
|
||
}
|
||
|
||
where += 'at line ' + (this.line + 1) + ', column ' + (this.column + 1);
|
||
|
||
if (!compact) {
|
||
snippet = this.getSnippet();
|
||
|
||
if (snippet) {
|
||
where += ':\n' + snippet;
|
||
}
|
||
}
|
||
|
||
return where;
|
||
};
|
||
|
||
|
||
var mark = Mark$1;
|
||
|
||
var YAMLException$3 = exception;
|
||
|
||
var TYPE_CONSTRUCTOR_OPTIONS = [
|
||
'kind',
|
||
'resolve',
|
||
'construct',
|
||
'instanceOf',
|
||
'predicate',
|
||
'represent',
|
||
'defaultStyle',
|
||
'styleAliases'
|
||
];
|
||
|
||
var YAML_NODE_KINDS = [
|
||
'scalar',
|
||
'sequence',
|
||
'mapping'
|
||
];
|
||
|
||
function compileStyleAliases(map) {
|
||
var result = {};
|
||
|
||
if (map !== null) {
|
||
Object.keys(map).forEach(function (style) {
|
||
map[style].forEach(function (alias) {
|
||
result[String(alias)] = style;
|
||
});
|
||
});
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
function Type$h(tag, options) {
|
||
options = options || {};
|
||
|
||
Object.keys(options).forEach(function (name) {
|
||
if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {
|
||
throw new YAMLException$3('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.');
|
||
}
|
||
});
|
||
|
||
// TODO: Add tag format check.
|
||
this.tag = tag;
|
||
this.kind = options['kind'] || null;
|
||
this.resolve = options['resolve'] || function () { return true; };
|
||
this.construct = options['construct'] || function (data) { return data; };
|
||
this.instanceOf = options['instanceOf'] || null;
|
||
this.predicate = options['predicate'] || null;
|
||
this.represent = options['represent'] || null;
|
||
this.defaultStyle = options['defaultStyle'] || null;
|
||
this.styleAliases = compileStyleAliases(options['styleAliases'] || null);
|
||
|
||
if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {
|
||
throw new YAMLException$3('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.');
|
||
}
|
||
}
|
||
|
||
var type = Type$h;
|
||
|
||
/*eslint-disable max-len*/
|
||
|
||
var common$4 = common$6;
|
||
var YAMLException$2 = exception;
|
||
var Type$g = type;
|
||
|
||
|
||
function compileList(schema, name, result) {
|
||
var exclude = [];
|
||
|
||
schema.include.forEach(function (includedSchema) {
|
||
result = compileList(includedSchema, name, result);
|
||
});
|
||
|
||
schema[name].forEach(function (currentType) {
|
||
result.forEach(function (previousType, previousIndex) {
|
||
if (previousType.tag === currentType.tag && previousType.kind === currentType.kind) {
|
||
exclude.push(previousIndex);
|
||
}
|
||
});
|
||
|
||
result.push(currentType);
|
||
});
|
||
|
||
return result.filter(function (type, index) {
|
||
return exclude.indexOf(index) === -1;
|
||
});
|
||
}
|
||
|
||
|
||
function compileMap(/* lists... */) {
|
||
var result = {
|
||
scalar: {},
|
||
sequence: {},
|
||
mapping: {},
|
||
fallback: {}
|
||
}, index, length;
|
||
|
||
function collectType(type) {
|
||
result[type.kind][type.tag] = result['fallback'][type.tag] = type;
|
||
}
|
||
|
||
for (index = 0, length = arguments.length; index < length; index += 1) {
|
||
arguments[index].forEach(collectType);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
|
||
function Schema$5(definition) {
|
||
this.include = definition.include || [];
|
||
this.implicit = definition.implicit || [];
|
||
this.explicit = definition.explicit || [];
|
||
|
||
this.implicit.forEach(function (type) {
|
||
if (type.loadKind && type.loadKind !== 'scalar') {
|
||
throw new YAMLException$2('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.');
|
||
}
|
||
});
|
||
|
||
this.compiledImplicit = compileList(this, 'implicit', []);
|
||
this.compiledExplicit = compileList(this, 'explicit', []);
|
||
this.compiledTypeMap = compileMap(this.compiledImplicit, this.compiledExplicit);
|
||
}
|
||
|
||
|
||
Schema$5.DEFAULT = null;
|
||
|
||
|
||
Schema$5.create = function createSchema() {
|
||
var schemas, types;
|
||
|
||
switch (arguments.length) {
|
||
case 1:
|
||
schemas = Schema$5.DEFAULT;
|
||
types = arguments[0];
|
||
break;
|
||
|
||
case 2:
|
||
schemas = arguments[0];
|
||
types = arguments[1];
|
||
break;
|
||
|
||
default:
|
||
throw new YAMLException$2('Wrong number of arguments for Schema.create function');
|
||
}
|
||
|
||
schemas = common$4.toArray(schemas);
|
||
types = common$4.toArray(types);
|
||
|
||
if (!schemas.every(function (schema) { return schema instanceof Schema$5; })) {
|
||
throw new YAMLException$2('Specified list of super schemas (or a single Schema object) contains a non-Schema object.');
|
||
}
|
||
|
||
if (!types.every(function (type) { return type instanceof Type$g; })) {
|
||
throw new YAMLException$2('Specified list of YAML types (or a single Type object) contains a non-Type object.');
|
||
}
|
||
|
||
return new Schema$5({
|
||
include: schemas,
|
||
explicit: types
|
||
});
|
||
};
|
||
|
||
|
||
var schema = Schema$5;
|
||
|
||
var Type$f = type;
|
||
|
||
var str = new Type$f('tag:yaml.org,2002:str', {
|
||
kind: 'scalar',
|
||
construct: function (data) { return data !== null ? data : ''; }
|
||
});
|
||
|
||
var Type$e = type;
|
||
|
||
var seq = new Type$e('tag:yaml.org,2002:seq', {
|
||
kind: 'sequence',
|
||
construct: function (data) { return data !== null ? data : []; }
|
||
});
|
||
|
||
var Type$d = type;
|
||
|
||
var map$2 = new Type$d('tag:yaml.org,2002:map', {
|
||
kind: 'mapping',
|
||
construct: function (data) { return data !== null ? data : {}; }
|
||
});
|
||
|
||
var Schema$4 = schema;
|
||
|
||
|
||
var failsafe = new Schema$4({
|
||
explicit: [
|
||
str,
|
||
seq,
|
||
map$2
|
||
]
|
||
});
|
||
|
||
var Type$c = type;
|
||
|
||
function resolveYamlNull(data) {
|
||
if (data === null) return true;
|
||
|
||
var max = data.length;
|
||
|
||
return (max === 1 && data === '~') ||
|
||
(max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'));
|
||
}
|
||
|
||
function constructYamlNull() {
|
||
return null;
|
||
}
|
||
|
||
function isNull(object) {
|
||
return object === null;
|
||
}
|
||
|
||
var _null = new Type$c('tag:yaml.org,2002:null', {
|
||
kind: 'scalar',
|
||
resolve: resolveYamlNull,
|
||
construct: constructYamlNull,
|
||
predicate: isNull,
|
||
represent: {
|
||
canonical: function () { return '~'; },
|
||
lowercase: function () { return 'null'; },
|
||
uppercase: function () { return 'NULL'; },
|
||
camelcase: function () { return 'Null'; }
|
||
},
|
||
defaultStyle: 'lowercase'
|
||
});
|
||
|
||
var Type$b = type;
|
||
|
||
function resolveYamlBoolean(data) {
|
||
if (data === null) return false;
|
||
|
||
var max = data.length;
|
||
|
||
return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||
|
||
(max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'));
|
||
}
|
||
|
||
function constructYamlBoolean(data) {
|
||
return data === 'true' ||
|
||
data === 'True' ||
|
||
data === 'TRUE';
|
||
}
|
||
|
||
function isBoolean(object) {
|
||
return Object.prototype.toString.call(object) === '[object Boolean]';
|
||
}
|
||
|
||
var bool = new Type$b('tag:yaml.org,2002:bool', {
|
||
kind: 'scalar',
|
||
resolve: resolveYamlBoolean,
|
||
construct: constructYamlBoolean,
|
||
predicate: isBoolean,
|
||
represent: {
|
||
lowercase: function (object) { return object ? 'true' : 'false'; },
|
||
uppercase: function (object) { return object ? 'TRUE' : 'FALSE'; },
|
||
camelcase: function (object) { return object ? 'True' : 'False'; }
|
||
},
|
||
defaultStyle: 'lowercase'
|
||
});
|
||
|
||
var common$3 = common$6;
|
||
var Type$a = type;
|
||
|
||
function isHexCode(c) {
|
||
return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) ||
|
||
((0x41/* A */ <= c) && (c <= 0x46/* F */)) ||
|
||
((0x61/* a */ <= c) && (c <= 0x66/* f */));
|
||
}
|
||
|
||
function isOctCode(c) {
|
||
return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */));
|
||
}
|
||
|
||
function isDecCode(c) {
|
||
return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */));
|
||
}
|
||
|
||
function resolveYamlInteger(data) {
|
||
if (data === null) return false;
|
||
|
||
var max = data.length,
|
||
index = 0,
|
||
hasDigits = false,
|
||
ch;
|
||
|
||
if (!max) return false;
|
||
|
||
ch = data[index];
|
||
|
||
// sign
|
||
if (ch === '-' || ch === '+') {
|
||
ch = data[++index];
|
||
}
|
||
|
||
if (ch === '0') {
|
||
// 0
|
||
if (index + 1 === max) return true;
|
||
ch = data[++index];
|
||
|
||
// base 2, base 8, base 16
|
||
|
||
if (ch === 'b') {
|
||
// base 2
|
||
index++;
|
||
|
||
for (; index < max; index++) {
|
||
ch = data[index];
|
||
if (ch === '_') continue;
|
||
if (ch !== '0' && ch !== '1') return false;
|
||
hasDigits = true;
|
||
}
|
||
return hasDigits && ch !== '_';
|
||
}
|
||
|
||
|
||
if (ch === 'x') {
|
||
// base 16
|
||
index++;
|
||
|
||
for (; index < max; index++) {
|
||
ch = data[index];
|
||
if (ch === '_') continue;
|
||
if (!isHexCode(data.charCodeAt(index))) return false;
|
||
hasDigits = true;
|
||
}
|
||
return hasDigits && ch !== '_';
|
||
}
|
||
|
||
// base 8
|
||
for (; index < max; index++) {
|
||
ch = data[index];
|
||
if (ch === '_') continue;
|
||
if (!isOctCode(data.charCodeAt(index))) return false;
|
||
hasDigits = true;
|
||
}
|
||
return hasDigits && ch !== '_';
|
||
}
|
||
|
||
// base 10 (except 0) or base 60
|
||
|
||
// value should not start with `_`;
|
||
if (ch === '_') return false;
|
||
|
||
for (; index < max; index++) {
|
||
ch = data[index];
|
||
if (ch === '_') continue;
|
||
if (ch === ':') break;
|
||
if (!isDecCode(data.charCodeAt(index))) {
|
||
return false;
|
||
}
|
||
hasDigits = true;
|
||
}
|
||
|
||
// Should have digits and should not end with `_`
|
||
if (!hasDigits || ch === '_') return false;
|
||
|
||
// if !base60 - done;
|
||
if (ch !== ':') return true;
|
||
|
||
// base60 almost not used, no needs to optimize
|
||
return /^(:[0-5]?[0-9])+$/.test(data.slice(index));
|
||
}
|
||
|
||
function constructYamlInteger(data) {
|
||
var value = data, sign = 1, ch, base, digits = [];
|
||
|
||
if (value.indexOf('_') !== -1) {
|
||
value = value.replace(/_/g, '');
|
||
}
|
||
|
||
ch = value[0];
|
||
|
||
if (ch === '-' || ch === '+') {
|
||
if (ch === '-') sign = -1;
|
||
value = value.slice(1);
|
||
ch = value[0];
|
||
}
|
||
|
||
if (value === '0') return 0;
|
||
|
||
if (ch === '0') {
|
||
if (value[1] === 'b') return sign * parseInt(value.slice(2), 2);
|
||
if (value[1] === 'x') return sign * parseInt(value, 16);
|
||
return sign * parseInt(value, 8);
|
||
}
|
||
|
||
if (value.indexOf(':') !== -1) {
|
||
value.split(':').forEach(function (v) {
|
||
digits.unshift(parseInt(v, 10));
|
||
});
|
||
|
||
value = 0;
|
||
base = 1;
|
||
|
||
digits.forEach(function (d) {
|
||
value += (d * base);
|
||
base *= 60;
|
||
});
|
||
|
||
return sign * value;
|
||
|
||
}
|
||
|
||
return sign * parseInt(value, 10);
|
||
}
|
||
|
||
function isInteger(object) {
|
||
return (Object.prototype.toString.call(object)) === '[object Number]' &&
|
||
(object % 1 === 0 && !common$3.isNegativeZero(object));
|
||
}
|
||
|
||
var int = new Type$a('tag:yaml.org,2002:int', {
|
||
kind: 'scalar',
|
||
resolve: resolveYamlInteger,
|
||
construct: constructYamlInteger,
|
||
predicate: isInteger,
|
||
represent: {
|
||
binary: function (obj) { return obj >= 0 ? '0b' + obj.toString(2) : '-0b' + obj.toString(2).slice(1); },
|
||
octal: function (obj) { return obj >= 0 ? '0' + obj.toString(8) : '-0' + obj.toString(8).slice(1); },
|
||
decimal: function (obj) { return obj.toString(10); },
|
||
/* eslint-disable max-len */
|
||
hexadecimal: function (obj) { return obj >= 0 ? '0x' + obj.toString(16).toUpperCase() : '-0x' + obj.toString(16).toUpperCase().slice(1); }
|
||
},
|
||
defaultStyle: 'decimal',
|
||
styleAliases: {
|
||
binary: [ 2, 'bin' ],
|
||
octal: [ 8, 'oct' ],
|
||
decimal: [ 10, 'dec' ],
|
||
hexadecimal: [ 16, 'hex' ]
|
||
}
|
||
});
|
||
|
||
var common$2 = common$6;
|
||
var Type$9 = type;
|
||
|
||
var YAML_FLOAT_PATTERN = new RegExp(
|
||
// 2.5e4, 2.5 and integers
|
||
'^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?' +
|
||
// .2e4, .2
|
||
// special case, seems not from spec
|
||
'|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?' +
|
||
// 20:59
|
||
'|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*' +
|
||
// .inf
|
||
'|[-+]?\\.(?:inf|Inf|INF)' +
|
||
// .nan
|
||
'|\\.(?:nan|NaN|NAN))$');
|
||
|
||
function resolveYamlFloat(data) {
|
||
if (data === null) return false;
|
||
|
||
if (!YAML_FLOAT_PATTERN.test(data) ||
|
||
// Quick hack to not allow integers end with `_`
|
||
// Probably should update regexp & check speed
|
||
data[data.length - 1] === '_') {
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
function constructYamlFloat(data) {
|
||
var value, sign, base, digits;
|
||
|
||
value = data.replace(/_/g, '').toLowerCase();
|
||
sign = value[0] === '-' ? -1 : 1;
|
||
digits = [];
|
||
|
||
if ('+-'.indexOf(value[0]) >= 0) {
|
||
value = value.slice(1);
|
||
}
|
||
|
||
if (value === '.inf') {
|
||
return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
|
||
|
||
} else if (value === '.nan') {
|
||
return NaN;
|
||
|
||
} else if (value.indexOf(':') >= 0) {
|
||
value.split(':').forEach(function (v) {
|
||
digits.unshift(parseFloat(v, 10));
|
||
});
|
||
|
||
value = 0.0;
|
||
base = 1;
|
||
|
||
digits.forEach(function (d) {
|
||
value += d * base;
|
||
base *= 60;
|
||
});
|
||
|
||
return sign * value;
|
||
|
||
}
|
||
return sign * parseFloat(value, 10);
|
||
}
|
||
|
||
|
||
var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;
|
||
|
||
function representYamlFloat(object, style) {
|
||
var res;
|
||
|
||
if (isNaN(object)) {
|
||
switch (style) {
|
||
case 'lowercase': return '.nan';
|
||
case 'uppercase': return '.NAN';
|
||
case 'camelcase': return '.NaN';
|
||
}
|
||
} else if (Number.POSITIVE_INFINITY === object) {
|
||
switch (style) {
|
||
case 'lowercase': return '.inf';
|
||
case 'uppercase': return '.INF';
|
||
case 'camelcase': return '.Inf';
|
||
}
|
||
} else if (Number.NEGATIVE_INFINITY === object) {
|
||
switch (style) {
|
||
case 'lowercase': return '-.inf';
|
||
case 'uppercase': return '-.INF';
|
||
case 'camelcase': return '-.Inf';
|
||
}
|
||
} else if (common$2.isNegativeZero(object)) {
|
||
return '-0.0';
|
||
}
|
||
|
||
res = object.toString(10);
|
||
|
||
// JS stringifier can build scientific format without dots: 5e-100,
|
||
// while YAML requres dot: 5.e-100. Fix it with simple hack
|
||
|
||
return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res;
|
||
}
|
||
|
||
function isFloat(object) {
|
||
return (Object.prototype.toString.call(object) === '[object Number]') &&
|
||
(object % 1 !== 0 || common$2.isNegativeZero(object));
|
||
}
|
||
|
||
var float = new Type$9('tag:yaml.org,2002:float', {
|
||
kind: 'scalar',
|
||
resolve: resolveYamlFloat,
|
||
construct: constructYamlFloat,
|
||
predicate: isFloat,
|
||
represent: representYamlFloat,
|
||
defaultStyle: 'lowercase'
|
||
});
|
||
|
||
var Schema$3 = schema;
|
||
|
||
|
||
var json = new Schema$3({
|
||
include: [
|
||
failsafe
|
||
],
|
||
implicit: [
|
||
_null,
|
||
bool,
|
||
int,
|
||
float
|
||
]
|
||
});
|
||
|
||
var Schema$2 = schema;
|
||
|
||
|
||
var core$1 = new Schema$2({
|
||
include: [
|
||
json
|
||
]
|
||
});
|
||
|
||
var Type$8 = type;
|
||
|
||
var YAML_DATE_REGEXP = new RegExp(
|
||
'^([0-9][0-9][0-9][0-9])' + // [1] year
|
||
'-([0-9][0-9])' + // [2] month
|
||
'-([0-9][0-9])$'); // [3] day
|
||
|
||
var YAML_TIMESTAMP_REGEXP = new RegExp(
|
||
'^([0-9][0-9][0-9][0-9])' + // [1] year
|
||
'-([0-9][0-9]?)' + // [2] month
|
||
'-([0-9][0-9]?)' + // [3] day
|
||
'(?:[Tt]|[ \\t]+)' + // ...
|
||
'([0-9][0-9]?)' + // [4] hour
|
||
':([0-9][0-9])' + // [5] minute
|
||
':([0-9][0-9])' + // [6] second
|
||
'(?:\\.([0-9]*))?' + // [7] fraction
|
||
'(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tz_hour
|
||
'(?::([0-9][0-9]))?))?$'); // [11] tz_minute
|
||
|
||
function resolveYamlTimestamp(data) {
|
||
if (data === null) return false;
|
||
if (YAML_DATE_REGEXP.exec(data) !== null) return true;
|
||
if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;
|
||
return false;
|
||
}
|
||
|
||
function constructYamlTimestamp(data) {
|
||
var match, year, month, day, hour, minute, second, fraction = 0,
|
||
delta = null, tz_hour, tz_minute, date;
|
||
|
||
match = YAML_DATE_REGEXP.exec(data);
|
||
if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);
|
||
|
||
if (match === null) throw new Error('Date resolve error');
|
||
|
||
// match: [1] year [2] month [3] day
|
||
|
||
year = +(match[1]);
|
||
month = +(match[2]) - 1; // JS month starts with 0
|
||
day = +(match[3]);
|
||
|
||
if (!match[4]) { // no hour
|
||
return new Date(Date.UTC(year, month, day));
|
||
}
|
||
|
||
// match: [4] hour [5] minute [6] second [7] fraction
|
||
|
||
hour = +(match[4]);
|
||
minute = +(match[5]);
|
||
second = +(match[6]);
|
||
|
||
if (match[7]) {
|
||
fraction = match[7].slice(0, 3);
|
||
while (fraction.length < 3) { // milli-seconds
|
||
fraction += '0';
|
||
}
|
||
fraction = +fraction;
|
||
}
|
||
|
||
// match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute
|
||
|
||
if (match[9]) {
|
||
tz_hour = +(match[10]);
|
||
tz_minute = +(match[11] || 0);
|
||
delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds
|
||
if (match[9] === '-') delta = -delta;
|
||
}
|
||
|
||
date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction));
|
||
|
||
if (delta) date.setTime(date.getTime() - delta);
|
||
|
||
return date;
|
||
}
|
||
|
||
function representYamlTimestamp(object /*, style*/) {
|
||
return object.toISOString();
|
||
}
|
||
|
||
var timestamp = new Type$8('tag:yaml.org,2002:timestamp', {
|
||
kind: 'scalar',
|
||
resolve: resolveYamlTimestamp,
|
||
construct: constructYamlTimestamp,
|
||
instanceOf: Date,
|
||
represent: representYamlTimestamp
|
||
});
|
||
|
||
var Type$7 = type;
|
||
|
||
function resolveYamlMerge(data) {
|
||
return data === '<<' || data === null;
|
||
}
|
||
|
||
var merge = new Type$7('tag:yaml.org,2002:merge', {
|
||
kind: 'scalar',
|
||
resolve: resolveYamlMerge
|
||
});
|
||
|
||
function commonjsRequire(path) {
|
||
throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
|
||
}
|
||
|
||
/*eslint-disable no-bitwise*/
|
||
|
||
var NodeBuffer;
|
||
|
||
try {
|
||
// A trick for browserified version, to not include `Buffer` shim
|
||
var _require$1 = commonjsRequire;
|
||
NodeBuffer = _require$1('buffer').Buffer;
|
||
} catch (__) {}
|
||
|
||
var Type$6 = type;
|
||
|
||
|
||
// [ 64, 65, 66 ] -> [ padding, CR, LF ]
|
||
var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r';
|
||
|
||
|
||
function resolveYamlBinary(data) {
|
||
if (data === null) return false;
|
||
|
||
var code, idx, bitlen = 0, max = data.length, map = BASE64_MAP;
|
||
|
||
// Convert one by one.
|
||
for (idx = 0; idx < max; idx++) {
|
||
code = map.indexOf(data.charAt(idx));
|
||
|
||
// Skip CR/LF
|
||
if (code > 64) continue;
|
||
|
||
// Fail on illegal characters
|
||
if (code < 0) return false;
|
||
|
||
bitlen += 6;
|
||
}
|
||
|
||
// If there are any bits left, source was corrupted
|
||
return (bitlen % 8) === 0;
|
||
}
|
||
|
||
function constructYamlBinary(data) {
|
||
var idx, tailbits,
|
||
input = data.replace(/[\r\n=]/g, ''), // remove CR/LF & padding to simplify scan
|
||
max = input.length,
|
||
map = BASE64_MAP,
|
||
bits = 0,
|
||
result = [];
|
||
|
||
// Collect by 6*4 bits (3 bytes)
|
||
|
||
for (idx = 0; idx < max; idx++) {
|
||
if ((idx % 4 === 0) && idx) {
|
||
result.push((bits >> 16) & 0xFF);
|
||
result.push((bits >> 8) & 0xFF);
|
||
result.push(bits & 0xFF);
|
||
}
|
||
|
||
bits = (bits << 6) | map.indexOf(input.charAt(idx));
|
||
}
|
||
|
||
// Dump tail
|
||
|
||
tailbits = (max % 4) * 6;
|
||
|
||
if (tailbits === 0) {
|
||
result.push((bits >> 16) & 0xFF);
|
||
result.push((bits >> 8) & 0xFF);
|
||
result.push(bits & 0xFF);
|
||
} else if (tailbits === 18) {
|
||
result.push((bits >> 10) & 0xFF);
|
||
result.push((bits >> 2) & 0xFF);
|
||
} else if (tailbits === 12) {
|
||
result.push((bits >> 4) & 0xFF);
|
||
}
|
||
|
||
// Wrap into Buffer for NodeJS and leave Array for browser
|
||
if (NodeBuffer) {
|
||
// Support node 6.+ Buffer API when available
|
||
return NodeBuffer.from ? NodeBuffer.from(result) : new NodeBuffer(result);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
function representYamlBinary(object /*, style*/) {
|
||
var result = '', bits = 0, idx, tail,
|
||
max = object.length,
|
||
map = BASE64_MAP;
|
||
|
||
// Convert every three bytes to 4 ASCII characters.
|
||
|
||
for (idx = 0; idx < max; idx++) {
|
||
if ((idx % 3 === 0) && idx) {
|
||
result += map[(bits >> 18) & 0x3F];
|
||
result += map[(bits >> 12) & 0x3F];
|
||
result += map[(bits >> 6) & 0x3F];
|
||
result += map[bits & 0x3F];
|
||
}
|
||
|
||
bits = (bits << 8) + object[idx];
|
||
}
|
||
|
||
// Dump tail
|
||
|
||
tail = max % 3;
|
||
|
||
if (tail === 0) {
|
||
result += map[(bits >> 18) & 0x3F];
|
||
result += map[(bits >> 12) & 0x3F];
|
||
result += map[(bits >> 6) & 0x3F];
|
||
result += map[bits & 0x3F];
|
||
} else if (tail === 2) {
|
||
result += map[(bits >> 10) & 0x3F];
|
||
result += map[(bits >> 4) & 0x3F];
|
||
result += map[(bits << 2) & 0x3F];
|
||
result += map[64];
|
||
} else if (tail === 1) {
|
||
result += map[(bits >> 2) & 0x3F];
|
||
result += map[(bits << 4) & 0x3F];
|
||
result += map[64];
|
||
result += map[64];
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
function isBinary(object) {
|
||
return NodeBuffer && NodeBuffer.isBuffer(object);
|
||
}
|
||
|
||
var binary$1 = new Type$6('tag:yaml.org,2002:binary', {
|
||
kind: 'scalar',
|
||
resolve: resolveYamlBinary,
|
||
construct: constructYamlBinary,
|
||
predicate: isBinary,
|
||
represent: representYamlBinary
|
||
});
|
||
|
||
var Type$5 = type;
|
||
|
||
var _hasOwnProperty$4 = Object.prototype.hasOwnProperty;
|
||
var _toString$2 = Object.prototype.toString;
|
||
|
||
function resolveYamlOmap(data) {
|
||
if (data === null) return true;
|
||
|
||
var objectKeys = [], index, length, pair, pairKey, pairHasKey,
|
||
object = data;
|
||
|
||
for (index = 0, length = object.length; index < length; index += 1) {
|
||
pair = object[index];
|
||
pairHasKey = false;
|
||
|
||
if (_toString$2.call(pair) !== '[object Object]') return false;
|
||
|
||
for (pairKey in pair) {
|
||
if (_hasOwnProperty$4.call(pair, pairKey)) {
|
||
if (!pairHasKey) pairHasKey = true;
|
||
else return false;
|
||
}
|
||
}
|
||
|
||
if (!pairHasKey) return false;
|
||
|
||
if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey);
|
||
else return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
function constructYamlOmap(data) {
|
||
return data !== null ? data : [];
|
||
}
|
||
|
||
var omap = new Type$5('tag:yaml.org,2002:omap', {
|
||
kind: 'sequence',
|
||
resolve: resolveYamlOmap,
|
||
construct: constructYamlOmap
|
||
});
|
||
|
||
var Type$4 = type;
|
||
|
||
var _toString$1 = Object.prototype.toString;
|
||
|
||
function resolveYamlPairs(data) {
|
||
if (data === null) return true;
|
||
|
||
var index, length, pair, keys, result,
|
||
object = data;
|
||
|
||
result = new Array(object.length);
|
||
|
||
for (index = 0, length = object.length; index < length; index += 1) {
|
||
pair = object[index];
|
||
|
||
if (_toString$1.call(pair) !== '[object Object]') return false;
|
||
|
||
keys = Object.keys(pair);
|
||
|
||
if (keys.length !== 1) return false;
|
||
|
||
result[index] = [ keys[0], pair[keys[0]] ];
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
function constructYamlPairs(data) {
|
||
if (data === null) return [];
|
||
|
||
var index, length, pair, keys, result,
|
||
object = data;
|
||
|
||
result = new Array(object.length);
|
||
|
||
for (index = 0, length = object.length; index < length; index += 1) {
|
||
pair = object[index];
|
||
|
||
keys = Object.keys(pair);
|
||
|
||
result[index] = [ keys[0], pair[keys[0]] ];
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
var pairs = new Type$4('tag:yaml.org,2002:pairs', {
|
||
kind: 'sequence',
|
||
resolve: resolveYamlPairs,
|
||
construct: constructYamlPairs
|
||
});
|
||
|
||
var Type$3 = type;
|
||
|
||
var _hasOwnProperty$3 = Object.prototype.hasOwnProperty;
|
||
|
||
function resolveYamlSet(data) {
|
||
if (data === null) return true;
|
||
|
||
var key, object = data;
|
||
|
||
for (key in object) {
|
||
if (_hasOwnProperty$3.call(object, key)) {
|
||
if (object[key] !== null) return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
function constructYamlSet(data) {
|
||
return data !== null ? data : {};
|
||
}
|
||
|
||
var set = new Type$3('tag:yaml.org,2002:set', {
|
||
kind: 'mapping',
|
||
resolve: resolveYamlSet,
|
||
construct: constructYamlSet
|
||
});
|
||
|
||
var Schema$1 = schema;
|
||
|
||
|
||
var default_safe = new Schema$1({
|
||
include: [
|
||
core$1
|
||
],
|
||
implicit: [
|
||
timestamp,
|
||
merge
|
||
],
|
||
explicit: [
|
||
binary$1,
|
||
omap,
|
||
pairs,
|
||
set
|
||
]
|
||
});
|
||
|
||
var Type$2 = type;
|
||
|
||
function resolveJavascriptUndefined() {
|
||
return true;
|
||
}
|
||
|
||
function constructJavascriptUndefined() {
|
||
/*eslint-disable no-undefined*/
|
||
return undefined;
|
||
}
|
||
|
||
function representJavascriptUndefined() {
|
||
return '';
|
||
}
|
||
|
||
function isUndefined(object) {
|
||
return typeof object === 'undefined';
|
||
}
|
||
|
||
var _undefined = new Type$2('tag:yaml.org,2002:js/undefined', {
|
||
kind: 'scalar',
|
||
resolve: resolveJavascriptUndefined,
|
||
construct: constructJavascriptUndefined,
|
||
predicate: isUndefined,
|
||
represent: representJavascriptUndefined
|
||
});
|
||
|
||
var Type$1 = type;
|
||
|
||
function resolveJavascriptRegExp(data) {
|
||
if (data === null) return false;
|
||
if (data.length === 0) return false;
|
||
|
||
var regexp = data,
|
||
tail = /\/([gim]*)$/.exec(data),
|
||
modifiers = '';
|
||
|
||
// if regexp starts with '/' it can have modifiers and must be properly closed
|
||
// `/foo/gim` - modifiers tail can be maximum 3 chars
|
||
if (regexp[0] === '/') {
|
||
if (tail) modifiers = tail[1];
|
||
|
||
if (modifiers.length > 3) return false;
|
||
// if expression starts with /, is should be properly terminated
|
||
if (regexp[regexp.length - modifiers.length - 1] !== '/') return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
function constructJavascriptRegExp(data) {
|
||
var regexp = data,
|
||
tail = /\/([gim]*)$/.exec(data),
|
||
modifiers = '';
|
||
|
||
// `/foo/gim` - tail can be maximum 4 chars
|
||
if (regexp[0] === '/') {
|
||
if (tail) modifiers = tail[1];
|
||
regexp = regexp.slice(1, regexp.length - modifiers.length - 1);
|
||
}
|
||
|
||
return new RegExp(regexp, modifiers);
|
||
}
|
||
|
||
function representJavascriptRegExp(object /*, style*/) {
|
||
var result = '/' + object.source + '/';
|
||
|
||
if (object.global) result += 'g';
|
||
if (object.multiline) result += 'm';
|
||
if (object.ignoreCase) result += 'i';
|
||
|
||
return result;
|
||
}
|
||
|
||
function isRegExp$1(object) {
|
||
return Object.prototype.toString.call(object) === '[object RegExp]';
|
||
}
|
||
|
||
var regexp = new Type$1('tag:yaml.org,2002:js/regexp', {
|
||
kind: 'scalar',
|
||
resolve: resolveJavascriptRegExp,
|
||
construct: constructJavascriptRegExp,
|
||
predicate: isRegExp$1,
|
||
represent: representJavascriptRegExp
|
||
});
|
||
|
||
var esprima;
|
||
|
||
// Browserified version does not have esprima
|
||
//
|
||
// 1. For node.js just require module as deps
|
||
// 2. For browser try to require mudule via external AMD system.
|
||
// If not found - try to fallback to window.esprima. If not
|
||
// found too - then fail to parse.
|
||
//
|
||
try {
|
||
// workaround to exclude package from browserify list.
|
||
var _require = commonjsRequire;
|
||
esprima = _require('esprima');
|
||
} catch (_) {
|
||
/* eslint-disable no-redeclare */
|
||
/* global window */
|
||
if (typeof window !== 'undefined') esprima = window.esprima;
|
||
}
|
||
|
||
var Type = type;
|
||
|
||
function resolveJavascriptFunction(data) {
|
||
if (data === null) return false;
|
||
|
||
try {
|
||
var source = '(' + data + ')',
|
||
ast = esprima.parse(source, { range: true });
|
||
|
||
if (ast.type !== 'Program' ||
|
||
ast.body.length !== 1 ||
|
||
ast.body[0].type !== 'ExpressionStatement' ||
|
||
(ast.body[0].expression.type !== 'ArrowFunctionExpression' &&
|
||
ast.body[0].expression.type !== 'FunctionExpression')) {
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
} catch (err) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
function constructJavascriptFunction(data) {
|
||
/*jslint evil:true*/
|
||
|
||
var source = '(' + data + ')',
|
||
ast = esprima.parse(source, { range: true }),
|
||
params = [],
|
||
body;
|
||
|
||
if (ast.type !== 'Program' ||
|
||
ast.body.length !== 1 ||
|
||
ast.body[0].type !== 'ExpressionStatement' ||
|
||
(ast.body[0].expression.type !== 'ArrowFunctionExpression' &&
|
||
ast.body[0].expression.type !== 'FunctionExpression')) {
|
||
throw new Error('Failed to resolve function');
|
||
}
|
||
|
||
ast.body[0].expression.params.forEach(function (param) {
|
||
params.push(param.name);
|
||
});
|
||
|
||
body = ast.body[0].expression.body.range;
|
||
|
||
// Esprima's ranges include the first '{' and the last '}' characters on
|
||
// function expressions. So cut them out.
|
||
if (ast.body[0].expression.body.type === 'BlockStatement') {
|
||
/*eslint-disable no-new-func*/
|
||
return new Function(params, source.slice(body[0] + 1, body[1] - 1));
|
||
}
|
||
// ES6 arrow functions can omit the BlockStatement. In that case, just return
|
||
// the body.
|
||
/*eslint-disable no-new-func*/
|
||
return new Function(params, 'return ' + source.slice(body[0], body[1]));
|
||
}
|
||
|
||
function representJavascriptFunction(object /*, style*/) {
|
||
return object.toString();
|
||
}
|
||
|
||
function isFunction$1(object) {
|
||
return Object.prototype.toString.call(object) === '[object Function]';
|
||
}
|
||
|
||
var _function = new Type('tag:yaml.org,2002:js/function', {
|
||
kind: 'scalar',
|
||
resolve: resolveJavascriptFunction,
|
||
construct: constructJavascriptFunction,
|
||
predicate: isFunction$1,
|
||
represent: representJavascriptFunction
|
||
});
|
||
|
||
var Schema = schema;
|
||
|
||
|
||
var default_full = Schema.DEFAULT = new Schema({
|
||
include: [
|
||
default_safe
|
||
],
|
||
explicit: [
|
||
_undefined,
|
||
regexp,
|
||
_function
|
||
]
|
||
});
|
||
|
||
/*eslint-disable max-len,no-use-before-define*/
|
||
|
||
var common$1 = common$6;
|
||
var YAMLException$1 = exception;
|
||
var Mark = mark;
|
||
var DEFAULT_SAFE_SCHEMA$1 = default_safe;
|
||
var DEFAULT_FULL_SCHEMA$1 = default_full;
|
||
|
||
|
||
var _hasOwnProperty$2 = Object.prototype.hasOwnProperty;
|
||
|
||
|
||
var CONTEXT_FLOW_IN = 1;
|
||
var CONTEXT_FLOW_OUT = 2;
|
||
var CONTEXT_BLOCK_IN = 3;
|
||
var CONTEXT_BLOCK_OUT = 4;
|
||
|
||
|
||
var CHOMPING_CLIP = 1;
|
||
var CHOMPING_STRIP = 2;
|
||
var CHOMPING_KEEP = 3;
|
||
|
||
|
||
var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
|
||
var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/;
|
||
var PATTERN_FLOW_INDICATORS = /[,\[\]\{\}]/;
|
||
var PATTERN_TAG_HANDLE = /^(?:!|!!|![a-z\-]+!)$/i;
|
||
var PATTERN_TAG_URI = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;
|
||
|
||
|
||
function _class$2(obj) { return Object.prototype.toString.call(obj); }
|
||
|
||
function is_EOL(c) {
|
||
return (c === 0x0A/* LF */) || (c === 0x0D/* CR */);
|
||
}
|
||
|
||
function is_WHITE_SPACE(c) {
|
||
return (c === 0x09/* Tab */) || (c === 0x20/* Space */);
|
||
}
|
||
|
||
function is_WS_OR_EOL(c) {
|
||
return (c === 0x09/* Tab */) ||
|
||
(c === 0x20/* Space */) ||
|
||
(c === 0x0A/* LF */) ||
|
||
(c === 0x0D/* CR */);
|
||
}
|
||
|
||
function is_FLOW_INDICATOR(c) {
|
||
return c === 0x2C/* , */ ||
|
||
c === 0x5B/* [ */ ||
|
||
c === 0x5D/* ] */ ||
|
||
c === 0x7B/* { */ ||
|
||
c === 0x7D/* } */;
|
||
}
|
||
|
||
function fromHexCode(c) {
|
||
var lc;
|
||
|
||
if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {
|
||
return c - 0x30;
|
||
}
|
||
|
||
/*eslint-disable no-bitwise*/
|
||
lc = c | 0x20;
|
||
|
||
if ((0x61/* a */ <= lc) && (lc <= 0x66/* f */)) {
|
||
return lc - 0x61 + 10;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
function escapedHexLen(c) {
|
||
if (c === 0x78/* x */) { return 2; }
|
||
if (c === 0x75/* u */) { return 4; }
|
||
if (c === 0x55/* U */) { return 8; }
|
||
return 0;
|
||
}
|
||
|
||
function fromDecimalCode(c) {
|
||
if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {
|
||
return c - 0x30;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
function simpleEscapeSequence(c) {
|
||
/* eslint-disable indent */
|
||
return (c === 0x30/* 0 */) ? '\x00' :
|
||
(c === 0x61/* a */) ? '\x07' :
|
||
(c === 0x62/* b */) ? '\x08' :
|
||
(c === 0x74/* t */) ? '\x09' :
|
||
(c === 0x09/* Tab */) ? '\x09' :
|
||
(c === 0x6E/* n */) ? '\x0A' :
|
||
(c === 0x76/* v */) ? '\x0B' :
|
||
(c === 0x66/* f */) ? '\x0C' :
|
||
(c === 0x72/* r */) ? '\x0D' :
|
||
(c === 0x65/* e */) ? '\x1B' :
|
||
(c === 0x20/* Space */) ? ' ' :
|
||
(c === 0x22/* " */) ? '\x22' :
|
||
(c === 0x2F/* / */) ? '/' :
|
||
(c === 0x5C/* \ */) ? '\x5C' :
|
||
(c === 0x4E/* N */) ? '\x85' :
|
||
(c === 0x5F/* _ */) ? '\xA0' :
|
||
(c === 0x4C/* L */) ? '\u2028' :
|
||
(c === 0x50/* P */) ? '\u2029' : '';
|
||
}
|
||
|
||
function charFromCodepoint(c) {
|
||
if (c <= 0xFFFF) {
|
||
return String.fromCharCode(c);
|
||
}
|
||
// Encode UTF-16 surrogate pair
|
||
// https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF
|
||
return String.fromCharCode(
|
||
((c - 0x010000) >> 10) + 0xD800,
|
||
((c - 0x010000) & 0x03FF) + 0xDC00
|
||
);
|
||
}
|
||
|
||
var simpleEscapeCheck = new Array(256); // integer, for fast access
|
||
var simpleEscapeMap = new Array(256);
|
||
for (var i$1 = 0; i$1 < 256; i$1++) {
|
||
simpleEscapeCheck[i$1] = simpleEscapeSequence(i$1) ? 1 : 0;
|
||
simpleEscapeMap[i$1] = simpleEscapeSequence(i$1);
|
||
}
|
||
|
||
|
||
function State$1(input, options) {
|
||
this.input = input;
|
||
|
||
this.filename = options['filename'] || null;
|
||
this.schema = options['schema'] || DEFAULT_FULL_SCHEMA$1;
|
||
this.onWarning = options['onWarning'] || null;
|
||
this.legacy = options['legacy'] || false;
|
||
this.json = options['json'] || false;
|
||
this.listener = options['listener'] || null;
|
||
|
||
this.implicitTypes = this.schema.compiledImplicit;
|
||
this.typeMap = this.schema.compiledTypeMap;
|
||
|
||
this.length = input.length;
|
||
this.position = 0;
|
||
this.line = 0;
|
||
this.lineStart = 0;
|
||
this.lineIndent = 0;
|
||
|
||
this.documents = [];
|
||
|
||
/*
|
||
this.version;
|
||
this.checkLineBreaks;
|
||
this.tagMap;
|
||
this.anchorMap;
|
||
this.tag;
|
||
this.anchor;
|
||
this.kind;
|
||
this.result;*/
|
||
|
||
}
|
||
|
||
|
||
function generateError(state, message) {
|
||
return new YAMLException$1(
|
||
message,
|
||
new Mark(state.filename, state.input, state.position, state.line, (state.position - state.lineStart)));
|
||
}
|
||
|
||
function throwError(state, message) {
|
||
throw generateError(state, message);
|
||
}
|
||
|
||
function throwWarning(state, message) {
|
||
if (state.onWarning) {
|
||
state.onWarning.call(null, generateError(state, message));
|
||
}
|
||
}
|
||
|
||
|
||
var directiveHandlers = {
|
||
|
||
YAML: function handleYamlDirective(state, name, args) {
|
||
|
||
var match, major, minor;
|
||
|
||
if (state.version !== null) {
|
||
throwError(state, 'duplication of %YAML directive');
|
||
}
|
||
|
||
if (args.length !== 1) {
|
||
throwError(state, 'YAML directive accepts exactly one argument');
|
||
}
|
||
|
||
match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]);
|
||
|
||
if (match === null) {
|
||
throwError(state, 'ill-formed argument of the YAML directive');
|
||
}
|
||
|
||
major = parseInt(match[1], 10);
|
||
minor = parseInt(match[2], 10);
|
||
|
||
if (major !== 1) {
|
||
throwError(state, 'unacceptable YAML version of the document');
|
||
}
|
||
|
||
state.version = args[0];
|
||
state.checkLineBreaks = (minor < 2);
|
||
|
||
if (minor !== 1 && minor !== 2) {
|
||
throwWarning(state, 'unsupported YAML version of the document');
|
||
}
|
||
},
|
||
|
||
TAG: function handleTagDirective(state, name, args) {
|
||
|
||
var handle, prefix;
|
||
|
||
if (args.length !== 2) {
|
||
throwError(state, 'TAG directive accepts exactly two arguments');
|
||
}
|
||
|
||
handle = args[0];
|
||
prefix = args[1];
|
||
|
||
if (!PATTERN_TAG_HANDLE.test(handle)) {
|
||
throwError(state, 'ill-formed tag handle (first argument) of the TAG directive');
|
||
}
|
||
|
||
if (_hasOwnProperty$2.call(state.tagMap, handle)) {
|
||
throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle');
|
||
}
|
||
|
||
if (!PATTERN_TAG_URI.test(prefix)) {
|
||
throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive');
|
||
}
|
||
|
||
state.tagMap[handle] = prefix;
|
||
}
|
||
};
|
||
|
||
|
||
function captureSegment(state, start, end, checkJson) {
|
||
var _position, _length, _character, _result;
|
||
|
||
if (start < end) {
|
||
_result = state.input.slice(start, end);
|
||
|
||
if (checkJson) {
|
||
for (_position = 0, _length = _result.length; _position < _length; _position += 1) {
|
||
_character = _result.charCodeAt(_position);
|
||
if (!(_character === 0x09 ||
|
||
(0x20 <= _character && _character <= 0x10FFFF))) {
|
||
throwError(state, 'expected valid JSON character');
|
||
}
|
||
}
|
||
} else if (PATTERN_NON_PRINTABLE.test(_result)) {
|
||
throwError(state, 'the stream contains non-printable characters');
|
||
}
|
||
|
||
state.result += _result;
|
||
}
|
||
}
|
||
|
||
function mergeMappings(state, destination, source, overridableKeys) {
|
||
var sourceKeys, key, index, quantity;
|
||
|
||
if (!common$1.isObject(source)) {
|
||
throwError(state, 'cannot merge mappings; the provided source object is unacceptable');
|
||
}
|
||
|
||
sourceKeys = Object.keys(source);
|
||
|
||
for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
|
||
key = sourceKeys[index];
|
||
|
||
if (!_hasOwnProperty$2.call(destination, key)) {
|
||
destination[key] = source[key];
|
||
overridableKeys[key] = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, startLine, startPos) {
|
||
var index, quantity;
|
||
|
||
// The output is a plain object here, so keys can only be strings.
|
||
// We need to convert keyNode to a string, but doing so can hang the process
|
||
// (deeply nested arrays that explode exponentially using aliases).
|
||
if (Array.isArray(keyNode)) {
|
||
keyNode = Array.prototype.slice.call(keyNode);
|
||
|
||
for (index = 0, quantity = keyNode.length; index < quantity; index += 1) {
|
||
if (Array.isArray(keyNode[index])) {
|
||
throwError(state, 'nested arrays are not supported inside keys');
|
||
}
|
||
|
||
if (typeof keyNode === 'object' && _class$2(keyNode[index]) === '[object Object]') {
|
||
keyNode[index] = '[object Object]';
|
||
}
|
||
}
|
||
}
|
||
|
||
// Avoid code execution in load() via toString property
|
||
// (still use its own toString for arrays, timestamps,
|
||
// and whatever user schema extensions happen to have @@toStringTag)
|
||
if (typeof keyNode === 'object' && _class$2(keyNode) === '[object Object]') {
|
||
keyNode = '[object Object]';
|
||
}
|
||
|
||
|
||
keyNode = String(keyNode);
|
||
|
||
if (_result === null) {
|
||
_result = {};
|
||
}
|
||
|
||
if (keyTag === 'tag:yaml.org,2002:merge') {
|
||
if (Array.isArray(valueNode)) {
|
||
for (index = 0, quantity = valueNode.length; index < quantity; index += 1) {
|
||
mergeMappings(state, _result, valueNode[index], overridableKeys);
|
||
}
|
||
} else {
|
||
mergeMappings(state, _result, valueNode, overridableKeys);
|
||
}
|
||
} else {
|
||
if (!state.json &&
|
||
!_hasOwnProperty$2.call(overridableKeys, keyNode) &&
|
||
_hasOwnProperty$2.call(_result, keyNode)) {
|
||
state.line = startLine || state.line;
|
||
state.position = startPos || state.position;
|
||
throwError(state, 'duplicated mapping key');
|
||
}
|
||
_result[keyNode] = valueNode;
|
||
delete overridableKeys[keyNode];
|
||
}
|
||
|
||
return _result;
|
||
}
|
||
|
||
function readLineBreak(state) {
|
||
var ch;
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if (ch === 0x0A/* LF */) {
|
||
state.position++;
|
||
} else if (ch === 0x0D/* CR */) {
|
||
state.position++;
|
||
if (state.input.charCodeAt(state.position) === 0x0A/* LF */) {
|
||
state.position++;
|
||
}
|
||
} else {
|
||
throwError(state, 'a line break is expected');
|
||
}
|
||
|
||
state.line += 1;
|
||
state.lineStart = state.position;
|
||
}
|
||
|
||
function skipSeparationSpace(state, allowComments, checkIndent) {
|
||
var lineBreaks = 0,
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
while (ch !== 0) {
|
||
while (is_WHITE_SPACE(ch)) {
|
||
ch = state.input.charCodeAt(++state.position);
|
||
}
|
||
|
||
if (allowComments && ch === 0x23/* # */) {
|
||
do {
|
||
ch = state.input.charCodeAt(++state.position);
|
||
} while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0);
|
||
}
|
||
|
||
if (is_EOL(ch)) {
|
||
readLineBreak(state);
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
lineBreaks++;
|
||
state.lineIndent = 0;
|
||
|
||
while (ch === 0x20/* Space */) {
|
||
state.lineIndent++;
|
||
ch = state.input.charCodeAt(++state.position);
|
||
}
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {
|
||
throwWarning(state, 'deficient indentation');
|
||
}
|
||
|
||
return lineBreaks;
|
||
}
|
||
|
||
function testDocumentSeparator(state) {
|
||
var _position = state.position,
|
||
ch;
|
||
|
||
ch = state.input.charCodeAt(_position);
|
||
|
||
// Condition state.position === state.lineStart is tested
|
||
// in parent on each call, for efficiency. No needs to test here again.
|
||
if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) &&
|
||
ch === state.input.charCodeAt(_position + 1) &&
|
||
ch === state.input.charCodeAt(_position + 2)) {
|
||
|
||
_position += 3;
|
||
|
||
ch = state.input.charCodeAt(_position);
|
||
|
||
if (ch === 0 || is_WS_OR_EOL(ch)) {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
function writeFoldedLines(state, count) {
|
||
if (count === 1) {
|
||
state.result += ' ';
|
||
} else if (count > 1) {
|
||
state.result += common$1.repeat('\n', count - 1);
|
||
}
|
||
}
|
||
|
||
|
||
function readPlainScalar(state, nodeIndent, withinFlowCollection) {
|
||
var preceding,
|
||
following,
|
||
captureStart,
|
||
captureEnd,
|
||
hasPendingContent,
|
||
_line,
|
||
_lineStart,
|
||
_lineIndent,
|
||
_kind = state.kind,
|
||
_result = state.result,
|
||
ch;
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if (is_WS_OR_EOL(ch) ||
|
||
is_FLOW_INDICATOR(ch) ||
|
||
ch === 0x23/* # */ ||
|
||
ch === 0x26/* & */ ||
|
||
ch === 0x2A/* * */ ||
|
||
ch === 0x21/* ! */ ||
|
||
ch === 0x7C/* | */ ||
|
||
ch === 0x3E/* > */ ||
|
||
ch === 0x27/* ' */ ||
|
||
ch === 0x22/* " */ ||
|
||
ch === 0x25/* % */ ||
|
||
ch === 0x40/* @ */ ||
|
||
ch === 0x60/* ` */) {
|
||
return false;
|
||
}
|
||
|
||
if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) {
|
||
following = state.input.charCodeAt(state.position + 1);
|
||
|
||
if (is_WS_OR_EOL(following) ||
|
||
withinFlowCollection && is_FLOW_INDICATOR(following)) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
state.kind = 'scalar';
|
||
state.result = '';
|
||
captureStart = captureEnd = state.position;
|
||
hasPendingContent = false;
|
||
|
||
while (ch !== 0) {
|
||
if (ch === 0x3A/* : */) {
|
||
following = state.input.charCodeAt(state.position + 1);
|
||
|
||
if (is_WS_OR_EOL(following) ||
|
||
withinFlowCollection && is_FLOW_INDICATOR(following)) {
|
||
break;
|
||
}
|
||
|
||
} else if (ch === 0x23/* # */) {
|
||
preceding = state.input.charCodeAt(state.position - 1);
|
||
|
||
if (is_WS_OR_EOL(preceding)) {
|
||
break;
|
||
}
|
||
|
||
} else if ((state.position === state.lineStart && testDocumentSeparator(state)) ||
|
||
withinFlowCollection && is_FLOW_INDICATOR(ch)) {
|
||
break;
|
||
|
||
} else if (is_EOL(ch)) {
|
||
_line = state.line;
|
||
_lineStart = state.lineStart;
|
||
_lineIndent = state.lineIndent;
|
||
skipSeparationSpace(state, false, -1);
|
||
|
||
if (state.lineIndent >= nodeIndent) {
|
||
hasPendingContent = true;
|
||
ch = state.input.charCodeAt(state.position);
|
||
continue;
|
||
} else {
|
||
state.position = captureEnd;
|
||
state.line = _line;
|
||
state.lineStart = _lineStart;
|
||
state.lineIndent = _lineIndent;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (hasPendingContent) {
|
||
captureSegment(state, captureStart, captureEnd, false);
|
||
writeFoldedLines(state, state.line - _line);
|
||
captureStart = captureEnd = state.position;
|
||
hasPendingContent = false;
|
||
}
|
||
|
||
if (!is_WHITE_SPACE(ch)) {
|
||
captureEnd = state.position + 1;
|
||
}
|
||
|
||
ch = state.input.charCodeAt(++state.position);
|
||
}
|
||
|
||
captureSegment(state, captureStart, captureEnd, false);
|
||
|
||
if (state.result) {
|
||
return true;
|
||
}
|
||
|
||
state.kind = _kind;
|
||
state.result = _result;
|
||
return false;
|
||
}
|
||
|
||
function readSingleQuotedScalar(state, nodeIndent) {
|
||
var ch,
|
||
captureStart, captureEnd;
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if (ch !== 0x27/* ' */) {
|
||
return false;
|
||
}
|
||
|
||
state.kind = 'scalar';
|
||
state.result = '';
|
||
state.position++;
|
||
captureStart = captureEnd = state.position;
|
||
|
||
while ((ch = state.input.charCodeAt(state.position)) !== 0) {
|
||
if (ch === 0x27/* ' */) {
|
||
captureSegment(state, captureStart, state.position, true);
|
||
ch = state.input.charCodeAt(++state.position);
|
||
|
||
if (ch === 0x27/* ' */) {
|
||
captureStart = state.position;
|
||
state.position++;
|
||
captureEnd = state.position;
|
||
} else {
|
||
return true;
|
||
}
|
||
|
||
} else if (is_EOL(ch)) {
|
||
captureSegment(state, captureStart, captureEnd, true);
|
||
writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
|
||
captureStart = captureEnd = state.position;
|
||
|
||
} else if (state.position === state.lineStart && testDocumentSeparator(state)) {
|
||
throwError(state, 'unexpected end of the document within a single quoted scalar');
|
||
|
||
} else {
|
||
state.position++;
|
||
captureEnd = state.position;
|
||
}
|
||
}
|
||
|
||
throwError(state, 'unexpected end of the stream within a single quoted scalar');
|
||
}
|
||
|
||
function readDoubleQuotedScalar(state, nodeIndent) {
|
||
var captureStart,
|
||
captureEnd,
|
||
hexLength,
|
||
hexResult,
|
||
tmp,
|
||
ch;
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if (ch !== 0x22/* " */) {
|
||
return false;
|
||
}
|
||
|
||
state.kind = 'scalar';
|
||
state.result = '';
|
||
state.position++;
|
||
captureStart = captureEnd = state.position;
|
||
|
||
while ((ch = state.input.charCodeAt(state.position)) !== 0) {
|
||
if (ch === 0x22/* " */) {
|
||
captureSegment(state, captureStart, state.position, true);
|
||
state.position++;
|
||
return true;
|
||
|
||
} else if (ch === 0x5C/* \ */) {
|
||
captureSegment(state, captureStart, state.position, true);
|
||
ch = state.input.charCodeAt(++state.position);
|
||
|
||
if (is_EOL(ch)) {
|
||
skipSeparationSpace(state, false, nodeIndent);
|
||
|
||
// TODO: rework to inline fn with no type cast?
|
||
} else if (ch < 256 && simpleEscapeCheck[ch]) {
|
||
state.result += simpleEscapeMap[ch];
|
||
state.position++;
|
||
|
||
} else if ((tmp = escapedHexLen(ch)) > 0) {
|
||
hexLength = tmp;
|
||
hexResult = 0;
|
||
|
||
for (; hexLength > 0; hexLength--) {
|
||
ch = state.input.charCodeAt(++state.position);
|
||
|
||
if ((tmp = fromHexCode(ch)) >= 0) {
|
||
hexResult = (hexResult << 4) + tmp;
|
||
|
||
} else {
|
||
throwError(state, 'expected hexadecimal character');
|
||
}
|
||
}
|
||
|
||
state.result += charFromCodepoint(hexResult);
|
||
|
||
state.position++;
|
||
|
||
} else {
|
||
throwError(state, 'unknown escape sequence');
|
||
}
|
||
|
||
captureStart = captureEnd = state.position;
|
||
|
||
} else if (is_EOL(ch)) {
|
||
captureSegment(state, captureStart, captureEnd, true);
|
||
writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
|
||
captureStart = captureEnd = state.position;
|
||
|
||
} else if (state.position === state.lineStart && testDocumentSeparator(state)) {
|
||
throwError(state, 'unexpected end of the document within a double quoted scalar');
|
||
|
||
} else {
|
||
state.position++;
|
||
captureEnd = state.position;
|
||
}
|
||
}
|
||
|
||
throwError(state, 'unexpected end of the stream within a double quoted scalar');
|
||
}
|
||
|
||
function readFlowCollection(state, nodeIndent) {
|
||
var readNext = true,
|
||
_line,
|
||
_tag = state.tag,
|
||
_result,
|
||
_anchor = state.anchor,
|
||
following,
|
||
terminator,
|
||
isPair,
|
||
isExplicitPair,
|
||
isMapping,
|
||
overridableKeys = {},
|
||
keyNode,
|
||
keyTag,
|
||
valueNode,
|
||
ch;
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if (ch === 0x5B/* [ */) {
|
||
terminator = 0x5D;/* ] */
|
||
isMapping = false;
|
||
_result = [];
|
||
} else if (ch === 0x7B/* { */) {
|
||
terminator = 0x7D;/* } */
|
||
isMapping = true;
|
||
_result = {};
|
||
} else {
|
||
return false;
|
||
}
|
||
|
||
if (state.anchor !== null) {
|
||
state.anchorMap[state.anchor] = _result;
|
||
}
|
||
|
||
ch = state.input.charCodeAt(++state.position);
|
||
|
||
while (ch !== 0) {
|
||
skipSeparationSpace(state, true, nodeIndent);
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if (ch === terminator) {
|
||
state.position++;
|
||
state.tag = _tag;
|
||
state.anchor = _anchor;
|
||
state.kind = isMapping ? 'mapping' : 'sequence';
|
||
state.result = _result;
|
||
return true;
|
||
} else if (!readNext) {
|
||
throwError(state, 'missed comma between flow collection entries');
|
||
}
|
||
|
||
keyTag = keyNode = valueNode = null;
|
||
isPair = isExplicitPair = false;
|
||
|
||
if (ch === 0x3F/* ? */) {
|
||
following = state.input.charCodeAt(state.position + 1);
|
||
|
||
if (is_WS_OR_EOL(following)) {
|
||
isPair = isExplicitPair = true;
|
||
state.position++;
|
||
skipSeparationSpace(state, true, nodeIndent);
|
||
}
|
||
}
|
||
|
||
_line = state.line;
|
||
composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
|
||
keyTag = state.tag;
|
||
keyNode = state.result;
|
||
skipSeparationSpace(state, true, nodeIndent);
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) {
|
||
isPair = true;
|
||
ch = state.input.charCodeAt(++state.position);
|
||
skipSeparationSpace(state, true, nodeIndent);
|
||
composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
|
||
valueNode = state.result;
|
||
}
|
||
|
||
if (isMapping) {
|
||
storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode);
|
||
} else if (isPair) {
|
||
_result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode));
|
||
} else {
|
||
_result.push(keyNode);
|
||
}
|
||
|
||
skipSeparationSpace(state, true, nodeIndent);
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if (ch === 0x2C/* , */) {
|
||
readNext = true;
|
||
ch = state.input.charCodeAt(++state.position);
|
||
} else {
|
||
readNext = false;
|
||
}
|
||
}
|
||
|
||
throwError(state, 'unexpected end of the stream within a flow collection');
|
||
}
|
||
|
||
function readBlockScalar(state, nodeIndent) {
|
||
var captureStart,
|
||
folding,
|
||
chomping = CHOMPING_CLIP,
|
||
didReadContent = false,
|
||
detectedIndent = false,
|
||
textIndent = nodeIndent,
|
||
emptyLines = 0,
|
||
atMoreIndented = false,
|
||
tmp,
|
||
ch;
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if (ch === 0x7C/* | */) {
|
||
folding = false;
|
||
} else if (ch === 0x3E/* > */) {
|
||
folding = true;
|
||
} else {
|
||
return false;
|
||
}
|
||
|
||
state.kind = 'scalar';
|
||
state.result = '';
|
||
|
||
while (ch !== 0) {
|
||
ch = state.input.charCodeAt(++state.position);
|
||
|
||
if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {
|
||
if (CHOMPING_CLIP === chomping) {
|
||
chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP;
|
||
} else {
|
||
throwError(state, 'repeat of a chomping mode identifier');
|
||
}
|
||
|
||
} else if ((tmp = fromDecimalCode(ch)) >= 0) {
|
||
if (tmp === 0) {
|
||
throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one');
|
||
} else if (!detectedIndent) {
|
||
textIndent = nodeIndent + tmp - 1;
|
||
detectedIndent = true;
|
||
} else {
|
||
throwError(state, 'repeat of an indentation width identifier');
|
||
}
|
||
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (is_WHITE_SPACE(ch)) {
|
||
do { ch = state.input.charCodeAt(++state.position); }
|
||
while (is_WHITE_SPACE(ch));
|
||
|
||
if (ch === 0x23/* # */) {
|
||
do { ch = state.input.charCodeAt(++state.position); }
|
||
while (!is_EOL(ch) && (ch !== 0));
|
||
}
|
||
}
|
||
|
||
while (ch !== 0) {
|
||
readLineBreak(state);
|
||
state.lineIndent = 0;
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
while ((!detectedIndent || state.lineIndent < textIndent) &&
|
||
(ch === 0x20/* Space */)) {
|
||
state.lineIndent++;
|
||
ch = state.input.charCodeAt(++state.position);
|
||
}
|
||
|
||
if (!detectedIndent && state.lineIndent > textIndent) {
|
||
textIndent = state.lineIndent;
|
||
}
|
||
|
||
if (is_EOL(ch)) {
|
||
emptyLines++;
|
||
continue;
|
||
}
|
||
|
||
// End of the scalar.
|
||
if (state.lineIndent < textIndent) {
|
||
|
||
// Perform the chomping.
|
||
if (chomping === CHOMPING_KEEP) {
|
||
state.result += common$1.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
|
||
} else if (chomping === CHOMPING_CLIP) {
|
||
if (didReadContent) { // i.e. only if the scalar is not empty.
|
||
state.result += '\n';
|
||
}
|
||
}
|
||
|
||
// Break this `while` cycle and go to the funciton's epilogue.
|
||
break;
|
||
}
|
||
|
||
// Folded style: use fancy rules to handle line breaks.
|
||
if (folding) {
|
||
|
||
// Lines starting with white space characters (more-indented lines) are not folded.
|
||
if (is_WHITE_SPACE(ch)) {
|
||
atMoreIndented = true;
|
||
// except for the first content line (cf. Example 8.1)
|
||
state.result += common$1.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
|
||
|
||
// End of more-indented block.
|
||
} else if (atMoreIndented) {
|
||
atMoreIndented = false;
|
||
state.result += common$1.repeat('\n', emptyLines + 1);
|
||
|
||
// Just one line break - perceive as the same line.
|
||
} else if (emptyLines === 0) {
|
||
if (didReadContent) { // i.e. only if we have already read some scalar content.
|
||
state.result += ' ';
|
||
}
|
||
|
||
// Several line breaks - perceive as different lines.
|
||
} else {
|
||
state.result += common$1.repeat('\n', emptyLines);
|
||
}
|
||
|
||
// Literal style: just add exact number of line breaks between content lines.
|
||
} else {
|
||
// Keep all line breaks except the header line break.
|
||
state.result += common$1.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
|
||
}
|
||
|
||
didReadContent = true;
|
||
detectedIndent = true;
|
||
emptyLines = 0;
|
||
captureStart = state.position;
|
||
|
||
while (!is_EOL(ch) && (ch !== 0)) {
|
||
ch = state.input.charCodeAt(++state.position);
|
||
}
|
||
|
||
captureSegment(state, captureStart, state.position, false);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
function readBlockSequence(state, nodeIndent) {
|
||
var _line,
|
||
_tag = state.tag,
|
||
_anchor = state.anchor,
|
||
_result = [],
|
||
following,
|
||
detected = false,
|
||
ch;
|
||
|
||
if (state.anchor !== null) {
|
||
state.anchorMap[state.anchor] = _result;
|
||
}
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
while (ch !== 0) {
|
||
|
||
if (ch !== 0x2D/* - */) {
|
||
break;
|
||
}
|
||
|
||
following = state.input.charCodeAt(state.position + 1);
|
||
|
||
if (!is_WS_OR_EOL(following)) {
|
||
break;
|
||
}
|
||
|
||
detected = true;
|
||
state.position++;
|
||
|
||
if (skipSeparationSpace(state, true, -1)) {
|
||
if (state.lineIndent <= nodeIndent) {
|
||
_result.push(null);
|
||
ch = state.input.charCodeAt(state.position);
|
||
continue;
|
||
}
|
||
}
|
||
|
||
_line = state.line;
|
||
composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true);
|
||
_result.push(state.result);
|
||
skipSeparationSpace(state, true, -1);
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {
|
||
throwError(state, 'bad indentation of a sequence entry');
|
||
} else if (state.lineIndent < nodeIndent) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (detected) {
|
||
state.tag = _tag;
|
||
state.anchor = _anchor;
|
||
state.kind = 'sequence';
|
||
state.result = _result;
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
function readBlockMapping(state, nodeIndent, flowIndent) {
|
||
var following,
|
||
allowCompact,
|
||
_line,
|
||
_pos,
|
||
_tag = state.tag,
|
||
_anchor = state.anchor,
|
||
_result = {},
|
||
overridableKeys = {},
|
||
keyTag = null,
|
||
keyNode = null,
|
||
valueNode = null,
|
||
atExplicitKey = false,
|
||
detected = false,
|
||
ch;
|
||
|
||
if (state.anchor !== null) {
|
||
state.anchorMap[state.anchor] = _result;
|
||
}
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
while (ch !== 0) {
|
||
following = state.input.charCodeAt(state.position + 1);
|
||
_line = state.line; // Save the current line.
|
||
_pos = state.position;
|
||
|
||
//
|
||
// Explicit notation case. There are two separate blocks:
|
||
// first for the key (denoted by "?") and second for the value (denoted by ":")
|
||
//
|
||
if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && is_WS_OR_EOL(following)) {
|
||
|
||
if (ch === 0x3F/* ? */) {
|
||
if (atExplicitKey) {
|
||
storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);
|
||
keyTag = keyNode = valueNode = null;
|
||
}
|
||
|
||
detected = true;
|
||
atExplicitKey = true;
|
||
allowCompact = true;
|
||
|
||
} else if (atExplicitKey) {
|
||
// i.e. 0x3A/* : */ === character after the explicit key.
|
||
atExplicitKey = false;
|
||
allowCompact = true;
|
||
|
||
} else {
|
||
throwError(state, 'incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line');
|
||
}
|
||
|
||
state.position += 1;
|
||
ch = following;
|
||
|
||
//
|
||
// Implicit notation case. Flow-style node as the key first, then ":", and the value.
|
||
//
|
||
} else if (composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {
|
||
|
||
if (state.line === _line) {
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
while (is_WHITE_SPACE(ch)) {
|
||
ch = state.input.charCodeAt(++state.position);
|
||
}
|
||
|
||
if (ch === 0x3A/* : */) {
|
||
ch = state.input.charCodeAt(++state.position);
|
||
|
||
if (!is_WS_OR_EOL(ch)) {
|
||
throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping');
|
||
}
|
||
|
||
if (atExplicitKey) {
|
||
storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);
|
||
keyTag = keyNode = valueNode = null;
|
||
}
|
||
|
||
detected = true;
|
||
atExplicitKey = false;
|
||
allowCompact = false;
|
||
keyTag = state.tag;
|
||
keyNode = state.result;
|
||
|
||
} else if (detected) {
|
||
throwError(state, 'can not read an implicit mapping pair; a colon is missed');
|
||
|
||
} else {
|
||
state.tag = _tag;
|
||
state.anchor = _anchor;
|
||
return true; // Keep the result of `composeNode`.
|
||
}
|
||
|
||
} else if (detected) {
|
||
throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key');
|
||
|
||
} else {
|
||
state.tag = _tag;
|
||
state.anchor = _anchor;
|
||
return true; // Keep the result of `composeNode`.
|
||
}
|
||
|
||
} else {
|
||
break; // Reading is done. Go to the epilogue.
|
||
}
|
||
|
||
//
|
||
// Common reading code for both explicit and implicit notations.
|
||
//
|
||
if (state.line === _line || state.lineIndent > nodeIndent) {
|
||
if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {
|
||
if (atExplicitKey) {
|
||
keyNode = state.result;
|
||
} else {
|
||
valueNode = state.result;
|
||
}
|
||
}
|
||
|
||
if (!atExplicitKey) {
|
||
storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _pos);
|
||
keyTag = keyNode = valueNode = null;
|
||
}
|
||
|
||
skipSeparationSpace(state, true, -1);
|
||
ch = state.input.charCodeAt(state.position);
|
||
}
|
||
|
||
if (state.lineIndent > nodeIndent && (ch !== 0)) {
|
||
throwError(state, 'bad indentation of a mapping entry');
|
||
} else if (state.lineIndent < nodeIndent) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Epilogue.
|
||
//
|
||
|
||
// Special case: last mapping's node contains only the key in explicit notation.
|
||
if (atExplicitKey) {
|
||
storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);
|
||
}
|
||
|
||
// Expose the resulting mapping.
|
||
if (detected) {
|
||
state.tag = _tag;
|
||
state.anchor = _anchor;
|
||
state.kind = 'mapping';
|
||
state.result = _result;
|
||
}
|
||
|
||
return detected;
|
||
}
|
||
|
||
function readTagProperty(state) {
|
||
var _position,
|
||
isVerbatim = false,
|
||
isNamed = false,
|
||
tagHandle,
|
||
tagName,
|
||
ch;
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if (ch !== 0x21/* ! */) return false;
|
||
|
||
if (state.tag !== null) {
|
||
throwError(state, 'duplication of a tag property');
|
||
}
|
||
|
||
ch = state.input.charCodeAt(++state.position);
|
||
|
||
if (ch === 0x3C/* < */) {
|
||
isVerbatim = true;
|
||
ch = state.input.charCodeAt(++state.position);
|
||
|
||
} else if (ch === 0x21/* ! */) {
|
||
isNamed = true;
|
||
tagHandle = '!!';
|
||
ch = state.input.charCodeAt(++state.position);
|
||
|
||
} else {
|
||
tagHandle = '!';
|
||
}
|
||
|
||
_position = state.position;
|
||
|
||
if (isVerbatim) {
|
||
do { ch = state.input.charCodeAt(++state.position); }
|
||
while (ch !== 0 && ch !== 0x3E/* > */);
|
||
|
||
if (state.position < state.length) {
|
||
tagName = state.input.slice(_position, state.position);
|
||
ch = state.input.charCodeAt(++state.position);
|
||
} else {
|
||
throwError(state, 'unexpected end of the stream within a verbatim tag');
|
||
}
|
||
} else {
|
||
while (ch !== 0 && !is_WS_OR_EOL(ch)) {
|
||
|
||
if (ch === 0x21/* ! */) {
|
||
if (!isNamed) {
|
||
tagHandle = state.input.slice(_position - 1, state.position + 1);
|
||
|
||
if (!PATTERN_TAG_HANDLE.test(tagHandle)) {
|
||
throwError(state, 'named tag handle cannot contain such characters');
|
||
}
|
||
|
||
isNamed = true;
|
||
_position = state.position + 1;
|
||
} else {
|
||
throwError(state, 'tag suffix cannot contain exclamation marks');
|
||
}
|
||
}
|
||
|
||
ch = state.input.charCodeAt(++state.position);
|
||
}
|
||
|
||
tagName = state.input.slice(_position, state.position);
|
||
|
||
if (PATTERN_FLOW_INDICATORS.test(tagName)) {
|
||
throwError(state, 'tag suffix cannot contain flow indicator characters');
|
||
}
|
||
}
|
||
|
||
if (tagName && !PATTERN_TAG_URI.test(tagName)) {
|
||
throwError(state, 'tag name cannot contain such characters: ' + tagName);
|
||
}
|
||
|
||
if (isVerbatim) {
|
||
state.tag = tagName;
|
||
|
||
} else if (_hasOwnProperty$2.call(state.tagMap, tagHandle)) {
|
||
state.tag = state.tagMap[tagHandle] + tagName;
|
||
|
||
} else if (tagHandle === '!') {
|
||
state.tag = '!' + tagName;
|
||
|
||
} else if (tagHandle === '!!') {
|
||
state.tag = 'tag:yaml.org,2002:' + tagName;
|
||
|
||
} else {
|
||
throwError(state, 'undeclared tag handle "' + tagHandle + '"');
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
function readAnchorProperty(state) {
|
||
var _position,
|
||
ch;
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if (ch !== 0x26/* & */) return false;
|
||
|
||
if (state.anchor !== null) {
|
||
throwError(state, 'duplication of an anchor property');
|
||
}
|
||
|
||
ch = state.input.charCodeAt(++state.position);
|
||
_position = state.position;
|
||
|
||
while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
|
||
ch = state.input.charCodeAt(++state.position);
|
||
}
|
||
|
||
if (state.position === _position) {
|
||
throwError(state, 'name of an anchor node must contain at least one character');
|
||
}
|
||
|
||
state.anchor = state.input.slice(_position, state.position);
|
||
return true;
|
||
}
|
||
|
||
function readAlias(state) {
|
||
var _position, alias,
|
||
ch;
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if (ch !== 0x2A/* * */) return false;
|
||
|
||
ch = state.input.charCodeAt(++state.position);
|
||
_position = state.position;
|
||
|
||
while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
|
||
ch = state.input.charCodeAt(++state.position);
|
||
}
|
||
|
||
if (state.position === _position) {
|
||
throwError(state, 'name of an alias node must contain at least one character');
|
||
}
|
||
|
||
alias = state.input.slice(_position, state.position);
|
||
|
||
if (!_hasOwnProperty$2.call(state.anchorMap, alias)) {
|
||
throwError(state, 'unidentified alias "' + alias + '"');
|
||
}
|
||
|
||
state.result = state.anchorMap[alias];
|
||
skipSeparationSpace(state, true, -1);
|
||
return true;
|
||
}
|
||
|
||
function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) {
|
||
var allowBlockStyles,
|
||
allowBlockScalars,
|
||
allowBlockCollections,
|
||
indentStatus = 1, // 1: this>parent, 0: this=parent, -1: this<parent
|
||
atNewLine = false,
|
||
hasContent = false,
|
||
typeIndex,
|
||
typeQuantity,
|
||
type,
|
||
flowIndent,
|
||
blockIndent;
|
||
|
||
if (state.listener !== null) {
|
||
state.listener('open', state);
|
||
}
|
||
|
||
state.tag = null;
|
||
state.anchor = null;
|
||
state.kind = null;
|
||
state.result = null;
|
||
|
||
allowBlockStyles = allowBlockScalars = allowBlockCollections =
|
||
CONTEXT_BLOCK_OUT === nodeContext ||
|
||
CONTEXT_BLOCK_IN === nodeContext;
|
||
|
||
if (allowToSeek) {
|
||
if (skipSeparationSpace(state, true, -1)) {
|
||
atNewLine = true;
|
||
|
||
if (state.lineIndent > parentIndent) {
|
||
indentStatus = 1;
|
||
} else if (state.lineIndent === parentIndent) {
|
||
indentStatus = 0;
|
||
} else if (state.lineIndent < parentIndent) {
|
||
indentStatus = -1;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (indentStatus === 1) {
|
||
while (readTagProperty(state) || readAnchorProperty(state)) {
|
||
if (skipSeparationSpace(state, true, -1)) {
|
||
atNewLine = true;
|
||
allowBlockCollections = allowBlockStyles;
|
||
|
||
if (state.lineIndent > parentIndent) {
|
||
indentStatus = 1;
|
||
} else if (state.lineIndent === parentIndent) {
|
||
indentStatus = 0;
|
||
} else if (state.lineIndent < parentIndent) {
|
||
indentStatus = -1;
|
||
}
|
||
} else {
|
||
allowBlockCollections = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (allowBlockCollections) {
|
||
allowBlockCollections = atNewLine || allowCompact;
|
||
}
|
||
|
||
if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {
|
||
if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {
|
||
flowIndent = parentIndent;
|
||
} else {
|
||
flowIndent = parentIndent + 1;
|
||
}
|
||
|
||
blockIndent = state.position - state.lineStart;
|
||
|
||
if (indentStatus === 1) {
|
||
if (allowBlockCollections &&
|
||
(readBlockSequence(state, blockIndent) ||
|
||
readBlockMapping(state, blockIndent, flowIndent)) ||
|
||
readFlowCollection(state, flowIndent)) {
|
||
hasContent = true;
|
||
} else {
|
||
if ((allowBlockScalars && readBlockScalar(state, flowIndent)) ||
|
||
readSingleQuotedScalar(state, flowIndent) ||
|
||
readDoubleQuotedScalar(state, flowIndent)) {
|
||
hasContent = true;
|
||
|
||
} else if (readAlias(state)) {
|
||
hasContent = true;
|
||
|
||
if (state.tag !== null || state.anchor !== null) {
|
||
throwError(state, 'alias node should not have any properties');
|
||
}
|
||
|
||
} else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {
|
||
hasContent = true;
|
||
|
||
if (state.tag === null) {
|
||
state.tag = '?';
|
||
}
|
||
}
|
||
|
||
if (state.anchor !== null) {
|
||
state.anchorMap[state.anchor] = state.result;
|
||
}
|
||
}
|
||
} else if (indentStatus === 0) {
|
||
// Special case: block sequences are allowed to have same indentation level as the parent.
|
||
// http://www.yaml.org/spec/1.2/spec.html#id2799784
|
||
hasContent = allowBlockCollections && readBlockSequence(state, blockIndent);
|
||
}
|
||
}
|
||
|
||
if (state.tag !== null && state.tag !== '!') {
|
||
if (state.tag === '?') {
|
||
// Implicit resolving is not allowed for non-scalar types, and '?'
|
||
// non-specific tag is only automatically assigned to plain scalars.
|
||
//
|
||
// We only need to check kind conformity in case user explicitly assigns '?'
|
||
// tag, for example like this: "!<?> [0]"
|
||
//
|
||
if (state.result !== null && state.kind !== 'scalar') {
|
||
throwError(state, 'unacceptable node kind for !<?> tag; it should be "scalar", not "' + state.kind + '"');
|
||
}
|
||
|
||
for (typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {
|
||
type = state.implicitTypes[typeIndex];
|
||
|
||
if (type.resolve(state.result)) { // `state.result` updated in resolver if matched
|
||
state.result = type.construct(state.result);
|
||
state.tag = type.tag;
|
||
if (state.anchor !== null) {
|
||
state.anchorMap[state.anchor] = state.result;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
} else if (_hasOwnProperty$2.call(state.typeMap[state.kind || 'fallback'], state.tag)) {
|
||
type = state.typeMap[state.kind || 'fallback'][state.tag];
|
||
|
||
if (state.result !== null && type.kind !== state.kind) {
|
||
throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be "' + type.kind + '", not "' + state.kind + '"');
|
||
}
|
||
|
||
if (!type.resolve(state.result)) { // `state.result` updated in resolver if matched
|
||
throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag');
|
||
} else {
|
||
state.result = type.construct(state.result);
|
||
if (state.anchor !== null) {
|
||
state.anchorMap[state.anchor] = state.result;
|
||
}
|
||
}
|
||
} else {
|
||
throwError(state, 'unknown tag !<' + state.tag + '>');
|
||
}
|
||
}
|
||
|
||
if (state.listener !== null) {
|
||
state.listener('close', state);
|
||
}
|
||
return state.tag !== null || state.anchor !== null || hasContent;
|
||
}
|
||
|
||
function readDocument(state) {
|
||
var documentStart = state.position,
|
||
_position,
|
||
directiveName,
|
||
directiveArgs,
|
||
hasDirectives = false,
|
||
ch;
|
||
|
||
state.version = null;
|
||
state.checkLineBreaks = state.legacy;
|
||
state.tagMap = {};
|
||
state.anchorMap = {};
|
||
|
||
while ((ch = state.input.charCodeAt(state.position)) !== 0) {
|
||
skipSeparationSpace(state, true, -1);
|
||
|
||
ch = state.input.charCodeAt(state.position);
|
||
|
||
if (state.lineIndent > 0 || ch !== 0x25/* % */) {
|
||
break;
|
||
}
|
||
|
||
hasDirectives = true;
|
||
ch = state.input.charCodeAt(++state.position);
|
||
_position = state.position;
|
||
|
||
while (ch !== 0 && !is_WS_OR_EOL(ch)) {
|
||
ch = state.input.charCodeAt(++state.position);
|
||
}
|
||
|
||
directiveName = state.input.slice(_position, state.position);
|
||
directiveArgs = [];
|
||
|
||
if (directiveName.length < 1) {
|
||
throwError(state, 'directive name must not be less than one character in length');
|
||
}
|
||
|
||
while (ch !== 0) {
|
||
while (is_WHITE_SPACE(ch)) {
|
||
ch = state.input.charCodeAt(++state.position);
|
||
}
|
||
|
||
if (ch === 0x23/* # */) {
|
||
do { ch = state.input.charCodeAt(++state.position); }
|
||
while (ch !== 0 && !is_EOL(ch));
|
||
break;
|
||
}
|
||
|
||
if (is_EOL(ch)) break;
|
||
|
||
_position = state.position;
|
||
|
||
while (ch !== 0 && !is_WS_OR_EOL(ch)) {
|
||
ch = state.input.charCodeAt(++state.position);
|
||
}
|
||
|
||
directiveArgs.push(state.input.slice(_position, state.position));
|
||
}
|
||
|
||
if (ch !== 0) readLineBreak(state);
|
||
|
||
if (_hasOwnProperty$2.call(directiveHandlers, directiveName)) {
|
||
directiveHandlers[directiveName](state, directiveName, directiveArgs);
|
||
} else {
|
||
throwWarning(state, 'unknown document directive "' + directiveName + '"');
|
||
}
|
||
}
|
||
|
||
skipSeparationSpace(state, true, -1);
|
||
|
||
if (state.lineIndent === 0 &&
|
||
state.input.charCodeAt(state.position) === 0x2D/* - */ &&
|
||
state.input.charCodeAt(state.position + 1) === 0x2D/* - */ &&
|
||
state.input.charCodeAt(state.position + 2) === 0x2D/* - */) {
|
||
state.position += 3;
|
||
skipSeparationSpace(state, true, -1);
|
||
|
||
} else if (hasDirectives) {
|
||
throwError(state, 'directives end mark is expected');
|
||
}
|
||
|
||
composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true);
|
||
skipSeparationSpace(state, true, -1);
|
||
|
||
if (state.checkLineBreaks &&
|
||
PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {
|
||
throwWarning(state, 'non-ASCII line breaks are interpreted as content');
|
||
}
|
||
|
||
state.documents.push(state.result);
|
||
|
||
if (state.position === state.lineStart && testDocumentSeparator(state)) {
|
||
|
||
if (state.input.charCodeAt(state.position) === 0x2E/* . */) {
|
||
state.position += 3;
|
||
skipSeparationSpace(state, true, -1);
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (state.position < (state.length - 1)) {
|
||
throwError(state, 'end of the stream or a document separator is expected');
|
||
} else {
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
function loadDocuments(input, options) {
|
||
input = String(input);
|
||
options = options || {};
|
||
|
||
if (input.length !== 0) {
|
||
|
||
// Add tailing `\n` if not exists
|
||
if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ &&
|
||
input.charCodeAt(input.length - 1) !== 0x0D/* CR */) {
|
||
input += '\n';
|
||
}
|
||
|
||
// Strip BOM
|
||
if (input.charCodeAt(0) === 0xFEFF) {
|
||
input = input.slice(1);
|
||
}
|
||
}
|
||
|
||
var state = new State$1(input, options);
|
||
|
||
var nullpos = input.indexOf('\0');
|
||
|
||
if (nullpos !== -1) {
|
||
state.position = nullpos;
|
||
throwError(state, 'null byte is not allowed in input');
|
||
}
|
||
|
||
// Use 0 as string terminator. That significantly simplifies bounds check.
|
||
state.input += '\0';
|
||
|
||
while (state.input.charCodeAt(state.position) === 0x20/* Space */) {
|
||
state.lineIndent += 1;
|
||
state.position += 1;
|
||
}
|
||
|
||
while (state.position < (state.length - 1)) {
|
||
readDocument(state);
|
||
}
|
||
|
||
return state.documents;
|
||
}
|
||
|
||
|
||
function loadAll(input, iterator, options) {
|
||
if (iterator !== null && typeof iterator === 'object' && typeof options === 'undefined') {
|
||
options = iterator;
|
||
iterator = null;
|
||
}
|
||
|
||
var documents = loadDocuments(input, options);
|
||
|
||
if (typeof iterator !== 'function') {
|
||
return documents;
|
||
}
|
||
|
||
for (var index = 0, length = documents.length; index < length; index += 1) {
|
||
iterator(documents[index]);
|
||
}
|
||
}
|
||
|
||
|
||
function load$1(input, options) {
|
||
var documents = loadDocuments(input, options);
|
||
|
||
if (documents.length === 0) {
|
||
/*eslint-disable no-undefined*/
|
||
return undefined;
|
||
} else if (documents.length === 1) {
|
||
return documents[0];
|
||
}
|
||
throw new YAMLException$1('expected a single document in the stream, but found more');
|
||
}
|
||
|
||
|
||
function safeLoadAll(input, iterator, options) {
|
||
if (typeof iterator === 'object' && iterator !== null && typeof options === 'undefined') {
|
||
options = iterator;
|
||
iterator = null;
|
||
}
|
||
|
||
return loadAll(input, iterator, common$1.extend({ schema: DEFAULT_SAFE_SCHEMA$1 }, options));
|
||
}
|
||
|
||
|
||
function safeLoad(input, options) {
|
||
return load$1(input, common$1.extend({ schema: DEFAULT_SAFE_SCHEMA$1 }, options));
|
||
}
|
||
|
||
|
||
loader$1.loadAll = loadAll;
|
||
loader$1.load = load$1;
|
||
loader$1.safeLoadAll = safeLoadAll;
|
||
loader$1.safeLoad = safeLoad;
|
||
|
||
var dumper$1 = {};
|
||
|
||
/*eslint-disable no-use-before-define*/
|
||
|
||
var common = common$6;
|
||
var YAMLException = exception;
|
||
var DEFAULT_FULL_SCHEMA = default_full;
|
||
var DEFAULT_SAFE_SCHEMA = default_safe;
|
||
|
||
var _toString = Object.prototype.toString;
|
||
var _hasOwnProperty$1 = Object.prototype.hasOwnProperty;
|
||
|
||
var CHAR_TAB = 0x09; /* Tab */
|
||
var CHAR_LINE_FEED = 0x0A; /* LF */
|
||
var CHAR_CARRIAGE_RETURN = 0x0D; /* CR */
|
||
var CHAR_SPACE = 0x20; /* Space */
|
||
var CHAR_EXCLAMATION = 0x21; /* ! */
|
||
var CHAR_DOUBLE_QUOTE = 0x22; /* " */
|
||
var CHAR_SHARP = 0x23; /* # */
|
||
var CHAR_PERCENT = 0x25; /* % */
|
||
var CHAR_AMPERSAND = 0x26; /* & */
|
||
var CHAR_SINGLE_QUOTE = 0x27; /* ' */
|
||
var CHAR_ASTERISK = 0x2A; /* * */
|
||
var CHAR_COMMA = 0x2C; /* , */
|
||
var CHAR_MINUS = 0x2D; /* - */
|
||
var CHAR_COLON = 0x3A; /* : */
|
||
var CHAR_EQUALS = 0x3D; /* = */
|
||
var CHAR_GREATER_THAN = 0x3E; /* > */
|
||
var CHAR_QUESTION = 0x3F; /* ? */
|
||
var CHAR_COMMERCIAL_AT = 0x40; /* @ */
|
||
var CHAR_LEFT_SQUARE_BRACKET = 0x5B; /* [ */
|
||
var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */
|
||
var CHAR_GRAVE_ACCENT = 0x60; /* ` */
|
||
var CHAR_LEFT_CURLY_BRACKET = 0x7B; /* { */
|
||
var CHAR_VERTICAL_LINE = 0x7C; /* | */
|
||
var CHAR_RIGHT_CURLY_BRACKET = 0x7D; /* } */
|
||
|
||
var ESCAPE_SEQUENCES = {};
|
||
|
||
ESCAPE_SEQUENCES[0x00] = '\\0';
|
||
ESCAPE_SEQUENCES[0x07] = '\\a';
|
||
ESCAPE_SEQUENCES[0x08] = '\\b';
|
||
ESCAPE_SEQUENCES[0x09] = '\\t';
|
||
ESCAPE_SEQUENCES[0x0A] = '\\n';
|
||
ESCAPE_SEQUENCES[0x0B] = '\\v';
|
||
ESCAPE_SEQUENCES[0x0C] = '\\f';
|
||
ESCAPE_SEQUENCES[0x0D] = '\\r';
|
||
ESCAPE_SEQUENCES[0x1B] = '\\e';
|
||
ESCAPE_SEQUENCES[0x22] = '\\"';
|
||
ESCAPE_SEQUENCES[0x5C] = '\\\\';
|
||
ESCAPE_SEQUENCES[0x85] = '\\N';
|
||
ESCAPE_SEQUENCES[0xA0] = '\\_';
|
||
ESCAPE_SEQUENCES[0x2028] = '\\L';
|
||
ESCAPE_SEQUENCES[0x2029] = '\\P';
|
||
|
||
var DEPRECATED_BOOLEANS_SYNTAX = [
|
||
'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',
|
||
'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'
|
||
];
|
||
|
||
function compileStyleMap(schema, map) {
|
||
var result, keys, index, length, tag, style, type;
|
||
|
||
if (map === null) return {};
|
||
|
||
result = {};
|
||
keys = Object.keys(map);
|
||
|
||
for (index = 0, length = keys.length; index < length; index += 1) {
|
||
tag = keys[index];
|
||
style = String(map[tag]);
|
||
|
||
if (tag.slice(0, 2) === '!!') {
|
||
tag = 'tag:yaml.org,2002:' + tag.slice(2);
|
||
}
|
||
type = schema.compiledTypeMap['fallback'][tag];
|
||
|
||
if (type && _hasOwnProperty$1.call(type.styleAliases, style)) {
|
||
style = type.styleAliases[style];
|
||
}
|
||
|
||
result[tag] = style;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
function encodeHex(character) {
|
||
var string, handle, length;
|
||
|
||
string = character.toString(16).toUpperCase();
|
||
|
||
if (character <= 0xFF) {
|
||
handle = 'x';
|
||
length = 2;
|
||
} else if (character <= 0xFFFF) {
|
||
handle = 'u';
|
||
length = 4;
|
||
} else if (character <= 0xFFFFFFFF) {
|
||
handle = 'U';
|
||
length = 8;
|
||
} else {
|
||
throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF');
|
||
}
|
||
|
||
return '\\' + handle + common.repeat('0', length - string.length) + string;
|
||
}
|
||
|
||
function State(options) {
|
||
this.schema = options['schema'] || DEFAULT_FULL_SCHEMA;
|
||
this.indent = Math.max(1, (options['indent'] || 2));
|
||
this.noArrayIndent = options['noArrayIndent'] || false;
|
||
this.skipInvalid = options['skipInvalid'] || false;
|
||
this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']);
|
||
this.styleMap = compileStyleMap(this.schema, options['styles'] || null);
|
||
this.sortKeys = options['sortKeys'] || false;
|
||
this.lineWidth = options['lineWidth'] || 80;
|
||
this.noRefs = options['noRefs'] || false;
|
||
this.noCompatMode = options['noCompatMode'] || false;
|
||
this.condenseFlow = options['condenseFlow'] || false;
|
||
|
||
this.implicitTypes = this.schema.compiledImplicit;
|
||
this.explicitTypes = this.schema.compiledExplicit;
|
||
|
||
this.tag = null;
|
||
this.result = '';
|
||
|
||
this.duplicates = [];
|
||
this.usedDuplicates = null;
|
||
}
|
||
|
||
// Indents every line in a string. Empty lines (\n only) are not indented.
|
||
function indentString(string, spaces) {
|
||
var ind = common.repeat(' ', spaces),
|
||
position = 0,
|
||
next = -1,
|
||
result = '',
|
||
line,
|
||
length = string.length;
|
||
|
||
while (position < length) {
|
||
next = string.indexOf('\n', position);
|
||
if (next === -1) {
|
||
line = string.slice(position);
|
||
position = length;
|
||
} else {
|
||
line = string.slice(position, next + 1);
|
||
position = next + 1;
|
||
}
|
||
|
||
if (line.length && line !== '\n') result += ind;
|
||
|
||
result += line;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
function generateNextLine(state, level) {
|
||
return '\n' + common.repeat(' ', state.indent * level);
|
||
}
|
||
|
||
function testImplicitResolving(state, str) {
|
||
var index, length, type;
|
||
|
||
for (index = 0, length = state.implicitTypes.length; index < length; index += 1) {
|
||
type = state.implicitTypes[index];
|
||
|
||
if (type.resolve(str)) {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
// [33] s-white ::= s-space | s-tab
|
||
function isWhitespace(c) {
|
||
return c === CHAR_SPACE || c === CHAR_TAB;
|
||
}
|
||
|
||
// Returns true if the character can be printed without escaping.
|
||
// From YAML 1.2: "any allowed characters known to be non-printable
|
||
// should also be escaped. [However,] This isn’t mandatory"
|
||
// Derived from nb-char - \t - #x85 - #xA0 - #x2028 - #x2029.
|
||
function isPrintable(c) {
|
||
return (0x00020 <= c && c <= 0x00007E)
|
||
|| ((0x000A1 <= c && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029)
|
||
|| ((0x0E000 <= c && c <= 0x00FFFD) && c !== 0xFEFF /* BOM */)
|
||
|| (0x10000 <= c && c <= 0x10FFFF);
|
||
}
|
||
|
||
// [34] ns-char ::= nb-char - s-white
|
||
// [27] nb-char ::= c-printable - b-char - c-byte-order-mark
|
||
// [26] b-char ::= b-line-feed | b-carriage-return
|
||
// [24] b-line-feed ::= #xA /* LF */
|
||
// [25] b-carriage-return ::= #xD /* CR */
|
||
// [3] c-byte-order-mark ::= #xFEFF
|
||
function isNsChar(c) {
|
||
return isPrintable(c) && !isWhitespace(c)
|
||
// byte-order-mark
|
||
&& c !== 0xFEFF
|
||
// b-char
|
||
&& c !== CHAR_CARRIAGE_RETURN
|
||
&& c !== CHAR_LINE_FEED;
|
||
}
|
||
|
||
// Simplified test for values allowed after the first character in plain style.
|
||
function isPlainSafe(c, prev) {
|
||
// Uses a subset of nb-char - c-flow-indicator - ":" - "#"
|
||
// where nb-char ::= c-printable - b-char - c-byte-order-mark.
|
||
return isPrintable(c) && c !== 0xFEFF
|
||
// - c-flow-indicator
|
||
&& c !== CHAR_COMMA
|
||
&& c !== CHAR_LEFT_SQUARE_BRACKET
|
||
&& c !== CHAR_RIGHT_SQUARE_BRACKET
|
||
&& c !== CHAR_LEFT_CURLY_BRACKET
|
||
&& c !== CHAR_RIGHT_CURLY_BRACKET
|
||
// - ":" - "#"
|
||
// /* An ns-char preceding */ "#"
|
||
&& c !== CHAR_COLON
|
||
&& ((c !== CHAR_SHARP) || (prev && isNsChar(prev)));
|
||
}
|
||
|
||
// Simplified test for values allowed as the first character in plain style.
|
||
function isPlainSafeFirst(c) {
|
||
// Uses a subset of ns-char - c-indicator
|
||
// where ns-char = nb-char - s-white.
|
||
return isPrintable(c) && c !== 0xFEFF
|
||
&& !isWhitespace(c) // - s-white
|
||
// - (c-indicator ::=
|
||
// “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”
|
||
&& c !== CHAR_MINUS
|
||
&& c !== CHAR_QUESTION
|
||
&& c !== CHAR_COLON
|
||
&& c !== CHAR_COMMA
|
||
&& c !== CHAR_LEFT_SQUARE_BRACKET
|
||
&& c !== CHAR_RIGHT_SQUARE_BRACKET
|
||
&& c !== CHAR_LEFT_CURLY_BRACKET
|
||
&& c !== CHAR_RIGHT_CURLY_BRACKET
|
||
// | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “"”
|
||
&& c !== CHAR_SHARP
|
||
&& c !== CHAR_AMPERSAND
|
||
&& c !== CHAR_ASTERISK
|
||
&& c !== CHAR_EXCLAMATION
|
||
&& c !== CHAR_VERTICAL_LINE
|
||
&& c !== CHAR_EQUALS
|
||
&& c !== CHAR_GREATER_THAN
|
||
&& c !== CHAR_SINGLE_QUOTE
|
||
&& c !== CHAR_DOUBLE_QUOTE
|
||
// | “%” | “@” | “`”)
|
||
&& c !== CHAR_PERCENT
|
||
&& c !== CHAR_COMMERCIAL_AT
|
||
&& c !== CHAR_GRAVE_ACCENT;
|
||
}
|
||
|
||
// Determines whether block indentation indicator is required.
|
||
function needIndentIndicator(string) {
|
||
var leadingSpaceRe = /^\n* /;
|
||
return leadingSpaceRe.test(string);
|
||
}
|
||
|
||
var STYLE_PLAIN = 1,
|
||
STYLE_SINGLE = 2,
|
||
STYLE_LITERAL = 3,
|
||
STYLE_FOLDED = 4,
|
||
STYLE_DOUBLE = 5;
|
||
|
||
// Determines which scalar styles are possible and returns the preferred style.
|
||
// lineWidth = -1 => no limit.
|
||
// Pre-conditions: str.length > 0.
|
||
// Post-conditions:
|
||
// STYLE_PLAIN or STYLE_SINGLE => no \n are in the string.
|
||
// STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).
|
||
// STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).
|
||
function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType) {
|
||
var i;
|
||
var char, prev_char;
|
||
var hasLineBreak = false;
|
||
var hasFoldableLine = false; // only checked if shouldTrackWidth
|
||
var shouldTrackWidth = lineWidth !== -1;
|
||
var previousLineBreak = -1; // count the first line correctly
|
||
var plain = isPlainSafeFirst(string.charCodeAt(0))
|
||
&& !isWhitespace(string.charCodeAt(string.length - 1));
|
||
|
||
if (singleLineOnly) {
|
||
// Case: no block styles.
|
||
// Check for disallowed characters to rule out plain and single.
|
||
for (i = 0; i < string.length; i++) {
|
||
char = string.charCodeAt(i);
|
||
if (!isPrintable(char)) {
|
||
return STYLE_DOUBLE;
|
||
}
|
||
prev_char = i > 0 ? string.charCodeAt(i - 1) : null;
|
||
plain = plain && isPlainSafe(char, prev_char);
|
||
}
|
||
} else {
|
||
// Case: block styles permitted.
|
||
for (i = 0; i < string.length; i++) {
|
||
char = string.charCodeAt(i);
|
||
if (char === CHAR_LINE_FEED) {
|
||
hasLineBreak = true;
|
||
// Check if any line can be folded.
|
||
if (shouldTrackWidth) {
|
||
hasFoldableLine = hasFoldableLine ||
|
||
// Foldable line = too long, and not more-indented.
|
||
(i - previousLineBreak - 1 > lineWidth &&
|
||
string[previousLineBreak + 1] !== ' ');
|
||
previousLineBreak = i;
|
||
}
|
||
} else if (!isPrintable(char)) {
|
||
return STYLE_DOUBLE;
|
||
}
|
||
prev_char = i > 0 ? string.charCodeAt(i - 1) : null;
|
||
plain = plain && isPlainSafe(char, prev_char);
|
||
}
|
||
// in case the end is missing a \n
|
||
hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&
|
||
(i - previousLineBreak - 1 > lineWidth &&
|
||
string[previousLineBreak + 1] !== ' '));
|
||
}
|
||
// Although every style can represent \n without escaping, prefer block styles
|
||
// for multiline, since they're more readable and they don't add empty lines.
|
||
// Also prefer folding a super-long line.
|
||
if (!hasLineBreak && !hasFoldableLine) {
|
||
// Strings interpretable as another type have to be quoted;
|
||
// e.g. the string 'true' vs. the boolean true.
|
||
return plain && !testAmbiguousType(string)
|
||
? STYLE_PLAIN : STYLE_SINGLE;
|
||
}
|
||
// Edge case: block indentation indicator can only have one digit.
|
||
if (indentPerLevel > 9 && needIndentIndicator(string)) {
|
||
return STYLE_DOUBLE;
|
||
}
|
||
// At this point we know block styles are valid.
|
||
// Prefer literal style unless we want to fold.
|
||
return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
|
||
}
|
||
|
||
// Note: line breaking/folding is implemented for only the folded style.
|
||
// NB. We drop the last trailing newline (if any) of a returned block scalar
|
||
// since the dumper adds its own newline. This always works:
|
||
// • No ending newline => unaffected; already using strip "-" chomping.
|
||
// • Ending newline => removed then restored.
|
||
// Importantly, this keeps the "+" chomp indicator from gaining an extra line.
|
||
function writeScalar(state, string, level, iskey) {
|
||
state.dump = (function () {
|
||
if (string.length === 0) {
|
||
return "''";
|
||
}
|
||
if (!state.noCompatMode &&
|
||
DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1) {
|
||
return "'" + string + "'";
|
||
}
|
||
|
||
var indent = state.indent * Math.max(1, level); // no 0-indent scalars
|
||
// As indentation gets deeper, let the width decrease monotonically
|
||
// to the lower bound min(state.lineWidth, 40).
|
||
// Note that this implies
|
||
// state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.
|
||
// state.lineWidth > 40 + state.indent: width decreases until the lower bound.
|
||
// This behaves better than a constant minimum width which disallows narrower options,
|
||
// or an indent threshold which causes the width to suddenly increase.
|
||
var lineWidth = state.lineWidth === -1
|
||
? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);
|
||
|
||
// Without knowing if keys are implicit/explicit, assume implicit for safety.
|
||
var singleLineOnly = iskey
|
||
// No block styles in flow mode.
|
||
|| (state.flowLevel > -1 && level >= state.flowLevel);
|
||
function testAmbiguity(string) {
|
||
return testImplicitResolving(state, string);
|
||
}
|
||
|
||
switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth, testAmbiguity)) {
|
||
case STYLE_PLAIN:
|
||
return string;
|
||
case STYLE_SINGLE:
|
||
return "'" + string.replace(/'/g, "''") + "'";
|
||
case STYLE_LITERAL:
|
||
return '|' + blockHeader(string, state.indent)
|
||
+ dropEndingNewline(indentString(string, indent));
|
||
case STYLE_FOLDED:
|
||
return '>' + blockHeader(string, state.indent)
|
||
+ dropEndingNewline(indentString(foldString(string, lineWidth), indent));
|
||
case STYLE_DOUBLE:
|
||
return '"' + escapeString(string) + '"';
|
||
default:
|
||
throw new YAMLException('impossible error: invalid scalar style');
|
||
}
|
||
}());
|
||
}
|
||
|
||
// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.
|
||
function blockHeader(string, indentPerLevel) {
|
||
var indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : '';
|
||
|
||
// note the special case: the string '\n' counts as a "trailing" empty line.
|
||
var clip = string[string.length - 1] === '\n';
|
||
var keep = clip && (string[string.length - 2] === '\n' || string === '\n');
|
||
var chomp = keep ? '+' : (clip ? '' : '-');
|
||
|
||
return indentIndicator + chomp + '\n';
|
||
}
|
||
|
||
// (See the note for writeScalar.)
|
||
function dropEndingNewline(string) {
|
||
return string[string.length - 1] === '\n' ? string.slice(0, -1) : string;
|
||
}
|
||
|
||
// Note: a long line without a suitable break point will exceed the width limit.
|
||
// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.
|
||
function foldString(string, width) {
|
||
// In folded style, $k$ consecutive newlines output as $k+1$ newlines—
|
||
// unless they're before or after a more-indented line, or at the very
|
||
// beginning or end, in which case $k$ maps to $k$.
|
||
// Therefore, parse each chunk as newline(s) followed by a content line.
|
||
var lineRe = /(\n+)([^\n]*)/g;
|
||
|
||
// first line (possibly an empty line)
|
||
var result = (function () {
|
||
var nextLF = string.indexOf('\n');
|
||
nextLF = nextLF !== -1 ? nextLF : string.length;
|
||
lineRe.lastIndex = nextLF;
|
||
return foldLine(string.slice(0, nextLF), width);
|
||
}());
|
||
// If we haven't reached the first content line yet, don't add an extra \n.
|
||
var prevMoreIndented = string[0] === '\n' || string[0] === ' ';
|
||
var moreIndented;
|
||
|
||
// rest of the lines
|
||
var match;
|
||
while ((match = lineRe.exec(string))) {
|
||
var prefix = match[1], line = match[2];
|
||
moreIndented = (line[0] === ' ');
|
||
result += prefix
|
||
+ (!prevMoreIndented && !moreIndented && line !== ''
|
||
? '\n' : '')
|
||
+ foldLine(line, width);
|
||
prevMoreIndented = moreIndented;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// Greedy line breaking.
|
||
// Picks the longest line under the limit each time,
|
||
// otherwise settles for the shortest line over the limit.
|
||
// NB. More-indented lines *cannot* be folded, as that would add an extra \n.
|
||
function foldLine(line, width) {
|
||
if (line === '' || line[0] === ' ') return line;
|
||
|
||
// Since a more-indented line adds a \n, breaks can't be followed by a space.
|
||
var breakRe = / [^ ]/g; // note: the match index will always be <= length-2.
|
||
var match;
|
||
// start is an inclusive index. end, curr, and next are exclusive.
|
||
var start = 0, end, curr = 0, next = 0;
|
||
var result = '';
|
||
|
||
// Invariants: 0 <= start <= length-1.
|
||
// 0 <= curr <= next <= max(0, length-2). curr - start <= width.
|
||
// Inside the loop:
|
||
// A match implies length >= 2, so curr and next are <= length-2.
|
||
while ((match = breakRe.exec(line))) {
|
||
next = match.index;
|
||
// maintain invariant: curr - start <= width
|
||
if (next - start > width) {
|
||
end = (curr > start) ? curr : next; // derive end <= length-2
|
||
result += '\n' + line.slice(start, end);
|
||
// skip the space that was output as \n
|
||
start = end + 1; // derive start <= length-1
|
||
}
|
||
curr = next;
|
||
}
|
||
|
||
// By the invariants, start <= length-1, so there is something left over.
|
||
// It is either the whole string or a part starting from non-whitespace.
|
||
result += '\n';
|
||
// Insert a break if the remainder is too long and there is a break available.
|
||
if (line.length - start > width && curr > start) {
|
||
result += line.slice(start, curr) + '\n' + line.slice(curr + 1);
|
||
} else {
|
||
result += line.slice(start);
|
||
}
|
||
|
||
return result.slice(1); // drop extra \n joiner
|
||
}
|
||
|
||
// Escapes a double-quoted string.
|
||
function escapeString(string) {
|
||
var result = '';
|
||
var char, nextChar;
|
||
var escapeSeq;
|
||
|
||
for (var i = 0; i < string.length; i++) {
|
||
char = string.charCodeAt(i);
|
||
// Check for surrogate pairs (reference Unicode 3.0 section "3.7 Surrogates").
|
||
if (char >= 0xD800 && char <= 0xDBFF/* high surrogate */) {
|
||
nextChar = string.charCodeAt(i + 1);
|
||
if (nextChar >= 0xDC00 && nextChar <= 0xDFFF/* low surrogate */) {
|
||
// Combine the surrogate pair and store it escaped.
|
||
result += encodeHex((char - 0xD800) * 0x400 + nextChar - 0xDC00 + 0x10000);
|
||
// Advance index one extra since we already used that char here.
|
||
i++; continue;
|
||
}
|
||
}
|
||
escapeSeq = ESCAPE_SEQUENCES[char];
|
||
result += !escapeSeq && isPrintable(char)
|
||
? string[i]
|
||
: escapeSeq || encodeHex(char);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
function writeFlowSequence(state, level, object) {
|
||
var _result = '',
|
||
_tag = state.tag,
|
||
index,
|
||
length;
|
||
|
||
for (index = 0, length = object.length; index < length; index += 1) {
|
||
// Write only valid elements.
|
||
if (writeNode(state, level, object[index], false, false)) {
|
||
if (index !== 0) _result += ',' + (!state.condenseFlow ? ' ' : '');
|
||
_result += state.dump;
|
||
}
|
||
}
|
||
|
||
state.tag = _tag;
|
||
state.dump = '[' + _result + ']';
|
||
}
|
||
|
||
function writeBlockSequence(state, level, object, compact) {
|
||
var _result = '',
|
||
_tag = state.tag,
|
||
index,
|
||
length;
|
||
|
||
for (index = 0, length = object.length; index < length; index += 1) {
|
||
// Write only valid elements.
|
||
if (writeNode(state, level + 1, object[index], true, true)) {
|
||
if (!compact || index !== 0) {
|
||
_result += generateNextLine(state, level);
|
||
}
|
||
|
||
if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
|
||
_result += '-';
|
||
} else {
|
||
_result += '- ';
|
||
}
|
||
|
||
_result += state.dump;
|
||
}
|
||
}
|
||
|
||
state.tag = _tag;
|
||
state.dump = _result || '[]'; // Empty sequence if no valid values.
|
||
}
|
||
|
||
function writeFlowMapping(state, level, object) {
|
||
var _result = '',
|
||
_tag = state.tag,
|
||
objectKeyList = Object.keys(object),
|
||
index,
|
||
length,
|
||
objectKey,
|
||
objectValue,
|
||
pairBuffer;
|
||
|
||
for (index = 0, length = objectKeyList.length; index < length; index += 1) {
|
||
|
||
pairBuffer = '';
|
||
if (index !== 0) pairBuffer += ', ';
|
||
|
||
if (state.condenseFlow) pairBuffer += '"';
|
||
|
||
objectKey = objectKeyList[index];
|
||
objectValue = object[objectKey];
|
||
|
||
if (!writeNode(state, level, objectKey, false, false)) {
|
||
continue; // Skip this pair because of invalid key;
|
||
}
|
||
|
||
if (state.dump.length > 1024) pairBuffer += '? ';
|
||
|
||
pairBuffer += state.dump + (state.condenseFlow ? '"' : '') + ':' + (state.condenseFlow ? '' : ' ');
|
||
|
||
if (!writeNode(state, level, objectValue, false, false)) {
|
||
continue; // Skip this pair because of invalid value.
|
||
}
|
||
|
||
pairBuffer += state.dump;
|
||
|
||
// Both key and value are valid.
|
||
_result += pairBuffer;
|
||
}
|
||
|
||
state.tag = _tag;
|
||
state.dump = '{' + _result + '}';
|
||
}
|
||
|
||
function writeBlockMapping(state, level, object, compact) {
|
||
var _result = '',
|
||
_tag = state.tag,
|
||
objectKeyList = Object.keys(object),
|
||
index,
|
||
length,
|
||
objectKey,
|
||
objectValue,
|
||
explicitPair,
|
||
pairBuffer;
|
||
|
||
// Allow sorting keys so that the output file is deterministic
|
||
if (state.sortKeys === true) {
|
||
// Default sorting
|
||
objectKeyList.sort();
|
||
} else if (typeof state.sortKeys === 'function') {
|
||
// Custom sort function
|
||
objectKeyList.sort(state.sortKeys);
|
||
} else if (state.sortKeys) {
|
||
// Something is wrong
|
||
throw new YAMLException('sortKeys must be a boolean or a function');
|
||
}
|
||
|
||
for (index = 0, length = objectKeyList.length; index < length; index += 1) {
|
||
pairBuffer = '';
|
||
|
||
if (!compact || index !== 0) {
|
||
pairBuffer += generateNextLine(state, level);
|
||
}
|
||
|
||
objectKey = objectKeyList[index];
|
||
objectValue = object[objectKey];
|
||
|
||
if (!writeNode(state, level + 1, objectKey, true, true, true)) {
|
||
continue; // Skip this pair because of invalid key.
|
||
}
|
||
|
||
explicitPair = (state.tag !== null && state.tag !== '?') ||
|
||
(state.dump && state.dump.length > 1024);
|
||
|
||
if (explicitPair) {
|
||
if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
|
||
pairBuffer += '?';
|
||
} else {
|
||
pairBuffer += '? ';
|
||
}
|
||
}
|
||
|
||
pairBuffer += state.dump;
|
||
|
||
if (explicitPair) {
|
||
pairBuffer += generateNextLine(state, level);
|
||
}
|
||
|
||
if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
|
||
continue; // Skip this pair because of invalid value.
|
||
}
|
||
|
||
if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
|
||
pairBuffer += ':';
|
||
} else {
|
||
pairBuffer += ': ';
|
||
}
|
||
|
||
pairBuffer += state.dump;
|
||
|
||
// Both key and value are valid.
|
||
_result += pairBuffer;
|
||
}
|
||
|
||
state.tag = _tag;
|
||
state.dump = _result || '{}'; // Empty mapping if no valid pairs.
|
||
}
|
||
|
||
function detectType(state, object, explicit) {
|
||
var _result, typeList, index, length, type, style;
|
||
|
||
typeList = explicit ? state.explicitTypes : state.implicitTypes;
|
||
|
||
for (index = 0, length = typeList.length; index < length; index += 1) {
|
||
type = typeList[index];
|
||
|
||
if ((type.instanceOf || type.predicate) &&
|
||
(!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&
|
||
(!type.predicate || type.predicate(object))) {
|
||
|
||
state.tag = explicit ? type.tag : '?';
|
||
|
||
if (type.represent) {
|
||
style = state.styleMap[type.tag] || type.defaultStyle;
|
||
|
||
if (_toString.call(type.represent) === '[object Function]') {
|
||
_result = type.represent(object, style);
|
||
} else if (_hasOwnProperty$1.call(type.represent, style)) {
|
||
_result = type.represent[style](object, style);
|
||
} else {
|
||
throw new YAMLException('!<' + type.tag + '> tag resolver accepts not "' + style + '" style');
|
||
}
|
||
|
||
state.dump = _result;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
// Serializes `object` and writes it to global `result`.
|
||
// Returns true on success, or false on invalid object.
|
||
//
|
||
function writeNode(state, level, object, block, compact, iskey) {
|
||
state.tag = null;
|
||
state.dump = object;
|
||
|
||
if (!detectType(state, object, false)) {
|
||
detectType(state, object, true);
|
||
}
|
||
|
||
var type = _toString.call(state.dump);
|
||
|
||
if (block) {
|
||
block = (state.flowLevel < 0 || state.flowLevel > level);
|
||
}
|
||
|
||
var objectOrArray = type === '[object Object]' || type === '[object Array]',
|
||
duplicateIndex,
|
||
duplicate;
|
||
|
||
if (objectOrArray) {
|
||
duplicateIndex = state.duplicates.indexOf(object);
|
||
duplicate = duplicateIndex !== -1;
|
||
}
|
||
|
||
if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {
|
||
compact = false;
|
||
}
|
||
|
||
if (duplicate && state.usedDuplicates[duplicateIndex]) {
|
||
state.dump = '*ref_' + duplicateIndex;
|
||
} else {
|
||
if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
|
||
state.usedDuplicates[duplicateIndex] = true;
|
||
}
|
||
if (type === '[object Object]') {
|
||
if (block && (Object.keys(state.dump).length !== 0)) {
|
||
writeBlockMapping(state, level, state.dump, compact);
|
||
if (duplicate) {
|
||
state.dump = '&ref_' + duplicateIndex + state.dump;
|
||
}
|
||
} else {
|
||
writeFlowMapping(state, level, state.dump);
|
||
if (duplicate) {
|
||
state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
|
||
}
|
||
}
|
||
} else if (type === '[object Array]') {
|
||
var arrayLevel = (state.noArrayIndent && (level > 0)) ? level - 1 : level;
|
||
if (block && (state.dump.length !== 0)) {
|
||
writeBlockSequence(state, arrayLevel, state.dump, compact);
|
||
if (duplicate) {
|
||
state.dump = '&ref_' + duplicateIndex + state.dump;
|
||
}
|
||
} else {
|
||
writeFlowSequence(state, arrayLevel, state.dump);
|
||
if (duplicate) {
|
||
state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
|
||
}
|
||
}
|
||
} else if (type === '[object String]') {
|
||
if (state.tag !== '?') {
|
||
writeScalar(state, state.dump, level, iskey);
|
||
}
|
||
} else {
|
||
if (state.skipInvalid) return false;
|
||
throw new YAMLException('unacceptable kind of an object to dump ' + type);
|
||
}
|
||
|
||
if (state.tag !== null && state.tag !== '?') {
|
||
state.dump = '!<' + state.tag + '> ' + state.dump;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
function getDuplicateReferences(object, state) {
|
||
var objects = [],
|
||
duplicatesIndexes = [],
|
||
index,
|
||
length;
|
||
|
||
inspectNode(object, objects, duplicatesIndexes);
|
||
|
||
for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) {
|
||
state.duplicates.push(objects[duplicatesIndexes[index]]);
|
||
}
|
||
state.usedDuplicates = new Array(length);
|
||
}
|
||
|
||
function inspectNode(object, objects, duplicatesIndexes) {
|
||
var objectKeyList,
|
||
index,
|
||
length;
|
||
|
||
if (object !== null && typeof object === 'object') {
|
||
index = objects.indexOf(object);
|
||
if (index !== -1) {
|
||
if (duplicatesIndexes.indexOf(index) === -1) {
|
||
duplicatesIndexes.push(index);
|
||
}
|
||
} else {
|
||
objects.push(object);
|
||
|
||
if (Array.isArray(object)) {
|
||
for (index = 0, length = object.length; index < length; index += 1) {
|
||
inspectNode(object[index], objects, duplicatesIndexes);
|
||
}
|
||
} else {
|
||
objectKeyList = Object.keys(object);
|
||
|
||
for (index = 0, length = objectKeyList.length; index < length; index += 1) {
|
||
inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
function dump(input, options) {
|
||
options = options || {};
|
||
|
||
var state = new State(options);
|
||
|
||
if (!state.noRefs) getDuplicateReferences(input, state);
|
||
|
||
if (writeNode(state, 0, input, true, true)) return state.dump + '\n';
|
||
|
||
return '';
|
||
}
|
||
|
||
function safeDump(input, options) {
|
||
return dump(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options));
|
||
}
|
||
|
||
dumper$1.dump = dump;
|
||
dumper$1.safeDump = safeDump;
|
||
|
||
var loader = loader$1;
|
||
var dumper = dumper$1;
|
||
|
||
|
||
function deprecated(name) {
|
||
return function () {
|
||
throw new Error('Function ' + name + ' is deprecated and cannot be used.');
|
||
};
|
||
}
|
||
|
||
|
||
jsYaml$1.Type = type;
|
||
jsYaml$1.Schema = schema;
|
||
jsYaml$1.FAILSAFE_SCHEMA = failsafe;
|
||
jsYaml$1.JSON_SCHEMA = json;
|
||
jsYaml$1.CORE_SCHEMA = core$1;
|
||
jsYaml$1.DEFAULT_SAFE_SCHEMA = default_safe;
|
||
jsYaml$1.DEFAULT_FULL_SCHEMA = default_full;
|
||
jsYaml$1.load = loader.load;
|
||
jsYaml$1.loadAll = loader.loadAll;
|
||
jsYaml$1.safeLoad = loader.safeLoad;
|
||
jsYaml$1.safeLoadAll = loader.safeLoadAll;
|
||
jsYaml$1.dump = dumper.dump;
|
||
jsYaml$1.safeDump = dumper.safeDump;
|
||
jsYaml$1.YAMLException = exception;
|
||
|
||
// Deprecated schema names from JS-YAML 2.0.x
|
||
jsYaml$1.MINIMAL_SCHEMA = failsafe;
|
||
jsYaml$1.SAFE_SCHEMA = default_safe;
|
||
jsYaml$1.DEFAULT_SCHEMA = default_full;
|
||
|
||
// Deprecated functions from JS-YAML 1.x.x
|
||
jsYaml$1.scan = deprecated('scan');
|
||
jsYaml$1.parse = deprecated('parse');
|
||
jsYaml$1.compose = deprecated('compose');
|
||
jsYaml$1.addConstructor = deprecated('addConstructor');
|
||
|
||
var yaml = jsYaml$1;
|
||
|
||
|
||
var jsYaml = yaml;
|
||
|
||
(function (module, exports) {
|
||
|
||
const yaml = jsYaml;
|
||
|
||
/**
|
||
* Default engines
|
||
*/
|
||
|
||
const engines = module.exports;
|
||
|
||
/**
|
||
* YAML
|
||
*/
|
||
|
||
engines.yaml = {
|
||
parse: yaml.safeLoad.bind(yaml),
|
||
stringify: yaml.safeDump.bind(yaml)
|
||
};
|
||
|
||
/**
|
||
* JSON
|
||
*/
|
||
|
||
engines.json = {
|
||
parse: JSON.parse.bind(JSON),
|
||
stringify: function(obj, options) {
|
||
const opts = Object.assign({replacer: null, space: 2}, options);
|
||
return JSON.stringify(obj, opts.replacer, opts.space);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* JavaScript
|
||
*/
|
||
|
||
engines.javascript = {
|
||
parse: function parse(str, options, wrap) {
|
||
/* eslint no-eval: 0 */
|
||
try {
|
||
if (wrap !== false) {
|
||
str = '(function() {\nreturn ' + str.trim() + ';\n}());';
|
||
}
|
||
return eval(str) || {};
|
||
} catch (err) {
|
||
if (wrap !== false && /(unexpected|identifier)/i.test(err.message)) {
|
||
return parse(str, options, false);
|
||
}
|
||
throw new SyntaxError(err);
|
||
}
|
||
},
|
||
stringify: function() {
|
||
throw new Error('stringifying JavaScript is not supported');
|
||
}
|
||
};
|
||
} (engines$2));
|
||
|
||
var enginesExports = engines$2.exports;
|
||
|
||
var utils$7 = {};
|
||
|
||
/*!
|
||
* strip-bom-string <https://github.com/jonschlinkert/strip-bom-string>
|
||
*
|
||
* Copyright (c) 2015, 2017, Jon Schlinkert.
|
||
* Released under the MIT License.
|
||
*/
|
||
|
||
var stripBomString = function(str) {
|
||
if (typeof str === 'string' && str.charAt(0) === '\ufeff') {
|
||
return str.slice(1);
|
||
}
|
||
return str;
|
||
};
|
||
|
||
(function (exports) {
|
||
|
||
const stripBom = stripBomString;
|
||
const typeOf = kindOf;
|
||
|
||
exports.define = function(obj, key, val) {
|
||
Reflect.defineProperty(obj, key, {
|
||
enumerable: false,
|
||
configurable: true,
|
||
writable: true,
|
||
value: val
|
||
});
|
||
};
|
||
|
||
/**
|
||
* Returns true if `val` is a buffer
|
||
*/
|
||
|
||
exports.isBuffer = function(val) {
|
||
return typeOf(val) === 'buffer';
|
||
};
|
||
|
||
/**
|
||
* Returns true if `val` is an object
|
||
*/
|
||
|
||
exports.isObject = function(val) {
|
||
return typeOf(val) === 'object';
|
||
};
|
||
|
||
/**
|
||
* Cast `input` to a buffer
|
||
*/
|
||
|
||
exports.toBuffer = function(input) {
|
||
return typeof input === 'string' ? Buffer.from(input) : input;
|
||
};
|
||
|
||
/**
|
||
* Cast `val` to a string.
|
||
*/
|
||
|
||
exports.toString = function(input) {
|
||
if (exports.isBuffer(input)) return stripBom(String(input));
|
||
if (typeof input !== 'string') {
|
||
throw new TypeError('expected input to be a string or buffer');
|
||
}
|
||
return stripBom(input);
|
||
};
|
||
|
||
/**
|
||
* Cast `val` to an array.
|
||
*/
|
||
|
||
exports.arrayify = function(val) {
|
||
return val ? (Array.isArray(val) ? val : [val]) : [];
|
||
};
|
||
|
||
/**
|
||
* Returns true if `str` starts with `substr`.
|
||
*/
|
||
|
||
exports.startsWith = function(str, substr, len) {
|
||
if (typeof len !== 'number') len = substr.length;
|
||
return str.slice(0, len) === substr;
|
||
};
|
||
} (utils$7));
|
||
|
||
const engines$1 = enginesExports;
|
||
const utils$6 = utils$7;
|
||
|
||
var defaults$4 = function(options) {
|
||
const opts = Object.assign({}, options);
|
||
|
||
// ensure that delimiters are an array
|
||
opts.delimiters = utils$6.arrayify(opts.delims || opts.delimiters || '---');
|
||
if (opts.delimiters.length === 1) {
|
||
opts.delimiters.push(opts.delimiters[0]);
|
||
}
|
||
|
||
opts.language = (opts.language || opts.lang || 'yaml').toLowerCase();
|
||
opts.engines = Object.assign({}, engines$1, opts.parsers, opts.engines);
|
||
return opts;
|
||
};
|
||
|
||
var engine = function(name, options) {
|
||
let engine = options.engines[name] || options.engines[aliase(name)];
|
||
if (typeof engine === 'undefined') {
|
||
throw new Error('gray-matter engine "' + name + '" is not registered');
|
||
}
|
||
if (typeof engine === 'function') {
|
||
engine = { parse: engine };
|
||
}
|
||
return engine;
|
||
};
|
||
|
||
function aliase(name) {
|
||
switch (name.toLowerCase()) {
|
||
case 'js':
|
||
case 'javascript':
|
||
return 'javascript';
|
||
case 'coffee':
|
||
case 'coffeescript':
|
||
case 'cson':
|
||
return 'coffee';
|
||
case 'yaml':
|
||
case 'yml':
|
||
return 'yaml';
|
||
default: {
|
||
return name;
|
||
}
|
||
}
|
||
}
|
||
|
||
const typeOf$1 = kindOf;
|
||
const getEngine$1 = engine;
|
||
const defaults$3 = defaults$4;
|
||
|
||
var stringify$2 = function(file, data, options) {
|
||
if (data == null && options == null) {
|
||
switch (typeOf$1(file)) {
|
||
case 'object':
|
||
data = file.data;
|
||
options = {};
|
||
break;
|
||
case 'string':
|
||
return file;
|
||
default: {
|
||
throw new TypeError('expected file to be a string or object');
|
||
}
|
||
}
|
||
}
|
||
|
||
const str = file.content;
|
||
const opts = defaults$3(options);
|
||
if (data == null) {
|
||
if (!opts.data) return file;
|
||
data = opts.data;
|
||
}
|
||
|
||
const language = file.language || opts.language;
|
||
const engine = getEngine$1(language, opts);
|
||
if (typeof engine.stringify !== 'function') {
|
||
throw new TypeError('expected "' + language + '.stringify" to be a function');
|
||
}
|
||
|
||
data = Object.assign({}, file.data, data);
|
||
const open = opts.delimiters[0];
|
||
const close = opts.delimiters[1];
|
||
const matter = engine.stringify(data, options).trim();
|
||
let buf = '';
|
||
|
||
if (matter !== '{}') {
|
||
buf = newline$1(open) + newline$1(matter) + newline$1(close);
|
||
}
|
||
|
||
if (typeof file.excerpt === 'string' && file.excerpt !== '') {
|
||
if (str.indexOf(file.excerpt.trim()) === -1) {
|
||
buf += newline$1(file.excerpt) + newline$1(close);
|
||
}
|
||
}
|
||
|
||
return buf + newline$1(str);
|
||
};
|
||
|
||
function newline$1(str) {
|
||
return str.slice(-1) !== '\n' ? str + '\n' : str;
|
||
}
|
||
|
||
const defaults$2 = defaults$4;
|
||
|
||
var excerpt$1 = function(file, options) {
|
||
const opts = defaults$2(options);
|
||
|
||
if (file.data == null) {
|
||
file.data = {};
|
||
}
|
||
|
||
if (typeof opts.excerpt === 'function') {
|
||
return opts.excerpt(file, opts);
|
||
}
|
||
|
||
const sep = file.data.excerpt_separator || opts.excerpt_separator;
|
||
if (sep == null && (opts.excerpt === false || opts.excerpt == null)) {
|
||
return file;
|
||
}
|
||
|
||
const delimiter = typeof opts.excerpt === 'string'
|
||
? opts.excerpt
|
||
: (sep || opts.delimiters[0]);
|
||
|
||
// if enabled, get the excerpt defined after front-matter
|
||
const idx = file.content.indexOf(delimiter);
|
||
if (idx !== -1) {
|
||
file.excerpt = file.content.slice(0, idx);
|
||
}
|
||
|
||
return file;
|
||
};
|
||
|
||
const typeOf = kindOf;
|
||
const stringify$1 = stringify$2;
|
||
const utils$5 = utils$7;
|
||
|
||
/**
|
||
* Normalize the given value to ensure an object is returned
|
||
* with the expected properties.
|
||
*/
|
||
|
||
var toFile$1 = function(file) {
|
||
if (typeOf(file) !== 'object') {
|
||
file = { content: file };
|
||
}
|
||
|
||
if (typeOf(file.data) !== 'object') {
|
||
file.data = {};
|
||
}
|
||
|
||
// if file was passed as an object, ensure that
|
||
// "file.content" is set
|
||
if (file.contents && file.content == null) {
|
||
file.content = file.contents;
|
||
}
|
||
|
||
// set non-enumerable properties on the file object
|
||
utils$5.define(file, 'orig', utils$5.toBuffer(file.content));
|
||
utils$5.define(file, 'language', file.language || '');
|
||
utils$5.define(file, 'matter', file.matter || '');
|
||
utils$5.define(file, 'stringify', function(data, options) {
|
||
if (options && options.language) {
|
||
file.language = options.language;
|
||
}
|
||
return stringify$1(file, data, options);
|
||
});
|
||
|
||
// strip BOM and ensure that "file.content" is a string
|
||
file.content = utils$5.toString(file.content);
|
||
file.isEmpty = false;
|
||
file.excerpt = '';
|
||
return file;
|
||
};
|
||
|
||
const getEngine = engine;
|
||
const defaults$1 = defaults$4;
|
||
|
||
var parse$7 = function(language, str, options) {
|
||
const opts = defaults$1(options);
|
||
const engine = getEngine(language, opts);
|
||
if (typeof engine.parse !== 'function') {
|
||
throw new TypeError('expected "' + language + '.parse" to be a function');
|
||
}
|
||
return engine.parse(str, opts);
|
||
};
|
||
|
||
const fs$1 = fs__default;
|
||
const sections = sectionMatter;
|
||
const defaults = defaults$4;
|
||
const stringify = stringify$2;
|
||
const excerpt = excerpt$1;
|
||
const engines = enginesExports;
|
||
const toFile = toFile$1;
|
||
const parse$6 = parse$7;
|
||
const utils$4 = utils$7;
|
||
|
||
/**
|
||
* Takes a string or object with `content` property, extracts
|
||
* and parses front-matter from the string, then returns an object
|
||
* with `data`, `content` and other [useful properties](#returned-object).
|
||
*
|
||
* ```js
|
||
* const matter = require('gray-matter');
|
||
* console.log(matter('---\ntitle: Home\n---\nOther stuff'));
|
||
* //=> { data: { title: 'Home'}, content: 'Other stuff' }
|
||
* ```
|
||
* @param {Object|String} `input` String, or object with `content` string
|
||
* @param {Object} `options`
|
||
* @return {Object}
|
||
* @api public
|
||
*/
|
||
|
||
function matter(input, options) {
|
||
if (input === '') {
|
||
return { data: {}, content: input, excerpt: '', orig: input };
|
||
}
|
||
|
||
let file = toFile(input);
|
||
const cached = matter.cache[file.content];
|
||
|
||
if (!options) {
|
||
if (cached) {
|
||
file = Object.assign({}, cached);
|
||
file.orig = cached.orig;
|
||
return file;
|
||
}
|
||
|
||
// only cache if there are no options passed. if we cache when options
|
||
// are passed, we would need to also cache options values, which would
|
||
// negate any performance benefits of caching
|
||
matter.cache[file.content] = file;
|
||
}
|
||
|
||
return parseMatter(file, options);
|
||
}
|
||
|
||
/**
|
||
* Parse front matter
|
||
*/
|
||
|
||
function parseMatter(file, options) {
|
||
const opts = defaults(options);
|
||
const open = opts.delimiters[0];
|
||
const close = '\n' + opts.delimiters[1];
|
||
let str = file.content;
|
||
|
||
if (opts.language) {
|
||
file.language = opts.language;
|
||
}
|
||
|
||
// get the length of the opening delimiter
|
||
const openLen = open.length;
|
||
if (!utils$4.startsWith(str, open, openLen)) {
|
||
excerpt(file, opts);
|
||
return file;
|
||
}
|
||
|
||
// if the next character after the opening delimiter is
|
||
// a character from the delimiter, then it's not a front-
|
||
// matter delimiter
|
||
if (str.charAt(openLen) === open.slice(-1)) {
|
||
return file;
|
||
}
|
||
|
||
// strip the opening delimiter
|
||
str = str.slice(openLen);
|
||
const len = str.length;
|
||
|
||
// use the language defined after first delimiter, if it exists
|
||
const language = matter.language(str, opts);
|
||
if (language.name) {
|
||
file.language = language.name;
|
||
str = str.slice(language.raw.length);
|
||
}
|
||
|
||
// get the index of the closing delimiter
|
||
let closeIndex = str.indexOf(close);
|
||
if (closeIndex === -1) {
|
||
closeIndex = len;
|
||
}
|
||
|
||
// get the raw front-matter block
|
||
file.matter = str.slice(0, closeIndex);
|
||
|
||
const block = file.matter.replace(/^\s*#[^\n]+/gm, '').trim();
|
||
if (block === '') {
|
||
file.isEmpty = true;
|
||
file.empty = file.content;
|
||
file.data = {};
|
||
} else {
|
||
|
||
// create file.data by parsing the raw file.matter block
|
||
file.data = parse$6(file.language, file.matter, opts);
|
||
}
|
||
|
||
// update file.content
|
||
if (closeIndex === len) {
|
||
file.content = '';
|
||
} else {
|
||
file.content = str.slice(closeIndex + close.length);
|
||
if (file.content[0] === '\r') {
|
||
file.content = file.content.slice(1);
|
||
}
|
||
if (file.content[0] === '\n') {
|
||
file.content = file.content.slice(1);
|
||
}
|
||
}
|
||
|
||
excerpt(file, opts);
|
||
|
||
if (opts.sections === true || typeof opts.section === 'function') {
|
||
sections(file, opts.section);
|
||
}
|
||
return file;
|
||
}
|
||
|
||
/**
|
||
* Expose engines
|
||
*/
|
||
|
||
matter.engines = engines;
|
||
|
||
/**
|
||
* Stringify an object to YAML or the specified language, and
|
||
* append it to the given string. By default, only YAML and JSON
|
||
* can be stringified. See the [engines](#engines) section to learn
|
||
* how to stringify other languages.
|
||
*
|
||
* ```js
|
||
* console.log(matter.stringify('foo bar baz', {title: 'Home'}));
|
||
* // results in:
|
||
* // ---
|
||
* // title: Home
|
||
* // ---
|
||
* // foo bar baz
|
||
* ```
|
||
* @param {String|Object} `file` The content string to append to stringified front-matter, or a file object with `file.content` string.
|
||
* @param {Object} `data` Front matter to stringify.
|
||
* @param {Object} `options` [Options](#options) to pass to gray-matter and [js-yaml].
|
||
* @return {String} Returns a string created by wrapping stringified yaml with delimiters, and appending that to the given string.
|
||
* @api public
|
||
*/
|
||
|
||
matter.stringify = function(file, data, options) {
|
||
if (typeof file === 'string') file = matter(file, options);
|
||
return stringify(file, data, options);
|
||
};
|
||
|
||
/**
|
||
* Synchronously read a file from the file system and parse
|
||
* front matter. Returns the same object as the [main function](#matter).
|
||
*
|
||
* ```js
|
||
* const file = matter.read('./content/blog-post.md');
|
||
* ```
|
||
* @param {String} `filepath` file path of the file to read.
|
||
* @param {Object} `options` [Options](#options) to pass to gray-matter.
|
||
* @return {Object} Returns [an object](#returned-object) with `data` and `content`
|
||
* @api public
|
||
*/
|
||
|
||
matter.read = function(filepath, options) {
|
||
const str = fs$1.readFileSync(filepath, 'utf8');
|
||
const file = matter(str, options);
|
||
file.path = filepath;
|
||
return file;
|
||
};
|
||
|
||
/**
|
||
* Returns true if the given `string` has front matter.
|
||
* @param {String} `string`
|
||
* @param {Object} `options`
|
||
* @return {Boolean} True if front matter exists.
|
||
* @api public
|
||
*/
|
||
|
||
matter.test = function(str, options) {
|
||
return utils$4.startsWith(str, defaults(options).delimiters[0]);
|
||
};
|
||
|
||
/**
|
||
* Detect the language to use, if one is defined after the
|
||
* first front-matter delimiter.
|
||
* @param {String} `string`
|
||
* @param {Object} `options`
|
||
* @return {Object} Object with `raw` (actual language string), and `name`, the language with whitespace trimmed
|
||
*/
|
||
|
||
matter.language = function(str, options) {
|
||
const opts = defaults(options);
|
||
const open = opts.delimiters[0];
|
||
|
||
if (matter.test(str)) {
|
||
str = str.slice(open.length);
|
||
}
|
||
|
||
const language = str.slice(0, str.search(/\r?\n/));
|
||
return {
|
||
raw: language,
|
||
name: language ? language.trim() : ''
|
||
};
|
||
};
|
||
|
||
/**
|
||
* Expose `matter`
|
||
*/
|
||
|
||
matter.cache = {};
|
||
matter.clearCache = function() {
|
||
matter.cache = {};
|
||
};
|
||
var grayMatter = matter;
|
||
|
||
var matter$1 = /*@__PURE__*/getDefaultExportFromCjs(grayMatter);
|
||
|
||
const frontmatterPlugin = (md, { grayMatterOptions, renderExcerpt = true } = {}) => {
|
||
const render = md.render.bind(md);
|
||
md.render = (src, env = {}) => {
|
||
const { data, content, excerpt = "" } = matter$1(src, grayMatterOptions);
|
||
env.content = content;
|
||
env.frontmatter = {
|
||
// allow providing default value
|
||
...env.frontmatter,
|
||
...data
|
||
};
|
||
env.excerpt = renderExcerpt && excerpt ? (
|
||
// render the excerpt with original markdown-it render method.
|
||
// here we spread `env` to avoid mutating the original object.
|
||
// using deep clone might be a safer choice.
|
||
render(excerpt, { ...env })
|
||
) : (
|
||
// use the raw excerpt directly
|
||
excerpt
|
||
);
|
||
return render(content, env);
|
||
};
|
||
};
|
||
|
||
const headersPlugin = (md, {
|
||
level = [2, 3],
|
||
shouldAllowNested = false,
|
||
slugify: slugify$1 = slugify,
|
||
format
|
||
} = {}) => {
|
||
const render = md.renderer.render.bind(md.renderer);
|
||
md.renderer.render = (tokens, options, env) => {
|
||
env.headers = resolveHeadersFromTokens(tokens, {
|
||
level,
|
||
shouldAllowHtml: false,
|
||
shouldAllowNested,
|
||
shouldEscapeText: false,
|
||
slugify: slugify$1,
|
||
format
|
||
});
|
||
return render(tokens, options, env);
|
||
};
|
||
};
|
||
|
||
const TAG_NAME_SCRIPT = "script";
|
||
const TAG_NAME_STYLE = "style";
|
||
const TAG_NAME_TEMPLATE = "template";
|
||
|
||
const SCRIPT_SETUP_TAG_OPEN_REGEXP = /^<script\s+.*?\bsetup\b.*?>$/is;
|
||
const createSfcRegexp = ({
|
||
customBlocks
|
||
}) => {
|
||
const sfcTags = Array.from(
|
||
/* @__PURE__ */ new Set([TAG_NAME_SCRIPT, TAG_NAME_STYLE, ...customBlocks])
|
||
).join("|");
|
||
return new RegExp(
|
||
`^\\s*(?<content>(?<tagOpen><(?<type>${sfcTags})\\s?.*?>)(?<contentStripped>.*)(?<tagClose><\\/\\k<type>\\s*>))\\s*$`,
|
||
"is"
|
||
);
|
||
};
|
||
|
||
const sfcPlugin = (md, { customBlocks = [] } = {}) => {
|
||
const sfcRegexp = createSfcRegexp({ customBlocks });
|
||
const render = md.render.bind(md);
|
||
md.render = (src, env = {}) => {
|
||
env.sfcBlocks = {
|
||
template: null,
|
||
script: null,
|
||
scriptSetup: null,
|
||
scripts: [],
|
||
styles: [],
|
||
customBlocks: []
|
||
};
|
||
const rendered = render(src, env);
|
||
env.sfcBlocks.template = {
|
||
type: TAG_NAME_TEMPLATE,
|
||
content: `<${TAG_NAME_TEMPLATE}>${rendered}</${TAG_NAME_TEMPLATE}>`,
|
||
contentStripped: rendered,
|
||
tagOpen: `<${TAG_NAME_TEMPLATE}>`,
|
||
tagClose: `</${TAG_NAME_TEMPLATE}>`
|
||
};
|
||
return rendered;
|
||
};
|
||
const htmlBlockRule = md.renderer.rules.html_block;
|
||
md.renderer.rules.html_block = (tokens, idx, options, env, self) => {
|
||
if (!env.sfcBlocks) {
|
||
return htmlBlockRule(tokens, idx, options, env, self);
|
||
}
|
||
const token = tokens[idx];
|
||
const content = token.content;
|
||
const match = content.match(sfcRegexp);
|
||
if (!match) {
|
||
return htmlBlockRule(tokens, idx, options, env, self);
|
||
}
|
||
const sfcBlock = match.groups;
|
||
if (sfcBlock.type === TAG_NAME_SCRIPT) {
|
||
env.sfcBlocks.scripts.push(sfcBlock);
|
||
if (SCRIPT_SETUP_TAG_OPEN_REGEXP.test(sfcBlock.tagOpen)) {
|
||
env.sfcBlocks.scriptSetup = sfcBlock;
|
||
} else {
|
||
env.sfcBlocks.script = sfcBlock;
|
||
}
|
||
} else if (sfcBlock.type === TAG_NAME_STYLE) {
|
||
env.sfcBlocks.styles.push(sfcBlock);
|
||
} else {
|
||
env.sfcBlocks.customBlocks.push(sfcBlock);
|
||
}
|
||
return "";
|
||
};
|
||
};
|
||
|
||
const titlePlugin = (md) => {
|
||
const render = md.renderer.render.bind(md.renderer);
|
||
md.renderer.render = (tokens, options, env) => {
|
||
const tokenIdx = tokens.findIndex((token) => token.tag === "h1");
|
||
env.title = tokenIdx > -1 ? resolveTitleFromToken(tokens[tokenIdx + 1], {
|
||
shouldAllowHtml: false,
|
||
shouldEscapeText: false
|
||
}) : "";
|
||
return render(tokens, options, env);
|
||
};
|
||
};
|
||
|
||
const createRenderHeaders = ({
|
||
listTag,
|
||
listClass,
|
||
itemClass,
|
||
linkTag,
|
||
linkClass
|
||
}) => {
|
||
const listTagString = htmlEscape(listTag);
|
||
const listClassString = listClass ? ` class="${htmlEscape(listClass)}"` : "";
|
||
const itemTagString = "li";
|
||
const itemClassString = itemClass ? ` class="${htmlEscape(itemClass)}"` : "";
|
||
const linkTagString = htmlEscape(linkTag);
|
||
const linkClassString = linkClass ? ` class="${htmlEscape(linkClass)}"` : "";
|
||
const linkTo = (link) => linkTag === "router-link" ? ` to="${link}"` : ` href="${link}"`;
|
||
const renderHeaders = (headers) => `<${listTagString}${listClassString}>${headers.map(
|
||
(header) => `<${itemTagString}${itemClassString}><${linkTagString}${linkClassString}${linkTo(header.link)}>${header.title}</${linkTagString}>${header.children.length > 0 ? renderHeaders(header.children) : ""}</${itemTagString}>`
|
||
).join("")}</${listTagString}>`;
|
||
return renderHeaders;
|
||
};
|
||
|
||
const createTocBlockRule = ({
|
||
pattern,
|
||
containerTag,
|
||
containerClass
|
||
}) => (state, startLine, endLine, silent) => {
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) {
|
||
return false;
|
||
}
|
||
const pos = state.bMarks[startLine] + state.tShift[startLine];
|
||
const max = state.eMarks[startLine];
|
||
const lineFirstToken = state.src.slice(pos, max).split(" ")[0];
|
||
if (!pattern.test(lineFirstToken))
|
||
return false;
|
||
if (silent)
|
||
return true;
|
||
state.line = startLine + 1;
|
||
const tokenOpen = state.push("toc_open", containerTag, 1);
|
||
tokenOpen.markup = "";
|
||
tokenOpen.map = [startLine, state.line];
|
||
if (containerClass) {
|
||
tokenOpen.attrSet("class", containerClass);
|
||
}
|
||
const tokenBody = state.push("toc_body", "", 0);
|
||
tokenBody.markup = lineFirstToken;
|
||
tokenBody.map = [startLine, state.line];
|
||
tokenBody.hidden = true;
|
||
const tokenClose = state.push("toc_close", containerTag, -1);
|
||
tokenClose.markup = "";
|
||
tokenBody.map = [startLine, state.line];
|
||
return true;
|
||
};
|
||
|
||
const tocPlugin = (md, {
|
||
pattern = /^\[\[toc\]\]$/i,
|
||
slugify: slugify$1 = slugify,
|
||
format,
|
||
level = [2, 3],
|
||
shouldAllowNested = false,
|
||
containerTag = "nav",
|
||
containerClass = "table-of-contents",
|
||
listTag = "ul",
|
||
listClass = "",
|
||
itemClass = "",
|
||
linkTag = "a",
|
||
linkClass = ""
|
||
} = {}) => {
|
||
md.block.ruler.before(
|
||
"heading",
|
||
"toc",
|
||
createTocBlockRule({
|
||
pattern,
|
||
containerTag,
|
||
containerClass
|
||
}),
|
||
{
|
||
alt: ["paragraph", "reference", "blockquote"]
|
||
}
|
||
);
|
||
const renderHeaders = createRenderHeaders({
|
||
listTag,
|
||
listClass,
|
||
itemClass,
|
||
linkTag,
|
||
linkClass
|
||
});
|
||
md.renderer.rules.toc_body = (tokens) => renderHeaders(
|
||
resolveHeadersFromTokens(tokens, {
|
||
level,
|
||
shouldAllowHtml: true,
|
||
shouldAllowNested,
|
||
shouldEscapeText: true,
|
||
slugify: slugify$1,
|
||
format
|
||
})
|
||
);
|
||
};
|
||
|
||
/* eslint-disable no-bitwise */
|
||
|
||
const decodeCache = {};
|
||
|
||
function getDecodeCache (exclude) {
|
||
let cache = decodeCache[exclude];
|
||
if (cache) { return cache }
|
||
|
||
cache = decodeCache[exclude] = [];
|
||
|
||
for (let i = 0; i < 128; i++) {
|
||
const ch = String.fromCharCode(i);
|
||
cache.push(ch);
|
||
}
|
||
|
||
for (let i = 0; i < exclude.length; i++) {
|
||
const ch = exclude.charCodeAt(i);
|
||
cache[ch] = '%' + ('0' + ch.toString(16).toUpperCase()).slice(-2);
|
||
}
|
||
|
||
return cache
|
||
}
|
||
|
||
// Decode percent-encoded string.
|
||
//
|
||
function decode$1 (string, exclude) {
|
||
if (typeof exclude !== 'string') {
|
||
exclude = decode$1.defaultChars;
|
||
}
|
||
|
||
const cache = getDecodeCache(exclude);
|
||
|
||
return string.replace(/(%[a-f0-9]{2})+/gi, function (seq) {
|
||
let result = '';
|
||
|
||
for (let i = 0, l = seq.length; i < l; i += 3) {
|
||
const b1 = parseInt(seq.slice(i + 1, i + 3), 16);
|
||
|
||
if (b1 < 0x80) {
|
||
result += cache[b1];
|
||
continue
|
||
}
|
||
|
||
if ((b1 & 0xE0) === 0xC0 && (i + 3 < l)) {
|
||
// 110xxxxx 10xxxxxx
|
||
const b2 = parseInt(seq.slice(i + 4, i + 6), 16);
|
||
|
||
if ((b2 & 0xC0) === 0x80) {
|
||
const chr = ((b1 << 6) & 0x7C0) | (b2 & 0x3F);
|
||
|
||
if (chr < 0x80) {
|
||
result += '\ufffd\ufffd';
|
||
} else {
|
||
result += String.fromCharCode(chr);
|
||
}
|
||
|
||
i += 3;
|
||
continue
|
||
}
|
||
}
|
||
|
||
if ((b1 & 0xF0) === 0xE0 && (i + 6 < l)) {
|
||
// 1110xxxx 10xxxxxx 10xxxxxx
|
||
const b2 = parseInt(seq.slice(i + 4, i + 6), 16);
|
||
const b3 = parseInt(seq.slice(i + 7, i + 9), 16);
|
||
|
||
if ((b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80) {
|
||
const chr = ((b1 << 12) & 0xF000) | ((b2 << 6) & 0xFC0) | (b3 & 0x3F);
|
||
|
||
if (chr < 0x800 || (chr >= 0xD800 && chr <= 0xDFFF)) {
|
||
result += '\ufffd\ufffd\ufffd';
|
||
} else {
|
||
result += String.fromCharCode(chr);
|
||
}
|
||
|
||
i += 6;
|
||
continue
|
||
}
|
||
}
|
||
|
||
if ((b1 & 0xF8) === 0xF0 && (i + 9 < l)) {
|
||
// 111110xx 10xxxxxx 10xxxxxx 10xxxxxx
|
||
const b2 = parseInt(seq.slice(i + 4, i + 6), 16);
|
||
const b3 = parseInt(seq.slice(i + 7, i + 9), 16);
|
||
const b4 = parseInt(seq.slice(i + 10, i + 12), 16);
|
||
|
||
if ((b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80 && (b4 & 0xC0) === 0x80) {
|
||
let chr = ((b1 << 18) & 0x1C0000) | ((b2 << 12) & 0x3F000) | ((b3 << 6) & 0xFC0) | (b4 & 0x3F);
|
||
|
||
if (chr < 0x10000 || chr > 0x10FFFF) {
|
||
result += '\ufffd\ufffd\ufffd\ufffd';
|
||
} else {
|
||
chr -= 0x10000;
|
||
result += String.fromCharCode(0xD800 + (chr >> 10), 0xDC00 + (chr & 0x3FF));
|
||
}
|
||
|
||
i += 9;
|
||
continue
|
||
}
|
||
}
|
||
|
||
result += '\ufffd';
|
||
}
|
||
|
||
return result
|
||
})
|
||
}
|
||
|
||
decode$1.defaultChars = ';/?:@&=+$,#';
|
||
decode$1.componentChars = '';
|
||
|
||
const encodeCache = {};
|
||
|
||
// Create a lookup array where anything but characters in `chars` string
|
||
// and alphanumeric chars is percent-encoded.
|
||
//
|
||
function getEncodeCache (exclude) {
|
||
let cache = encodeCache[exclude];
|
||
if (cache) { return cache }
|
||
|
||
cache = encodeCache[exclude] = [];
|
||
|
||
for (let i = 0; i < 128; i++) {
|
||
const ch = String.fromCharCode(i);
|
||
|
||
if (/^[0-9a-z]$/i.test(ch)) {
|
||
// always allow unencoded alphanumeric characters
|
||
cache.push(ch);
|
||
} else {
|
||
cache.push('%' + ('0' + i.toString(16).toUpperCase()).slice(-2));
|
||
}
|
||
}
|
||
|
||
for (let i = 0; i < exclude.length; i++) {
|
||
cache[exclude.charCodeAt(i)] = exclude[i];
|
||
}
|
||
|
||
return cache
|
||
}
|
||
|
||
// Encode unsafe characters with percent-encoding, skipping already
|
||
// encoded sequences.
|
||
//
|
||
// - string - string to encode
|
||
// - exclude - list of characters to ignore (in addition to a-zA-Z0-9)
|
||
// - keepEscaped - don't encode '%' in a correct escape sequence (default: true)
|
||
//
|
||
function encode$1 (string, exclude, keepEscaped) {
|
||
if (typeof exclude !== 'string') {
|
||
// encode(string, keepEscaped)
|
||
keepEscaped = exclude;
|
||
exclude = encode$1.defaultChars;
|
||
}
|
||
|
||
if (typeof keepEscaped === 'undefined') {
|
||
keepEscaped = true;
|
||
}
|
||
|
||
const cache = getEncodeCache(exclude);
|
||
let result = '';
|
||
|
||
for (let i = 0, l = string.length; i < l; i++) {
|
||
const code = string.charCodeAt(i);
|
||
|
||
if (keepEscaped && code === 0x25 /* % */ && i + 2 < l) {
|
||
if (/^[0-9a-f]{2}$/i.test(string.slice(i + 1, i + 3))) {
|
||
result += string.slice(i, i + 3);
|
||
i += 2;
|
||
continue
|
||
}
|
||
}
|
||
|
||
if (code < 128) {
|
||
result += cache[code];
|
||
continue
|
||
}
|
||
|
||
if (code >= 0xD800 && code <= 0xDFFF) {
|
||
if (code >= 0xD800 && code <= 0xDBFF && i + 1 < l) {
|
||
const nextCode = string.charCodeAt(i + 1);
|
||
if (nextCode >= 0xDC00 && nextCode <= 0xDFFF) {
|
||
result += encodeURIComponent(string[i] + string[i + 1]);
|
||
i++;
|
||
continue
|
||
}
|
||
}
|
||
result += '%EF%BF%BD';
|
||
continue
|
||
}
|
||
|
||
result += encodeURIComponent(string[i]);
|
||
}
|
||
|
||
return result
|
||
}
|
||
|
||
encode$1.defaultChars = ";/?:@&=+$,-_.!~*'()#";
|
||
encode$1.componentChars = "-_.!~*'()";
|
||
|
||
function format$1 (url) {
|
||
let result = '';
|
||
|
||
result += url.protocol || '';
|
||
result += url.slashes ? '//' : '';
|
||
result += url.auth ? url.auth + '@' : '';
|
||
|
||
if (url.hostname && url.hostname.indexOf(':') !== -1) {
|
||
// ipv6 address
|
||
result += '[' + url.hostname + ']';
|
||
} else {
|
||
result += url.hostname || '';
|
||
}
|
||
|
||
result += url.port ? ':' + url.port : '';
|
||
result += url.pathname || '';
|
||
result += url.search || '';
|
||
result += url.hash || '';
|
||
|
||
return result
|
||
}
|
||
|
||
// 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.
|
||
|
||
//
|
||
// Changes from joyent/node:
|
||
//
|
||
// 1. No leading slash in paths,
|
||
// e.g. in `url.parse('http://foo?bar')` pathname is ``, not `/`
|
||
//
|
||
// 2. Backslashes are not replaced with slashes,
|
||
// so `http:\\example.org\` is treated like a relative path
|
||
//
|
||
// 3. Trailing colon is treated like a part of the path,
|
||
// i.e. in `http://example.org:foo` pathname is `:foo`
|
||
//
|
||
// 4. Nothing is URL-encoded in the resulting object,
|
||
// (in joyent/node some chars in auth and paths are encoded)
|
||
//
|
||
// 5. `url.parse()` does not have `parseQueryString` argument
|
||
//
|
||
// 6. Removed extraneous result properties: `host`, `path`, `query`, etc.,
|
||
// which can be constructed using other parts of the url.
|
||
//
|
||
|
||
function Url () {
|
||
this.protocol = null;
|
||
this.slashes = null;
|
||
this.auth = null;
|
||
this.port = null;
|
||
this.hostname = null;
|
||
this.hash = null;
|
||
this.search = null;
|
||
this.pathname = null;
|
||
}
|
||
|
||
// Reference: RFC 3986, RFC 1808, RFC 2396
|
||
|
||
// define these here so at least they only have to be
|
||
// compiled once on the first module load.
|
||
const protocolPattern = /^([a-z0-9.+-]+:)/i;
|
||
const portPattern = /:[0-9]*$/;
|
||
|
||
// Special case for a simple path URL
|
||
/* eslint-disable-next-line no-useless-escape */
|
||
const simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/;
|
||
|
||
// RFC 2396: characters reserved for delimiting URLs.
|
||
// We actually just auto-escape these.
|
||
const delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'];
|
||
|
||
// RFC 2396: characters not allowed for various reasons.
|
||
const unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims);
|
||
|
||
// Allowed by RFCs, but cause of XSS attacks. Always escape these.
|
||
const autoEscape = ['\''].concat(unwise);
|
||
// Characters that are never ever allowed in a hostname.
|
||
// Note that any invalid chars are also handled, but these
|
||
// are the ones that are *expected* to be seen, so we fast-path
|
||
// them.
|
||
const nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape);
|
||
const hostEndingChars = ['/', '?', '#'];
|
||
const hostnameMaxLen = 255;
|
||
const hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/;
|
||
const hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/;
|
||
// protocols that can allow "unsafe" and "unwise" chars.
|
||
// protocols that never have a hostname.
|
||
const hostlessProtocol = {
|
||
javascript: true,
|
||
'javascript:': true
|
||
};
|
||
// protocols that always contain a // bit.
|
||
const slashedProtocol = {
|
||
http: true,
|
||
https: true,
|
||
ftp: true,
|
||
gopher: true,
|
||
file: true,
|
||
'http:': true,
|
||
'https:': true,
|
||
'ftp:': true,
|
||
'gopher:': true,
|
||
'file:': true
|
||
};
|
||
|
||
function urlParse (url, slashesDenoteHost) {
|
||
if (url && url instanceof Url) return url
|
||
|
||
const u = new Url();
|
||
u.parse(url, slashesDenoteHost);
|
||
return u
|
||
}
|
||
|
||
Url.prototype.parse = function (url, slashesDenoteHost) {
|
||
let lowerProto, hec, slashes;
|
||
let rest = url;
|
||
|
||
// trim before proceeding.
|
||
// This is to support parse stuff like " http://foo.com \n"
|
||
rest = rest.trim();
|
||
|
||
if (!slashesDenoteHost && url.split('#').length === 1) {
|
||
// Try fast path regexp
|
||
const simplePath = simplePathPattern.exec(rest);
|
||
if (simplePath) {
|
||
this.pathname = simplePath[1];
|
||
if (simplePath[2]) {
|
||
this.search = simplePath[2];
|
||
}
|
||
return this
|
||
}
|
||
}
|
||
|
||
let proto = protocolPattern.exec(rest);
|
||
if (proto) {
|
||
proto = proto[0];
|
||
lowerProto = proto.toLowerCase();
|
||
this.protocol = proto;
|
||
rest = rest.substr(proto.length);
|
||
}
|
||
|
||
// figure out if it's got a host
|
||
// user@server is *always* interpreted as a hostname, and url
|
||
// resolution will treat //foo/bar as host=foo,path=bar because that's
|
||
// how the browser resolves relative URLs.
|
||
/* eslint-disable-next-line no-useless-escape */
|
||
if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
|
||
slashes = rest.substr(0, 2) === '//';
|
||
if (slashes && !(proto && hostlessProtocol[proto])) {
|
||
rest = rest.substr(2);
|
||
this.slashes = true;
|
||
}
|
||
}
|
||
|
||
if (!hostlessProtocol[proto] &&
|
||
(slashes || (proto && !slashedProtocol[proto]))) {
|
||
// there's a hostname.
|
||
// the first instance of /, ?, ;, or # ends the host.
|
||
//
|
||
// If there is an @ in the hostname, then non-host chars *are* allowed
|
||
// to the left of the last @ sign, unless some host-ending character
|
||
// comes *before* the @-sign.
|
||
// URLs are obnoxious.
|
||
//
|
||
// ex:
|
||
// http://a@b@c/ => user:a@b host:c
|
||
// http://a@b?@c => user:a host:c path:/?@c
|
||
|
||
// v0.12 TODO(isaacs): This is not quite how Chrome does things.
|
||
// Review our test case against browsers more comprehensively.
|
||
|
||
// find the first instance of any hostEndingChars
|
||
let hostEnd = -1;
|
||
for (let i = 0; i < hostEndingChars.length; i++) {
|
||
hec = rest.indexOf(hostEndingChars[i]);
|
||
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) {
|
||
hostEnd = hec;
|
||
}
|
||
}
|
||
|
||
// at this point, either we have an explicit point where the
|
||
// auth portion cannot go past, or the last @ char is the decider.
|
||
let auth, atSign;
|
||
if (hostEnd === -1) {
|
||
// atSign can be anywhere.
|
||
atSign = rest.lastIndexOf('@');
|
||
} else {
|
||
// atSign must be in auth portion.
|
||
// http://a@b/c@d => host:b auth:a path:/c@d
|
||
atSign = rest.lastIndexOf('@', hostEnd);
|
||
}
|
||
|
||
// Now we have a portion which is definitely the auth.
|
||
// Pull that off.
|
||
if (atSign !== -1) {
|
||
auth = rest.slice(0, atSign);
|
||
rest = rest.slice(atSign + 1);
|
||
this.auth = auth;
|
||
}
|
||
|
||
// the host is the remaining to the left of the first non-host char
|
||
hostEnd = -1;
|
||
for (let i = 0; i < nonHostChars.length; i++) {
|
||
hec = rest.indexOf(nonHostChars[i]);
|
||
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) {
|
||
hostEnd = hec;
|
||
}
|
||
}
|
||
// if we still have not hit it, then the entire thing is a host.
|
||
if (hostEnd === -1) {
|
||
hostEnd = rest.length;
|
||
}
|
||
|
||
if (rest[hostEnd - 1] === ':') { hostEnd--; }
|
||
const host = rest.slice(0, hostEnd);
|
||
rest = rest.slice(hostEnd);
|
||
|
||
// pull out port.
|
||
this.parseHost(host);
|
||
|
||
// we've indicated that there is a hostname,
|
||
// so even if it's empty, it has to be present.
|
||
this.hostname = this.hostname || '';
|
||
|
||
// if hostname begins with [ and ends with ]
|
||
// assume that it's an IPv6 address.
|
||
const ipv6Hostname = this.hostname[0] === '[' &&
|
||
this.hostname[this.hostname.length - 1] === ']';
|
||
|
||
// validate a little.
|
||
if (!ipv6Hostname) {
|
||
const hostparts = this.hostname.split(/\./);
|
||
for (let i = 0, l = hostparts.length; i < l; i++) {
|
||
const part = hostparts[i];
|
||
if (!part) { continue }
|
||
if (!part.match(hostnamePartPattern)) {
|
||
let newpart = '';
|
||
for (let j = 0, k = part.length; j < k; j++) {
|
||
if (part.charCodeAt(j) > 127) {
|
||
// we replace non-ASCII char with a temporary placeholder
|
||
// we need this to make sure size of hostname is not
|
||
// broken by replacing non-ASCII by nothing
|
||
newpart += 'x';
|
||
} else {
|
||
newpart += part[j];
|
||
}
|
||
}
|
||
// we test again with ASCII char only
|
||
if (!newpart.match(hostnamePartPattern)) {
|
||
const validParts = hostparts.slice(0, i);
|
||
const notHost = hostparts.slice(i + 1);
|
||
const bit = part.match(hostnamePartStart);
|
||
if (bit) {
|
||
validParts.push(bit[1]);
|
||
notHost.unshift(bit[2]);
|
||
}
|
||
if (notHost.length) {
|
||
rest = notHost.join('.') + rest;
|
||
}
|
||
this.hostname = validParts.join('.');
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (this.hostname.length > hostnameMaxLen) {
|
||
this.hostname = '';
|
||
}
|
||
|
||
// strip [ and ] from the hostname
|
||
// the host field still retains them, though
|
||
if (ipv6Hostname) {
|
||
this.hostname = this.hostname.substr(1, this.hostname.length - 2);
|
||
}
|
||
}
|
||
|
||
// chop off from the tail first.
|
||
const hash = rest.indexOf('#');
|
||
if (hash !== -1) {
|
||
// got a fragment string.
|
||
this.hash = rest.substr(hash);
|
||
rest = rest.slice(0, hash);
|
||
}
|
||
const qm = rest.indexOf('?');
|
||
if (qm !== -1) {
|
||
this.search = rest.substr(qm);
|
||
rest = rest.slice(0, qm);
|
||
}
|
||
if (rest) { this.pathname = rest; }
|
||
if (slashedProtocol[lowerProto] &&
|
||
this.hostname && !this.pathname) {
|
||
this.pathname = '';
|
||
}
|
||
|
||
return this
|
||
};
|
||
|
||
Url.prototype.parseHost = function (host) {
|
||
let port = portPattern.exec(host);
|
||
if (port) {
|
||
port = port[0];
|
||
if (port !== ':') {
|
||
this.port = port.substr(1);
|
||
}
|
||
host = host.substr(0, host.length - port.length);
|
||
}
|
||
if (host) { this.hostname = host; }
|
||
};
|
||
|
||
var mdurl = /*#__PURE__*/Object.freeze({
|
||
__proto__: null,
|
||
decode: decode$1,
|
||
encode: encode$1,
|
||
format: format$1,
|
||
parse: urlParse
|
||
});
|
||
|
||
var Any = /[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
|
||
|
||
var Cc = /[\0-\x1F\x7F-\x9F]/;
|
||
|
||
var regex$1 = /[\xAD\u0600-\u0605\u061C\u06DD\u070F\u0890\u0891\u08E2\u180E\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u206F\uFEFF\uFFF9-\uFFFB]|\uD804[\uDCBD\uDCCD]|\uD80D[\uDC30-\uDC3F]|\uD82F[\uDCA0-\uDCA3]|\uD834[\uDD73-\uDD7A]|\uDB40[\uDC01\uDC20-\uDC7F]/;
|
||
|
||
var P$1 = /[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061D-\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1B7D\u1B7E\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u2E52-\u2E5D\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDEAD\uDF55-\uDF59\uDF86-\uDF89]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDC4B-\uDC4F\uDC5A\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDEB9\uDF3C-\uDF3E]|\uD806[\uDC3B\uDD44-\uDD46\uDDE2\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2\uDF00-\uDF09]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8\uDF43-\uDF4F\uDFFF]|\uD809[\uDC70-\uDC74]|\uD80B[\uDFF1\uDFF2]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDE97-\uDE9A\uDFE2]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD83A[\uDD5E\uDD5F]/;
|
||
|
||
var Z$1 = /[ \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/;
|
||
|
||
var ucmicro = /*#__PURE__*/Object.freeze({
|
||
__proto__: null,
|
||
Any: Any,
|
||
Cc: Cc,
|
||
Cf: regex$1,
|
||
P: P$1,
|
||
Z: Z$1
|
||
});
|
||
|
||
// Generated using scripts/write-decode-map.ts
|
||
var htmlDecodeTree = new Uint16Array(
|
||
// prettier-ignore
|
||
"\u1d41<\xd5\u0131\u028a\u049d\u057b\u05d0\u0675\u06de\u07a2\u07d6\u080f\u0a4a\u0a91\u0da1\u0e6d\u0f09\u0f26\u10ca\u1228\u12e1\u1415\u149d\u14c3\u14df\u1525\0\0\0\0\0\0\u156b\u16cd\u198d\u1c12\u1ddd\u1f7e\u2060\u21b0\u228d\u23c0\u23fb\u2442\u2824\u2912\u2d08\u2e48\u2fce\u3016\u32ba\u3639\u37ac\u38fe\u3a28\u3a71\u3ae0\u3b2e\u0800EMabcfglmnoprstu\\bfms\x7f\x84\x8b\x90\x95\x98\xa6\xb3\xb9\xc8\xcflig\u803b\xc6\u40c6P\u803b&\u4026cute\u803b\xc1\u40c1reve;\u4102\u0100iyx}rc\u803b\xc2\u40c2;\u4410r;\uc000\ud835\udd04rave\u803b\xc0\u40c0pha;\u4391acr;\u4100d;\u6a53\u0100gp\x9d\xa1on;\u4104f;\uc000\ud835\udd38plyFunction;\u6061ing\u803b\xc5\u40c5\u0100cs\xbe\xc3r;\uc000\ud835\udc9cign;\u6254ilde\u803b\xc3\u40c3ml\u803b\xc4\u40c4\u0400aceforsu\xe5\xfb\xfe\u0117\u011c\u0122\u0127\u012a\u0100cr\xea\xf2kslash;\u6216\u0176\xf6\xf8;\u6ae7ed;\u6306y;\u4411\u0180crt\u0105\u010b\u0114ause;\u6235noullis;\u612ca;\u4392r;\uc000\ud835\udd05pf;\uc000\ud835\udd39eve;\u42d8c\xf2\u0113mpeq;\u624e\u0700HOacdefhilorsu\u014d\u0151\u0156\u0180\u019e\u01a2\u01b5\u01b7\u01ba\u01dc\u0215\u0273\u0278\u027ecy;\u4427PY\u803b\xa9\u40a9\u0180cpy\u015d\u0162\u017aute;\u4106\u0100;i\u0167\u0168\u62d2talDifferentialD;\u6145leys;\u612d\u0200aeio\u0189\u018e\u0194\u0198ron;\u410cdil\u803b\xc7\u40c7rc;\u4108nint;\u6230ot;\u410a\u0100dn\u01a7\u01adilla;\u40b8terDot;\u40b7\xf2\u017fi;\u43a7rcle\u0200DMPT\u01c7\u01cb\u01d1\u01d6ot;\u6299inus;\u6296lus;\u6295imes;\u6297o\u0100cs\u01e2\u01f8kwiseContourIntegral;\u6232eCurly\u0100DQ\u0203\u020foubleQuote;\u601duote;\u6019\u0200lnpu\u021e\u0228\u0247\u0255on\u0100;e\u0225\u0226\u6237;\u6a74\u0180git\u022f\u0236\u023aruent;\u6261nt;\u622fourIntegral;\u622e\u0100fr\u024c\u024e;\u6102oduct;\u6210nterClockwiseContourIntegral;\u6233oss;\u6a2fcr;\uc000\ud835\udc9ep\u0100;C\u0284\u0285\u62d3ap;\u624d\u0580DJSZacefios\u02a0\u02ac\u02b0\u02b4\u02b8\u02cb\u02d7\u02e1\u02e6\u0333\u048d\u0100;o\u0179\u02a5trahd;\u6911cy;\u4402cy;\u4405cy;\u440f\u0180grs\u02bf\u02c4\u02c7ger;\u6021r;\u61a1hv;\u6ae4\u0100ay\u02d0\u02d5ron;\u410e;\u4414l\u0100;t\u02dd\u02de\u6207a;\u4394r;\uc000\ud835\udd07\u0100af\u02eb\u0327\u0100cm\u02f0\u0322ritical\u0200ADGT\u0300\u0306\u0316\u031ccute;\u40b4o\u0174\u030b\u030d;\u42d9bleAcute;\u42ddrave;\u4060ilde;\u42dcond;\u62c4ferentialD;\u6146\u0470\u033d\0\0\0\u0342\u0354\0\u0405f;\uc000\ud835\udd3b\u0180;DE\u0348\u0349\u034d\u40a8ot;\u60dcqual;\u6250ble\u0300CDLRUV\u0363\u0372\u0382\u03cf\u03e2\u03f8ontourIntegra\xec\u0239o\u0274\u0379\0\0\u037b\xbb\u0349nArrow;\u61d3\u0100eo\u0387\u03a4ft\u0180ART\u0390\u0396\u03a1rrow;\u61d0ightArrow;\u61d4e\xe5\u02cang\u0100LR\u03ab\u03c4eft\u0100AR\u03b3\u03b9rrow;\u67f8ightArrow;\u67faightArrow;\u67f9ight\u0100AT\u03d8\u03derrow;\u61d2ee;\u62a8p\u0241\u03e9\0\0\u03efrrow;\u61d1ownArrow;\u61d5erticalBar;\u6225n\u0300ABLRTa\u0412\u042a\u0430\u045e\u047f\u037crrow\u0180;BU\u041d\u041e\u0422\u6193ar;\u6913pArrow;\u61f5reve;\u4311eft\u02d2\u043a\0\u0446\0\u0450ightVector;\u6950eeVector;\u695eector\u0100;B\u0459\u045a\u61bdar;\u6956ight\u01d4\u0467\0\u0471eeVector;\u695fector\u0100;B\u047a\u047b\u61c1ar;\u6957ee\u0100;A\u0486\u0487\u62a4rrow;\u61a7\u0100ct\u0492\u0497r;\uc000\ud835\udc9frok;\u4110\u0800NTacdfglmopqstux\u04bd\u04c0\u04c4\u04cb\u04de\u04e2\u04e7\u04ee\u04f5\u0521\u052f\u0536\u0552\u055d\u0560\u0565G;\u414aH\u803b\xd0\u40d0cute\u803b\xc9\u40c9\u0180aiy\u04d2\u04d7\u04dcron;\u411arc\u803b\xca\u40ca;\u442dot;\u4116r;\uc000\ud835\udd08rave\u803b\xc8\u40c8ement;\u6208\u0100ap\u04fa\u04fecr;\u4112ty\u0253\u0506\0\0\u0512mallSquare;\u65fberySmallSquare;\u65ab\u0100gp\u0526\u052aon;\u4118f;\uc000\ud835\udd3csilon;\u4395u\u0100ai\u053c\u0549l\u0100;T\u0542\u0543\u6a75ilde;\u6242librium;\u61cc\u0100ci\u0557\u055ar;\u6130m;\u6a73a;\u4397ml\u803b\xcb\u40cb\u0100ip\u056a\u056fsts;\u6203onentialE;\u6147\u0280cfios\u0585\u0588\u058d\u05b2\u05ccy;\u4424r;\uc000\ud835\udd09lled\u0253\u0597\0\0\u05a3mallSquare;\u65fcerySmallSquare;\u65aa\u0370\u05ba\0\u05bf\0\0\u05c4f;\uc000\ud835\udd3dAll;\u6200riertrf;\u6131c\xf2\u05cb\u0600JTabcdfgorst\u05e8\u05ec\u05ef\u05fa\u0600\u0612\u0616\u061b\u061d\u0623\u066c\u0672cy;\u4403\u803b>\u403emma\u0100;d\u05f7\u05f8\u4393;\u43dcreve;\u411e\u0180eiy\u0607\u060c\u0610dil;\u4122rc;\u411c;\u4413ot;\u4120r;\uc000\ud835\udd0a;\u62d9pf;\uc000\ud835\udd3eeater\u0300EFGLST\u0635\u0644\u064e\u0656\u065b\u0666qual\u0100;L\u063e\u063f\u6265ess;\u62dbullEqual;\u6267reater;\u6aa2ess;\u6277lantEqual;\u6a7eilde;\u6273cr;\uc000\ud835\udca2;\u626b\u0400Aacfiosu\u0685\u068b\u0696\u069b\u069e\u06aa\u06be\u06caRDcy;\u442a\u0100ct\u0690\u0694ek;\u42c7;\u405eirc;\u4124r;\u610clbertSpace;\u610b\u01f0\u06af\0\u06b2f;\u610dizontalLine;\u6500\u0100ct\u06c3\u06c5\xf2\u06a9rok;\u4126mp\u0144\u06d0\u06d8ownHum\xf0\u012fqual;\u624f\u0700EJOacdfgmnostu\u06fa\u06fe\u0703\u0707\u070e\u071a\u071e\u0721\u0728\u0744\u0778\u078b\u078f\u0795cy;\u4415lig;\u4132cy;\u4401cute\u803b\xcd\u40cd\u0100iy\u0713\u0718rc\u803b\xce\u40ce;\u4418ot;\u4130r;\u6111rave\u803b\xcc\u40cc\u0180;ap\u0720\u072f\u073f\u0100cg\u0734\u0737r;\u412ainaryI;\u6148lie\xf3\u03dd\u01f4\u0749\0\u0762\u0100;e\u074d\u074e\u622c\u0100gr\u0753\u0758ral;\u622bsection;\u62c2isible\u0100CT\u076c\u0772omma;\u6063imes;\u6062\u0180gpt\u077f\u0783\u0788on;\u412ef;\uc000\ud835\udd40a;\u4399cr;\u6110ilde;\u4128\u01eb\u079a\0\u079ecy;\u4406l\u803b\xcf\u40cf\u0280cfosu\u07ac\u07b7\u07bc\u07c2\u07d0\u0100iy\u07b1\u07b5rc;\u4134;\u4419r;\uc000\ud835\udd0dpf;\uc000\ud835\udd41\u01e3\u07c7\0\u07ccr;\uc000\ud835\udca5rcy;\u4408kcy;\u4404\u0380HJacfos\u07e4\u07e8\u07ec\u07f1\u07fd\u0802\u0808cy;\u4425cy;\u440cppa;\u439a\u0100ey\u07f6\u07fbdil;\u4136;\u441ar;\uc000\ud835\udd0epf;\uc000\ud835\udd42cr;\uc000\ud835\udca6\u0580JTaceflmost\u0825\u0829\u082c\u0850\u0863\u09b3\u09b8\u09c7\u09cd\u0a37\u0a47cy;\u4409\u803b<\u403c\u0280cmnpr\u0837\u083c\u0841\u0844\u084dute;\u4139bda;\u439bg;\u67ealacetrf;\u6112r;\u619e\u0180aey\u0857\u085c\u0861ron;\u413ddil;\u413b;\u441b\u0100fs\u0868\u0970t\u0500ACDFRTUVar\u087e\u08a9\u08b1\u08e0\u08e6\u08fc\u092f\u095b\u0390\u096a\u0100nr\u0883\u088fgleBracket;\u67e8row\u0180;BR\u0899\u089a\u089e\u6190ar;\u61e4ightArrow;\u61c6eiling;\u6308o\u01f5\u08b7\0\u08c3bleBracket;\u67e6n\u01d4\u08c8\0\u08d2eeVector;\u6961ector\u0100;B\u08db\u08dc\u61c3ar;\u6959loor;\u630aight\u0100AV\u08ef\u08f5rrow;\u6194ector;\u694e\u0100er\u0901\u0917e\u0180;AV\u0909\u090a\u0910\u62a3rrow;\u61a4ector;\u695aiangle\u0180;BE\u0924\u0925\u0929\u62b2ar;\u69cfqual;\u62b4p\u0180DTV\u0937\u0942\u094cownVector;\u6951eeVector;\u6960ector\u0100;B\u0956\u0957\u61bfar;\u6958ector\u0100;B\u0965\u0966\u61bcar;\u6952ight\xe1\u039cs\u0300EFGLST\u097e\u098b\u0995\u099d\u09a2\u09adqualGreater;\u62daullEqual;\u6266reater;\u6276ess;\u6aa1lantEqual;\u6a7dilde;\u6272r;\uc000\ud835\udd0f\u0100;e\u09bd\u09be\u62d8ftarrow;\u61daidot;\u413f\u0180npw\u09d4\u0a16\u0a1bg\u0200LRlr\u09de\u09f7\u0a02\u0a10eft\u0100AR\u09e6\u09ecrrow;\u67f5ightArrow;\u67f7ightArrow;\u67f6eft\u0100ar\u03b3\u0a0aight\xe1\u03bfight\xe1\u03caf;\uc000\ud835\udd43er\u0100LR\u0a22\u0a2ceftArrow;\u6199ightArrow;\u6198\u0180cht\u0a3e\u0a40\u0a42\xf2\u084c;\u61b0rok;\u4141;\u626a\u0400acefiosu\u0a5a\u0a5d\u0a60\u0a77\u0a7c\u0a85\u0a8b\u0a8ep;\u6905y;\u441c\u0100dl\u0a65\u0a6fiumSpace;\u605flintrf;\u6133r;\uc000\ud835\udd10nusPlus;\u6213pf;\uc000\ud835\udd44c\xf2\u0a76;\u439c\u0480Jacefostu\u0aa3\u0aa7\u0aad\u0ac0\u0b14\u0b19\u0d91\u0d97\u0d9ecy;\u440acute;\u4143\u0180aey\u0ab4\u0ab9\u0aberon;\u4147dil;\u4145;\u441d\u0180gsw\u0ac7\u0af0\u0b0eative\u0180MTV\u0ad3\u0adf\u0ae8ediumSpace;\u600bhi\u0100cn\u0ae6\u0ad8\xeb\u0ad9eryThi\xee\u0ad9ted\u0100GL\u0af8\u0b06reaterGreate\xf2\u0673essLes\xf3\u0a48Line;\u400ar;\uc000\ud835\udd11\u0200Bnpt\u0b22\u0b28\u0b37\u0b3areak;\u6060BreakingSpace;\u40a0f;\u6115\u0680;CDEGHLNPRSTV\u0b55\u0b56\u0b6a\u0b7c\u0ba1\u0beb\u0c04\u0c5e\u0c84\u0ca6\u0cd8\u0d61\u0d85\u6aec\u0100ou\u0b5b\u0b64ngruent;\u6262pCap;\u626doubleVerticalBar;\u6226\u0180lqx\u0b83\u0b8a\u0b9bement;\u6209ual\u0100;T\u0b92\u0b93\u6260ilde;\uc000\u2242\u0338ists;\u6204reater\u0380;EFGLST\u0bb6\u0bb7\u0bbd\u0bc9\u0bd3\u0bd8\u0be5\u626fqual;\u6271ullEqual;\uc000\u2267\u0338reater;\uc000\u226b\u0338ess;\u6279lantEqual;\uc000\u2a7e\u0338ilde;\u6275ump\u0144\u0bf2\u0bfdownHump;\uc000\u224e\u0338qual;\uc000\u224f\u0338e\u0100fs\u0c0a\u0c27tTriangle\u0180;BE\u0c1a\u0c1b\u0c21\u62eaar;\uc000\u29cf\u0338qual;\u62ecs\u0300;EGLST\u0c35\u0c36\u0c3c\u0c44\u0c4b\u0c58\u626equal;\u6270reater;\u6278ess;\uc000\u226a\u0338lantEqual;\uc000\u2a7d\u0338ilde;\u6274ested\u0100GL\u0c68\u0c79reaterGreater;\uc000\u2aa2\u0338essLess;\uc000\u2aa1\u0338recedes\u0180;ES\u0c92\u0c93\u0c9b\u6280qual;\uc000\u2aaf\u0338lantEqual;\u62e0\u0100ei\u0cab\u0cb9verseElement;\u620cghtTriangle\u0180;BE\u0ccb\u0ccc\u0cd2\u62ebar;\uc000\u29d0\u0338qual;\u62ed\u0100qu\u0cdd\u0d0cuareSu\u0100bp\u0ce8\u0cf9set\u0100;E\u0cf0\u0cf3\uc000\u228f\u0338qual;\u62e2erset\u0100;E\u0d03\u0d06\uc000\u2290\u0338qual;\u62e3\u0180bcp\u0d13\u0d24\u0d4eset\u0100;E\u0d1b\u0d1e\uc000\u2282\u20d2qual;\u6288ceeds\u0200;EST\u0d32\u0d33\u0d3b\u0d46\u6281qual;\uc000\u2ab0\u0338lantEqual;\u62e1ilde;\uc000\u227f\u0338erset\u0100;E\u0d58\u0d5b\uc000\u2283\u20d2qual;\u6289ilde\u0200;EFT\u0d6e\u0d6f\u0d75\u0d7f\u6241qual;\u6244ullEqual;\u6247ilde;\u6249erticalBar;\u6224cr;\uc000\ud835\udca9ilde\u803b\xd1\u40d1;\u439d\u0700Eacdfgmoprstuv\u0dbd\u0dc2\u0dc9\u0dd5\u0ddb\u0de0\u0de7\u0dfc\u0e02\u0e20\u0e22\u0e32\u0e3f\u0e44lig;\u4152cute\u803b\xd3\u40d3\u0100iy\u0dce\u0dd3rc\u803b\xd4\u40d4;\u441eblac;\u4150r;\uc000\ud835\udd12rave\u803b\xd2\u40d2\u0180aei\u0dee\u0df2\u0df6cr;\u414cga;\u43a9cron;\u439fpf;\uc000\ud835\udd46enCurly\u0100DQ\u0e0e\u0e1aoubleQuote;\u601cuote;\u6018;\u6a54\u0100cl\u0e27\u0e2cr;\uc000\ud835\udcaaash\u803b\xd8\u40d8i\u016c\u0e37\u0e3cde\u803b\xd5\u40d5es;\u6a37ml\u803b\xd6\u40d6er\u0100BP\u0e4b\u0e60\u0100ar\u0e50\u0e53r;\u603eac\u0100ek\u0e5a\u0e5c;\u63deet;\u63b4arenthesis;\u63dc\u0480acfhilors\u0e7f\u0e87\u0e8a\u0e8f\u0e92\u0e94\u0e9d\u0eb0\u0efcrtialD;\u6202y;\u441fr;\uc000\ud835\udd13i;\u43a6;\u43a0usMinus;\u40b1\u0100ip\u0ea2\u0eadncareplan\xe5\u069df;\u6119\u0200;eio\u0eb9\u0eba\u0ee0\u0ee4\u6abbcedes\u0200;EST\u0ec8\u0ec9\u0ecf\u0eda\u627aqual;\u6aaflantEqual;\u627cilde;\u627eme;\u6033\u0100dp\u0ee9\u0eeeuct;\u620fortion\u0100;a\u0225\u0ef9l;\u621d\u0100ci\u0f01\u0f06r;\uc000\ud835\udcab;\u43a8\u0200Ufos\u0f11\u0f16\u0f1b\u0f1fOT\u803b\"\u4022r;\uc000\ud835\udd14pf;\u611acr;\uc000\ud835\udcac\u0600BEacefhiorsu\u0f3e\u0f43\u0f47\u0f60\u0f73\u0fa7\u0faa\u0fad\u1096\u10a9\u10b4\u10bearr;\u6910G\u803b\xae\u40ae\u0180cnr\u0f4e\u0f53\u0f56ute;\u4154g;\u67ebr\u0100;t\u0f5c\u0f5d\u61a0l;\u6916\u0180aey\u0f67\u0f6c\u0f71ron;\u4158dil;\u4156;\u4420\u0100;v\u0f78\u0f79\u611cerse\u0100EU\u0f82\u0f99\u0100lq\u0f87\u0f8eement;\u620builibrium;\u61cbpEquilibrium;\u696fr\xbb\u0f79o;\u43a1ght\u0400ACDFTUVa\u0fc1\u0feb\u0ff3\u1022\u1028\u105b\u1087\u03d8\u0100nr\u0fc6\u0fd2gleBracket;\u67e9row\u0180;BL\u0fdc\u0fdd\u0fe1\u6192ar;\u61e5eftArrow;\u61c4eiling;\u6309o\u01f5\u0ff9\0\u1005bleBracket;\u67e7n\u01d4\u100a\0\u1014eeVector;\u695dector\u0100;B\u101d\u101e\u61c2ar;\u6955loor;\u630b\u0100er\u102d\u1043e\u0180;AV\u1035\u1036\u103c\u62a2rrow;\u61a6ector;\u695biangle\u0180;BE\u1050\u1051\u1055\u62b3ar;\u69d0qual;\u62b5p\u0180DTV\u1063\u106e\u1078ownVector;\u694feeVector;\u695cector\u0100;B\u1082\u1083\u61bear;\u6954ector\u0100;B\u1091\u1092\u61c0ar;\u6953\u0100pu\u109b\u109ef;\u611dndImplies;\u6970ightarrow;\u61db\u0100ch\u10b9\u10bcr;\u611b;\u61b1leDelayed;\u69f4\u0680HOacfhimoqstu\u10e4\u10f1\u10f7\u10fd\u1119\u111e\u1151\u1156\u1161\u1167\u11b5\u11bb\u11bf\u0100Cc\u10e9\u10eeHcy;\u4429y;\u4428FTcy;\u442ccute;\u415a\u0280;aeiy\u1108\u1109\u110e\u1113\u1117\u6abcron;\u4160dil;\u415erc;\u415c;\u4421r;\uc000\ud835\udd16ort\u0200DLRU\u112a\u1134\u113e\u1149ownArrow\xbb\u041eeftArrow\xbb\u089aightArrow\xbb\u0fddpArrow;\u6191gma;\u43a3allCircle;\u6218pf;\uc000\ud835\udd4a\u0272\u116d\0\0\u1170t;\u621aare\u0200;ISU\u117b\u117c\u1189\u11af\u65a1ntersection;\u6293u\u0100bp\u118f\u119eset\u0100;E\u1197\u1198\u628fqual;\u6291erset\u0100;E\u11a8\u11a9\u6290qual;\u6292nion;\u6294cr;\uc000\ud835\udcaear;\u62c6\u0200bcmp\u11c8\u11db\u1209\u120b\u0100;s\u11cd\u11ce\u62d0et\u0100;E\u11cd\u11d5qual;\u6286\u0100ch\u11e0\u1205eeds\u0200;EST\u11ed\u11ee\u11f4\u11ff\u627bqual;\u6ab0lantEqual;\u627dilde;\u627fTh\xe1\u0f8c;\u6211\u0180;es\u1212\u1213\u1223\u62d1rset\u0100;E\u121c\u121d\u6283qual;\u6287et\xbb\u1213\u0580HRSacfhiors\u123e\u1244\u1249\u1255\u125e\u1271\u1276\u129f\u12c2\u12c8\u12d1ORN\u803b\xde\u40deADE;\u6122\u0100Hc\u124e\u1252cy;\u440by;\u4426\u0100bu\u125a\u125c;\u4009;\u43a4\u0180aey\u1265\u126a\u126fron;\u4164dil;\u4162;\u4422r;\uc000\ud835\udd17\u0100ei\u127b\u1289\u01f2\u1280\0\u1287efore;\u6234a;\u4398\u0100cn\u128e\u1298kSpace;\uc000\u205f\u200aSpace;\u6009lde\u0200;EFT\u12ab\u12ac\u12b2\u12bc\u623cqual;\u6243ullEqual;\u6245ilde;\u6248pf;\uc000\ud835\udd4bipleDot;\u60db\u0100ct\u12d6\u12dbr;\uc000\ud835\udcafrok;\u4166\u0ae1\u12f7\u130e\u131a\u1326\0\u132c\u1331\0\0\0\0\0\u1338\u133d\u1377\u1385\0\u13ff\u1404\u140a\u1410\u0100cr\u12fb\u1301ute\u803b\xda\u40dar\u0100;o\u1307\u1308\u619fcir;\u6949r\u01e3\u1313\0\u1316y;\u440eve;\u416c\u0100iy\u131e\u1323rc\u803b\xdb\u40db;\u4423blac;\u4170r;\uc000\ud835\udd18rave\u803b\xd9\u40d9acr;\u416a\u0100di\u1341\u1369er\u0100BP\u1348\u135d\u0100ar\u134d\u1350r;\u405fac\u0100ek\u1357\u1359;\u63dfet;\u63b5arenthesis;\u63ddon\u0100;P\u1370\u1371\u62c3lus;\u628e\u0100gp\u137b\u137fon;\u4172f;\uc000\ud835\udd4c\u0400ADETadps\u1395\u13ae\u13b8\u13c4\u03e8\u13d2\u13d7\u13f3rrow\u0180;BD\u1150\u13a0\u13a4ar;\u6912ownArrow;\u61c5ownArrow;\u6195quilibrium;\u696eee\u0100;A\u13cb\u13cc\u62a5rrow;\u61a5own\xe1\u03f3er\u0100LR\u13de\u13e8eftArrow;\u6196ightArrow;\u6197i\u0100;l\u13f9\u13fa\u43d2on;\u43a5ing;\u416ecr;\uc000\ud835\udcb0ilde;\u4168ml\u803b\xdc\u40dc\u0480Dbcdefosv\u1427\u142c\u1430\u1433\u143e\u1485\u148a\u1490\u1496ash;\u62abar;\u6aeby;\u4412ash\u0100;l\u143b\u143c\u62a9;\u6ae6\u0100er\u1443\u1445;\u62c1\u0180bty\u144c\u1450\u147aar;\u6016\u0100;i\u144f\u1455cal\u0200BLST\u1461\u1465\u146a\u1474ar;\u6223ine;\u407ceparator;\u6758ilde;\u6240ThinSpace;\u600ar;\uc000\ud835\udd19pf;\uc000\ud835\udd4dcr;\uc000\ud835\udcb1dash;\u62aa\u0280cefos\u14a7\u14ac\u14b1\u14b6\u14bcirc;\u4174dge;\u62c0r;\uc000\ud835\udd1apf;\uc000\ud835\udd4ecr;\uc000\ud835\udcb2\u0200fios\u14cb\u14d0\u14d2\u14d8r;\uc000\ud835\udd1b;\u439epf;\uc000\ud835\udd4fcr;\uc000\ud835\udcb3\u0480AIUacfosu\u14f1\u14f5\u14f9\u14fd\u1504\u150f\u1514\u151a\u1520cy;\u442fcy;\u4407cy;\u442ecute\u803b\xdd\u40dd\u0100iy\u1509\u150drc;\u4176;\u442br;\uc000\ud835\udd1cpf;\uc000\ud835\udd50cr;\uc000\ud835\udcb4ml;\u4178\u0400Hacdefos\u1535\u1539\u153f\u154b\u154f\u155d\u1560\u1564cy;\u4416cute;\u4179\u0100ay\u1544\u1549ron;\u417d;\u4417ot;\u417b\u01f2\u1554\0\u155boWidt\xe8\u0ad9a;\u4396r;\u6128pf;\u6124cr;\uc000\ud835\udcb5\u0be1\u1583\u158a\u1590\0\u15b0\u15b6\u15bf\0\0\0\0\u15c6\u15db\u15eb\u165f\u166d\0\u1695\u169b\u16b2\u16b9\0\u16becute\u803b\xe1\u40e1reve;\u4103\u0300;Ediuy\u159c\u159d\u15a1\u15a3\u15a8\u15ad\u623e;\uc000\u223e\u0333;\u623frc\u803b\xe2\u40e2te\u80bb\xb4\u0306;\u4430lig\u803b\xe6\u40e6\u0100;r\xb2\u15ba;\uc000\ud835\udd1erave\u803b\xe0\u40e0\u0100ep\u15ca\u15d6\u0100fp\u15cf\u15d4sym;\u6135\xe8\u15d3ha;\u43b1\u0100ap\u15dfc\u0100cl\u15e4\u15e7r;\u4101g;\u6a3f\u0264\u15f0\0\0\u160a\u0280;adsv\u15fa\u15fb\u15ff\u1601\u1607\u6227nd;\u6a55;\u6a5clope;\u6a58;\u6a5a\u0380;elmrsz\u1618\u1619\u161b\u161e\u163f\u164f\u1659\u6220;\u69a4e\xbb\u1619sd\u0100;a\u1625\u1626\u6221\u0461\u1630\u1632\u1634\u1636\u1638\u163a\u163c\u163e;\u69a8;\u69a9;\u69aa;\u69ab;\u69ac;\u69ad;\u69ae;\u69aft\u0100;v\u1645\u1646\u621fb\u0100;d\u164c\u164d\u62be;\u699d\u0100pt\u1654\u1657h;\u6222\xbb\xb9arr;\u637c\u0100gp\u1663\u1667on;\u4105f;\uc000\ud835\udd52\u0380;Eaeiop\u12c1\u167b\u167d\u1682\u1684\u1687\u168a;\u6a70cir;\u6a6f;\u624ad;\u624bs;\u4027rox\u0100;e\u12c1\u1692\xf1\u1683ing\u803b\xe5\u40e5\u0180cty\u16a1\u16a6\u16a8r;\uc000\ud835\udcb6;\u402amp\u0100;e\u12c1\u16af\xf1\u0288ilde\u803b\xe3\u40e3ml\u803b\xe4\u40e4\u0100ci\u16c2\u16c8onin\xf4\u0272nt;\u6a11\u0800Nabcdefiklnoprsu\u16ed\u16f1\u1730\u173c\u1743\u1748\u1778\u177d\u17e0\u17e6\u1839\u1850\u170d\u193d\u1948\u1970ot;\u6aed\u0100cr\u16f6\u171ek\u0200ceps\u1700\u1705\u170d\u1713ong;\u624cpsilon;\u43f6rime;\u6035im\u0100;e\u171a\u171b\u623dq;\u62cd\u0176\u1722\u1726ee;\u62bded\u0100;g\u172c\u172d\u6305e\xbb\u172drk\u0100;t\u135c\u1737brk;\u63b6\u0100oy\u1701\u1741;\u4431quo;\u601e\u0280cmprt\u1753\u175b\u1761\u1764\u1768aus\u0100;e\u010a\u0109ptyv;\u69b0s\xe9\u170cno\xf5\u0113\u0180ahw\u176f\u1771\u1773;\u43b2;\u6136een;\u626cr;\uc000\ud835\udd1fg\u0380costuvw\u178d\u179d\u17b3\u17c1\u17d5\u17db\u17de\u0180aiu\u1794\u1796\u179a\xf0\u0760rc;\u65efp\xbb\u1371\u0180dpt\u17a4\u17a8\u17adot;\u6a00lus;\u6a01imes;\u6a02\u0271\u17b9\0\0\u17becup;\u6a06ar;\u6605riangle\u0100du\u17cd\u17d2own;\u65bdp;\u65b3plus;\u6a04e\xe5\u1444\xe5\u14adarow;\u690d\u0180ako\u17ed\u1826\u1835\u0100cn\u17f2\u1823k\u0180lst\u17fa\u05ab\u1802ozenge;\u69ebriangle\u0200;dlr\u1812\u1813\u1818\u181d\u65b4own;\u65beeft;\u65c2ight;\u65b8k;\u6423\u01b1\u182b\0\u1833\u01b2\u182f\0\u1831;\u6592;\u65914;\u6593ck;\u6588\u0100eo\u183e\u184d\u0100;q\u1843\u1846\uc000=\u20e5uiv;\uc000\u2261\u20e5t;\u6310\u0200ptwx\u1859\u185e\u1867\u186cf;\uc000\ud835\udd53\u0100;t\u13cb\u1863om\xbb\u13cctie;\u62c8\u0600DHUVbdhmptuv\u1885\u1896\u18aa\u18bb\u18d7\u18db\u18ec\u18ff\u1905\u190a\u1910\u1921\u0200LRlr\u188e\u1890\u1892\u1894;\u6557;\u6554;\u6556;\u6553\u0280;DUdu\u18a1\u18a2\u18a4\u18a6\u18a8\u6550;\u6566;\u6569;\u6564;\u6567\u0200LRlr\u18b3\u18b5\u18b7\u18b9;\u655d;\u655a;\u655c;\u6559\u0380;HLRhlr\u18ca\u18cb\u18cd\u18cf\u18d1\u18d3\u18d5\u6551;\u656c;\u6563;\u6560;\u656b;\u6562;\u655fox;\u69c9\u0200LRlr\u18e4\u18e6\u18e8\u18ea;\u6555;\u6552;\u6510;\u650c\u0280;DUdu\u06bd\u18f7\u18f9\u18fb\u18fd;\u6565;\u6568;\u652c;\u6534inus;\u629flus;\u629eimes;\u62a0\u0200LRlr\u1919\u191b\u191d\u191f;\u655b;\u6558;\u6518;\u6514\u0380;HLRhlr\u1930\u1931\u1933\u1935\u1937\u1939\u193b\u6502;\u656a;\u6561;\u655e;\u653c;\u6524;\u651c\u0100ev\u0123\u1942bar\u803b\xa6\u40a6\u0200ceio\u1951\u1956\u195a\u1960r;\uc000\ud835\udcb7mi;\u604fm\u0100;e\u171a\u171cl\u0180;bh\u1968\u1969\u196b\u405c;\u69c5sub;\u67c8\u016c\u1974\u197el\u0100;e\u1979\u197a\u6022t\xbb\u197ap\u0180;Ee\u012f\u1985\u1987;\u6aae\u0100;q\u06dc\u06db\u0ce1\u19a7\0\u19e8\u1a11\u1a15\u1a32\0\u1a37\u1a50\0\0\u1ab4\0\0\u1ac1\0\0\u1b21\u1b2e\u1b4d\u1b52\0\u1bfd\0\u1c0c\u0180cpr\u19ad\u19b2\u19ddute;\u4107\u0300;abcds\u19bf\u19c0\u19c4\u19ca\u19d5\u19d9\u6229nd;\u6a44rcup;\u6a49\u0100au\u19cf\u19d2p;\u6a4bp;\u6a47ot;\u6a40;\uc000\u2229\ufe00\u0100eo\u19e2\u19e5t;\u6041\xee\u0693\u0200aeiu\u19f0\u19fb\u1a01\u1a05\u01f0\u19f5\0\u19f8s;\u6a4don;\u410ddil\u803b\xe7\u40e7rc;\u4109ps\u0100;s\u1a0c\u1a0d\u6a4cm;\u6a50ot;\u410b\u0180dmn\u1a1b\u1a20\u1a26il\u80bb\xb8\u01adptyv;\u69b2t\u8100\xa2;e\u1a2d\u1a2e\u40a2r\xe4\u01b2r;\uc000\ud835\udd20\u0180cei\u1a3d\u1a40\u1a4dy;\u4447ck\u0100;m\u1a47\u1a48\u6713ark\xbb\u1a48;\u43c7r\u0380;Ecefms\u1a5f\u1a60\u1a62\u1a6b\u1aa4\u1aaa\u1aae\u65cb;\u69c3\u0180;el\u1a69\u1a6a\u1a6d\u42c6q;\u6257e\u0261\u1a74\0\0\u1a88rrow\u0100lr\u1a7c\u1a81eft;\u61baight;\u61bb\u0280RSacd\u1a92\u1a94\u1a96\u1a9a\u1a9f\xbb\u0f47;\u64c8st;\u629birc;\u629aash;\u629dnint;\u6a10id;\u6aefcir;\u69c2ubs\u0100;u\u1abb\u1abc\u6663it\xbb\u1abc\u02ec\u1ac7\u1ad4\u1afa\0\u1b0aon\u0100;e\u1acd\u1ace\u403a\u0100;q\xc7\xc6\u026d\u1ad9\0\0\u1ae2a\u0100;t\u1ade\u1adf\u402c;\u4040\u0180;fl\u1ae8\u1ae9\u1aeb\u6201\xee\u1160e\u0100mx\u1af1\u1af6ent\xbb\u1ae9e\xf3\u024d\u01e7\u1afe\0\u1b07\u0100;d\u12bb\u1b02ot;\u6a6dn\xf4\u0246\u0180fry\u1b10\u1b14\u1b17;\uc000\ud835\udd54o\xe4\u0254\u8100\xa9;s\u0155\u1b1dr;\u6117\u0100ao\u1b25\u1b29rr;\u61b5ss;\u6717\u0100cu\u1b32\u1b37r;\uc000\ud835\udcb8\u0100bp\u1b3c\u1b44\u0100;e\u1b41\u1b42\u6acf;\u6ad1\u0100;e\u1b49\u1b4a\u6ad0;\u6ad2dot;\u62ef\u0380delprvw\u1b60\u1b6c\u1b77\u1b82\u1bac\u1bd4\u1bf9arr\u0100lr\u1b68\u1b6a;\u6938;\u6935\u0270\u1b72\0\0\u1b75r;\u62dec;\u62dfarr\u0100;p\u1b7f\u1b80\u61b6;\u693d\u0300;bcdos\u1b8f\u1b90\u1b96\u1ba1\u1ba5\u1ba8\u622arcap;\u6a48\u0100au\u1b9b\u1b9ep;\u6a46p;\u6a4aot;\u628dr;\u6a45;\uc000\u222a\ufe00\u0200alrv\u1bb5\u1bbf\u1bde\u1be3rr\u0100;m\u1bbc\u1bbd\u61b7;\u693cy\u0180evw\u1bc7\u1bd4\u1bd8q\u0270\u1bce\0\0\u1bd2re\xe3\u1b73u\xe3\u1b75ee;\u62ceedge;\u62cfen\u803b\xa4\u40a4earrow\u0100lr\u1bee\u1bf3eft\xbb\u1b80ight\xbb\u1bbde\xe4\u1bdd\u0100ci\u1c01\u1c07onin\xf4\u01f7nt;\u6231lcty;\u632d\u0980AHabcdefhijlorstuwz\u1c38\u1c3b\u1c3f\u1c5d\u1c69\u1c75\u1c8a\u1c9e\u1cac\u1cb7\u1cfb\u1cff\u1d0d\u1d7b\u1d91\u1dab\u1dbb\u1dc6\u1dcdr\xf2\u0381ar;\u6965\u0200glrs\u1c48\u1c4d\u1c52\u1c54ger;\u6020eth;\u6138\xf2\u1133h\u0100;v\u1c5a\u1c5b\u6010\xbb\u090a\u016b\u1c61\u1c67arow;\u690fa\xe3\u0315\u0100ay\u1c6e\u1c73ron;\u410f;\u4434\u0180;ao\u0332\u1c7c\u1c84\u0100gr\u02bf\u1c81r;\u61catseq;\u6a77\u0180glm\u1c91\u1c94\u1c98\u803b\xb0\u40b0ta;\u43b4ptyv;\u69b1\u0100ir\u1ca3\u1ca8sht;\u697f;\uc000\ud835\udd21ar\u0100lr\u1cb3\u1cb5\xbb\u08dc\xbb\u101e\u0280aegsv\u1cc2\u0378\u1cd6\u1cdc\u1ce0m\u0180;os\u0326\u1cca\u1cd4nd\u0100;s\u0326\u1cd1uit;\u6666amma;\u43ddin;\u62f2\u0180;io\u1ce7\u1ce8\u1cf8\u40f7de\u8100\xf7;o\u1ce7\u1cf0ntimes;\u62c7n\xf8\u1cf7cy;\u4452c\u026f\u1d06\0\0\u1d0arn;\u631eop;\u630d\u0280lptuw\u1d18\u1d1d\u1d22\u1d49\u1d55lar;\u4024f;\uc000\ud835\udd55\u0280;emps\u030b\u1d2d\u1d37\u1d3d\u1d42q\u0100;d\u0352\u1d33ot;\u6251inus;\u6238lus;\u6214quare;\u62a1blebarwedg\xe5\xfan\u0180adh\u112e\u1d5d\u1d67ownarrow\xf3\u1c83arpoon\u0100lr\u1d72\u1d76ef\xf4\u1cb4igh\xf4\u1cb6\u0162\u1d7f\u1d85karo\xf7\u0f42\u026f\u1d8a\0\0\u1d8ern;\u631fop;\u630c\u0180cot\u1d98\u1da3\u1da6\u0100ry\u1d9d\u1da1;\uc000\ud835\udcb9;\u4455l;\u69f6rok;\u4111\u0100dr\u1db0\u1db4ot;\u62f1i\u0100;f\u1dba\u1816\u65bf\u0100ah\u1dc0\u1dc3r\xf2\u0429a\xf2\u0fa6angle;\u69a6\u0100ci\u1dd2\u1dd5y;\u445fgrarr;\u67ff\u0900Dacdefglmnopqrstux\u1e01\u1e09\u1e19\u1e38\u0578\u1e3c\u1e49\u1e61\u1e7e\u1ea5\u1eaf\u1ebd\u1ee1\u1f2a\u1f37\u1f44\u1f4e\u1f5a\u0100Do\u1e06\u1d34o\xf4\u1c89\u0100cs\u1e0e\u1e14ute\u803b\xe9\u40e9ter;\u6a6e\u0200aioy\u1e22\u1e27\u1e31\u1e36ron;\u411br\u0100;c\u1e2d\u1e2e\u6256\u803b\xea\u40ealon;\u6255;\u444dot;\u4117\u0100Dr\u1e41\u1e45ot;\u6252;\uc000\ud835\udd22\u0180;rs\u1e50\u1e51\u1e57\u6a9aave\u803b\xe8\u40e8\u0100;d\u1e5c\u1e5d\u6a96ot;\u6a98\u0200;ils\u1e6a\u1e6b\u1e72\u1e74\u6a99nters;\u63e7;\u6113\u0100;d\u1e79\u1e7a\u6a95ot;\u6a97\u0180aps\u1e85\u1e89\u1e97cr;\u4113ty\u0180;sv\u1e92\u1e93\u1e95\u6205et\xbb\u1e93p\u01001;\u1e9d\u1ea4\u0133\u1ea1\u1ea3;\u6004;\u6005\u6003\u0100gs\u1eaa\u1eac;\u414bp;\u6002\u0100gp\u1eb4\u1eb8on;\u4119f;\uc000\ud835\udd56\u0180als\u1ec4\u1ece\u1ed2r\u0100;s\u1eca\u1ecb\u62d5l;\u69e3us;\u6a71i\u0180;lv\u1eda\u1edb\u1edf\u43b5on\xbb\u1edb;\u43f5\u0200csuv\u1eea\u1ef3\u1f0b\u1f23\u0100io\u1eef\u1e31rc\xbb\u1e2e\u0269\u1ef9\0\0\u1efb\xed\u0548ant\u0100gl\u1f02\u1f06tr\xbb\u1e5dess\xbb\u1e7a\u0180aei\u1f12\u1f16\u1f1als;\u403dst;\u625fv\u0100;D\u0235\u1f20D;\u6a78parsl;\u69e5\u0100Da\u1f2f\u1f33ot;\u6253rr;\u6971\u0180cdi\u1f3e\u1f41\u1ef8r;\u612fo\xf4\u0352\u0100ah\u1f49\u1f4b;\u43b7\u803b\xf0\u40f0\u0100mr\u1f53\u1f57l\u803b\xeb\u40ebo;\u60ac\u0180cip\u1f61\u1f64\u1f67l;\u4021s\xf4\u056e\u0100eo\u1f6c\u1f74ctatio\xee\u0559nential\xe5\u0579\u09e1\u1f92\0\u1f9e\0\u1fa1\u1fa7\0\0\u1fc6\u1fcc\0\u1fd3\0\u1fe6\u1fea\u2000\0\u2008\u205allingdotse\xf1\u1e44y;\u4444male;\u6640\u0180ilr\u1fad\u1fb3\u1fc1lig;\u8000\ufb03\u0269\u1fb9\0\0\u1fbdg;\u8000\ufb00ig;\u8000\ufb04;\uc000\ud835\udd23lig;\u8000\ufb01lig;\uc000fj\u0180alt\u1fd9\u1fdc\u1fe1t;\u666dig;\u8000\ufb02ns;\u65b1of;\u4192\u01f0\u1fee\0\u1ff3f;\uc000\ud835\udd57\u0100ak\u05bf\u1ff7\u0100;v\u1ffc\u1ffd\u62d4;\u6ad9artint;\u6a0d\u0100ao\u200c\u2055\u0100cs\u2011\u2052\u03b1\u201a\u2030\u2038\u2045\u2048\0\u2050\u03b2\u2022\u2025\u2027\u202a\u202c\0\u202e\u803b\xbd\u40bd;\u6153\u803b\xbc\u40bc;\u6155;\u6159;\u615b\u01b3\u2034\0\u2036;\u6154;\u6156\u02b4\u203e\u2041\0\0\u2043\u803b\xbe\u40be;\u6157;\u615c5;\u6158\u01b6\u204c\0\u204e;\u615a;\u615d8;\u615el;\u6044wn;\u6322cr;\uc000\ud835\udcbb\u0880Eabcdefgijlnorstv\u2082\u2089\u209f\u20a5\u20b0\u20b4\u20f0\u20f5\u20fa\u20ff\u2103\u2112\u2138\u0317\u213e\u2152\u219e\u0100;l\u064d\u2087;\u6a8c\u0180cmp\u2090\u2095\u209dute;\u41f5ma\u0100;d\u209c\u1cda\u43b3;\u6a86reve;\u411f\u0100iy\u20aa\u20aerc;\u411d;\u4433ot;\u4121\u0200;lqs\u063e\u0642\u20bd\u20c9\u0180;qs\u063e\u064c\u20c4lan\xf4\u0665\u0200;cdl\u0665\u20d2\u20d5\u20e5c;\u6aa9ot\u0100;o\u20dc\u20dd\u6a80\u0100;l\u20e2\u20e3\u6a82;\u6a84\u0100;e\u20ea\u20ed\uc000\u22db\ufe00s;\u6a94r;\uc000\ud835\udd24\u0100;g\u0673\u061bmel;\u6137cy;\u4453\u0200;Eaj\u065a\u210c\u210e\u2110;\u6a92;\u6aa5;\u6aa4\u0200Eaes\u211b\u211d\u2129\u2134;\u6269p\u0100;p\u2123\u2124\u6a8arox\xbb\u2124\u0100;q\u212e\u212f\u6a88\u0100;q\u212e\u211bim;\u62e7pf;\uc000\ud835\udd58\u0100ci\u2143\u2146r;\u610am\u0180;el\u066b\u214e\u2150;\u6a8e;\u6a90\u8300>;cdlqr\u05ee\u2160\u216a\u216e\u2173\u2179\u0100ci\u2165\u2167;\u6aa7r;\u6a7aot;\u62d7Par;\u6995uest;\u6a7c\u0280adels\u2184\u216a\u2190\u0656\u219b\u01f0\u2189\0\u218epro\xf8\u209er;\u6978q\u0100lq\u063f\u2196les\xf3\u2088i\xed\u066b\u0100en\u21a3\u21adrtneqq;\uc000\u2269\ufe00\xc5\u21aa\u0500Aabcefkosy\u21c4\u21c7\u21f1\u21f5\u21fa\u2218\u221d\u222f\u2268\u227dr\xf2\u03a0\u0200ilmr\u21d0\u21d4\u21d7\u21dbrs\xf0\u1484f\xbb\u2024il\xf4\u06a9\u0100dr\u21e0\u21e4cy;\u444a\u0180;cw\u08f4\u21eb\u21efir;\u6948;\u61adar;\u610firc;\u4125\u0180alr\u2201\u220e\u2213rts\u0100;u\u2209\u220a\u6665it\xbb\u220alip;\u6026con;\u62b9r;\uc000\ud835\udd25s\u0100ew\u2223\u2229arow;\u6925arow;\u6926\u0280amopr\u223a\u223e\u2243\u225e\u2263rr;\u61fftht;\u623bk\u0100lr\u2249\u2253eftarrow;\u61a9ightarrow;\u61aaf;\uc000\ud835\udd59bar;\u6015\u0180clt\u226f\u2274\u2278r;\uc000\ud835\udcbdas\xe8\u21f4rok;\u4127\u0100bp\u2282\u2287ull;\u6043hen\xbb\u1c5b\u0ae1\u22a3\0\u22aa\0\u22b8\u22c5\u22ce\0\u22d5\u22f3\0\0\u22f8\u2322\u2367\u2362\u237f\0\u2386\u23aa\u23b4cute\u803b\xed\u40ed\u0180;iy\u0771\u22b0\u22b5rc\u803b\xee\u40ee;\u4438\u0100cx\u22bc\u22bfy;\u4435cl\u803b\xa1\u40a1\u0100fr\u039f\u22c9;\uc000\ud835\udd26rave\u803b\xec\u40ec\u0200;ino\u073e\u22dd\u22e9\u22ee\u0100in\u22e2\u22e6nt;\u6a0ct;\u622dfin;\u69dcta;\u6129lig;\u4133\u0180aop\u22fe\u231a\u231d\u0180cgt\u2305\u2308\u2317r;\u412b\u0180elp\u071f\u230f\u2313in\xe5\u078ear\xf4\u0720h;\u4131f;\u62b7ed;\u41b5\u0280;cfot\u04f4\u232c\u2331\u233d\u2341are;\u6105in\u0100;t\u2338\u2339\u621eie;\u69dddo\xf4\u2319\u0280;celp\u0757\u234c\u2350\u235b\u2361al;\u62ba\u0100gr\u2355\u2359er\xf3\u1563\xe3\u234darhk;\u6a17rod;\u6a3c\u0200cgpt\u236f\u2372\u2376\u237by;\u4451on;\u412ff;\uc000\ud835\udd5aa;\u43b9uest\u803b\xbf\u40bf\u0100ci\u238a\u238fr;\uc000\ud835\udcben\u0280;Edsv\u04f4\u239b\u239d\u23a1\u04f3;\u62f9ot;\u62f5\u0100;v\u23a6\u23a7\u62f4;\u62f3\u0100;i\u0777\u23aelde;\u4129\u01eb\u23b8\0\u23bccy;\u4456l\u803b\xef\u40ef\u0300cfmosu\u23cc\u23d7\u23dc\u23e1\u23e7\u23f5\u0100iy\u23d1\u23d5rc;\u4135;\u4439r;\uc000\ud835\udd27ath;\u4237pf;\uc000\ud835\udd5b\u01e3\u23ec\0\u23f1r;\uc000\ud835\udcbfrcy;\u4458kcy;\u4454\u0400acfghjos\u240b\u2416\u2422\u2427\u242d\u2431\u2435\u243bppa\u0100;v\u2413\u2414\u43ba;\u43f0\u0100ey\u241b\u2420dil;\u4137;\u443ar;\uc000\ud835\udd28reen;\u4138cy;\u4445cy;\u445cpf;\uc000\ud835\udd5ccr;\uc000\ud835\udcc0\u0b80ABEHabcdefghjlmnoprstuv\u2470\u2481\u2486\u248d\u2491\u250e\u253d\u255a\u2580\u264e\u265e\u2665\u2679\u267d\u269a\u26b2\u26d8\u275d\u2768\u278b\u27c0\u2801\u2812\u0180art\u2477\u247a\u247cr\xf2\u09c6\xf2\u0395ail;\u691barr;\u690e\u0100;g\u0994\u248b;\u6a8bar;\u6962\u0963\u24a5\0\u24aa\0\u24b1\0\0\0\0\0\u24b5\u24ba\0\u24c6\u24c8\u24cd\0\u24f9ute;\u413amptyv;\u69b4ra\xee\u084cbda;\u43bbg\u0180;dl\u088e\u24c1\u24c3;\u6991\xe5\u088e;\u6a85uo\u803b\xab\u40abr\u0400;bfhlpst\u0899\u24de\u24e6\u24e9\u24eb\u24ee\u24f1\u24f5\u0100;f\u089d\u24e3s;\u691fs;\u691d\xeb\u2252p;\u61abl;\u6939im;\u6973l;\u61a2\u0180;ae\u24ff\u2500\u2504\u6aabil;\u6919\u0100;s\u2509\u250a\u6aad;\uc000\u2aad\ufe00\u0180abr\u2515\u2519\u251drr;\u690crk;\u6772\u0100ak\u2522\u252cc\u0100ek\u2528\u252a;\u407b;\u405b\u0100es\u2531\u2533;\u698bl\u0100du\u2539\u253b;\u698f;\u698d\u0200aeuy\u2546\u254b\u2556\u2558ron;\u413e\u0100di\u2550\u2554il;\u413c\xec\u08b0\xe2\u2529;\u443b\u0200cqrs\u2563\u2566\u256d\u257da;\u6936uo\u0100;r\u0e19\u1746\u0100du\u2572\u2577har;\u6967shar;\u694bh;\u61b2\u0280;fgqs\u258b\u258c\u0989\u25f3\u25ff\u6264t\u0280ahlrt\u2598\u25a4\u25b7\u25c2\u25e8rrow\u0100;t\u0899\u25a1a\xe9\u24f6arpoon\u0100du\u25af\u25b4own\xbb\u045ap\xbb\u0966eftarrows;\u61c7ight\u0180ahs\u25cd\u25d6\u25derrow\u0100;s\u08f4\u08a7arpoon\xf3\u0f98quigarro\xf7\u21f0hreetimes;\u62cb\u0180;qs\u258b\u0993\u25falan\xf4\u09ac\u0280;cdgs\u09ac\u260a\u260d\u261d\u2628c;\u6aa8ot\u0100;o\u2614\u2615\u6a7f\u0100;r\u261a\u261b\u6a81;\u6a83\u0100;e\u2622\u2625\uc000\u22da\ufe00s;\u6a93\u0280adegs\u2633\u2639\u263d\u2649\u264bppro\xf8\u24c6ot;\u62d6q\u0100gq\u2643\u2645\xf4\u0989gt\xf2\u248c\xf4\u099bi\xed\u09b2\u0180ilr\u2655\u08e1\u265asht;\u697c;\uc000\ud835\udd29\u0100;E\u099c\u2663;\u6a91\u0161\u2669\u2676r\u0100du\u25b2\u266e\u0100;l\u0965\u2673;\u696alk;\u6584cy;\u4459\u0280;acht\u0a48\u2688\u268b\u2691\u2696r\xf2\u25c1orne\xf2\u1d08ard;\u696bri;\u65fa\u0100io\u269f\u26a4dot;\u4140ust\u0100;a\u26ac\u26ad\u63b0che\xbb\u26ad\u0200Eaes\u26bb\u26bd\u26c9\u26d4;\u6268p\u0100;p\u26c3\u26c4\u6a89rox\xbb\u26c4\u0100;q\u26ce\u26cf\u6a87\u0100;q\u26ce\u26bbim;\u62e6\u0400abnoptwz\u26e9\u26f4\u26f7\u271a\u272f\u2741\u2747\u2750\u0100nr\u26ee\u26f1g;\u67ecr;\u61fdr\xeb\u08c1g\u0180lmr\u26ff\u270d\u2714eft\u0100ar\u09e6\u2707ight\xe1\u09f2apsto;\u67fcight\xe1\u09fdparrow\u0100lr\u2725\u2729ef\xf4\u24edight;\u61ac\u0180afl\u2736\u2739\u273dr;\u6985;\uc000\ud835\udd5dus;\u6a2dimes;\u6a34\u0161\u274b\u274fst;\u6217\xe1\u134e\u0180;ef\u2757\u2758\u1800\u65cange\xbb\u2758ar\u0100;l\u2764\u2765\u4028t;\u6993\u0280achmt\u2773\u2776\u277c\u2785\u2787r\xf2\u08a8orne\xf2\u1d8car\u0100;d\u0f98\u2783;\u696d;\u600eri;\u62bf\u0300achiqt\u2798\u279d\u0a40\u27a2\u27ae\u27bbquo;\u6039r;\uc000\ud835\udcc1m\u0180;eg\u09b2\u27aa\u27ac;\u6a8d;\u6a8f\u0100bu\u252a\u27b3o\u0100;r\u0e1f\u27b9;\u601arok;\u4142\u8400<;cdhilqr\u082b\u27d2\u2639\u27dc\u27e0\u27e5\u27ea\u27f0\u0100ci\u27d7\u27d9;\u6aa6r;\u6a79re\xe5\u25f2mes;\u62c9arr;\u6976uest;\u6a7b\u0100Pi\u27f5\u27f9ar;\u6996\u0180;ef\u2800\u092d\u181b\u65c3r\u0100du\u2807\u280dshar;\u694ahar;\u6966\u0100en\u2817\u2821rtneqq;\uc000\u2268\ufe00\xc5\u281e\u0700Dacdefhilnopsu\u2840\u2845\u2882\u288e\u2893\u28a0\u28a5\u28a8\u28da\u28e2\u28e4\u0a83\u28f3\u2902Dot;\u623a\u0200clpr\u284e\u2852\u2863\u287dr\u803b\xaf\u40af\u0100et\u2857\u2859;\u6642\u0100;e\u285e\u285f\u6720se\xbb\u285f\u0100;s\u103b\u2868to\u0200;dlu\u103b\u2873\u2877\u287bow\xee\u048cef\xf4\u090f\xf0\u13d1ker;\u65ae\u0100oy\u2887\u288cmma;\u6a29;\u443cash;\u6014asuredangle\xbb\u1626r;\uc000\ud835\udd2ao;\u6127\u0180cdn\u28af\u28b4\u28c9ro\u803b\xb5\u40b5\u0200;acd\u1464\u28bd\u28c0\u28c4s\xf4\u16a7ir;\u6af0ot\u80bb\xb7\u01b5us\u0180;bd\u28d2\u1903\u28d3\u6212\u0100;u\u1d3c\u28d8;\u6a2a\u0163\u28de\u28e1p;\u6adb\xf2\u2212\xf0\u0a81\u0100dp\u28e9\u28eeels;\u62a7f;\uc000\ud835\udd5e\u0100ct\u28f8\u28fdr;\uc000\ud835\udcc2pos\xbb\u159d\u0180;lm\u2909\u290a\u290d\u43bctimap;\u62b8\u0c00GLRVabcdefghijlmoprstuvw\u2942\u2953\u297e\u2989\u2998\u29da\u29e9\u2a15\u2a1a\u2a58\u2a5d\u2a83\u2a95\u2aa4\u2aa8\u2b04\u2b07\u2b44\u2b7f\u2bae\u2c34\u2c67\u2c7c\u2ce9\u0100gt\u2947\u294b;\uc000\u22d9\u0338\u0100;v\u2950\u0bcf\uc000\u226b\u20d2\u0180elt\u295a\u2972\u2976ft\u0100ar\u2961\u2967rrow;\u61cdightarrow;\u61ce;\uc000\u22d8\u0338\u0100;v\u297b\u0c47\uc000\u226a\u20d2ightarrow;\u61cf\u0100Dd\u298e\u2993ash;\u62afash;\u62ae\u0280bcnpt\u29a3\u29a7\u29ac\u29b1\u29ccla\xbb\u02deute;\u4144g;\uc000\u2220\u20d2\u0280;Eiop\u0d84\u29bc\u29c0\u29c5\u29c8;\uc000\u2a70\u0338d;\uc000\u224b\u0338s;\u4149ro\xf8\u0d84ur\u0100;a\u29d3\u29d4\u666el\u0100;s\u29d3\u0b38\u01f3\u29df\0\u29e3p\u80bb\xa0\u0b37mp\u0100;e\u0bf9\u0c00\u0280aeouy\u29f4\u29fe\u2a03\u2a10\u2a13\u01f0\u29f9\0\u29fb;\u6a43on;\u4148dil;\u4146ng\u0100;d\u0d7e\u2a0aot;\uc000\u2a6d\u0338p;\u6a42;\u443dash;\u6013\u0380;Aadqsx\u0b92\u2a29\u2a2d\u2a3b\u2a41\u2a45\u2a50rr;\u61d7r\u0100hr\u2a33\u2a36k;\u6924\u0100;o\u13f2\u13f0ot;\uc000\u2250\u0338ui\xf6\u0b63\u0100ei\u2a4a\u2a4ear;\u6928\xed\u0b98ist\u0100;s\u0ba0\u0b9fr;\uc000\ud835\udd2b\u0200Eest\u0bc5\u2a66\u2a79\u2a7c\u0180;qs\u0bbc\u2a6d\u0be1\u0180;qs\u0bbc\u0bc5\u2a74lan\xf4\u0be2i\xed\u0bea\u0100;r\u0bb6\u2a81\xbb\u0bb7\u0180Aap\u2a8a\u2a8d\u2a91r\xf2\u2971rr;\u61aear;\u6af2\u0180;sv\u0f8d\u2a9c\u0f8c\u0100;d\u2aa1\u2aa2\u62fc;\u62facy;\u445a\u0380AEadest\u2ab7\u2aba\u2abe\u2ac2\u2ac5\u2af6\u2af9r\xf2\u2966;\uc000\u2266\u0338rr;\u619ar;\u6025\u0200;fqs\u0c3b\u2ace\u2ae3\u2aeft\u0100ar\u2ad4\u2ad9rro\xf7\u2ac1ightarro\xf7\u2a90\u0180;qs\u0c3b\u2aba\u2aealan\xf4\u0c55\u0100;s\u0c55\u2af4\xbb\u0c36i\xed\u0c5d\u0100;r\u0c35\u2afei\u0100;e\u0c1a\u0c25i\xe4\u0d90\u0100pt\u2b0c\u2b11f;\uc000\ud835\udd5f\u8180\xac;in\u2b19\u2b1a\u2b36\u40acn\u0200;Edv\u0b89\u2b24\u2b28\u2b2e;\uc000\u22f9\u0338ot;\uc000\u22f5\u0338\u01e1\u0b89\u2b33\u2b35;\u62f7;\u62f6i\u0100;v\u0cb8\u2b3c\u01e1\u0cb8\u2b41\u2b43;\u62fe;\u62fd\u0180aor\u2b4b\u2b63\u2b69r\u0200;ast\u0b7b\u2b55\u2b5a\u2b5flle\xec\u0b7bl;\uc000\u2afd\u20e5;\uc000\u2202\u0338lint;\u6a14\u0180;ce\u0c92\u2b70\u2b73u\xe5\u0ca5\u0100;c\u0c98\u2b78\u0100;e\u0c92\u2b7d\xf1\u0c98\u0200Aait\u2b88\u2b8b\u2b9d\u2ba7r\xf2\u2988rr\u0180;cw\u2b94\u2b95\u2b99\u619b;\uc000\u2933\u0338;\uc000\u219d\u0338ghtarrow\xbb\u2b95ri\u0100;e\u0ccb\u0cd6\u0380chimpqu\u2bbd\u2bcd\u2bd9\u2b04\u0b78\u2be4\u2bef\u0200;cer\u0d32\u2bc6\u0d37\u2bc9u\xe5\u0d45;\uc000\ud835\udcc3ort\u026d\u2b05\0\0\u2bd6ar\xe1\u2b56m\u0100;e\u0d6e\u2bdf\u0100;q\u0d74\u0d73su\u0100bp\u2beb\u2bed\xe5\u0cf8\xe5\u0d0b\u0180bcp\u2bf6\u2c11\u2c19\u0200;Ees\u2bff\u2c00\u0d22\u2c04\u6284;\uc000\u2ac5\u0338et\u0100;e\u0d1b\u2c0bq\u0100;q\u0d23\u2c00c\u0100;e\u0d32\u2c17\xf1\u0d38\u0200;Ees\u2c22\u2c23\u0d5f\u2c27\u6285;\uc000\u2ac6\u0338et\u0100;e\u0d58\u2c2eq\u0100;q\u0d60\u2c23\u0200gilr\u2c3d\u2c3f\u2c45\u2c47\xec\u0bd7lde\u803b\xf1\u40f1\xe7\u0c43iangle\u0100lr\u2c52\u2c5ceft\u0100;e\u0c1a\u2c5a\xf1\u0c26ight\u0100;e\u0ccb\u2c65\xf1\u0cd7\u0100;m\u2c6c\u2c6d\u43bd\u0180;es\u2c74\u2c75\u2c79\u4023ro;\u6116p;\u6007\u0480DHadgilrs\u2c8f\u2c94\u2c99\u2c9e\u2ca3\u2cb0\u2cb6\u2cd3\u2ce3ash;\u62adarr;\u6904p;\uc000\u224d\u20d2ash;\u62ac\u0100et\u2ca8\u2cac;\uc000\u2265\u20d2;\uc000>\u20d2nfin;\u69de\u0180Aet\u2cbd\u2cc1\u2cc5rr;\u6902;\uc000\u2264\u20d2\u0100;r\u2cca\u2ccd\uc000<\u20d2ie;\uc000\u22b4\u20d2\u0100At\u2cd8\u2cdcrr;\u6903rie;\uc000\u22b5\u20d2im;\uc000\u223c\u20d2\u0180Aan\u2cf0\u2cf4\u2d02rr;\u61d6r\u0100hr\u2cfa\u2cfdk;\u6923\u0100;o\u13e7\u13e5ear;\u6927\u1253\u1a95\0\0\0\0\0\0\0\0\0\0\0\0\0\u2d2d\0\u2d38\u2d48\u2d60\u2d65\u2d72\u2d84\u1b07\0\0\u2d8d\u2dab\0\u2dc8\u2dce\0\u2ddc\u2e19\u2e2b\u2e3e\u2e43\u0100cs\u2d31\u1a97ute\u803b\xf3\u40f3\u0100iy\u2d3c\u2d45r\u0100;c\u1a9e\u2d42\u803b\xf4\u40f4;\u443e\u0280abios\u1aa0\u2d52\u2d57\u01c8\u2d5alac;\u4151v;\u6a38old;\u69bclig;\u4153\u0100cr\u2d69\u2d6dir;\u69bf;\uc000\ud835\udd2c\u036f\u2d79\0\0\u2d7c\0\u2d82n;\u42dbave\u803b\xf2\u40f2;\u69c1\u0100bm\u2d88\u0df4ar;\u69b5\u0200acit\u2d95\u2d98\u2da5\u2da8r\xf2\u1a80\u0100ir\u2d9d\u2da0r;\u69beoss;\u69bbn\xe5\u0e52;\u69c0\u0180aei\u2db1\u2db5\u2db9cr;\u414dga;\u43c9\u0180cdn\u2dc0\u2dc5\u01cdron;\u43bf;\u69b6pf;\uc000\ud835\udd60\u0180ael\u2dd4\u2dd7\u01d2r;\u69b7rp;\u69b9\u0380;adiosv\u2dea\u2deb\u2dee\u2e08\u2e0d\u2e10\u2e16\u6228r\xf2\u1a86\u0200;efm\u2df7\u2df8\u2e02\u2e05\u6a5dr\u0100;o\u2dfe\u2dff\u6134f\xbb\u2dff\u803b\xaa\u40aa\u803b\xba\u40bagof;\u62b6r;\u6a56lope;\u6a57;\u6a5b\u0180clo\u2e1f\u2e21\u2e27\xf2\u2e01ash\u803b\xf8\u40f8l;\u6298i\u016c\u2e2f\u2e34de\u803b\xf5\u40f5es\u0100;a\u01db\u2e3as;\u6a36ml\u803b\xf6\u40f6bar;\u633d\u0ae1\u2e5e\0\u2e7d\0\u2e80\u2e9d\0\u2ea2\u2eb9\0\0\u2ecb\u0e9c\0\u2f13\0\0\u2f2b\u2fbc\0\u2fc8r\u0200;ast\u0403\u2e67\u2e72\u0e85\u8100\xb6;l\u2e6d\u2e6e\u40b6le\xec\u0403\u0269\u2e78\0\0\u2e7bm;\u6af3;\u6afdy;\u443fr\u0280cimpt\u2e8b\u2e8f\u2e93\u1865\u2e97nt;\u4025od;\u402eil;\u6030enk;\u6031r;\uc000\ud835\udd2d\u0180imo\u2ea8\u2eb0\u2eb4\u0100;v\u2ead\u2eae\u43c6;\u43d5ma\xf4\u0a76ne;\u660e\u0180;tv\u2ebf\u2ec0\u2ec8\u43c0chfork\xbb\u1ffd;\u43d6\u0100au\u2ecf\u2edfn\u0100ck\u2ed5\u2eddk\u0100;h\u21f4\u2edb;\u610e\xf6\u21f4s\u0480;abcdemst\u2ef3\u2ef4\u1908\u2ef9\u2efd\u2f04\u2f06\u2f0a\u2f0e\u402bcir;\u6a23ir;\u6a22\u0100ou\u1d40\u2f02;\u6a25;\u6a72n\u80bb\xb1\u0e9dim;\u6a26wo;\u6a27\u0180ipu\u2f19\u2f20\u2f25ntint;\u6a15f;\uc000\ud835\udd61nd\u803b\xa3\u40a3\u0500;Eaceinosu\u0ec8\u2f3f\u2f41\u2f44\u2f47\u2f81\u2f89\u2f92\u2f7e\u2fb6;\u6ab3p;\u6ab7u\xe5\u0ed9\u0100;c\u0ece\u2f4c\u0300;acens\u0ec8\u2f59\u2f5f\u2f66\u2f68\u2f7eppro\xf8\u2f43urlye\xf1\u0ed9\xf1\u0ece\u0180aes\u2f6f\u2f76\u2f7approx;\u6ab9qq;\u6ab5im;\u62e8i\xed\u0edfme\u0100;s\u2f88\u0eae\u6032\u0180Eas\u2f78\u2f90\u2f7a\xf0\u2f75\u0180dfp\u0eec\u2f99\u2faf\u0180als\u2fa0\u2fa5\u2faalar;\u632eine;\u6312urf;\u6313\u0100;t\u0efb\u2fb4\xef\u0efbrel;\u62b0\u0100ci\u2fc0\u2fc5r;\uc000\ud835\udcc5;\u43c8ncsp;\u6008\u0300fiopsu\u2fda\u22e2\u2fdf\u2fe5\u2feb\u2ff1r;\uc000\ud835\udd2epf;\uc000\ud835\udd62rime;\u6057cr;\uc000\ud835\udcc6\u0180aeo\u2ff8\u3009\u3013t\u0100ei\u2ffe\u3005rnion\xf3\u06b0nt;\u6a16st\u0100;e\u3010\u3011\u403f\xf1\u1f19\xf4\u0f14\u0a80ABHabcdefhilmnoprstux\u3040\u3051\u3055\u3059\u30e0\u310e\u312b\u3147\u3162\u3172\u318e\u3206\u3215\u3224\u3229\u3258\u326e\u3272\u3290\u32b0\u32b7\u0180art\u3047\u304a\u304cr\xf2\u10b3\xf2\u03ddail;\u691car\xf2\u1c65ar;\u6964\u0380cdenqrt\u3068\u3075\u3078\u307f\u308f\u3094\u30cc\u0100eu\u306d\u3071;\uc000\u223d\u0331te;\u4155i\xe3\u116emptyv;\u69b3g\u0200;del\u0fd1\u3089\u308b\u308d;\u6992;\u69a5\xe5\u0fd1uo\u803b\xbb\u40bbr\u0580;abcfhlpstw\u0fdc\u30ac\u30af\u30b7\u30b9\u30bc\u30be\u30c0\u30c3\u30c7\u30cap;\u6975\u0100;f\u0fe0\u30b4s;\u6920;\u6933s;\u691e\xeb\u225d\xf0\u272el;\u6945im;\u6974l;\u61a3;\u619d\u0100ai\u30d1\u30d5il;\u691ao\u0100;n\u30db\u30dc\u6236al\xf3\u0f1e\u0180abr\u30e7\u30ea\u30eer\xf2\u17e5rk;\u6773\u0100ak\u30f3\u30fdc\u0100ek\u30f9\u30fb;\u407d;\u405d\u0100es\u3102\u3104;\u698cl\u0100du\u310a\u310c;\u698e;\u6990\u0200aeuy\u3117\u311c\u3127\u3129ron;\u4159\u0100di\u3121\u3125il;\u4157\xec\u0ff2\xe2\u30fa;\u4440\u0200clqs\u3134\u3137\u313d\u3144a;\u6937dhar;\u6969uo\u0100;r\u020e\u020dh;\u61b3\u0180acg\u314e\u315f\u0f44l\u0200;ips\u0f78\u3158\u315b\u109cn\xe5\u10bbar\xf4\u0fa9t;\u65ad\u0180ilr\u3169\u1023\u316esht;\u697d;\uc000\ud835\udd2f\u0100ao\u3177\u3186r\u0100du\u317d\u317f\xbb\u047b\u0100;l\u1091\u3184;\u696c\u0100;v\u318b\u318c\u43c1;\u43f1\u0180gns\u3195\u31f9\u31fcht\u0300ahlrst\u31a4\u31b0\u31c2\u31d8\u31e4\u31eerrow\u0100;t\u0fdc\u31ada\xe9\u30c8arpoon\u0100du\u31bb\u31bfow\xee\u317ep\xbb\u1092eft\u0100ah\u31ca\u31d0rrow\xf3\u0feaarpoon\xf3\u0551ightarrows;\u61c9quigarro\xf7\u30cbhreetimes;\u62ccg;\u42daingdotse\xf1\u1f32\u0180ahm\u320d\u3210\u3213r\xf2\u0feaa\xf2\u0551;\u600foust\u0100;a\u321e\u321f\u63b1che\xbb\u321fmid;\u6aee\u0200abpt\u3232\u323d\u3240\u3252\u0100nr\u3237\u323ag;\u67edr;\u61fer\xeb\u1003\u0180afl\u3247\u324a\u324er;\u6986;\uc000\ud835\udd63us;\u6a2eimes;\u6a35\u0100ap\u325d\u3267r\u0100;g\u3263\u3264\u4029t;\u6994olint;\u6a12ar\xf2\u31e3\u0200achq\u327b\u3280\u10bc\u3285quo;\u603ar;\uc000\ud835\udcc7\u0100bu\u30fb\u328ao\u0100;r\u0214\u0213\u0180hir\u3297\u329b\u32a0re\xe5\u31f8mes;\u62cai\u0200;efl\u32aa\u1059\u1821\u32ab\u65b9tri;\u69celuhar;\u6968;\u611e\u0d61\u32d5\u32db\u32df\u332c\u3338\u3371\0\u337a\u33a4\0\0\u33ec\u33f0\0\u3428\u3448\u345a\u34ad\u34b1\u34ca\u34f1\0\u3616\0\0\u3633cute;\u415bqu\xef\u27ba\u0500;Eaceinpsy\u11ed\u32f3\u32f5\u32ff\u3302\u330b\u330f\u331f\u3326\u3329;\u6ab4\u01f0\u32fa\0\u32fc;\u6ab8on;\u4161u\xe5\u11fe\u0100;d\u11f3\u3307il;\u415frc;\u415d\u0180Eas\u3316\u3318\u331b;\u6ab6p;\u6abaim;\u62e9olint;\u6a13i\xed\u1204;\u4441ot\u0180;be\u3334\u1d47\u3335\u62c5;\u6a66\u0380Aacmstx\u3346\u334a\u3357\u335b\u335e\u3363\u336drr;\u61d8r\u0100hr\u3350\u3352\xeb\u2228\u0100;o\u0a36\u0a34t\u803b\xa7\u40a7i;\u403bwar;\u6929m\u0100in\u3369\xf0nu\xf3\xf1t;\u6736r\u0100;o\u3376\u2055\uc000\ud835\udd30\u0200acoy\u3382\u3386\u3391\u33a0rp;\u666f\u0100hy\u338b\u338fcy;\u4449;\u4448rt\u026d\u3399\0\0\u339ci\xe4\u1464ara\xec\u2e6f\u803b\xad\u40ad\u0100gm\u33a8\u33b4ma\u0180;fv\u33b1\u33b2\u33b2\u43c3;\u43c2\u0400;deglnpr\u12ab\u33c5\u33c9\u33ce\u33d6\u33de\u33e1\u33e6ot;\u6a6a\u0100;q\u12b1\u12b0\u0100;E\u33d3\u33d4\u6a9e;\u6aa0\u0100;E\u33db\u33dc\u6a9d;\u6a9fe;\u6246lus;\u6a24arr;\u6972ar\xf2\u113d\u0200aeit\u33f8\u3408\u340f\u3417\u0100ls\u33fd\u3404lsetm\xe9\u336ahp;\u6a33parsl;\u69e4\u0100dl\u1463\u3414e;\u6323\u0100;e\u341c\u341d\u6aaa\u0100;s\u3422\u3423\u6aac;\uc000\u2aac\ufe00\u0180flp\u342e\u3433\u3442tcy;\u444c\u0100;b\u3438\u3439\u402f\u0100;a\u343e\u343f\u69c4r;\u633ff;\uc000\ud835\udd64a\u0100dr\u344d\u0402es\u0100;u\u3454\u3455\u6660it\xbb\u3455\u0180csu\u3460\u3479\u349f\u0100au\u3465\u346fp\u0100;s\u1188\u346b;\uc000\u2293\ufe00p\u0100;s\u11b4\u3475;\uc000\u2294\ufe00u\u0100bp\u347f\u348f\u0180;es\u1197\u119c\u3486et\u0100;e\u1197\u348d\xf1\u119d\u0180;es\u11a8\u11ad\u3496et\u0100;e\u11a8\u349d\xf1\u11ae\u0180;af\u117b\u34a6\u05b0r\u0165\u34ab\u05b1\xbb\u117car\xf2\u1148\u0200cemt\u34b9\u34be\u34c2\u34c5r;\uc000\ud835\udcc8tm\xee\xf1i\xec\u3415ar\xe6\u11be\u0100ar\u34ce\u34d5r\u0100;f\u34d4\u17bf\u6606\u0100an\u34da\u34edight\u0100ep\u34e3\u34eapsilo\xee\u1ee0h\xe9\u2eafs\xbb\u2852\u0280bcmnp\u34fb\u355e\u1209\u358b\u358e\u0480;Edemnprs\u350e\u350f\u3511\u3515\u351e\u3523\u352c\u3531\u3536\u6282;\u6ac5ot;\u6abd\u0100;d\u11da\u351aot;\u6ac3ult;\u6ac1\u0100Ee\u3528\u352a;\u6acb;\u628alus;\u6abfarr;\u6979\u0180eiu\u353d\u3552\u3555t\u0180;en\u350e\u3545\u354bq\u0100;q\u11da\u350feq\u0100;q\u352b\u3528m;\u6ac7\u0100bp\u355a\u355c;\u6ad5;\u6ad3c\u0300;acens\u11ed\u356c\u3572\u3579\u357b\u3326ppro\xf8\u32faurlye\xf1\u11fe\xf1\u11f3\u0180aes\u3582\u3588\u331bppro\xf8\u331aq\xf1\u3317g;\u666a\u0680123;Edehlmnps\u35a9\u35ac\u35af\u121c\u35b2\u35b4\u35c0\u35c9\u35d5\u35da\u35df\u35e8\u35ed\u803b\xb9\u40b9\u803b\xb2\u40b2\u803b\xb3\u40b3;\u6ac6\u0100os\u35b9\u35bct;\u6abeub;\u6ad8\u0100;d\u1222\u35c5ot;\u6ac4s\u0100ou\u35cf\u35d2l;\u67c9b;\u6ad7arr;\u697bult;\u6ac2\u0100Ee\u35e4\u35e6;\u6acc;\u628blus;\u6ac0\u0180eiu\u35f4\u3609\u360ct\u0180;en\u121c\u35fc\u3602q\u0100;q\u1222\u35b2eq\u0100;q\u35e7\u35e4m;\u6ac8\u0100bp\u3611\u3613;\u6ad4;\u6ad6\u0180Aan\u361c\u3620\u362drr;\u61d9r\u0100hr\u3626\u3628\xeb\u222e\u0100;o\u0a2b\u0a29war;\u692alig\u803b\xdf\u40df\u0be1\u3651\u365d\u3660\u12ce\u3673\u3679\0\u367e\u36c2\0\0\0\0\0\u36db\u3703\0\u3709\u376c\0\0\0\u3787\u0272\u3656\0\0\u365bget;\u6316;\u43c4r\xeb\u0e5f\u0180aey\u3666\u366b\u3670ron;\u4165dil;\u4163;\u4442lrec;\u6315r;\uc000\ud835\udd31\u0200eiko\u3686\u369d\u36b5\u36bc\u01f2\u368b\0\u3691e\u01004f\u1284\u1281a\u0180;sv\u3698\u3699\u369b\u43b8ym;\u43d1\u0100cn\u36a2\u36b2k\u0100as\u36a8\u36aeppro\xf8\u12c1im\xbb\u12acs\xf0\u129e\u0100as\u36ba\u36ae\xf0\u12c1rn\u803b\xfe\u40fe\u01ec\u031f\u36c6\u22e7es\u8180\xd7;bd\u36cf\u36d0\u36d8\u40d7\u0100;a\u190f\u36d5r;\u6a31;\u6a30\u0180eps\u36e1\u36e3\u3700\xe1\u2a4d\u0200;bcf\u0486\u36ec\u36f0\u36f4ot;\u6336ir;\u6af1\u0100;o\u36f9\u36fc\uc000\ud835\udd65rk;\u6ada\xe1\u3362rime;\u6034\u0180aip\u370f\u3712\u3764d\xe5\u1248\u0380adempst\u3721\u374d\u3740\u3751\u3757\u375c\u375fngle\u0280;dlqr\u3730\u3731\u3736\u3740\u3742\u65b5own\xbb\u1dbbeft\u0100;e\u2800\u373e\xf1\u092e;\u625cight\u0100;e\u32aa\u374b\xf1\u105aot;\u65ecinus;\u6a3alus;\u6a39b;\u69cdime;\u6a3bezium;\u63e2\u0180cht\u3772\u377d\u3781\u0100ry\u3777\u377b;\uc000\ud835\udcc9;\u4446cy;\u445brok;\u4167\u0100io\u378b\u378ex\xf4\u1777head\u0100lr\u3797\u37a0eftarro\xf7\u084fightarrow\xbb\u0f5d\u0900AHabcdfghlmoprstuw\u37d0\u37d3\u37d7\u37e4\u37f0\u37fc\u380e\u381c\u3823\u3834\u3851\u385d\u386b\u38a9\u38cc\u38d2\u38ea\u38f6r\xf2\u03edar;\u6963\u0100cr\u37dc\u37e2ute\u803b\xfa\u40fa\xf2\u1150r\u01e3\u37ea\0\u37edy;\u445eve;\u416d\u0100iy\u37f5\u37farc\u803b\xfb\u40fb;\u4443\u0180abh\u3803\u3806\u380br\xf2\u13adlac;\u4171a\xf2\u13c3\u0100ir\u3813\u3818sht;\u697e;\uc000\ud835\udd32rave\u803b\xf9\u40f9\u0161\u3827\u3831r\u0100lr\u382c\u382e\xbb\u0957\xbb\u1083lk;\u6580\u0100ct\u3839\u384d\u026f\u383f\0\0\u384arn\u0100;e\u3845\u3846\u631cr\xbb\u3846op;\u630fri;\u65f8\u0100al\u3856\u385acr;\u416b\u80bb\xa8\u0349\u0100gp\u3862\u3866on;\u4173f;\uc000\ud835\udd66\u0300adhlsu\u114b\u3878\u387d\u1372\u3891\u38a0own\xe1\u13b3arpoon\u0100lr\u3888\u388cef\xf4\u382digh\xf4\u382fi\u0180;hl\u3899\u389a\u389c\u43c5\xbb\u13faon\xbb\u389aparrows;\u61c8\u0180cit\u38b0\u38c4\u38c8\u026f\u38b6\0\0\u38c1rn\u0100;e\u38bc\u38bd\u631dr\xbb\u38bdop;\u630eng;\u416fri;\u65f9cr;\uc000\ud835\udcca\u0180dir\u38d9\u38dd\u38e2ot;\u62f0lde;\u4169i\u0100;f\u3730\u38e8\xbb\u1813\u0100am\u38ef\u38f2r\xf2\u38a8l\u803b\xfc\u40fcangle;\u69a7\u0780ABDacdeflnoprsz\u391c\u391f\u3929\u392d\u39b5\u39b8\u39bd\u39df\u39e4\u39e8\u39f3\u39f9\u39fd\u3a01\u3a20r\xf2\u03f7ar\u0100;v\u3926\u3927\u6ae8;\u6ae9as\xe8\u03e1\u0100nr\u3932\u3937grt;\u699c\u0380eknprst\u34e3\u3946\u394b\u3952\u395d\u3964\u3996app\xe1\u2415othin\xe7\u1e96\u0180hir\u34eb\u2ec8\u3959op\xf4\u2fb5\u0100;h\u13b7\u3962\xef\u318d\u0100iu\u3969\u396dgm\xe1\u33b3\u0100bp\u3972\u3984setneq\u0100;q\u397d\u3980\uc000\u228a\ufe00;\uc000\u2acb\ufe00setneq\u0100;q\u398f\u3992\uc000\u228b\ufe00;\uc000\u2acc\ufe00\u0100hr\u399b\u399fet\xe1\u369ciangle\u0100lr\u39aa\u39afeft\xbb\u0925ight\xbb\u1051y;\u4432ash\xbb\u1036\u0180elr\u39c4\u39d2\u39d7\u0180;be\u2dea\u39cb\u39cfar;\u62bbq;\u625alip;\u62ee\u0100bt\u39dc\u1468a\xf2\u1469r;\uc000\ud835\udd33tr\xe9\u39aesu\u0100bp\u39ef\u39f1\xbb\u0d1c\xbb\u0d59pf;\uc000\ud835\udd67ro\xf0\u0efbtr\xe9\u39b4\u0100cu\u3a06\u3a0br;\uc000\ud835\udccb\u0100bp\u3a10\u3a18n\u0100Ee\u3980\u3a16\xbb\u397en\u0100Ee\u3992\u3a1e\xbb\u3990igzag;\u699a\u0380cefoprs\u3a36\u3a3b\u3a56\u3a5b\u3a54\u3a61\u3a6airc;\u4175\u0100di\u3a40\u3a51\u0100bg\u3a45\u3a49ar;\u6a5fe\u0100;q\u15fa\u3a4f;\u6259erp;\u6118r;\uc000\ud835\udd34pf;\uc000\ud835\udd68\u0100;e\u1479\u3a66at\xe8\u1479cr;\uc000\ud835\udccc\u0ae3\u178e\u3a87\0\u3a8b\0\u3a90\u3a9b\0\0\u3a9d\u3aa8\u3aab\u3aaf\0\0\u3ac3\u3ace\0\u3ad8\u17dc\u17dftr\xe9\u17d1r;\uc000\ud835\udd35\u0100Aa\u3a94\u3a97r\xf2\u03c3r\xf2\u09f6;\u43be\u0100Aa\u3aa1\u3aa4r\xf2\u03b8r\xf2\u09eba\xf0\u2713is;\u62fb\u0180dpt\u17a4\u3ab5\u3abe\u0100fl\u3aba\u17a9;\uc000\ud835\udd69im\xe5\u17b2\u0100Aa\u3ac7\u3acar\xf2\u03cer\xf2\u0a01\u0100cq\u3ad2\u17b8r;\uc000\ud835\udccd\u0100pt\u17d6\u3adcr\xe9\u17d4\u0400acefiosu\u3af0\u3afd\u3b08\u3b0c\u3b11\u3b15\u3b1b\u3b21c\u0100uy\u3af6\u3afbte\u803b\xfd\u40fd;\u444f\u0100iy\u3b02\u3b06rc;\u4177;\u444bn\u803b\xa5\u40a5r;\uc000\ud835\udd36cy;\u4457pf;\uc000\ud835\udd6acr;\uc000\ud835\udcce\u0100cm\u3b26\u3b29y;\u444el\u803b\xff\u40ff\u0500acdefhiosw\u3b42\u3b48\u3b54\u3b58\u3b64\u3b69\u3b6d\u3b74\u3b7a\u3b80cute;\u417a\u0100ay\u3b4d\u3b52ron;\u417e;\u4437ot;\u417c\u0100et\u3b5d\u3b61tr\xe6\u155fa;\u43b6r;\uc000\ud835\udd37cy;\u4436grarr;\u61ddpf;\uc000\ud835\udd6bcr;\uc000\ud835\udccf\u0100jn\u3b85\u3b87;\u600dj;\u600c"
|
||
.split("")
|
||
.map((c) => c.charCodeAt(0)));
|
||
|
||
// Generated using scripts/write-decode-map.ts
|
||
var xmlDecodeTree = new Uint16Array(
|
||
// prettier-ignore
|
||
"\u0200aglq\t\x15\x18\x1b\u026d\x0f\0\0\x12p;\u4026os;\u4027t;\u403et;\u403cuot;\u4022"
|
||
.split("")
|
||
.map((c) => c.charCodeAt(0)));
|
||
|
||
// Adapted from https://github.com/mathiasbynens/he/blob/36afe179392226cf1b6ccdb16ebbb7a5a844d93a/src/he.js#L106-L134
|
||
var _a;
|
||
const decodeMap = new Map([
|
||
[0, 65533],
|
||
// C1 Unicode control character reference replacements
|
||
[128, 8364],
|
||
[130, 8218],
|
||
[131, 402],
|
||
[132, 8222],
|
||
[133, 8230],
|
||
[134, 8224],
|
||
[135, 8225],
|
||
[136, 710],
|
||
[137, 8240],
|
||
[138, 352],
|
||
[139, 8249],
|
||
[140, 338],
|
||
[142, 381],
|
||
[145, 8216],
|
||
[146, 8217],
|
||
[147, 8220],
|
||
[148, 8221],
|
||
[149, 8226],
|
||
[150, 8211],
|
||
[151, 8212],
|
||
[152, 732],
|
||
[153, 8482],
|
||
[154, 353],
|
||
[155, 8250],
|
||
[156, 339],
|
||
[158, 382],
|
||
[159, 376],
|
||
]);
|
||
/**
|
||
* Polyfill for `String.fromCodePoint`. It is used to create a string from a Unicode code point.
|
||
*/
|
||
const fromCodePoint$1 =
|
||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, node/no-unsupported-features/es-builtins
|
||
(_a = String.fromCodePoint) !== null && _a !== void 0 ? _a : function (codePoint) {
|
||
let output = "";
|
||
if (codePoint > 0xffff) {
|
||
codePoint -= 0x10000;
|
||
output += String.fromCharCode(((codePoint >>> 10) & 0x3ff) | 0xd800);
|
||
codePoint = 0xdc00 | (codePoint & 0x3ff);
|
||
}
|
||
output += String.fromCharCode(codePoint);
|
||
return output;
|
||
};
|
||
/**
|
||
* Replace the given code point with a replacement character if it is a
|
||
* surrogate or is outside the valid range. Otherwise return the code
|
||
* point unchanged.
|
||
*/
|
||
function replaceCodePoint(codePoint) {
|
||
var _a;
|
||
if ((codePoint >= 0xd800 && codePoint <= 0xdfff) || codePoint > 0x10ffff) {
|
||
return 0xfffd;
|
||
}
|
||
return (_a = decodeMap.get(codePoint)) !== null && _a !== void 0 ? _a : codePoint;
|
||
}
|
||
|
||
var CharCodes;
|
||
(function (CharCodes) {
|
||
CharCodes[CharCodes["NUM"] = 35] = "NUM";
|
||
CharCodes[CharCodes["SEMI"] = 59] = "SEMI";
|
||
CharCodes[CharCodes["EQUALS"] = 61] = "EQUALS";
|
||
CharCodes[CharCodes["ZERO"] = 48] = "ZERO";
|
||
CharCodes[CharCodes["NINE"] = 57] = "NINE";
|
||
CharCodes[CharCodes["LOWER_A"] = 97] = "LOWER_A";
|
||
CharCodes[CharCodes["LOWER_F"] = 102] = "LOWER_F";
|
||
CharCodes[CharCodes["LOWER_X"] = 120] = "LOWER_X";
|
||
CharCodes[CharCodes["LOWER_Z"] = 122] = "LOWER_Z";
|
||
CharCodes[CharCodes["UPPER_A"] = 65] = "UPPER_A";
|
||
CharCodes[CharCodes["UPPER_F"] = 70] = "UPPER_F";
|
||
CharCodes[CharCodes["UPPER_Z"] = 90] = "UPPER_Z";
|
||
})(CharCodes || (CharCodes = {}));
|
||
/** Bit that needs to be set to convert an upper case ASCII character to lower case */
|
||
const TO_LOWER_BIT = 0b100000;
|
||
var BinTrieFlags;
|
||
(function (BinTrieFlags) {
|
||
BinTrieFlags[BinTrieFlags["VALUE_LENGTH"] = 49152] = "VALUE_LENGTH";
|
||
BinTrieFlags[BinTrieFlags["BRANCH_LENGTH"] = 16256] = "BRANCH_LENGTH";
|
||
BinTrieFlags[BinTrieFlags["JUMP_TABLE"] = 127] = "JUMP_TABLE";
|
||
})(BinTrieFlags || (BinTrieFlags = {}));
|
||
function isNumber(code) {
|
||
return code >= CharCodes.ZERO && code <= CharCodes.NINE;
|
||
}
|
||
function isHexadecimalCharacter(code) {
|
||
return ((code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_F) ||
|
||
(code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_F));
|
||
}
|
||
function isAsciiAlphaNumeric(code) {
|
||
return ((code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_Z) ||
|
||
(code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_Z) ||
|
||
isNumber(code));
|
||
}
|
||
/**
|
||
* Checks if the given character is a valid end character for an entity in an attribute.
|
||
*
|
||
* Attribute values that aren't terminated properly aren't parsed, and shouldn't lead to a parser error.
|
||
* See the example in https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state
|
||
*/
|
||
function isEntityInAttributeInvalidEnd(code) {
|
||
return code === CharCodes.EQUALS || isAsciiAlphaNumeric(code);
|
||
}
|
||
var EntityDecoderState;
|
||
(function (EntityDecoderState) {
|
||
EntityDecoderState[EntityDecoderState["EntityStart"] = 0] = "EntityStart";
|
||
EntityDecoderState[EntityDecoderState["NumericStart"] = 1] = "NumericStart";
|
||
EntityDecoderState[EntityDecoderState["NumericDecimal"] = 2] = "NumericDecimal";
|
||
EntityDecoderState[EntityDecoderState["NumericHex"] = 3] = "NumericHex";
|
||
EntityDecoderState[EntityDecoderState["NamedEntity"] = 4] = "NamedEntity";
|
||
})(EntityDecoderState || (EntityDecoderState = {}));
|
||
var DecodingMode;
|
||
(function (DecodingMode) {
|
||
/** Entities in text nodes that can end with any character. */
|
||
DecodingMode[DecodingMode["Legacy"] = 0] = "Legacy";
|
||
/** Only allow entities terminated with a semicolon. */
|
||
DecodingMode[DecodingMode["Strict"] = 1] = "Strict";
|
||
/** Entities in attributes have limitations on ending characters. */
|
||
DecodingMode[DecodingMode["Attribute"] = 2] = "Attribute";
|
||
})(DecodingMode || (DecodingMode = {}));
|
||
/**
|
||
* Token decoder with support of writing partial entities.
|
||
*/
|
||
class EntityDecoder {
|
||
constructor(
|
||
/** The tree used to decode entities. */
|
||
decodeTree,
|
||
/**
|
||
* The function that is called when a codepoint is decoded.
|
||
*
|
||
* For multi-byte named entities, this will be called multiple times,
|
||
* with the second codepoint, and the same `consumed` value.
|
||
*
|
||
* @param codepoint The decoded codepoint.
|
||
* @param consumed The number of bytes consumed by the decoder.
|
||
*/
|
||
emitCodePoint,
|
||
/** An object that is used to produce errors. */
|
||
errors) {
|
||
this.decodeTree = decodeTree;
|
||
this.emitCodePoint = emitCodePoint;
|
||
this.errors = errors;
|
||
/** The current state of the decoder. */
|
||
this.state = EntityDecoderState.EntityStart;
|
||
/** Characters that were consumed while parsing an entity. */
|
||
this.consumed = 1;
|
||
/**
|
||
* The result of the entity.
|
||
*
|
||
* Either the result index of a numeric entity, or the codepoint of a
|
||
* numeric entity.
|
||
*/
|
||
this.result = 0;
|
||
/** The current index in the decode tree. */
|
||
this.treeIndex = 0;
|
||
/** The number of characters that were consumed in excess. */
|
||
this.excess = 1;
|
||
/** The mode in which the decoder is operating. */
|
||
this.decodeMode = DecodingMode.Strict;
|
||
}
|
||
/** Resets the instance to make it reusable. */
|
||
startEntity(decodeMode) {
|
||
this.decodeMode = decodeMode;
|
||
this.state = EntityDecoderState.EntityStart;
|
||
this.result = 0;
|
||
this.treeIndex = 0;
|
||
this.excess = 1;
|
||
this.consumed = 1;
|
||
}
|
||
/**
|
||
* Write an entity to the decoder. This can be called multiple times with partial entities.
|
||
* If the entity is incomplete, the decoder will return -1.
|
||
*
|
||
* Mirrors the implementation of `getDecoder`, but with the ability to stop decoding if the
|
||
* entity is incomplete, and resume when the next string is written.
|
||
*
|
||
* @param string The string containing the entity (or a continuation of the entity).
|
||
* @param offset The offset at which the entity begins. Should be 0 if this is not the first call.
|
||
* @returns The number of characters that were consumed, or -1 if the entity is incomplete.
|
||
*/
|
||
write(str, offset) {
|
||
switch (this.state) {
|
||
case EntityDecoderState.EntityStart: {
|
||
if (str.charCodeAt(offset) === CharCodes.NUM) {
|
||
this.state = EntityDecoderState.NumericStart;
|
||
this.consumed += 1;
|
||
return this.stateNumericStart(str, offset + 1);
|
||
}
|
||
this.state = EntityDecoderState.NamedEntity;
|
||
return this.stateNamedEntity(str, offset);
|
||
}
|
||
case EntityDecoderState.NumericStart: {
|
||
return this.stateNumericStart(str, offset);
|
||
}
|
||
case EntityDecoderState.NumericDecimal: {
|
||
return this.stateNumericDecimal(str, offset);
|
||
}
|
||
case EntityDecoderState.NumericHex: {
|
||
return this.stateNumericHex(str, offset);
|
||
}
|
||
case EntityDecoderState.NamedEntity: {
|
||
return this.stateNamedEntity(str, offset);
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Switches between the numeric decimal and hexadecimal states.
|
||
*
|
||
* Equivalent to the `Numeric character reference state` in the HTML spec.
|
||
*
|
||
* @param str The string containing the entity (or a continuation of the entity).
|
||
* @param offset The current offset.
|
||
* @returns The number of characters that were consumed, or -1 if the entity is incomplete.
|
||
*/
|
||
stateNumericStart(str, offset) {
|
||
if (offset >= str.length) {
|
||
return -1;
|
||
}
|
||
if ((str.charCodeAt(offset) | TO_LOWER_BIT) === CharCodes.LOWER_X) {
|
||
this.state = EntityDecoderState.NumericHex;
|
||
this.consumed += 1;
|
||
return this.stateNumericHex(str, offset + 1);
|
||
}
|
||
this.state = EntityDecoderState.NumericDecimal;
|
||
return this.stateNumericDecimal(str, offset);
|
||
}
|
||
addToNumericResult(str, start, end, base) {
|
||
if (start !== end) {
|
||
const digitCount = end - start;
|
||
this.result =
|
||
this.result * Math.pow(base, digitCount) +
|
||
parseInt(str.substr(start, digitCount), base);
|
||
this.consumed += digitCount;
|
||
}
|
||
}
|
||
/**
|
||
* Parses a hexadecimal numeric entity.
|
||
*
|
||
* Equivalent to the `Hexademical character reference state` in the HTML spec.
|
||
*
|
||
* @param str The string containing the entity (or a continuation of the entity).
|
||
* @param offset The current offset.
|
||
* @returns The number of characters that were consumed, or -1 if the entity is incomplete.
|
||
*/
|
||
stateNumericHex(str, offset) {
|
||
const startIdx = offset;
|
||
while (offset < str.length) {
|
||
const char = str.charCodeAt(offset);
|
||
if (isNumber(char) || isHexadecimalCharacter(char)) {
|
||
offset += 1;
|
||
}
|
||
else {
|
||
this.addToNumericResult(str, startIdx, offset, 16);
|
||
return this.emitNumericEntity(char, 3);
|
||
}
|
||
}
|
||
this.addToNumericResult(str, startIdx, offset, 16);
|
||
return -1;
|
||
}
|
||
/**
|
||
* Parses a decimal numeric entity.
|
||
*
|
||
* Equivalent to the `Decimal character reference state` in the HTML spec.
|
||
*
|
||
* @param str The string containing the entity (or a continuation of the entity).
|
||
* @param offset The current offset.
|
||
* @returns The number of characters that were consumed, or -1 if the entity is incomplete.
|
||
*/
|
||
stateNumericDecimal(str, offset) {
|
||
const startIdx = offset;
|
||
while (offset < str.length) {
|
||
const char = str.charCodeAt(offset);
|
||
if (isNumber(char)) {
|
||
offset += 1;
|
||
}
|
||
else {
|
||
this.addToNumericResult(str, startIdx, offset, 10);
|
||
return this.emitNumericEntity(char, 2);
|
||
}
|
||
}
|
||
this.addToNumericResult(str, startIdx, offset, 10);
|
||
return -1;
|
||
}
|
||
/**
|
||
* Validate and emit a numeric entity.
|
||
*
|
||
* Implements the logic from the `Hexademical character reference start
|
||
* state` and `Numeric character reference end state` in the HTML spec.
|
||
*
|
||
* @param lastCp The last code point of the entity. Used to see if the
|
||
* entity was terminated with a semicolon.
|
||
* @param expectedLength The minimum number of characters that should be
|
||
* consumed. Used to validate that at least one digit
|
||
* was consumed.
|
||
* @returns The number of characters that were consumed.
|
||
*/
|
||
emitNumericEntity(lastCp, expectedLength) {
|
||
var _a;
|
||
// Ensure we consumed at least one digit.
|
||
if (this.consumed <= expectedLength) {
|
||
(_a = this.errors) === null || _a === void 0 ? void 0 : _a.absenceOfDigitsInNumericCharacterReference(this.consumed);
|
||
return 0;
|
||
}
|
||
// Figure out if this is a legit end of the entity
|
||
if (lastCp === CharCodes.SEMI) {
|
||
this.consumed += 1;
|
||
}
|
||
else if (this.decodeMode === DecodingMode.Strict) {
|
||
return 0;
|
||
}
|
||
this.emitCodePoint(replaceCodePoint(this.result), this.consumed);
|
||
if (this.errors) {
|
||
if (lastCp !== CharCodes.SEMI) {
|
||
this.errors.missingSemicolonAfterCharacterReference();
|
||
}
|
||
this.errors.validateNumericCharacterReference(this.result);
|
||
}
|
||
return this.consumed;
|
||
}
|
||
/**
|
||
* Parses a named entity.
|
||
*
|
||
* Equivalent to the `Named character reference state` in the HTML spec.
|
||
*
|
||
* @param str The string containing the entity (or a continuation of the entity).
|
||
* @param offset The current offset.
|
||
* @returns The number of characters that were consumed, or -1 if the entity is incomplete.
|
||
*/
|
||
stateNamedEntity(str, offset) {
|
||
const { decodeTree } = this;
|
||
let current = decodeTree[this.treeIndex];
|
||
// The mask is the number of bytes of the value, including the current byte.
|
||
let valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14;
|
||
for (; offset < str.length; offset++, this.excess++) {
|
||
const char = str.charCodeAt(offset);
|
||
this.treeIndex = determineBranch(decodeTree, current, this.treeIndex + Math.max(1, valueLength), char);
|
||
if (this.treeIndex < 0) {
|
||
return this.result === 0 ||
|
||
// If we are parsing an attribute
|
||
(this.decodeMode === DecodingMode.Attribute &&
|
||
// We shouldn't have consumed any characters after the entity,
|
||
(valueLength === 0 ||
|
||
// And there should be no invalid characters.
|
||
isEntityInAttributeInvalidEnd(char)))
|
||
? 0
|
||
: this.emitNotTerminatedNamedEntity();
|
||
}
|
||
current = decodeTree[this.treeIndex];
|
||
valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14;
|
||
// If the branch is a value, store it and continue
|
||
if (valueLength !== 0) {
|
||
// If the entity is terminated by a semicolon, we are done.
|
||
if (char === CharCodes.SEMI) {
|
||
return this.emitNamedEntityData(this.treeIndex, valueLength, this.consumed + this.excess);
|
||
}
|
||
// If we encounter a non-terminated (legacy) entity while parsing strictly, then ignore it.
|
||
if (this.decodeMode !== DecodingMode.Strict) {
|
||
this.result = this.treeIndex;
|
||
this.consumed += this.excess;
|
||
this.excess = 0;
|
||
}
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
/**
|
||
* Emit a named entity that was not terminated with a semicolon.
|
||
*
|
||
* @returns The number of characters consumed.
|
||
*/
|
||
emitNotTerminatedNamedEntity() {
|
||
var _a;
|
||
const { result, decodeTree } = this;
|
||
const valueLength = (decodeTree[result] & BinTrieFlags.VALUE_LENGTH) >> 14;
|
||
this.emitNamedEntityData(result, valueLength, this.consumed);
|
||
(_a = this.errors) === null || _a === void 0 ? void 0 : _a.missingSemicolonAfterCharacterReference();
|
||
return this.consumed;
|
||
}
|
||
/**
|
||
* Emit a named entity.
|
||
*
|
||
* @param result The index of the entity in the decode tree.
|
||
* @param valueLength The number of bytes in the entity.
|
||
* @param consumed The number of characters consumed.
|
||
*
|
||
* @returns The number of characters consumed.
|
||
*/
|
||
emitNamedEntityData(result, valueLength, consumed) {
|
||
const { decodeTree } = this;
|
||
this.emitCodePoint(valueLength === 1
|
||
? decodeTree[result] & ~BinTrieFlags.VALUE_LENGTH
|
||
: decodeTree[result + 1], consumed);
|
||
if (valueLength === 3) {
|
||
// For multi-byte values, we need to emit the second byte.
|
||
this.emitCodePoint(decodeTree[result + 2], consumed);
|
||
}
|
||
return consumed;
|
||
}
|
||
/**
|
||
* Signal to the parser that the end of the input was reached.
|
||
*
|
||
* Remaining data will be emitted and relevant errors will be produced.
|
||
*
|
||
* @returns The number of characters consumed.
|
||
*/
|
||
end() {
|
||
var _a;
|
||
switch (this.state) {
|
||
case EntityDecoderState.NamedEntity: {
|
||
// Emit a named entity if we have one.
|
||
return this.result !== 0 &&
|
||
(this.decodeMode !== DecodingMode.Attribute ||
|
||
this.result === this.treeIndex)
|
||
? this.emitNotTerminatedNamedEntity()
|
||
: 0;
|
||
}
|
||
// Otherwise, emit a numeric entity if we have one.
|
||
case EntityDecoderState.NumericDecimal: {
|
||
return this.emitNumericEntity(0, 2);
|
||
}
|
||
case EntityDecoderState.NumericHex: {
|
||
return this.emitNumericEntity(0, 3);
|
||
}
|
||
case EntityDecoderState.NumericStart: {
|
||
(_a = this.errors) === null || _a === void 0 ? void 0 : _a.absenceOfDigitsInNumericCharacterReference(this.consumed);
|
||
return 0;
|
||
}
|
||
case EntityDecoderState.EntityStart: {
|
||
// Return 0 if we have no entity.
|
||
return 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Creates a function that decodes entities in a string.
|
||
*
|
||
* @param decodeTree The decode tree.
|
||
* @returns A function that decodes entities in a string.
|
||
*/
|
||
function getDecoder(decodeTree) {
|
||
let ret = "";
|
||
const decoder = new EntityDecoder(decodeTree, (str) => (ret += fromCodePoint$1(str)));
|
||
return function decodeWithTrie(str, decodeMode) {
|
||
let lastIndex = 0;
|
||
let offset = 0;
|
||
while ((offset = str.indexOf("&", offset)) >= 0) {
|
||
ret += str.slice(lastIndex, offset);
|
||
decoder.startEntity(decodeMode);
|
||
const len = decoder.write(str,
|
||
// Skip the "&"
|
||
offset + 1);
|
||
if (len < 0) {
|
||
lastIndex = offset + decoder.end();
|
||
break;
|
||
}
|
||
lastIndex = offset + len;
|
||
// If `len` is 0, skip the current `&` and continue.
|
||
offset = len === 0 ? lastIndex + 1 : lastIndex;
|
||
}
|
||
const result = ret + str.slice(lastIndex);
|
||
// Make sure we don't keep a reference to the final string.
|
||
ret = "";
|
||
return result;
|
||
};
|
||
}
|
||
/**
|
||
* Determines the branch of the current node that is taken given the current
|
||
* character. This function is used to traverse the trie.
|
||
*
|
||
* @param decodeTree The trie.
|
||
* @param current The current node.
|
||
* @param nodeIdx The index right after the current node and its value.
|
||
* @param char The current character.
|
||
* @returns The index of the next node, or -1 if no branch is taken.
|
||
*/
|
||
function determineBranch(decodeTree, current, nodeIdx, char) {
|
||
const branchCount = (current & BinTrieFlags.BRANCH_LENGTH) >> 7;
|
||
const jumpOffset = current & BinTrieFlags.JUMP_TABLE;
|
||
// Case 1: Single branch encoded in jump offset
|
||
if (branchCount === 0) {
|
||
return jumpOffset !== 0 && char === jumpOffset ? nodeIdx : -1;
|
||
}
|
||
// Case 2: Multiple branches encoded in jump table
|
||
if (jumpOffset) {
|
||
const value = char - jumpOffset;
|
||
return value < 0 || value >= branchCount
|
||
? -1
|
||
: decodeTree[nodeIdx + value] - 1;
|
||
}
|
||
// Case 3: Multiple branches encoded in dictionary
|
||
// Binary search for the character.
|
||
let lo = nodeIdx;
|
||
let hi = lo + branchCount - 1;
|
||
while (lo <= hi) {
|
||
const mid = (lo + hi) >>> 1;
|
||
const midVal = decodeTree[mid];
|
||
if (midVal < char) {
|
||
lo = mid + 1;
|
||
}
|
||
else if (midVal > char) {
|
||
hi = mid - 1;
|
||
}
|
||
else {
|
||
return decodeTree[mid + branchCount];
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
const htmlDecoder = getDecoder(htmlDecodeTree);
|
||
getDecoder(xmlDecodeTree);
|
||
/**
|
||
* Decodes an HTML string.
|
||
*
|
||
* @param str The string to decode.
|
||
* @param mode The decoding mode.
|
||
* @returns The decoded string.
|
||
*/
|
||
function decodeHTML(str, mode = DecodingMode.Legacy) {
|
||
return htmlDecoder(str, mode);
|
||
}
|
||
|
||
// Utilities
|
||
//
|
||
|
||
|
||
function _class$1 (obj) { return Object.prototype.toString.call(obj) }
|
||
|
||
function isString$1 (obj) { return _class$1(obj) === '[object String]' }
|
||
|
||
const _hasOwnProperty = Object.prototype.hasOwnProperty;
|
||
|
||
function has (object, key) {
|
||
return _hasOwnProperty.call(object, key)
|
||
}
|
||
|
||
// Merge objects
|
||
//
|
||
function assign$1 (obj /* from1, from2, from3, ... */) {
|
||
const sources = Array.prototype.slice.call(arguments, 1);
|
||
|
||
sources.forEach(function (source) {
|
||
if (!source) { return }
|
||
|
||
if (typeof source !== 'object') {
|
||
throw new TypeError(source + 'must be object')
|
||
}
|
||
|
||
Object.keys(source).forEach(function (key) {
|
||
obj[key] = source[key];
|
||
});
|
||
});
|
||
|
||
return obj
|
||
}
|
||
|
||
// Remove element from array and put another array at those position.
|
||
// Useful for some operations with tokens
|
||
function arrayReplaceAt (src, pos, newElements) {
|
||
return [].concat(src.slice(0, pos), newElements, src.slice(pos + 1))
|
||
}
|
||
|
||
function isValidEntityCode (c) {
|
||
/* eslint no-bitwise:0 */
|
||
// broken sequence
|
||
if (c >= 0xD800 && c <= 0xDFFF) { return false }
|
||
// never used
|
||
if (c >= 0xFDD0 && c <= 0xFDEF) { return false }
|
||
if ((c & 0xFFFF) === 0xFFFF || (c & 0xFFFF) === 0xFFFE) { return false }
|
||
// control codes
|
||
if (c >= 0x00 && c <= 0x08) { return false }
|
||
if (c === 0x0B) { return false }
|
||
if (c >= 0x0E && c <= 0x1F) { return false }
|
||
if (c >= 0x7F && c <= 0x9F) { return false }
|
||
// out of range
|
||
if (c > 0x10FFFF) { return false }
|
||
return true
|
||
}
|
||
|
||
function fromCodePoint (c) {
|
||
/* eslint no-bitwise:0 */
|
||
if (c > 0xffff) {
|
||
c -= 0x10000;
|
||
const surrogate1 = 0xd800 + (c >> 10);
|
||
const surrogate2 = 0xdc00 + (c & 0x3ff);
|
||
|
||
return String.fromCharCode(surrogate1, surrogate2)
|
||
}
|
||
return String.fromCharCode(c)
|
||
}
|
||
|
||
const UNESCAPE_MD_RE = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g;
|
||
const ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/gi;
|
||
const UNESCAPE_ALL_RE = new RegExp(UNESCAPE_MD_RE.source + '|' + ENTITY_RE.source, 'gi');
|
||
|
||
const DIGITAL_ENTITY_TEST_RE = /^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))$/i;
|
||
|
||
function replaceEntityPattern (match, name) {
|
||
if (name.charCodeAt(0) === 0x23/* # */ && DIGITAL_ENTITY_TEST_RE.test(name)) {
|
||
const code = name[1].toLowerCase() === 'x'
|
||
? parseInt(name.slice(2), 16)
|
||
: parseInt(name.slice(1), 10);
|
||
|
||
if (isValidEntityCode(code)) {
|
||
return fromCodePoint(code)
|
||
}
|
||
|
||
return match
|
||
}
|
||
|
||
const decoded = decodeHTML(match);
|
||
if (decoded !== match) {
|
||
return decoded
|
||
}
|
||
|
||
return match
|
||
}
|
||
|
||
/* function replaceEntities(str) {
|
||
if (str.indexOf('&') < 0) { return str; }
|
||
|
||
return str.replace(ENTITY_RE, replaceEntityPattern);
|
||
} */
|
||
|
||
function unescapeMd (str) {
|
||
if (str.indexOf('\\') < 0) { return str }
|
||
return str.replace(UNESCAPE_MD_RE, '$1')
|
||
}
|
||
|
||
function unescapeAll (str) {
|
||
if (str.indexOf('\\') < 0 && str.indexOf('&') < 0) { return str }
|
||
|
||
return str.replace(UNESCAPE_ALL_RE, function (match, escaped, entity) {
|
||
if (escaped) { return escaped }
|
||
return replaceEntityPattern(match, entity)
|
||
})
|
||
}
|
||
|
||
const HTML_ESCAPE_TEST_RE$1 = /[&<>"]/;
|
||
const HTML_ESCAPE_REPLACE_RE$1 = /[&<>"]/g;
|
||
const HTML_REPLACEMENTS$1 = {
|
||
'&': '&',
|
||
'<': '<',
|
||
'>': '>',
|
||
'"': '"'
|
||
};
|
||
|
||
function replaceUnsafeChar$1 (ch) {
|
||
return HTML_REPLACEMENTS$1[ch]
|
||
}
|
||
|
||
function escapeHtml$1 (str) {
|
||
if (HTML_ESCAPE_TEST_RE$1.test(str)) {
|
||
return str.replace(HTML_ESCAPE_REPLACE_RE$1, replaceUnsafeChar$1)
|
||
}
|
||
return str
|
||
}
|
||
|
||
const REGEXP_ESCAPE_RE = /[.?*+^$[\]\\(){}|-]/g;
|
||
|
||
function escapeRE$1 (str) {
|
||
return str.replace(REGEXP_ESCAPE_RE, '\\$&')
|
||
}
|
||
|
||
function isSpace (code) {
|
||
switch (code) {
|
||
case 0x09:
|
||
case 0x20:
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
// Zs (unicode class) || [\t\f\v\r\n]
|
||
function isWhiteSpace (code) {
|
||
if (code >= 0x2000 && code <= 0x200A) { return true }
|
||
switch (code) {
|
||
case 0x09: // \t
|
||
case 0x0A: // \n
|
||
case 0x0B: // \v
|
||
case 0x0C: // \f
|
||
case 0x0D: // \r
|
||
case 0x20:
|
||
case 0xA0:
|
||
case 0x1680:
|
||
case 0x202F:
|
||
case 0x205F:
|
||
case 0x3000:
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
/* eslint-disable max-len */
|
||
|
||
// Currently without astral characters support.
|
||
function isPunctChar (ch) {
|
||
return P$1.test(ch)
|
||
}
|
||
|
||
// Markdown ASCII punctuation characters.
|
||
//
|
||
// !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, or ~
|
||
// http://spec.commonmark.org/0.15/#ascii-punctuation-character
|
||
//
|
||
// Don't confuse with unicode punctuation !!! It lacks some chars in ascii range.
|
||
//
|
||
function isMdAsciiPunct (ch) {
|
||
switch (ch) {
|
||
case 0x21/* ! */:
|
||
case 0x22/* " */:
|
||
case 0x23/* # */:
|
||
case 0x24/* $ */:
|
||
case 0x25/* % */:
|
||
case 0x26/* & */:
|
||
case 0x27/* ' */:
|
||
case 0x28/* ( */:
|
||
case 0x29/* ) */:
|
||
case 0x2A/* * */:
|
||
case 0x2B/* + */:
|
||
case 0x2C/* , */:
|
||
case 0x2D/* - */:
|
||
case 0x2E/* . */:
|
||
case 0x2F/* / */:
|
||
case 0x3A/* : */:
|
||
case 0x3B/* ; */:
|
||
case 0x3C/* < */:
|
||
case 0x3D/* = */:
|
||
case 0x3E/* > */:
|
||
case 0x3F/* ? */:
|
||
case 0x40/* @ */:
|
||
case 0x5B/* [ */:
|
||
case 0x5C/* \ */:
|
||
case 0x5D/* ] */:
|
||
case 0x5E/* ^ */:
|
||
case 0x5F/* _ */:
|
||
case 0x60/* ` */:
|
||
case 0x7B/* { */:
|
||
case 0x7C/* | */:
|
||
case 0x7D/* } */:
|
||
case 0x7E/* ~ */:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
// Hepler to unify [reference labels].
|
||
//
|
||
function normalizeReference (str) {
|
||
// Trim and collapse whitespace
|
||
//
|
||
str = str.trim().replace(/\s+/g, ' ');
|
||
|
||
// In node v10 'ẞ'.toLowerCase() === 'Ṿ', which is presumed to be a bug
|
||
// fixed in v12 (couldn't find any details).
|
||
//
|
||
// So treat this one as a special case
|
||
// (remove this when node v10 is no longer supported).
|
||
//
|
||
if ('ẞ'.toLowerCase() === 'Ṿ') {
|
||
str = str.replace(/ẞ/g, 'ß');
|
||
}
|
||
|
||
// .toLowerCase().toUpperCase() should get rid of all differences
|
||
// between letter variants.
|
||
//
|
||
// Simple .toLowerCase() doesn't normalize 125 code points correctly,
|
||
// and .toUpperCase doesn't normalize 6 of them (list of exceptions:
|
||
// İ, ϴ, ẞ, Ω, K, Å - those are already uppercased, but have differently
|
||
// uppercased versions).
|
||
//
|
||
// Here's an example showing how it happens. Lets take greek letter omega:
|
||
// uppercase U+0398 (Θ), U+03f4 (ϴ) and lowercase U+03b8 (θ), U+03d1 (ϑ)
|
||
//
|
||
// Unicode entries:
|
||
// 0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8;
|
||
// 03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398
|
||
// 03D1;GREEK THETA SYMBOL;Ll;0;L;<compat> 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398
|
||
// 03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L;<compat> 0398;;;;N;;;;03B8;
|
||
//
|
||
// Case-insensitive comparison should treat all of them as equivalent.
|
||
//
|
||
// But .toLowerCase() doesn't change ϑ (it's already lowercase),
|
||
// and .toUpperCase() doesn't change ϴ (already uppercase).
|
||
//
|
||
// Applying first lower then upper case normalizes any character:
|
||
// '\u0398\u03f4\u03b8\u03d1'.toLowerCase().toUpperCase() === '\u0398\u0398\u0398\u0398'
|
||
//
|
||
// Note: this is equivalent to unicode case folding; unicode normalization
|
||
// is a different step that is not required here.
|
||
//
|
||
// Final result should be uppercased, because it's later stored in an object
|
||
// (this avoid a conflict with Object.prototype members,
|
||
// most notably, `__proto__`)
|
||
//
|
||
return str.toLowerCase().toUpperCase()
|
||
}
|
||
|
||
// Re-export libraries commonly used in both markdown-it and its plugins,
|
||
// so plugins won't have to depend on them explicitly, which reduces their
|
||
// bundled size (e.g. a browser build).
|
||
//
|
||
const lib = { mdurl, ucmicro };
|
||
|
||
var utils$3 = /*#__PURE__*/Object.freeze({
|
||
__proto__: null,
|
||
arrayReplaceAt: arrayReplaceAt,
|
||
assign: assign$1,
|
||
escapeHtml: escapeHtml$1,
|
||
escapeRE: escapeRE$1,
|
||
fromCodePoint: fromCodePoint,
|
||
has: has,
|
||
isMdAsciiPunct: isMdAsciiPunct,
|
||
isPunctChar: isPunctChar,
|
||
isSpace: isSpace,
|
||
isString: isString$1,
|
||
isValidEntityCode: isValidEntityCode,
|
||
isWhiteSpace: isWhiteSpace,
|
||
lib: lib,
|
||
normalizeReference: normalizeReference,
|
||
unescapeAll: unescapeAll,
|
||
unescapeMd: unescapeMd
|
||
});
|
||
|
||
// Parse link label
|
||
//
|
||
// this function assumes that first character ("[") already matches;
|
||
// returns the end of the label
|
||
//
|
||
|
||
function parseLinkLabel (state, start, disableNested) {
|
||
let level, found, marker, prevPos;
|
||
|
||
const max = state.posMax;
|
||
const oldPos = state.pos;
|
||
|
||
state.pos = start + 1;
|
||
level = 1;
|
||
|
||
while (state.pos < max) {
|
||
marker = state.src.charCodeAt(state.pos);
|
||
if (marker === 0x5D /* ] */) {
|
||
level--;
|
||
if (level === 0) {
|
||
found = true;
|
||
break
|
||
}
|
||
}
|
||
|
||
prevPos = state.pos;
|
||
state.md.inline.skipToken(state);
|
||
if (marker === 0x5B /* [ */) {
|
||
if (prevPos === state.pos - 1) {
|
||
// increase level if we find text `[`, which is not a part of any token
|
||
level++;
|
||
} else if (disableNested) {
|
||
state.pos = oldPos;
|
||
return -1
|
||
}
|
||
}
|
||
}
|
||
|
||
let labelEnd = -1;
|
||
|
||
if (found) {
|
||
labelEnd = state.pos;
|
||
}
|
||
|
||
// restore old state
|
||
state.pos = oldPos;
|
||
|
||
return labelEnd
|
||
}
|
||
|
||
// Parse link destination
|
||
//
|
||
|
||
|
||
function parseLinkDestination (str, start, max) {
|
||
let code;
|
||
let pos = start;
|
||
|
||
const result = {
|
||
ok: false,
|
||
pos: 0,
|
||
lines: 0,
|
||
str: ''
|
||
};
|
||
|
||
if (str.charCodeAt(pos) === 0x3C /* < */) {
|
||
pos++;
|
||
while (pos < max) {
|
||
code = str.charCodeAt(pos);
|
||
if (code === 0x0A /* \n */) { return result }
|
||
if (code === 0x3C /* < */) { return result }
|
||
if (code === 0x3E /* > */) {
|
||
result.pos = pos + 1;
|
||
result.str = unescapeAll(str.slice(start + 1, pos));
|
||
result.ok = true;
|
||
return result
|
||
}
|
||
if (code === 0x5C /* \ */ && pos + 1 < max) {
|
||
pos += 2;
|
||
continue
|
||
}
|
||
|
||
pos++;
|
||
}
|
||
|
||
// no closing '>'
|
||
return result
|
||
}
|
||
|
||
// this should be ... } else { ... branch
|
||
|
||
let level = 0;
|
||
while (pos < max) {
|
||
code = str.charCodeAt(pos);
|
||
|
||
if (code === 0x20) { break }
|
||
|
||
// ascii control characters
|
||
if (code < 0x20 || code === 0x7F) { break }
|
||
|
||
if (code === 0x5C /* \ */ && pos + 1 < max) {
|
||
if (str.charCodeAt(pos + 1) === 0x20) { break }
|
||
pos += 2;
|
||
continue
|
||
}
|
||
|
||
if (code === 0x28 /* ( */) {
|
||
level++;
|
||
if (level > 32) { return result }
|
||
}
|
||
|
||
if (code === 0x29 /* ) */) {
|
||
if (level === 0) { break }
|
||
level--;
|
||
}
|
||
|
||
pos++;
|
||
}
|
||
|
||
if (start === pos) { return result }
|
||
if (level !== 0) { return result }
|
||
|
||
result.str = unescapeAll(str.slice(start, pos));
|
||
result.pos = pos;
|
||
result.ok = true;
|
||
return result
|
||
}
|
||
|
||
// Parse link title
|
||
//
|
||
|
||
|
||
function parseLinkTitle (str, start, max) {
|
||
let code, marker;
|
||
let lines = 0;
|
||
let pos = start;
|
||
|
||
const result = {
|
||
ok: false,
|
||
pos: 0,
|
||
lines: 0,
|
||
str: ''
|
||
};
|
||
|
||
if (pos >= max) { return result }
|
||
|
||
marker = str.charCodeAt(pos);
|
||
|
||
if (marker !== 0x22 /* " */ && marker !== 0x27 /* ' */ && marker !== 0x28 /* ( */) { return result }
|
||
|
||
pos++;
|
||
|
||
// if opening marker is "(", switch it to closing marker ")"
|
||
if (marker === 0x28) { marker = 0x29; }
|
||
|
||
while (pos < max) {
|
||
code = str.charCodeAt(pos);
|
||
if (code === marker) {
|
||
result.pos = pos + 1;
|
||
result.lines = lines;
|
||
result.str = unescapeAll(str.slice(start + 1, pos));
|
||
result.ok = true;
|
||
return result
|
||
} else if (code === 0x28 /* ( */ && marker === 0x29 /* ) */) {
|
||
return result
|
||
} else if (code === 0x0A) {
|
||
lines++;
|
||
} else if (code === 0x5C /* \ */ && pos + 1 < max) {
|
||
pos++;
|
||
if (str.charCodeAt(pos) === 0x0A) {
|
||
lines++;
|
||
}
|
||
}
|
||
|
||
pos++;
|
||
}
|
||
|
||
return result
|
||
}
|
||
|
||
// Just a shortcut for bulk export
|
||
|
||
var helpers = /*#__PURE__*/Object.freeze({
|
||
__proto__: null,
|
||
parseLinkDestination: parseLinkDestination,
|
||
parseLinkLabel: parseLinkLabel,
|
||
parseLinkTitle: parseLinkTitle
|
||
});
|
||
|
||
/**
|
||
* class Renderer
|
||
*
|
||
* Generates HTML from parsed token stream. Each instance has independent
|
||
* copy of rules. Those can be rewritten with ease. Also, you can add new
|
||
* rules if you create plugin and adds new token types.
|
||
**/
|
||
|
||
|
||
const default_rules = {};
|
||
|
||
default_rules.code_inline = function (tokens, idx, options, env, slf) {
|
||
const token = tokens[idx];
|
||
|
||
return '<code' + slf.renderAttrs(token) + '>' +
|
||
escapeHtml$1(token.content) +
|
||
'</code>'
|
||
};
|
||
|
||
default_rules.code_block = function (tokens, idx, options, env, slf) {
|
||
const token = tokens[idx];
|
||
|
||
return '<pre' + slf.renderAttrs(token) + '><code>' +
|
||
escapeHtml$1(tokens[idx].content) +
|
||
'</code></pre>\n'
|
||
};
|
||
|
||
default_rules.fence = function (tokens, idx, options, env, slf) {
|
||
const token = tokens[idx];
|
||
const info = token.info ? unescapeAll(token.info).trim() : '';
|
||
let langName = '';
|
||
let langAttrs = '';
|
||
|
||
if (info) {
|
||
const arr = info.split(/(\s+)/g);
|
||
langName = arr[0];
|
||
langAttrs = arr.slice(2).join('');
|
||
}
|
||
|
||
let highlighted;
|
||
if (options.highlight) {
|
||
highlighted = options.highlight(token.content, langName, langAttrs) || escapeHtml$1(token.content);
|
||
} else {
|
||
highlighted = escapeHtml$1(token.content);
|
||
}
|
||
|
||
if (highlighted.indexOf('<pre') === 0) {
|
||
return highlighted + '\n'
|
||
}
|
||
|
||
// If language exists, inject class gently, without modifying original token.
|
||
// May be, one day we will add .deepClone() for token and simplify this part, but
|
||
// now we prefer to keep things local.
|
||
if (info) {
|
||
const i = token.attrIndex('class');
|
||
const tmpAttrs = token.attrs ? token.attrs.slice() : [];
|
||
|
||
if (i < 0) {
|
||
tmpAttrs.push(['class', options.langPrefix + langName]);
|
||
} else {
|
||
tmpAttrs[i] = tmpAttrs[i].slice();
|
||
tmpAttrs[i][1] += ' ' + options.langPrefix + langName;
|
||
}
|
||
|
||
// Fake token just to render attributes
|
||
const tmpToken = {
|
||
attrs: tmpAttrs
|
||
};
|
||
|
||
return `<pre><code${slf.renderAttrs(tmpToken)}>${highlighted}</code></pre>\n`
|
||
}
|
||
|
||
return `<pre><code${slf.renderAttrs(token)}>${highlighted}</code></pre>\n`
|
||
};
|
||
|
||
default_rules.image = function (tokens, idx, options, env, slf) {
|
||
const token = tokens[idx];
|
||
|
||
// "alt" attr MUST be set, even if empty. Because it's mandatory and
|
||
// should be placed on proper position for tests.
|
||
//
|
||
// Replace content with actual value
|
||
|
||
token.attrs[token.attrIndex('alt')][1] =
|
||
slf.renderInlineAsText(token.children, options, env);
|
||
|
||
return slf.renderToken(tokens, idx, options)
|
||
};
|
||
|
||
default_rules.hardbreak = function (tokens, idx, options /*, env */) {
|
||
return options.xhtmlOut ? '<br />\n' : '<br>\n'
|
||
};
|
||
default_rules.softbreak = function (tokens, idx, options /*, env */) {
|
||
return options.breaks ? (options.xhtmlOut ? '<br />\n' : '<br>\n') : '\n'
|
||
};
|
||
|
||
default_rules.text = function (tokens, idx /*, options, env */) {
|
||
return escapeHtml$1(tokens[idx].content)
|
||
};
|
||
|
||
default_rules.html_block = function (tokens, idx /*, options, env */) {
|
||
return tokens[idx].content
|
||
};
|
||
default_rules.html_inline = function (tokens, idx /*, options, env */) {
|
||
return tokens[idx].content
|
||
};
|
||
|
||
/**
|
||
* new Renderer()
|
||
*
|
||
* Creates new [[Renderer]] instance and fill [[Renderer#rules]] with defaults.
|
||
**/
|
||
function Renderer () {
|
||
/**
|
||
* Renderer#rules -> Object
|
||
*
|
||
* Contains render rules for tokens. Can be updated and extended.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* md.renderer.rules.strong_open = function () { return '<b>'; };
|
||
* md.renderer.rules.strong_close = function () { return '</b>'; };
|
||
*
|
||
* var result = md.renderInline(...);
|
||
* ```
|
||
*
|
||
* Each rule is called as independent static function with fixed signature:
|
||
*
|
||
* ```javascript
|
||
* function my_token_render(tokens, idx, options, env, renderer) {
|
||
* // ...
|
||
* return renderedHTML;
|
||
* }
|
||
* ```
|
||
*
|
||
* See [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js)
|
||
* for more details and examples.
|
||
**/
|
||
this.rules = assign$1({}, default_rules);
|
||
}
|
||
|
||
/**
|
||
* Renderer.renderAttrs(token) -> String
|
||
*
|
||
* Render token attributes to string.
|
||
**/
|
||
Renderer.prototype.renderAttrs = function renderAttrs (token) {
|
||
let i, l, result;
|
||
|
||
if (!token.attrs) { return '' }
|
||
|
||
result = '';
|
||
|
||
for (i = 0, l = token.attrs.length; i < l; i++) {
|
||
result += ' ' + escapeHtml$1(token.attrs[i][0]) + '="' + escapeHtml$1(token.attrs[i][1]) + '"';
|
||
}
|
||
|
||
return result
|
||
};
|
||
|
||
/**
|
||
* Renderer.renderToken(tokens, idx, options) -> String
|
||
* - tokens (Array): list of tokens
|
||
* - idx (Numbed): token index to render
|
||
* - options (Object): params of parser instance
|
||
*
|
||
* Default token renderer. Can be overriden by custom function
|
||
* in [[Renderer#rules]].
|
||
**/
|
||
Renderer.prototype.renderToken = function renderToken (tokens, idx, options) {
|
||
const token = tokens[idx];
|
||
let result = '';
|
||
|
||
// Tight list paragraphs
|
||
if (token.hidden) {
|
||
return ''
|
||
}
|
||
|
||
// Insert a newline between hidden paragraph and subsequent opening
|
||
// block-level tag.
|
||
//
|
||
// For example, here we should insert a newline before blockquote:
|
||
// - a
|
||
// >
|
||
//
|
||
if (token.block && token.nesting !== -1 && idx && tokens[idx - 1].hidden) {
|
||
result += '\n';
|
||
}
|
||
|
||
// Add token name, e.g. `<img`
|
||
result += (token.nesting === -1 ? '</' : '<') + token.tag;
|
||
|
||
// Encode attributes, e.g. `<img src="foo"`
|
||
result += this.renderAttrs(token);
|
||
|
||
// Add a slash for self-closing tags, e.g. `<img src="foo" /`
|
||
if (token.nesting === 0 && options.xhtmlOut) {
|
||
result += ' /';
|
||
}
|
||
|
||
// Check if we need to add a newline after this tag
|
||
let needLf = false;
|
||
if (token.block) {
|
||
needLf = true;
|
||
|
||
if (token.nesting === 1) {
|
||
if (idx + 1 < tokens.length) {
|
||
const nextToken = tokens[idx + 1];
|
||
|
||
if (nextToken.type === 'inline' || nextToken.hidden) {
|
||
// Block-level tag containing an inline tag.
|
||
//
|
||
needLf = false;
|
||
} else if (nextToken.nesting === -1 && nextToken.tag === token.tag) {
|
||
// Opening tag + closing tag of the same type. E.g. `<li></li>`.
|
||
//
|
||
needLf = false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
result += needLf ? '>\n' : '>';
|
||
|
||
return result
|
||
};
|
||
|
||
/**
|
||
* Renderer.renderInline(tokens, options, env) -> String
|
||
* - tokens (Array): list on block tokens to render
|
||
* - options (Object): params of parser instance
|
||
* - env (Object): additional data from parsed input (references, for example)
|
||
*
|
||
* The same as [[Renderer.render]], but for single token of `inline` type.
|
||
**/
|
||
Renderer.prototype.renderInline = function (tokens, options, env) {
|
||
let result = '';
|
||
const rules = this.rules;
|
||
|
||
for (let i = 0, len = tokens.length; i < len; i++) {
|
||
const type = tokens[i].type;
|
||
|
||
if (typeof rules[type] !== 'undefined') {
|
||
result += rules[type](tokens, i, options, env, this);
|
||
} else {
|
||
result += this.renderToken(tokens, i, options);
|
||
}
|
||
}
|
||
|
||
return result
|
||
};
|
||
|
||
/** internal
|
||
* Renderer.renderInlineAsText(tokens, options, env) -> String
|
||
* - tokens (Array): list on block tokens to render
|
||
* - options (Object): params of parser instance
|
||
* - env (Object): additional data from parsed input (references, for example)
|
||
*
|
||
* Special kludge for image `alt` attributes to conform CommonMark spec.
|
||
* Don't try to use it! Spec requires to show `alt` content with stripped markup,
|
||
* instead of simple escaping.
|
||
**/
|
||
Renderer.prototype.renderInlineAsText = function (tokens, options, env) {
|
||
let result = '';
|
||
|
||
for (let i = 0, len = tokens.length; i < len; i++) {
|
||
switch (tokens[i].type) {
|
||
case 'text':
|
||
result += tokens[i].content;
|
||
break
|
||
case 'image':
|
||
result += this.renderInlineAsText(tokens[i].children, options, env);
|
||
break
|
||
case 'html_inline':
|
||
case 'html_block':
|
||
result += tokens[i].content;
|
||
break
|
||
case 'softbreak':
|
||
case 'hardbreak':
|
||
result += '\n';
|
||
break
|
||
// all other tokens are skipped
|
||
}
|
||
}
|
||
|
||
return result
|
||
};
|
||
|
||
/**
|
||
* Renderer.render(tokens, options, env) -> String
|
||
* - tokens (Array): list on block tokens to render
|
||
* - options (Object): params of parser instance
|
||
* - env (Object): additional data from parsed input (references, for example)
|
||
*
|
||
* Takes token stream and generates HTML. Probably, you will never need to call
|
||
* this method directly.
|
||
**/
|
||
Renderer.prototype.render = function (tokens, options, env) {
|
||
let result = '';
|
||
const rules = this.rules;
|
||
|
||
for (let i = 0, len = tokens.length; i < len; i++) {
|
||
const type = tokens[i].type;
|
||
|
||
if (type === 'inline') {
|
||
result += this.renderInline(tokens[i].children, options, env);
|
||
} else if (typeof rules[type] !== 'undefined') {
|
||
result += rules[type](tokens, i, options, env, this);
|
||
} else {
|
||
result += this.renderToken(tokens, i, options, env);
|
||
}
|
||
}
|
||
|
||
return result
|
||
};
|
||
|
||
/**
|
||
* class Ruler
|
||
*
|
||
* Helper class, used by [[MarkdownIt#core]], [[MarkdownIt#block]] and
|
||
* [[MarkdownIt#inline]] to manage sequences of functions (rules):
|
||
*
|
||
* - keep rules in defined order
|
||
* - assign the name to each rule
|
||
* - enable/disable rules
|
||
* - add/replace rules
|
||
* - allow assign rules to additional named chains (in the same)
|
||
* - cacheing lists of active rules
|
||
*
|
||
* You will not need use this class directly until write plugins. For simple
|
||
* rules control use [[MarkdownIt.disable]], [[MarkdownIt.enable]] and
|
||
* [[MarkdownIt.use]].
|
||
**/
|
||
|
||
/**
|
||
* new Ruler()
|
||
**/
|
||
function Ruler () {
|
||
// List of added rules. Each element is:
|
||
//
|
||
// {
|
||
// name: XXX,
|
||
// enabled: Boolean,
|
||
// fn: Function(),
|
||
// alt: [ name2, name3 ]
|
||
// }
|
||
//
|
||
this.__rules__ = [];
|
||
|
||
// Cached rule chains.
|
||
//
|
||
// First level - chain name, '' for default.
|
||
// Second level - diginal anchor for fast filtering by charcodes.
|
||
//
|
||
this.__cache__ = null;
|
||
}
|
||
|
||
// Helper methods, should not be used directly
|
||
|
||
// Find rule index by name
|
||
//
|
||
Ruler.prototype.__find__ = function (name) {
|
||
for (let i = 0; i < this.__rules__.length; i++) {
|
||
if (this.__rules__[i].name === name) {
|
||
return i
|
||
}
|
||
}
|
||
return -1
|
||
};
|
||
|
||
// Build rules lookup cache
|
||
//
|
||
Ruler.prototype.__compile__ = function () {
|
||
const self = this;
|
||
const chains = [''];
|
||
|
||
// collect unique names
|
||
self.__rules__.forEach(function (rule) {
|
||
if (!rule.enabled) { return }
|
||
|
||
rule.alt.forEach(function (altName) {
|
||
if (chains.indexOf(altName) < 0) {
|
||
chains.push(altName);
|
||
}
|
||
});
|
||
});
|
||
|
||
self.__cache__ = {};
|
||
|
||
chains.forEach(function (chain) {
|
||
self.__cache__[chain] = [];
|
||
self.__rules__.forEach(function (rule) {
|
||
if (!rule.enabled) { return }
|
||
|
||
if (chain && rule.alt.indexOf(chain) < 0) { return }
|
||
|
||
self.__cache__[chain].push(rule.fn);
|
||
});
|
||
});
|
||
};
|
||
|
||
/**
|
||
* Ruler.at(name, fn [, options])
|
||
* - name (String): rule name to replace.
|
||
* - fn (Function): new rule function.
|
||
* - options (Object): new rule options (not mandatory).
|
||
*
|
||
* Replace rule by name with new function & options. Throws error if name not
|
||
* found.
|
||
*
|
||
* ##### Options:
|
||
*
|
||
* - __alt__ - array with names of "alternate" chains.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* Replace existing typographer replacement rule with new one:
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* md.core.ruler.at('replacements', function replace(state) {
|
||
* //...
|
||
* });
|
||
* ```
|
||
**/
|
||
Ruler.prototype.at = function (name, fn, options) {
|
||
const index = this.__find__(name);
|
||
const opt = options || {};
|
||
|
||
if (index === -1) { throw new Error('Parser rule not found: ' + name) }
|
||
|
||
this.__rules__[index].fn = fn;
|
||
this.__rules__[index].alt = opt.alt || [];
|
||
this.__cache__ = null;
|
||
};
|
||
|
||
/**
|
||
* Ruler.before(beforeName, ruleName, fn [, options])
|
||
* - beforeName (String): new rule will be added before this one.
|
||
* - ruleName (String): name of added rule.
|
||
* - fn (Function): rule function.
|
||
* - options (Object): rule options (not mandatory).
|
||
*
|
||
* Add new rule to chain before one with given name. See also
|
||
* [[Ruler.after]], [[Ruler.push]].
|
||
*
|
||
* ##### Options:
|
||
*
|
||
* - __alt__ - array with names of "alternate" chains.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* md.block.ruler.before('paragraph', 'my_rule', function replace(state) {
|
||
* //...
|
||
* });
|
||
* ```
|
||
**/
|
||
Ruler.prototype.before = function (beforeName, ruleName, fn, options) {
|
||
const index = this.__find__(beforeName);
|
||
const opt = options || {};
|
||
|
||
if (index === -1) { throw new Error('Parser rule not found: ' + beforeName) }
|
||
|
||
this.__rules__.splice(index, 0, {
|
||
name: ruleName,
|
||
enabled: true,
|
||
fn,
|
||
alt: opt.alt || []
|
||
});
|
||
|
||
this.__cache__ = null;
|
||
};
|
||
|
||
/**
|
||
* Ruler.after(afterName, ruleName, fn [, options])
|
||
* - afterName (String): new rule will be added after this one.
|
||
* - ruleName (String): name of added rule.
|
||
* - fn (Function): rule function.
|
||
* - options (Object): rule options (not mandatory).
|
||
*
|
||
* Add new rule to chain after one with given name. See also
|
||
* [[Ruler.before]], [[Ruler.push]].
|
||
*
|
||
* ##### Options:
|
||
*
|
||
* - __alt__ - array with names of "alternate" chains.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* md.inline.ruler.after('text', 'my_rule', function replace(state) {
|
||
* //...
|
||
* });
|
||
* ```
|
||
**/
|
||
Ruler.prototype.after = function (afterName, ruleName, fn, options) {
|
||
const index = this.__find__(afterName);
|
||
const opt = options || {};
|
||
|
||
if (index === -1) { throw new Error('Parser rule not found: ' + afterName) }
|
||
|
||
this.__rules__.splice(index + 1, 0, {
|
||
name: ruleName,
|
||
enabled: true,
|
||
fn,
|
||
alt: opt.alt || []
|
||
});
|
||
|
||
this.__cache__ = null;
|
||
};
|
||
|
||
/**
|
||
* Ruler.push(ruleName, fn [, options])
|
||
* - ruleName (String): name of added rule.
|
||
* - fn (Function): rule function.
|
||
* - options (Object): rule options (not mandatory).
|
||
*
|
||
* Push new rule to the end of chain. See also
|
||
* [[Ruler.before]], [[Ruler.after]].
|
||
*
|
||
* ##### Options:
|
||
*
|
||
* - __alt__ - array with names of "alternate" chains.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* md.core.ruler.push('my_rule', function replace(state) {
|
||
* //...
|
||
* });
|
||
* ```
|
||
**/
|
||
Ruler.prototype.push = function (ruleName, fn, options) {
|
||
const opt = options || {};
|
||
|
||
this.__rules__.push({
|
||
name: ruleName,
|
||
enabled: true,
|
||
fn,
|
||
alt: opt.alt || []
|
||
});
|
||
|
||
this.__cache__ = null;
|
||
};
|
||
|
||
/**
|
||
* Ruler.enable(list [, ignoreInvalid]) -> Array
|
||
* - list (String|Array): list of rule names to enable.
|
||
* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
|
||
*
|
||
* Enable rules with given names. If any rule name not found - throw Error.
|
||
* Errors can be disabled by second param.
|
||
*
|
||
* Returns list of found rule names (if no exception happened).
|
||
*
|
||
* See also [[Ruler.disable]], [[Ruler.enableOnly]].
|
||
**/
|
||
Ruler.prototype.enable = function (list, ignoreInvalid) {
|
||
if (!Array.isArray(list)) { list = [list]; }
|
||
|
||
const result = [];
|
||
|
||
// Search by name and enable
|
||
list.forEach(function (name) {
|
||
const idx = this.__find__(name);
|
||
|
||
if (idx < 0) {
|
||
if (ignoreInvalid) { return }
|
||
throw new Error('Rules manager: invalid rule name ' + name)
|
||
}
|
||
this.__rules__[idx].enabled = true;
|
||
result.push(name);
|
||
}, this);
|
||
|
||
this.__cache__ = null;
|
||
return result
|
||
};
|
||
|
||
/**
|
||
* Ruler.enableOnly(list [, ignoreInvalid])
|
||
* - list (String|Array): list of rule names to enable (whitelist).
|
||
* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
|
||
*
|
||
* Enable rules with given names, and disable everything else. If any rule name
|
||
* not found - throw Error. Errors can be disabled by second param.
|
||
*
|
||
* See also [[Ruler.disable]], [[Ruler.enable]].
|
||
**/
|
||
Ruler.prototype.enableOnly = function (list, ignoreInvalid) {
|
||
if (!Array.isArray(list)) { list = [list]; }
|
||
|
||
this.__rules__.forEach(function (rule) { rule.enabled = false; });
|
||
|
||
this.enable(list, ignoreInvalid);
|
||
};
|
||
|
||
/**
|
||
* Ruler.disable(list [, ignoreInvalid]) -> Array
|
||
* - list (String|Array): list of rule names to disable.
|
||
* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
|
||
*
|
||
* Disable rules with given names. If any rule name not found - throw Error.
|
||
* Errors can be disabled by second param.
|
||
*
|
||
* Returns list of found rule names (if no exception happened).
|
||
*
|
||
* See also [[Ruler.enable]], [[Ruler.enableOnly]].
|
||
**/
|
||
Ruler.prototype.disable = function (list, ignoreInvalid) {
|
||
if (!Array.isArray(list)) { list = [list]; }
|
||
|
||
const result = [];
|
||
|
||
// Search by name and disable
|
||
list.forEach(function (name) {
|
||
const idx = this.__find__(name);
|
||
|
||
if (idx < 0) {
|
||
if (ignoreInvalid) { return }
|
||
throw new Error('Rules manager: invalid rule name ' + name)
|
||
}
|
||
this.__rules__[idx].enabled = false;
|
||
result.push(name);
|
||
}, this);
|
||
|
||
this.__cache__ = null;
|
||
return result
|
||
};
|
||
|
||
/**
|
||
* Ruler.getRules(chainName) -> Array
|
||
*
|
||
* Return array of active functions (rules) for given chain name. It analyzes
|
||
* rules configuration, compiles caches if not exists and returns result.
|
||
*
|
||
* Default chain name is `''` (empty string). It can't be skipped. That's
|
||
* done intentionally, to keep signature monomorphic for high speed.
|
||
**/
|
||
Ruler.prototype.getRules = function (chainName) {
|
||
if (this.__cache__ === null) {
|
||
this.__compile__();
|
||
}
|
||
|
||
// Chain can be empty, if rules disabled. But we still have to return Array.
|
||
return this.__cache__[chainName] || []
|
||
};
|
||
|
||
// Token class
|
||
|
||
/**
|
||
* class Token
|
||
**/
|
||
|
||
/**
|
||
* new Token(type, tag, nesting)
|
||
*
|
||
* Create new token and fill passed properties.
|
||
**/
|
||
function Token (type, tag, nesting) {
|
||
/**
|
||
* Token#type -> String
|
||
*
|
||
* Type of the token (string, e.g. "paragraph_open")
|
||
**/
|
||
this.type = type;
|
||
|
||
/**
|
||
* Token#tag -> String
|
||
*
|
||
* html tag name, e.g. "p"
|
||
**/
|
||
this.tag = tag;
|
||
|
||
/**
|
||
* Token#attrs -> Array
|
||
*
|
||
* Html attributes. Format: `[ [ name1, value1 ], [ name2, value2 ] ]`
|
||
**/
|
||
this.attrs = null;
|
||
|
||
/**
|
||
* Token#map -> Array
|
||
*
|
||
* Source map info. Format: `[ line_begin, line_end ]`
|
||
**/
|
||
this.map = null;
|
||
|
||
/**
|
||
* Token#nesting -> Number
|
||
*
|
||
* Level change (number in {-1, 0, 1} set), where:
|
||
*
|
||
* - `1` means the tag is opening
|
||
* - `0` means the tag is self-closing
|
||
* - `-1` means the tag is closing
|
||
**/
|
||
this.nesting = nesting;
|
||
|
||
/**
|
||
* Token#level -> Number
|
||
*
|
||
* nesting level, the same as `state.level`
|
||
**/
|
||
this.level = 0;
|
||
|
||
/**
|
||
* Token#children -> Array
|
||
*
|
||
* An array of child nodes (inline and img tokens)
|
||
**/
|
||
this.children = null;
|
||
|
||
/**
|
||
* Token#content -> String
|
||
*
|
||
* In a case of self-closing tag (code, html, fence, etc.),
|
||
* it has contents of this tag.
|
||
**/
|
||
this.content = '';
|
||
|
||
/**
|
||
* Token#markup -> String
|
||
*
|
||
* '*' or '_' for emphasis, fence string for fence, etc.
|
||
**/
|
||
this.markup = '';
|
||
|
||
/**
|
||
* Token#info -> String
|
||
*
|
||
* Additional information:
|
||
*
|
||
* - Info string for "fence" tokens
|
||
* - The value "auto" for autolink "link_open" and "link_close" tokens
|
||
* - The string value of the item marker for ordered-list "list_item_open" tokens
|
||
**/
|
||
this.info = '';
|
||
|
||
/**
|
||
* Token#meta -> Object
|
||
*
|
||
* A place for plugins to store an arbitrary data
|
||
**/
|
||
this.meta = null;
|
||
|
||
/**
|
||
* Token#block -> Boolean
|
||
*
|
||
* True for block-level tokens, false for inline tokens.
|
||
* Used in renderer to calculate line breaks
|
||
**/
|
||
this.block = false;
|
||
|
||
/**
|
||
* Token#hidden -> Boolean
|
||
*
|
||
* If it's true, ignore this element when rendering. Used for tight lists
|
||
* to hide paragraphs.
|
||
**/
|
||
this.hidden = false;
|
||
}
|
||
|
||
/**
|
||
* Token.attrIndex(name) -> Number
|
||
*
|
||
* Search attribute index by name.
|
||
**/
|
||
Token.prototype.attrIndex = function attrIndex (name) {
|
||
if (!this.attrs) { return -1 }
|
||
|
||
const attrs = this.attrs;
|
||
|
||
for (let i = 0, len = attrs.length; i < len; i++) {
|
||
if (attrs[i][0] === name) { return i }
|
||
}
|
||
return -1
|
||
};
|
||
|
||
/**
|
||
* Token.attrPush(attrData)
|
||
*
|
||
* Add `[ name, value ]` attribute to list. Init attrs if necessary
|
||
**/
|
||
Token.prototype.attrPush = function attrPush (attrData) {
|
||
if (this.attrs) {
|
||
this.attrs.push(attrData);
|
||
} else {
|
||
this.attrs = [attrData];
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Token.attrSet(name, value)
|
||
*
|
||
* Set `name` attribute to `value`. Override old value if exists.
|
||
**/
|
||
Token.prototype.attrSet = function attrSet (name, value) {
|
||
const idx = this.attrIndex(name);
|
||
const attrData = [name, value];
|
||
|
||
if (idx < 0) {
|
||
this.attrPush(attrData);
|
||
} else {
|
||
this.attrs[idx] = attrData;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Token.attrGet(name)
|
||
*
|
||
* Get the value of attribute `name`, or null if it does not exist.
|
||
**/
|
||
Token.prototype.attrGet = function attrGet (name) {
|
||
const idx = this.attrIndex(name);
|
||
let value = null;
|
||
if (idx >= 0) {
|
||
value = this.attrs[idx][1];
|
||
}
|
||
return value
|
||
};
|
||
|
||
/**
|
||
* Token.attrJoin(name, value)
|
||
*
|
||
* Join value to existing attribute via space. Or create new attribute if not
|
||
* exists. Useful to operate with token classes.
|
||
**/
|
||
Token.prototype.attrJoin = function attrJoin (name, value) {
|
||
const idx = this.attrIndex(name);
|
||
|
||
if (idx < 0) {
|
||
this.attrPush([name, value]);
|
||
} else {
|
||
this.attrs[idx][1] = this.attrs[idx][1] + ' ' + value;
|
||
}
|
||
};
|
||
|
||
// Core state object
|
||
//
|
||
|
||
|
||
function StateCore (src, md, env) {
|
||
this.src = src;
|
||
this.env = env;
|
||
this.tokens = [];
|
||
this.inlineMode = false;
|
||
this.md = md; // link to parser instance
|
||
}
|
||
|
||
// re-export Token class to use in core rules
|
||
StateCore.prototype.Token = Token;
|
||
|
||
// Normalize input string
|
||
|
||
// https://spec.commonmark.org/0.29/#line-ending
|
||
const NEWLINES_RE = /\r\n?|\n/g;
|
||
const NULL_RE = /\0/g;
|
||
|
||
function normalize (state) {
|
||
let str;
|
||
|
||
// Normalize newlines
|
||
str = state.src.replace(NEWLINES_RE, '\n');
|
||
|
||
// Replace NULL characters
|
||
str = str.replace(NULL_RE, '\uFFFD');
|
||
|
||
state.src = str;
|
||
}
|
||
|
||
function block (state) {
|
||
let token;
|
||
|
||
if (state.inlineMode) {
|
||
token = new state.Token('inline', '', 0);
|
||
token.content = state.src;
|
||
token.map = [0, 1];
|
||
token.children = [];
|
||
state.tokens.push(token);
|
||
} else {
|
||
state.md.block.parse(state.src, state.md, state.env, state.tokens);
|
||
}
|
||
}
|
||
|
||
function inline (state) {
|
||
const tokens = state.tokens;
|
||
|
||
// Parse inlines
|
||
for (let i = 0, l = tokens.length; i < l; i++) {
|
||
const tok = tokens[i];
|
||
if (tok.type === 'inline') {
|
||
state.md.inline.parse(tok.content, state.md, state.env, tok.children);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Replace link-like texts with link nodes.
|
||
//
|
||
// Currently restricted by `md.validateLink()` to http/https/ftp
|
||
//
|
||
|
||
|
||
function isLinkOpen$1 (str) {
|
||
return /^<a[>\s]/i.test(str)
|
||
}
|
||
function isLinkClose$1 (str) {
|
||
return /^<\/a\s*>/i.test(str)
|
||
}
|
||
|
||
function linkify$1 (state) {
|
||
const blockTokens = state.tokens;
|
||
|
||
if (!state.md.options.linkify) { return }
|
||
|
||
for (let j = 0, l = blockTokens.length; j < l; j++) {
|
||
if (blockTokens[j].type !== 'inline' ||
|
||
!state.md.linkify.pretest(blockTokens[j].content)) {
|
||
continue
|
||
}
|
||
|
||
let tokens = blockTokens[j].children;
|
||
|
||
let htmlLinkLevel = 0;
|
||
|
||
// We scan from the end, to keep position when new tags added.
|
||
// Use reversed logic in links start/end match
|
||
for (let i = tokens.length - 1; i >= 0; i--) {
|
||
const currentToken = tokens[i];
|
||
|
||
// Skip content of markdown links
|
||
if (currentToken.type === 'link_close') {
|
||
i--;
|
||
while (tokens[i].level !== currentToken.level && tokens[i].type !== 'link_open') {
|
||
i--;
|
||
}
|
||
continue
|
||
}
|
||
|
||
// Skip content of html tag links
|
||
if (currentToken.type === 'html_inline') {
|
||
if (isLinkOpen$1(currentToken.content) && htmlLinkLevel > 0) {
|
||
htmlLinkLevel--;
|
||
}
|
||
if (isLinkClose$1(currentToken.content)) {
|
||
htmlLinkLevel++;
|
||
}
|
||
}
|
||
if (htmlLinkLevel > 0) { continue }
|
||
|
||
if (currentToken.type === 'text' && state.md.linkify.test(currentToken.content)) {
|
||
const text = currentToken.content;
|
||
let links = state.md.linkify.match(text);
|
||
|
||
// Now split string to nodes
|
||
const nodes = [];
|
||
let level = currentToken.level;
|
||
let lastPos = 0;
|
||
|
||
// forbid escape sequence at the start of the string,
|
||
// this avoids http\://example.com/ from being linkified as
|
||
// http:<a href="//example.com/">//example.com/</a>
|
||
if (links.length > 0 &&
|
||
links[0].index === 0 &&
|
||
i > 0 &&
|
||
tokens[i - 1].type === 'text_special') {
|
||
links = links.slice(1);
|
||
}
|
||
|
||
for (let ln = 0; ln < links.length; ln++) {
|
||
const url = links[ln].url;
|
||
const fullUrl = state.md.normalizeLink(url);
|
||
if (!state.md.validateLink(fullUrl)) { continue }
|
||
|
||
let urlText = links[ln].text;
|
||
|
||
// Linkifier might send raw hostnames like "example.com", where url
|
||
// starts with domain name. So we prepend http:// in those cases,
|
||
// and remove it afterwards.
|
||
//
|
||
if (!links[ln].schema) {
|
||
urlText = state.md.normalizeLinkText('http://' + urlText).replace(/^http:\/\//, '');
|
||
} else if (links[ln].schema === 'mailto:' && !/^mailto:/i.test(urlText)) {
|
||
urlText = state.md.normalizeLinkText('mailto:' + urlText).replace(/^mailto:/, '');
|
||
} else {
|
||
urlText = state.md.normalizeLinkText(urlText);
|
||
}
|
||
|
||
const pos = links[ln].index;
|
||
|
||
if (pos > lastPos) {
|
||
const token = new state.Token('text', '', 0);
|
||
token.content = text.slice(lastPos, pos);
|
||
token.level = level;
|
||
nodes.push(token);
|
||
}
|
||
|
||
const token_o = new state.Token('link_open', 'a', 1);
|
||
token_o.attrs = [['href', fullUrl]];
|
||
token_o.level = level++;
|
||
token_o.markup = 'linkify';
|
||
token_o.info = 'auto';
|
||
nodes.push(token_o);
|
||
|
||
const token_t = new state.Token('text', '', 0);
|
||
token_t.content = urlText;
|
||
token_t.level = level;
|
||
nodes.push(token_t);
|
||
|
||
const token_c = new state.Token('link_close', 'a', -1);
|
||
token_c.level = --level;
|
||
token_c.markup = 'linkify';
|
||
token_c.info = 'auto';
|
||
nodes.push(token_c);
|
||
|
||
lastPos = links[ln].lastIndex;
|
||
}
|
||
if (lastPos < text.length) {
|
||
const token = new state.Token('text', '', 0);
|
||
token.content = text.slice(lastPos);
|
||
token.level = level;
|
||
nodes.push(token);
|
||
}
|
||
|
||
// replace current node
|
||
blockTokens[j].children = tokens = arrayReplaceAt(tokens, i, nodes);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Simple typographic replacements
|
||
//
|
||
// (c) (C) → ©
|
||
// (tm) (TM) → ™
|
||
// (r) (R) → ®
|
||
// +- → ±
|
||
// ... → … (also ?.... → ?.., !.... → !..)
|
||
// ???????? → ???, !!!!! → !!!, `,,` → `,`
|
||
// -- → –, --- → —
|
||
//
|
||
|
||
// TODO:
|
||
// - fractionals 1/2, 1/4, 3/4 -> ½, ¼, ¾
|
||
// - multiplications 2 x 4 -> 2 × 4
|
||
|
||
const RARE_RE = /\+-|\.\.|\?\?\?\?|!!!!|,,|--/;
|
||
|
||
// Workaround for phantomjs - need regex without /g flag,
|
||
// or root check will fail every second time
|
||
const SCOPED_ABBR_TEST_RE = /\((c|tm|r)\)/i;
|
||
|
||
const SCOPED_ABBR_RE = /\((c|tm|r)\)/ig;
|
||
const SCOPED_ABBR = {
|
||
c: '©',
|
||
r: '®',
|
||
tm: '™'
|
||
};
|
||
|
||
function replaceFn (match, name) {
|
||
return SCOPED_ABBR[name.toLowerCase()]
|
||
}
|
||
|
||
function replace_scoped (inlineTokens) {
|
||
let inside_autolink = 0;
|
||
|
||
for (let i = inlineTokens.length - 1; i >= 0; i--) {
|
||
const token = inlineTokens[i];
|
||
|
||
if (token.type === 'text' && !inside_autolink) {
|
||
token.content = token.content.replace(SCOPED_ABBR_RE, replaceFn);
|
||
}
|
||
|
||
if (token.type === 'link_open' && token.info === 'auto') {
|
||
inside_autolink--;
|
||
}
|
||
|
||
if (token.type === 'link_close' && token.info === 'auto') {
|
||
inside_autolink++;
|
||
}
|
||
}
|
||
}
|
||
|
||
function replace_rare (inlineTokens) {
|
||
let inside_autolink = 0;
|
||
|
||
for (let i = inlineTokens.length - 1; i >= 0; i--) {
|
||
const token = inlineTokens[i];
|
||
|
||
if (token.type === 'text' && !inside_autolink) {
|
||
if (RARE_RE.test(token.content)) {
|
||
token.content = token.content
|
||
.replace(/\+-/g, '±')
|
||
// .., ..., ....... -> …
|
||
// but ?..... & !..... -> ?.. & !..
|
||
.replace(/\.{2,}/g, '…').replace(/([?!])…/g, '$1..')
|
||
.replace(/([?!]){4,}/g, '$1$1$1').replace(/,{2,}/g, ',')
|
||
// em-dash
|
||
.replace(/(^|[^-])---(?=[^-]|$)/mg, '$1\u2014')
|
||
// en-dash
|
||
.replace(/(^|\s)--(?=\s|$)/mg, '$1\u2013')
|
||
.replace(/(^|[^-\s])--(?=[^-\s]|$)/mg, '$1\u2013');
|
||
}
|
||
}
|
||
|
||
if (token.type === 'link_open' && token.info === 'auto') {
|
||
inside_autolink--;
|
||
}
|
||
|
||
if (token.type === 'link_close' && token.info === 'auto') {
|
||
inside_autolink++;
|
||
}
|
||
}
|
||
}
|
||
|
||
function replace (state) {
|
||
let blkIdx;
|
||
|
||
if (!state.md.options.typographer) { return }
|
||
|
||
for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {
|
||
if (state.tokens[blkIdx].type !== 'inline') { continue }
|
||
|
||
if (SCOPED_ABBR_TEST_RE.test(state.tokens[blkIdx].content)) {
|
||
replace_scoped(state.tokens[blkIdx].children);
|
||
}
|
||
|
||
if (RARE_RE.test(state.tokens[blkIdx].content)) {
|
||
replace_rare(state.tokens[blkIdx].children);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Convert straight quotation marks to typographic ones
|
||
//
|
||
|
||
|
||
const QUOTE_TEST_RE = /['"]/;
|
||
const QUOTE_RE = /['"]/g;
|
||
const APOSTROPHE = '\u2019'; /* ’ */
|
||
|
||
function replaceAt (str, index, ch) {
|
||
return str.slice(0, index) + ch + str.slice(index + 1)
|
||
}
|
||
|
||
function process_inlines (tokens, state) {
|
||
let j;
|
||
|
||
const stack = [];
|
||
|
||
for (let i = 0; i < tokens.length; i++) {
|
||
const token = tokens[i];
|
||
|
||
const thisLevel = tokens[i].level;
|
||
|
||
for (j = stack.length - 1; j >= 0; j--) {
|
||
if (stack[j].level <= thisLevel) { break }
|
||
}
|
||
stack.length = j + 1;
|
||
|
||
if (token.type !== 'text') { continue }
|
||
|
||
let text = token.content;
|
||
let pos = 0;
|
||
let max = text.length;
|
||
|
||
/* eslint no-labels:0,block-scoped-var:0 */
|
||
OUTER:
|
||
while (pos < max) {
|
||
QUOTE_RE.lastIndex = pos;
|
||
const t = QUOTE_RE.exec(text);
|
||
if (!t) { break }
|
||
|
||
let canOpen = true;
|
||
let canClose = true;
|
||
pos = t.index + 1;
|
||
const isSingle = (t[0] === "'");
|
||
|
||
// Find previous character,
|
||
// default to space if it's the beginning of the line
|
||
//
|
||
let lastChar = 0x20;
|
||
|
||
if (t.index - 1 >= 0) {
|
||
lastChar = text.charCodeAt(t.index - 1);
|
||
} else {
|
||
for (j = i - 1; j >= 0; j--) {
|
||
if (tokens[j].type === 'softbreak' || tokens[j].type === 'hardbreak') break // lastChar defaults to 0x20
|
||
if (!tokens[j].content) continue // should skip all tokens except 'text', 'html_inline' or 'code_inline'
|
||
|
||
lastChar = tokens[j].content.charCodeAt(tokens[j].content.length - 1);
|
||
break
|
||
}
|
||
}
|
||
|
||
// Find next character,
|
||
// default to space if it's the end of the line
|
||
//
|
||
let nextChar = 0x20;
|
||
|
||
if (pos < max) {
|
||
nextChar = text.charCodeAt(pos);
|
||
} else {
|
||
for (j = i + 1; j < tokens.length; j++) {
|
||
if (tokens[j].type === 'softbreak' || tokens[j].type === 'hardbreak') break // nextChar defaults to 0x20
|
||
if (!tokens[j].content) continue // should skip all tokens except 'text', 'html_inline' or 'code_inline'
|
||
|
||
nextChar = tokens[j].content.charCodeAt(0);
|
||
break
|
||
}
|
||
}
|
||
|
||
const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));
|
||
const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));
|
||
|
||
const isLastWhiteSpace = isWhiteSpace(lastChar);
|
||
const isNextWhiteSpace = isWhiteSpace(nextChar);
|
||
|
||
if (isNextWhiteSpace) {
|
||
canOpen = false;
|
||
} else if (isNextPunctChar) {
|
||
if (!(isLastWhiteSpace || isLastPunctChar)) {
|
||
canOpen = false;
|
||
}
|
||
}
|
||
|
||
if (isLastWhiteSpace) {
|
||
canClose = false;
|
||
} else if (isLastPunctChar) {
|
||
if (!(isNextWhiteSpace || isNextPunctChar)) {
|
||
canClose = false;
|
||
}
|
||
}
|
||
|
||
if (nextChar === 0x22 /* " */ && t[0] === '"') {
|
||
if (lastChar >= 0x30 /* 0 */ && lastChar <= 0x39 /* 9 */) {
|
||
// special case: 1"" - count first quote as an inch
|
||
canClose = canOpen = false;
|
||
}
|
||
}
|
||
|
||
if (canOpen && canClose) {
|
||
// Replace quotes in the middle of punctuation sequence, but not
|
||
// in the middle of the words, i.e.:
|
||
//
|
||
// 1. foo " bar " baz - not replaced
|
||
// 2. foo-"-bar-"-baz - replaced
|
||
// 3. foo"bar"baz - not replaced
|
||
//
|
||
canOpen = isLastPunctChar;
|
||
canClose = isNextPunctChar;
|
||
}
|
||
|
||
if (!canOpen && !canClose) {
|
||
// middle of word
|
||
if (isSingle) {
|
||
token.content = replaceAt(token.content, t.index, APOSTROPHE);
|
||
}
|
||
continue
|
||
}
|
||
|
||
if (canClose) {
|
||
// this could be a closing quote, rewind the stack to get a match
|
||
for (j = stack.length - 1; j >= 0; j--) {
|
||
let item = stack[j];
|
||
if (stack[j].level < thisLevel) { break }
|
||
if (item.single === isSingle && stack[j].level === thisLevel) {
|
||
item = stack[j];
|
||
|
||
let openQuote;
|
||
let closeQuote;
|
||
if (isSingle) {
|
||
openQuote = state.md.options.quotes[2];
|
||
closeQuote = state.md.options.quotes[3];
|
||
} else {
|
||
openQuote = state.md.options.quotes[0];
|
||
closeQuote = state.md.options.quotes[1];
|
||
}
|
||
|
||
// replace token.content *before* tokens[item.token].content,
|
||
// because, if they are pointing at the same token, replaceAt
|
||
// could mess up indices when quote length != 1
|
||
token.content = replaceAt(token.content, t.index, closeQuote);
|
||
tokens[item.token].content = replaceAt(
|
||
tokens[item.token].content, item.pos, openQuote);
|
||
|
||
pos += closeQuote.length - 1;
|
||
if (item.token === i) { pos += openQuote.length - 1; }
|
||
|
||
text = token.content;
|
||
max = text.length;
|
||
|
||
stack.length = j;
|
||
continue OUTER
|
||
}
|
||
}
|
||
}
|
||
|
||
if (canOpen) {
|
||
stack.push({
|
||
token: i,
|
||
pos: t.index,
|
||
single: isSingle,
|
||
level: thisLevel
|
||
});
|
||
} else if (canClose && isSingle) {
|
||
token.content = replaceAt(token.content, t.index, APOSTROPHE);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
function smartquotes (state) {
|
||
/* eslint max-depth:0 */
|
||
if (!state.md.options.typographer) { return }
|
||
|
||
for (let blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {
|
||
if (state.tokens[blkIdx].type !== 'inline' ||
|
||
!QUOTE_TEST_RE.test(state.tokens[blkIdx].content)) {
|
||
continue
|
||
}
|
||
|
||
process_inlines(state.tokens[blkIdx].children, state);
|
||
}
|
||
}
|
||
|
||
// Join raw text tokens with the rest of the text
|
||
//
|
||
// This is set as a separate rule to provide an opportunity for plugins
|
||
// to run text replacements after text join, but before escape join.
|
||
//
|
||
// For example, `\:)` shouldn't be replaced with an emoji.
|
||
//
|
||
|
||
function text_join (state) {
|
||
let curr, last;
|
||
const blockTokens = state.tokens;
|
||
const l = blockTokens.length;
|
||
|
||
for (let j = 0; j < l; j++) {
|
||
if (blockTokens[j].type !== 'inline') continue
|
||
|
||
const tokens = blockTokens[j].children;
|
||
const max = tokens.length;
|
||
|
||
for (curr = 0; curr < max; curr++) {
|
||
if (tokens[curr].type === 'text_special') {
|
||
tokens[curr].type = 'text';
|
||
}
|
||
}
|
||
|
||
for (curr = last = 0; curr < max; curr++) {
|
||
if (tokens[curr].type === 'text' &&
|
||
curr + 1 < max &&
|
||
tokens[curr + 1].type === 'text') {
|
||
// collapse two adjacent text nodes
|
||
tokens[curr + 1].content = tokens[curr].content + tokens[curr + 1].content;
|
||
} else {
|
||
if (curr !== last) { tokens[last] = tokens[curr]; }
|
||
|
||
last++;
|
||
}
|
||
}
|
||
|
||
if (curr !== last) {
|
||
tokens.length = last;
|
||
}
|
||
}
|
||
}
|
||
|
||
/** internal
|
||
* class Core
|
||
*
|
||
* Top-level rules executor. Glues block/inline parsers and does intermediate
|
||
* transformations.
|
||
**/
|
||
|
||
|
||
const _rules$2 = [
|
||
['normalize', normalize],
|
||
['block', block],
|
||
['inline', inline],
|
||
['linkify', linkify$1],
|
||
['replacements', replace],
|
||
['smartquotes', smartquotes],
|
||
// `text_join` finds `text_special` tokens (for escape sequences)
|
||
// and joins them with the rest of the text
|
||
['text_join', text_join]
|
||
];
|
||
|
||
/**
|
||
* new Core()
|
||
**/
|
||
function Core () {
|
||
/**
|
||
* Core#ruler -> Ruler
|
||
*
|
||
* [[Ruler]] instance. Keep configuration of core rules.
|
||
**/
|
||
this.ruler = new Ruler();
|
||
|
||
for (let i = 0; i < _rules$2.length; i++) {
|
||
this.ruler.push(_rules$2[i][0], _rules$2[i][1]);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Core.process(state)
|
||
*
|
||
* Executes core chain rules.
|
||
**/
|
||
Core.prototype.process = function (state) {
|
||
const rules = this.ruler.getRules('');
|
||
|
||
for (let i = 0, l = rules.length; i < l; i++) {
|
||
rules[i](state);
|
||
}
|
||
};
|
||
|
||
Core.prototype.State = StateCore;
|
||
|
||
// Parser state class
|
||
|
||
|
||
function StateBlock (src, md, env, tokens) {
|
||
this.src = src;
|
||
|
||
// link to parser instance
|
||
this.md = md;
|
||
|
||
this.env = env;
|
||
|
||
//
|
||
// Internal state vartiables
|
||
//
|
||
|
||
this.tokens = tokens;
|
||
|
||
this.bMarks = []; // line begin offsets for fast jumps
|
||
this.eMarks = []; // line end offsets for fast jumps
|
||
this.tShift = []; // offsets of the first non-space characters (tabs not expanded)
|
||
this.sCount = []; // indents for each line (tabs expanded)
|
||
|
||
// An amount of virtual spaces (tabs expanded) between beginning
|
||
// of each line (bMarks) and real beginning of that line.
|
||
//
|
||
// It exists only as a hack because blockquotes override bMarks
|
||
// losing information in the process.
|
||
//
|
||
// It's used only when expanding tabs, you can think about it as
|
||
// an initial tab length, e.g. bsCount=21 applied to string `\t123`
|
||
// means first tab should be expanded to 4-21%4 === 3 spaces.
|
||
//
|
||
this.bsCount = [];
|
||
|
||
// block parser variables
|
||
|
||
// required block content indent (for example, if we are
|
||
// inside a list, it would be positioned after list marker)
|
||
this.blkIndent = 0;
|
||
this.line = 0; // line index in src
|
||
this.lineMax = 0; // lines count
|
||
this.tight = false; // loose/tight mode for lists
|
||
this.ddIndent = -1; // indent of the current dd block (-1 if there isn't any)
|
||
this.listIndent = -1; // indent of the current list block (-1 if there isn't any)
|
||
|
||
// can be 'blockquote', 'list', 'root', 'paragraph' or 'reference'
|
||
// used in lists to determine if they interrupt a paragraph
|
||
this.parentType = 'root';
|
||
|
||
this.level = 0;
|
||
|
||
// Create caches
|
||
// Generate markers.
|
||
const s = this.src;
|
||
|
||
for (let start = 0, pos = 0, indent = 0, offset = 0, len = s.length, indent_found = false; pos < len; pos++) {
|
||
const ch = s.charCodeAt(pos);
|
||
|
||
if (!indent_found) {
|
||
if (isSpace(ch)) {
|
||
indent++;
|
||
|
||
if (ch === 0x09) {
|
||
offset += 4 - offset % 4;
|
||
} else {
|
||
offset++;
|
||
}
|
||
continue
|
||
} else {
|
||
indent_found = true;
|
||
}
|
||
}
|
||
|
||
if (ch === 0x0A || pos === len - 1) {
|
||
if (ch !== 0x0A) { pos++; }
|
||
this.bMarks.push(start);
|
||
this.eMarks.push(pos);
|
||
this.tShift.push(indent);
|
||
this.sCount.push(offset);
|
||
this.bsCount.push(0);
|
||
|
||
indent_found = false;
|
||
indent = 0;
|
||
offset = 0;
|
||
start = pos + 1;
|
||
}
|
||
}
|
||
|
||
// Push fake entry to simplify cache bounds checks
|
||
this.bMarks.push(s.length);
|
||
this.eMarks.push(s.length);
|
||
this.tShift.push(0);
|
||
this.sCount.push(0);
|
||
this.bsCount.push(0);
|
||
|
||
this.lineMax = this.bMarks.length - 1; // don't count last fake line
|
||
}
|
||
|
||
// Push new token to "stream".
|
||
//
|
||
StateBlock.prototype.push = function (type, tag, nesting) {
|
||
const token = new Token(type, tag, nesting);
|
||
token.block = true;
|
||
|
||
if (nesting < 0) this.level--; // closing tag
|
||
token.level = this.level;
|
||
if (nesting > 0) this.level++; // opening tag
|
||
|
||
this.tokens.push(token);
|
||
return token
|
||
};
|
||
|
||
StateBlock.prototype.isEmpty = function isEmpty (line) {
|
||
return this.bMarks[line] + this.tShift[line] >= this.eMarks[line]
|
||
};
|
||
|
||
StateBlock.prototype.skipEmptyLines = function skipEmptyLines (from) {
|
||
for (let max = this.lineMax; from < max; from++) {
|
||
if (this.bMarks[from] + this.tShift[from] < this.eMarks[from]) {
|
||
break
|
||
}
|
||
}
|
||
return from
|
||
};
|
||
|
||
// Skip spaces from given position.
|
||
StateBlock.prototype.skipSpaces = function skipSpaces (pos) {
|
||
for (let max = this.src.length; pos < max; pos++) {
|
||
const ch = this.src.charCodeAt(pos);
|
||
if (!isSpace(ch)) { break }
|
||
}
|
||
return pos
|
||
};
|
||
|
||
// Skip spaces from given position in reverse.
|
||
StateBlock.prototype.skipSpacesBack = function skipSpacesBack (pos, min) {
|
||
if (pos <= min) { return pos }
|
||
|
||
while (pos > min) {
|
||
if (!isSpace(this.src.charCodeAt(--pos))) { return pos + 1 }
|
||
}
|
||
return pos
|
||
};
|
||
|
||
// Skip char codes from given position
|
||
StateBlock.prototype.skipChars = function skipChars (pos, code) {
|
||
for (let max = this.src.length; pos < max; pos++) {
|
||
if (this.src.charCodeAt(pos) !== code) { break }
|
||
}
|
||
return pos
|
||
};
|
||
|
||
// Skip char codes reverse from given position - 1
|
||
StateBlock.prototype.skipCharsBack = function skipCharsBack (pos, code, min) {
|
||
if (pos <= min) { return pos }
|
||
|
||
while (pos > min) {
|
||
if (code !== this.src.charCodeAt(--pos)) { return pos + 1 }
|
||
}
|
||
return pos
|
||
};
|
||
|
||
// cut lines range from source.
|
||
StateBlock.prototype.getLines = function getLines (begin, end, indent, keepLastLF) {
|
||
if (begin >= end) {
|
||
return ''
|
||
}
|
||
|
||
const queue = new Array(end - begin);
|
||
|
||
for (let i = 0, line = begin; line < end; line++, i++) {
|
||
let lineIndent = 0;
|
||
const lineStart = this.bMarks[line];
|
||
let first = lineStart;
|
||
let last;
|
||
|
||
if (line + 1 < end || keepLastLF) {
|
||
// No need for bounds check because we have fake entry on tail.
|
||
last = this.eMarks[line] + 1;
|
||
} else {
|
||
last = this.eMarks[line];
|
||
}
|
||
|
||
while (first < last && lineIndent < indent) {
|
||
const ch = this.src.charCodeAt(first);
|
||
|
||
if (isSpace(ch)) {
|
||
if (ch === 0x09) {
|
||
lineIndent += 4 - (lineIndent + this.bsCount[line]) % 4;
|
||
} else {
|
||
lineIndent++;
|
||
}
|
||
} else if (first - lineStart < this.tShift[line]) {
|
||
// patched tShift masked characters to look like spaces (blockquotes, list markers)
|
||
lineIndent++;
|
||
} else {
|
||
break
|
||
}
|
||
|
||
first++;
|
||
}
|
||
|
||
if (lineIndent > indent) {
|
||
// partially expanding tabs in code blocks, e.g '\t\tfoobar'
|
||
// with indent=2 becomes ' \tfoobar'
|
||
queue[i] = new Array(lineIndent - indent + 1).join(' ') + this.src.slice(first, last);
|
||
} else {
|
||
queue[i] = this.src.slice(first, last);
|
||
}
|
||
}
|
||
|
||
return queue.join('')
|
||
};
|
||
|
||
// re-export Token class to use in block rules
|
||
StateBlock.prototype.Token = Token;
|
||
|
||
// GFM table, https://github.github.com/gfm/#tables-extension-
|
||
|
||
|
||
function getLine (state, line) {
|
||
const pos = state.bMarks[line] + state.tShift[line];
|
||
const max = state.eMarks[line];
|
||
|
||
return state.src.slice(pos, max)
|
||
}
|
||
|
||
function escapedSplit (str) {
|
||
const result = [];
|
||
const max = str.length;
|
||
|
||
let pos = 0;
|
||
let ch = str.charCodeAt(pos);
|
||
let isEscaped = false;
|
||
let lastPos = 0;
|
||
let current = '';
|
||
|
||
while (pos < max) {
|
||
if (ch === 0x7c/* | */) {
|
||
if (!isEscaped) {
|
||
// pipe separating cells, '|'
|
||
result.push(current + str.substring(lastPos, pos));
|
||
current = '';
|
||
lastPos = pos + 1;
|
||
} else {
|
||
// escaped pipe, '\|'
|
||
current += str.substring(lastPos, pos - 1);
|
||
lastPos = pos;
|
||
}
|
||
}
|
||
|
||
isEscaped = (ch === 0x5c/* \ */);
|
||
pos++;
|
||
|
||
ch = str.charCodeAt(pos);
|
||
}
|
||
|
||
result.push(current + str.substring(lastPos));
|
||
|
||
return result
|
||
}
|
||
|
||
function table (state, startLine, endLine, silent) {
|
||
// should have at least two lines
|
||
if (startLine + 2 > endLine) { return false }
|
||
|
||
let nextLine = startLine + 1;
|
||
|
||
if (state.sCount[nextLine] < state.blkIndent) { return false }
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[nextLine] - state.blkIndent >= 4) { return false }
|
||
|
||
// first character of the second line should be '|', '-', ':',
|
||
// and no other characters are allowed but spaces;
|
||
// basically, this is the equivalent of /^[-:|][-:|\s]*$/ regexp
|
||
|
||
let pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
if (pos >= state.eMarks[nextLine]) { return false }
|
||
|
||
const firstCh = state.src.charCodeAt(pos++);
|
||
if (firstCh !== 0x7C/* | */ && firstCh !== 0x2D/* - */ && firstCh !== 0x3A/* : */) { return false }
|
||
|
||
if (pos >= state.eMarks[nextLine]) { return false }
|
||
|
||
const secondCh = state.src.charCodeAt(pos++);
|
||
if (secondCh !== 0x7C/* | */ && secondCh !== 0x2D/* - */ && secondCh !== 0x3A/* : */ && !isSpace(secondCh)) {
|
||
return false
|
||
}
|
||
|
||
// if first character is '-', then second character must not be a space
|
||
// (due to parsing ambiguity with list)
|
||
if (firstCh === 0x2D/* - */ && isSpace(secondCh)) { return false }
|
||
|
||
while (pos < state.eMarks[nextLine]) {
|
||
const ch = state.src.charCodeAt(pos);
|
||
|
||
if (ch !== 0x7C/* | */ && ch !== 0x2D/* - */ && ch !== 0x3A/* : */ && !isSpace(ch)) { return false }
|
||
|
||
pos++;
|
||
}
|
||
|
||
let lineText = getLine(state, startLine + 1);
|
||
let columns = lineText.split('|');
|
||
const aligns = [];
|
||
for (let i = 0; i < columns.length; i++) {
|
||
const t = columns[i].trim();
|
||
if (!t) {
|
||
// allow empty columns before and after table, but not in between columns;
|
||
// e.g. allow ` |---| `, disallow ` ---||--- `
|
||
if (i === 0 || i === columns.length - 1) {
|
||
continue
|
||
} else {
|
||
return false
|
||
}
|
||
}
|
||
|
||
if (!/^:?-+:?$/.test(t)) { return false }
|
||
if (t.charCodeAt(t.length - 1) === 0x3A/* : */) {
|
||
aligns.push(t.charCodeAt(0) === 0x3A/* : */ ? 'center' : 'right');
|
||
} else if (t.charCodeAt(0) === 0x3A/* : */) {
|
||
aligns.push('left');
|
||
} else {
|
||
aligns.push('');
|
||
}
|
||
}
|
||
|
||
lineText = getLine(state, startLine).trim();
|
||
if (lineText.indexOf('|') === -1) { return false }
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
|
||
columns = escapedSplit(lineText);
|
||
if (columns.length && columns[0] === '') columns.shift();
|
||
if (columns.length && columns[columns.length - 1] === '') columns.pop();
|
||
|
||
// header row will define an amount of columns in the entire table,
|
||
// and align row should be exactly the same (the rest of the rows can differ)
|
||
const columnCount = columns.length;
|
||
if (columnCount === 0 || columnCount !== aligns.length) { return false }
|
||
|
||
if (silent) { return true }
|
||
|
||
const oldParentType = state.parentType;
|
||
state.parentType = 'table';
|
||
|
||
// use 'blockquote' lists for termination because it's
|
||
// the most similar to tables
|
||
const terminatorRules = state.md.block.ruler.getRules('blockquote');
|
||
|
||
const token_to = state.push('table_open', 'table', 1);
|
||
const tableLines = [startLine, 0];
|
||
token_to.map = tableLines;
|
||
|
||
const token_tho = state.push('thead_open', 'thead', 1);
|
||
token_tho.map = [startLine, startLine + 1];
|
||
|
||
const token_htro = state.push('tr_open', 'tr', 1);
|
||
token_htro.map = [startLine, startLine + 1];
|
||
|
||
for (let i = 0; i < columns.length; i++) {
|
||
const token_ho = state.push('th_open', 'th', 1);
|
||
if (aligns[i]) {
|
||
token_ho.attrs = [['style', 'text-align:' + aligns[i]]];
|
||
}
|
||
|
||
const token_il = state.push('inline', '', 0);
|
||
token_il.content = columns[i].trim();
|
||
token_il.children = [];
|
||
|
||
state.push('th_close', 'th', -1);
|
||
}
|
||
|
||
state.push('tr_close', 'tr', -1);
|
||
state.push('thead_close', 'thead', -1);
|
||
|
||
let tbodyLines;
|
||
|
||
for (nextLine = startLine + 2; nextLine < endLine; nextLine++) {
|
||
if (state.sCount[nextLine] < state.blkIndent) { break }
|
||
|
||
let terminate = false;
|
||
for (let i = 0, l = terminatorRules.length; i < l; i++) {
|
||
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
||
terminate = true;
|
||
break
|
||
}
|
||
}
|
||
|
||
if (terminate) { break }
|
||
lineText = getLine(state, nextLine).trim();
|
||
if (!lineText) { break }
|
||
if (state.sCount[nextLine] - state.blkIndent >= 4) { break }
|
||
columns = escapedSplit(lineText);
|
||
if (columns.length && columns[0] === '') columns.shift();
|
||
if (columns.length && columns[columns.length - 1] === '') columns.pop();
|
||
|
||
if (nextLine === startLine + 2) {
|
||
const token_tbo = state.push('tbody_open', 'tbody', 1);
|
||
token_tbo.map = tbodyLines = [startLine + 2, 0];
|
||
}
|
||
|
||
const token_tro = state.push('tr_open', 'tr', 1);
|
||
token_tro.map = [nextLine, nextLine + 1];
|
||
|
||
for (let i = 0; i < columnCount; i++) {
|
||
const token_tdo = state.push('td_open', 'td', 1);
|
||
if (aligns[i]) {
|
||
token_tdo.attrs = [['style', 'text-align:' + aligns[i]]];
|
||
}
|
||
|
||
const token_il = state.push('inline', '', 0);
|
||
token_il.content = columns[i] ? columns[i].trim() : '';
|
||
token_il.children = [];
|
||
|
||
state.push('td_close', 'td', -1);
|
||
}
|
||
state.push('tr_close', 'tr', -1);
|
||
}
|
||
|
||
if (tbodyLines) {
|
||
state.push('tbody_close', 'tbody', -1);
|
||
tbodyLines[1] = nextLine;
|
||
}
|
||
|
||
state.push('table_close', 'table', -1);
|
||
tableLines[1] = nextLine;
|
||
|
||
state.parentType = oldParentType;
|
||
state.line = nextLine;
|
||
return true
|
||
}
|
||
|
||
// Code block (4 spaces padded)
|
||
|
||
function code (state, startLine, endLine/*, silent */) {
|
||
if (state.sCount[startLine] - state.blkIndent < 4) { return false }
|
||
|
||
let nextLine = startLine + 1;
|
||
let last = nextLine;
|
||
|
||
while (nextLine < endLine) {
|
||
if (state.isEmpty(nextLine)) {
|
||
nextLine++;
|
||
continue
|
||
}
|
||
|
||
if (state.sCount[nextLine] - state.blkIndent >= 4) {
|
||
nextLine++;
|
||
last = nextLine;
|
||
continue
|
||
}
|
||
break
|
||
}
|
||
|
||
state.line = last;
|
||
|
||
const token = state.push('code_block', 'code', 0);
|
||
token.content = state.getLines(startLine, last, 4 + state.blkIndent, false) + '\n';
|
||
token.map = [startLine, state.line];
|
||
|
||
return true
|
||
}
|
||
|
||
// fences (``` lang, ~~~ lang)
|
||
|
||
function fence (state, startLine, endLine, silent) {
|
||
let pos = state.bMarks[startLine] + state.tShift[startLine];
|
||
let max = state.eMarks[startLine];
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
|
||
|
||
if (pos + 3 > max) { return false }
|
||
|
||
const marker = state.src.charCodeAt(pos);
|
||
|
||
if (marker !== 0x7E/* ~ */ && marker !== 0x60 /* ` */) {
|
||
return false
|
||
}
|
||
|
||
// scan marker length
|
||
let mem = pos;
|
||
pos = state.skipChars(pos, marker);
|
||
|
||
let len = pos - mem;
|
||
|
||
if (len < 3) { return false }
|
||
|
||
const markup = state.src.slice(mem, pos);
|
||
const params = state.src.slice(pos, max);
|
||
|
||
if (marker === 0x60 /* ` */) {
|
||
if (params.indexOf(String.fromCharCode(marker)) >= 0) {
|
||
return false
|
||
}
|
||
}
|
||
|
||
// Since start is found, we can report success here in validation mode
|
||
if (silent) { return true }
|
||
|
||
// search end of block
|
||
let nextLine = startLine;
|
||
let haveEndMarker = false;
|
||
|
||
for (;;) {
|
||
nextLine++;
|
||
if (nextLine >= endLine) {
|
||
// unclosed block should be autoclosed by end of document.
|
||
// also block seems to be autoclosed by end of parent
|
||
break
|
||
}
|
||
|
||
pos = mem = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
max = state.eMarks[nextLine];
|
||
|
||
if (pos < max && state.sCount[nextLine] < state.blkIndent) {
|
||
// non-empty line with negative indent should stop the list:
|
||
// - ```
|
||
// test
|
||
break
|
||
}
|
||
|
||
if (state.src.charCodeAt(pos) !== marker) { continue }
|
||
|
||
if (state.sCount[nextLine] - state.blkIndent >= 4) {
|
||
// closing fence should be indented less than 4 spaces
|
||
continue
|
||
}
|
||
|
||
pos = state.skipChars(pos, marker);
|
||
|
||
// closing code fence must be at least as long as the opening one
|
||
if (pos - mem < len) { continue }
|
||
|
||
// make sure tail has spaces only
|
||
pos = state.skipSpaces(pos);
|
||
|
||
if (pos < max) { continue }
|
||
|
||
haveEndMarker = true;
|
||
// found!
|
||
break
|
||
}
|
||
|
||
// If a fence has heading spaces, they should be removed from its inner block
|
||
len = state.sCount[startLine];
|
||
|
||
state.line = nextLine + (haveEndMarker ? 1 : 0);
|
||
|
||
const token = state.push('fence', 'code', 0);
|
||
token.info = params;
|
||
token.content = state.getLines(startLine + 1, nextLine, len, true);
|
||
token.markup = markup;
|
||
token.map = [startLine, state.line];
|
||
|
||
return true
|
||
}
|
||
|
||
// Block quotes
|
||
|
||
|
||
function blockquote (state, startLine, endLine, silent) {
|
||
let pos = state.bMarks[startLine] + state.tShift[startLine];
|
||
let max = state.eMarks[startLine];
|
||
|
||
const oldLineMax = state.lineMax;
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
|
||
|
||
// check the block quote marker
|
||
if (state.src.charCodeAt(pos) !== 0x3E/* > */) { return false }
|
||
|
||
// we know that it's going to be a valid blockquote,
|
||
// so no point trying to find the end of it in silent mode
|
||
if (silent) { return true }
|
||
|
||
const oldBMarks = [];
|
||
const oldBSCount = [];
|
||
const oldSCount = [];
|
||
const oldTShift = [];
|
||
|
||
const terminatorRules = state.md.block.ruler.getRules('blockquote');
|
||
|
||
const oldParentType = state.parentType;
|
||
state.parentType = 'blockquote';
|
||
let lastLineEmpty = false;
|
||
let nextLine;
|
||
|
||
// Search the end of the block
|
||
//
|
||
// Block ends with either:
|
||
// 1. an empty line outside:
|
||
// ```
|
||
// > test
|
||
//
|
||
// ```
|
||
// 2. an empty line inside:
|
||
// ```
|
||
// >
|
||
// test
|
||
// ```
|
||
// 3. another tag:
|
||
// ```
|
||
// > test
|
||
// - - -
|
||
// ```
|
||
for (nextLine = startLine; nextLine < endLine; nextLine++) {
|
||
// check if it's outdented, i.e. it's inside list item and indented
|
||
// less than said list item:
|
||
//
|
||
// ```
|
||
// 1. anything
|
||
// > current blockquote
|
||
// 2. checking this line
|
||
// ```
|
||
const isOutdented = state.sCount[nextLine] < state.blkIndent;
|
||
|
||
pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
max = state.eMarks[nextLine];
|
||
|
||
if (pos >= max) {
|
||
// Case 1: line is not inside the blockquote, and this line is empty.
|
||
break
|
||
}
|
||
|
||
if (state.src.charCodeAt(pos++) === 0x3E/* > */ && !isOutdented) {
|
||
// This line is inside the blockquote.
|
||
|
||
// set offset past spaces and ">"
|
||
let initial = state.sCount[nextLine] + 1;
|
||
let spaceAfterMarker;
|
||
let adjustTab;
|
||
|
||
// skip one optional space after '>'
|
||
if (state.src.charCodeAt(pos) === 0x20 /* space */) {
|
||
// ' > test '
|
||
// ^ -- position start of line here:
|
||
pos++;
|
||
initial++;
|
||
adjustTab = false;
|
||
spaceAfterMarker = true;
|
||
} else if (state.src.charCodeAt(pos) === 0x09 /* tab */) {
|
||
spaceAfterMarker = true;
|
||
|
||
if ((state.bsCount[nextLine] + initial) % 4 === 3) {
|
||
// ' >\t test '
|
||
// ^ -- position start of line here (tab has width===1)
|
||
pos++;
|
||
initial++;
|
||
adjustTab = false;
|
||
} else {
|
||
// ' >\t test '
|
||
// ^ -- position start of line here + shift bsCount slightly
|
||
// to make extra space appear
|
||
adjustTab = true;
|
||
}
|
||
} else {
|
||
spaceAfterMarker = false;
|
||
}
|
||
|
||
let offset = initial;
|
||
oldBMarks.push(state.bMarks[nextLine]);
|
||
state.bMarks[nextLine] = pos;
|
||
|
||
while (pos < max) {
|
||
const ch = state.src.charCodeAt(pos);
|
||
|
||
if (isSpace(ch)) {
|
||
if (ch === 0x09) {
|
||
offset += 4 - (offset + state.bsCount[nextLine] + (adjustTab ? 1 : 0)) % 4;
|
||
} else {
|
||
offset++;
|
||
}
|
||
} else {
|
||
break
|
||
}
|
||
|
||
pos++;
|
||
}
|
||
|
||
lastLineEmpty = pos >= max;
|
||
|
||
oldBSCount.push(state.bsCount[nextLine]);
|
||
state.bsCount[nextLine] = state.sCount[nextLine] + 1 + (spaceAfterMarker ? 1 : 0);
|
||
|
||
oldSCount.push(state.sCount[nextLine]);
|
||
state.sCount[nextLine] = offset - initial;
|
||
|
||
oldTShift.push(state.tShift[nextLine]);
|
||
state.tShift[nextLine] = pos - state.bMarks[nextLine];
|
||
continue
|
||
}
|
||
|
||
// Case 2: line is not inside the blockquote, and the last line was empty.
|
||
if (lastLineEmpty) { break }
|
||
|
||
// Case 3: another tag found.
|
||
let terminate = false;
|
||
for (let i = 0, l = terminatorRules.length; i < l; i++) {
|
||
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
||
terminate = true;
|
||
break
|
||
}
|
||
}
|
||
|
||
if (terminate) {
|
||
// Quirk to enforce "hard termination mode" for paragraphs;
|
||
// normally if you call `tokenize(state, startLine, nextLine)`,
|
||
// paragraphs will look below nextLine for paragraph continuation,
|
||
// but if blockquote is terminated by another tag, they shouldn't
|
||
state.lineMax = nextLine;
|
||
|
||
if (state.blkIndent !== 0) {
|
||
// state.blkIndent was non-zero, we now set it to zero,
|
||
// so we need to re-calculate all offsets to appear as
|
||
// if indent wasn't changed
|
||
oldBMarks.push(state.bMarks[nextLine]);
|
||
oldBSCount.push(state.bsCount[nextLine]);
|
||
oldTShift.push(state.tShift[nextLine]);
|
||
oldSCount.push(state.sCount[nextLine]);
|
||
state.sCount[nextLine] -= state.blkIndent;
|
||
}
|
||
|
||
break
|
||
}
|
||
|
||
oldBMarks.push(state.bMarks[nextLine]);
|
||
oldBSCount.push(state.bsCount[nextLine]);
|
||
oldTShift.push(state.tShift[nextLine]);
|
||
oldSCount.push(state.sCount[nextLine]);
|
||
|
||
// A negative indentation means that this is a paragraph continuation
|
||
//
|
||
state.sCount[nextLine] = -1;
|
||
}
|
||
|
||
const oldIndent = state.blkIndent;
|
||
state.blkIndent = 0;
|
||
|
||
const token_o = state.push('blockquote_open', 'blockquote', 1);
|
||
token_o.markup = '>';
|
||
const lines = [startLine, 0];
|
||
token_o.map = lines;
|
||
|
||
state.md.block.tokenize(state, startLine, nextLine);
|
||
|
||
const token_c = state.push('blockquote_close', 'blockquote', -1);
|
||
token_c.markup = '>';
|
||
|
||
state.lineMax = oldLineMax;
|
||
state.parentType = oldParentType;
|
||
lines[1] = state.line;
|
||
|
||
// Restore original tShift; this might not be necessary since the parser
|
||
// has already been here, but just to make sure we can do that.
|
||
for (let i = 0; i < oldTShift.length; i++) {
|
||
state.bMarks[i + startLine] = oldBMarks[i];
|
||
state.tShift[i + startLine] = oldTShift[i];
|
||
state.sCount[i + startLine] = oldSCount[i];
|
||
state.bsCount[i + startLine] = oldBSCount[i];
|
||
}
|
||
state.blkIndent = oldIndent;
|
||
|
||
return true
|
||
}
|
||
|
||
// Horizontal rule
|
||
|
||
|
||
function hr (state, startLine, endLine, silent) {
|
||
const max = state.eMarks[startLine];
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
|
||
|
||
let pos = state.bMarks[startLine] + state.tShift[startLine];
|
||
const marker = state.src.charCodeAt(pos++);
|
||
|
||
// Check hr marker
|
||
if (marker !== 0x2A/* * */ &&
|
||
marker !== 0x2D/* - */ &&
|
||
marker !== 0x5F/* _ */) {
|
||
return false
|
||
}
|
||
|
||
// markers can be mixed with spaces, but there should be at least 3 of them
|
||
|
||
let cnt = 1;
|
||
while (pos < max) {
|
||
const ch = state.src.charCodeAt(pos++);
|
||
if (ch !== marker && !isSpace(ch)) { return false }
|
||
if (ch === marker) { cnt++; }
|
||
}
|
||
|
||
if (cnt < 3) { return false }
|
||
|
||
if (silent) { return true }
|
||
|
||
state.line = startLine + 1;
|
||
|
||
const token = state.push('hr', 'hr', 0);
|
||
token.map = [startLine, state.line];
|
||
token.markup = Array(cnt + 1).join(String.fromCharCode(marker));
|
||
|
||
return true
|
||
}
|
||
|
||
// Lists
|
||
|
||
|
||
// Search `[-+*][\n ]`, returns next pos after marker on success
|
||
// or -1 on fail.
|
||
function skipBulletListMarker (state, startLine) {
|
||
const max = state.eMarks[startLine];
|
||
let pos = state.bMarks[startLine] + state.tShift[startLine];
|
||
|
||
const marker = state.src.charCodeAt(pos++);
|
||
// Check bullet
|
||
if (marker !== 0x2A/* * */ &&
|
||
marker !== 0x2D/* - */ &&
|
||
marker !== 0x2B/* + */) {
|
||
return -1
|
||
}
|
||
|
||
if (pos < max) {
|
||
const ch = state.src.charCodeAt(pos);
|
||
|
||
if (!isSpace(ch)) {
|
||
// " -test " - is not a list item
|
||
return -1
|
||
}
|
||
}
|
||
|
||
return pos
|
||
}
|
||
|
||
// Search `\d+[.)][\n ]`, returns next pos after marker on success
|
||
// or -1 on fail.
|
||
function skipOrderedListMarker (state, startLine) {
|
||
const start = state.bMarks[startLine] + state.tShift[startLine];
|
||
const max = state.eMarks[startLine];
|
||
let pos = start;
|
||
|
||
// List marker should have at least 2 chars (digit + dot)
|
||
if (pos + 1 >= max) { return -1 }
|
||
|
||
let ch = state.src.charCodeAt(pos++);
|
||
|
||
if (ch < 0x30/* 0 */ || ch > 0x39/* 9 */) { return -1 }
|
||
|
||
for (;;) {
|
||
// EOL -> fail
|
||
if (pos >= max) { return -1 }
|
||
|
||
ch = state.src.charCodeAt(pos++);
|
||
|
||
if (ch >= 0x30/* 0 */ && ch <= 0x39/* 9 */) {
|
||
// List marker should have no more than 9 digits
|
||
// (prevents integer overflow in browsers)
|
||
if (pos - start >= 10) { return -1 }
|
||
|
||
continue
|
||
}
|
||
|
||
// found valid marker
|
||
if (ch === 0x29/* ) */ || ch === 0x2e/* . */) {
|
||
break
|
||
}
|
||
|
||
return -1
|
||
}
|
||
|
||
if (pos < max) {
|
||
ch = state.src.charCodeAt(pos);
|
||
|
||
if (!isSpace(ch)) {
|
||
// " 1.test " - is not a list item
|
||
return -1
|
||
}
|
||
}
|
||
return pos
|
||
}
|
||
|
||
function markTightParagraphs (state, idx) {
|
||
const level = state.level + 2;
|
||
|
||
for (let i = idx + 2, l = state.tokens.length - 2; i < l; i++) {
|
||
if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') {
|
||
state.tokens[i + 2].hidden = true;
|
||
state.tokens[i].hidden = true;
|
||
i += 2;
|
||
}
|
||
}
|
||
}
|
||
|
||
function list (state, startLine, endLine, silent) {
|
||
let max, pos, start, token;
|
||
let nextLine = startLine;
|
||
let tight = true;
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[nextLine] - state.blkIndent >= 4) { return false }
|
||
|
||
// Special case:
|
||
// - item 1
|
||
// - item 2
|
||
// - item 3
|
||
// - item 4
|
||
// - this one is a paragraph continuation
|
||
if (state.listIndent >= 0 &&
|
||
state.sCount[nextLine] - state.listIndent >= 4 &&
|
||
state.sCount[nextLine] < state.blkIndent) {
|
||
return false
|
||
}
|
||
|
||
let isTerminatingParagraph = false;
|
||
|
||
// limit conditions when list can interrupt
|
||
// a paragraph (validation mode only)
|
||
if (silent && state.parentType === 'paragraph') {
|
||
// Next list item should still terminate previous list item;
|
||
//
|
||
// This code can fail if plugins use blkIndent as well as lists,
|
||
// but I hope the spec gets fixed long before that happens.
|
||
//
|
||
if (state.sCount[nextLine] >= state.blkIndent) {
|
||
isTerminatingParagraph = true;
|
||
}
|
||
}
|
||
|
||
// Detect list type and position after marker
|
||
let isOrdered;
|
||
let markerValue;
|
||
let posAfterMarker;
|
||
if ((posAfterMarker = skipOrderedListMarker(state, nextLine)) >= 0) {
|
||
isOrdered = true;
|
||
start = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
markerValue = Number(state.src.slice(start, posAfterMarker - 1));
|
||
|
||
// If we're starting a new ordered list right after
|
||
// a paragraph, it should start with 1.
|
||
if (isTerminatingParagraph && markerValue !== 1) return false
|
||
} else if ((posAfterMarker = skipBulletListMarker(state, nextLine)) >= 0) {
|
||
isOrdered = false;
|
||
} else {
|
||
return false
|
||
}
|
||
|
||
// If we're starting a new unordered list right after
|
||
// a paragraph, first line should not be empty.
|
||
if (isTerminatingParagraph) {
|
||
if (state.skipSpaces(posAfterMarker) >= state.eMarks[nextLine]) return false
|
||
}
|
||
|
||
// For validation mode we can terminate immediately
|
||
if (silent) { return true }
|
||
|
||
// We should terminate list on style change. Remember first one to compare.
|
||
const markerCharCode = state.src.charCodeAt(posAfterMarker - 1);
|
||
|
||
// Start list
|
||
const listTokIdx = state.tokens.length;
|
||
|
||
if (isOrdered) {
|
||
token = state.push('ordered_list_open', 'ol', 1);
|
||
if (markerValue !== 1) {
|
||
token.attrs = [['start', markerValue]];
|
||
}
|
||
} else {
|
||
token = state.push('bullet_list_open', 'ul', 1);
|
||
}
|
||
|
||
const listLines = [nextLine, 0];
|
||
token.map = listLines;
|
||
token.markup = String.fromCharCode(markerCharCode);
|
||
|
||
//
|
||
// Iterate list items
|
||
//
|
||
|
||
let prevEmptyEnd = false;
|
||
const terminatorRules = state.md.block.ruler.getRules('list');
|
||
|
||
const oldParentType = state.parentType;
|
||
state.parentType = 'list';
|
||
|
||
while (nextLine < endLine) {
|
||
pos = posAfterMarker;
|
||
max = state.eMarks[nextLine];
|
||
|
||
const initial = state.sCount[nextLine] + posAfterMarker - (state.bMarks[nextLine] + state.tShift[nextLine]);
|
||
let offset = initial;
|
||
|
||
while (pos < max) {
|
||
const ch = state.src.charCodeAt(pos);
|
||
|
||
if (ch === 0x09) {
|
||
offset += 4 - (offset + state.bsCount[nextLine]) % 4;
|
||
} else if (ch === 0x20) {
|
||
offset++;
|
||
} else {
|
||
break
|
||
}
|
||
|
||
pos++;
|
||
}
|
||
|
||
const contentStart = pos;
|
||
let indentAfterMarker;
|
||
|
||
if (contentStart >= max) {
|
||
// trimming space in "- \n 3" case, indent is 1 here
|
||
indentAfterMarker = 1;
|
||
} else {
|
||
indentAfterMarker = offset - initial;
|
||
}
|
||
|
||
// If we have more than 4 spaces, the indent is 1
|
||
// (the rest is just indented code block)
|
||
if (indentAfterMarker > 4) { indentAfterMarker = 1; }
|
||
|
||
// " - test"
|
||
// ^^^^^ - calculating total length of this thing
|
||
const indent = initial + indentAfterMarker;
|
||
|
||
// Run subparser & write tokens
|
||
token = state.push('list_item_open', 'li', 1);
|
||
token.markup = String.fromCharCode(markerCharCode);
|
||
const itemLines = [nextLine, 0];
|
||
token.map = itemLines;
|
||
if (isOrdered) {
|
||
token.info = state.src.slice(start, posAfterMarker - 1);
|
||
}
|
||
|
||
// change current state, then restore it after parser subcall
|
||
const oldTight = state.tight;
|
||
const oldTShift = state.tShift[nextLine];
|
||
const oldSCount = state.sCount[nextLine];
|
||
|
||
// - example list
|
||
// ^ listIndent position will be here
|
||
// ^ blkIndent position will be here
|
||
//
|
||
const oldListIndent = state.listIndent;
|
||
state.listIndent = state.blkIndent;
|
||
state.blkIndent = indent;
|
||
|
||
state.tight = true;
|
||
state.tShift[nextLine] = contentStart - state.bMarks[nextLine];
|
||
state.sCount[nextLine] = offset;
|
||
|
||
if (contentStart >= max && state.isEmpty(nextLine + 1)) {
|
||
// workaround for this case
|
||
// (list item is empty, list terminates before "foo"):
|
||
// ~~~~~~~~
|
||
// -
|
||
//
|
||
// foo
|
||
// ~~~~~~~~
|
||
state.line = Math.min(state.line + 2, endLine);
|
||
} else {
|
||
state.md.block.tokenize(state, nextLine, endLine, true);
|
||
}
|
||
|
||
// If any of list item is tight, mark list as tight
|
||
if (!state.tight || prevEmptyEnd) {
|
||
tight = false;
|
||
}
|
||
// Item become loose if finish with empty line,
|
||
// but we should filter last element, because it means list finish
|
||
prevEmptyEnd = (state.line - nextLine) > 1 && state.isEmpty(state.line - 1);
|
||
|
||
state.blkIndent = state.listIndent;
|
||
state.listIndent = oldListIndent;
|
||
state.tShift[nextLine] = oldTShift;
|
||
state.sCount[nextLine] = oldSCount;
|
||
state.tight = oldTight;
|
||
|
||
token = state.push('list_item_close', 'li', -1);
|
||
token.markup = String.fromCharCode(markerCharCode);
|
||
|
||
nextLine = state.line;
|
||
itemLines[1] = nextLine;
|
||
|
||
if (nextLine >= endLine) { break }
|
||
|
||
//
|
||
// Try to check if list is terminated or continued.
|
||
//
|
||
if (state.sCount[nextLine] < state.blkIndent) { break }
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[nextLine] - state.blkIndent >= 4) { break }
|
||
|
||
// fail if terminating block found
|
||
let terminate = false;
|
||
for (let i = 0, l = terminatorRules.length; i < l; i++) {
|
||
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
||
terminate = true;
|
||
break
|
||
}
|
||
}
|
||
if (terminate) { break }
|
||
|
||
// fail if list has another type
|
||
if (isOrdered) {
|
||
posAfterMarker = skipOrderedListMarker(state, nextLine);
|
||
if (posAfterMarker < 0) { break }
|
||
start = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
} else {
|
||
posAfterMarker = skipBulletListMarker(state, nextLine);
|
||
if (posAfterMarker < 0) { break }
|
||
}
|
||
|
||
if (markerCharCode !== state.src.charCodeAt(posAfterMarker - 1)) { break }
|
||
}
|
||
|
||
// Finalize list
|
||
if (isOrdered) {
|
||
token = state.push('ordered_list_close', 'ol', -1);
|
||
} else {
|
||
token = state.push('bullet_list_close', 'ul', -1);
|
||
}
|
||
token.markup = String.fromCharCode(markerCharCode);
|
||
|
||
listLines[1] = nextLine;
|
||
state.line = nextLine;
|
||
|
||
state.parentType = oldParentType;
|
||
|
||
// mark paragraphs tight if needed
|
||
if (tight) {
|
||
markTightParagraphs(state, listTokIdx);
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
function reference (state, startLine, _endLine, silent) {
|
||
let lines = 0;
|
||
|
||
let pos = state.bMarks[startLine] + state.tShift[startLine];
|
||
let max = state.eMarks[startLine];
|
||
let nextLine = startLine + 1;
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
|
||
|
||
if (state.src.charCodeAt(pos) !== 0x5B/* [ */) { return false }
|
||
|
||
// Simple check to quickly interrupt scan on [link](url) at the start of line.
|
||
// Can be useful on practice: https://github.com/markdown-it/markdown-it/issues/54
|
||
while (++pos < max) {
|
||
if (state.src.charCodeAt(pos) === 0x5D /* ] */ &&
|
||
state.src.charCodeAt(pos - 1) !== 0x5C/* \ */) {
|
||
if (pos + 1 === max) { return false }
|
||
if (state.src.charCodeAt(pos + 1) !== 0x3A/* : */) { return false }
|
||
break
|
||
}
|
||
}
|
||
|
||
const endLine = state.lineMax;
|
||
|
||
// jump line-by-line until empty one or EOF
|
||
const terminatorRules = state.md.block.ruler.getRules('reference');
|
||
|
||
const oldParentType = state.parentType;
|
||
state.parentType = 'reference';
|
||
|
||
for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
|
||
// this would be a code block normally, but after paragraph
|
||
// it's considered a lazy continuation regardless of what's there
|
||
if (state.sCount[nextLine] - state.blkIndent > 3) { continue }
|
||
|
||
// quirk for blockquotes, this line should already be checked by that rule
|
||
if (state.sCount[nextLine] < 0) { continue }
|
||
|
||
// Some tags can terminate paragraph without empty line.
|
||
let terminate = false;
|
||
for (let i = 0, l = terminatorRules.length; i < l; i++) {
|
||
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
||
terminate = true;
|
||
break
|
||
}
|
||
}
|
||
if (terminate) { break }
|
||
}
|
||
|
||
const str = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
|
||
max = str.length;
|
||
let labelEnd = -1;
|
||
|
||
for (pos = 1; pos < max; pos++) {
|
||
const ch = str.charCodeAt(pos);
|
||
if (ch === 0x5B /* [ */) {
|
||
return false
|
||
} else if (ch === 0x5D /* ] */) {
|
||
labelEnd = pos;
|
||
break
|
||
} else if (ch === 0x0A /* \n */) {
|
||
lines++;
|
||
} else if (ch === 0x5C /* \ */) {
|
||
pos++;
|
||
if (pos < max && str.charCodeAt(pos) === 0x0A) {
|
||
lines++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (labelEnd < 0 || str.charCodeAt(labelEnd + 1) !== 0x3A/* : */) { return false }
|
||
|
||
// [label]: destination 'title'
|
||
// ^^^ skip optional whitespace here
|
||
for (pos = labelEnd + 2; pos < max; pos++) {
|
||
const ch = str.charCodeAt(pos);
|
||
if (ch === 0x0A) {
|
||
lines++;
|
||
} else if (isSpace(ch)) ; else {
|
||
break
|
||
}
|
||
}
|
||
|
||
// [label]: destination 'title'
|
||
// ^^^^^^^^^^^ parse this
|
||
const destRes = state.md.helpers.parseLinkDestination(str, pos, max);
|
||
if (!destRes.ok) { return false }
|
||
|
||
const href = state.md.normalizeLink(destRes.str);
|
||
if (!state.md.validateLink(href)) { return false }
|
||
|
||
pos = destRes.pos;
|
||
lines += destRes.lines;
|
||
|
||
// save cursor state, we could require to rollback later
|
||
const destEndPos = pos;
|
||
const destEndLineNo = lines;
|
||
|
||
// [label]: destination 'title'
|
||
// ^^^ skipping those spaces
|
||
const start = pos;
|
||
for (; pos < max; pos++) {
|
||
const ch = str.charCodeAt(pos);
|
||
if (ch === 0x0A) {
|
||
lines++;
|
||
} else if (isSpace(ch)) ; else {
|
||
break
|
||
}
|
||
}
|
||
|
||
// [label]: destination 'title'
|
||
// ^^^^^^^ parse this
|
||
const titleRes = state.md.helpers.parseLinkTitle(str, pos, max);
|
||
let title;
|
||
|
||
if (pos < max && start !== pos && titleRes.ok) {
|
||
title = titleRes.str;
|
||
pos = titleRes.pos;
|
||
lines += titleRes.lines;
|
||
} else {
|
||
title = '';
|
||
pos = destEndPos;
|
||
lines = destEndLineNo;
|
||
}
|
||
|
||
// skip trailing spaces until the rest of the line
|
||
while (pos < max) {
|
||
const ch = str.charCodeAt(pos);
|
||
if (!isSpace(ch)) { break }
|
||
pos++;
|
||
}
|
||
|
||
if (pos < max && str.charCodeAt(pos) !== 0x0A) {
|
||
if (title) {
|
||
// garbage at the end of the line after title,
|
||
// but it could still be a valid reference if we roll back
|
||
title = '';
|
||
pos = destEndPos;
|
||
lines = destEndLineNo;
|
||
while (pos < max) {
|
||
const ch = str.charCodeAt(pos);
|
||
if (!isSpace(ch)) { break }
|
||
pos++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pos < max && str.charCodeAt(pos) !== 0x0A) {
|
||
// garbage at the end of the line
|
||
return false
|
||
}
|
||
|
||
const label = normalizeReference(str.slice(1, labelEnd));
|
||
if (!label) {
|
||
// CommonMark 0.20 disallows empty labels
|
||
return false
|
||
}
|
||
|
||
// Reference can not terminate anything. This check is for safety only.
|
||
/* istanbul ignore if */
|
||
if (silent) { return true }
|
||
|
||
if (typeof state.env.references === 'undefined') {
|
||
state.env.references = {};
|
||
}
|
||
if (typeof state.env.references[label] === 'undefined') {
|
||
state.env.references[label] = { title, href };
|
||
}
|
||
|
||
state.parentType = oldParentType;
|
||
|
||
state.line = startLine + lines + 1;
|
||
return true
|
||
}
|
||
|
||
// Regexps to match html elements
|
||
|
||
const attr_name = '[a-zA-Z_:][a-zA-Z0-9:._-]*';
|
||
|
||
const unquoted = '[^"\'=<>`\\x00-\\x20]+';
|
||
const single_quoted = "'[^']*'";
|
||
const double_quoted = '"[^"]*"';
|
||
|
||
const attr_value = '(?:' + unquoted + '|' + single_quoted + '|' + double_quoted + ')';
|
||
|
||
const attribute = '(?:\\s+' + attr_name + '(?:\\s*=\\s*' + attr_value + ')?)';
|
||
|
||
const open_tag = '<[A-Za-z][A-Za-z0-9\\-]*' + attribute + '*\\s*\\/?>';
|
||
|
||
const close_tag = '<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>';
|
||
const comment = '<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->';
|
||
const processing = '<[?][\\s\\S]*?[?]>';
|
||
const declaration = '<![A-Z]+\\s+[^>]*>';
|
||
const cdata = '<!\\[CDATA\\[[\\s\\S]*?\\]\\]>';
|
||
|
||
const HTML_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag + '|' + comment +
|
||
'|' + processing + '|' + declaration + '|' + cdata + ')');
|
||
const HTML_OPEN_CLOSE_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag + ')');
|
||
|
||
// HTML block
|
||
|
||
|
||
// An array of opening and corresponding closing sequences for html tags,
|
||
// last argument defines whether it can terminate a paragraph or not
|
||
//
|
||
const HTML_SEQUENCES = [
|
||
[/^<(script|pre|style|textarea)(?=(\s|>|$))/i, /<\/(script|pre|style|textarea)>/i, true],
|
||
[/^<!--/, /-->/, true],
|
||
[/^<\?/, /\?>/, true],
|
||
[/^<![A-Z]/, />/, true],
|
||
[/^<!\[CDATA\[/, /\]\]>/, true],
|
||
[new RegExp('^</?(' + block_names.join('|') + ')(?=(\\s|/?>|$))', 'i'), /^$/, true],
|
||
[new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\s*$'), /^$/, false]
|
||
];
|
||
|
||
function html_block (state, startLine, endLine, silent) {
|
||
let pos = state.bMarks[startLine] + state.tShift[startLine];
|
||
let max = state.eMarks[startLine];
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
|
||
|
||
if (!state.md.options.html) { return false }
|
||
|
||
if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false }
|
||
|
||
let lineText = state.src.slice(pos, max);
|
||
|
||
let i = 0;
|
||
for (; i < HTML_SEQUENCES.length; i++) {
|
||
if (HTML_SEQUENCES[i][0].test(lineText)) { break }
|
||
}
|
||
if (i === HTML_SEQUENCES.length) { return false }
|
||
|
||
if (silent) {
|
||
// true if this sequence can be a terminator, false otherwise
|
||
return HTML_SEQUENCES[i][2]
|
||
}
|
||
|
||
let nextLine = startLine + 1;
|
||
|
||
// If we are here - we detected HTML block.
|
||
// Let's roll down till block end.
|
||
if (!HTML_SEQUENCES[i][1].test(lineText)) {
|
||
for (; nextLine < endLine; nextLine++) {
|
||
if (state.sCount[nextLine] < state.blkIndent) { break }
|
||
|
||
pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
max = state.eMarks[nextLine];
|
||
lineText = state.src.slice(pos, max);
|
||
|
||
if (HTML_SEQUENCES[i][1].test(lineText)) {
|
||
if (lineText.length !== 0) { nextLine++; }
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
state.line = nextLine;
|
||
|
||
const token = state.push('html_block', '', 0);
|
||
token.map = [startLine, nextLine];
|
||
token.content = state.getLines(startLine, nextLine, state.blkIndent, true);
|
||
|
||
return true
|
||
}
|
||
|
||
// heading (#, ##, ...)
|
||
|
||
|
||
function heading (state, startLine, endLine, silent) {
|
||
let pos = state.bMarks[startLine] + state.tShift[startLine];
|
||
let max = state.eMarks[startLine];
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
|
||
|
||
let ch = state.src.charCodeAt(pos);
|
||
|
||
if (ch !== 0x23/* # */ || pos >= max) { return false }
|
||
|
||
// count heading level
|
||
let level = 1;
|
||
ch = state.src.charCodeAt(++pos);
|
||
while (ch === 0x23/* # */ && pos < max && level <= 6) {
|
||
level++;
|
||
ch = state.src.charCodeAt(++pos);
|
||
}
|
||
|
||
if (level > 6 || (pos < max && !isSpace(ch))) { return false }
|
||
|
||
if (silent) { return true }
|
||
|
||
// Let's cut tails like ' ### ' from the end of string
|
||
|
||
max = state.skipSpacesBack(max, pos);
|
||
const tmp = state.skipCharsBack(max, 0x23, pos); // #
|
||
if (tmp > pos && isSpace(state.src.charCodeAt(tmp - 1))) {
|
||
max = tmp;
|
||
}
|
||
|
||
state.line = startLine + 1;
|
||
|
||
const token_o = state.push('heading_open', 'h' + String(level), 1);
|
||
token_o.markup = '########'.slice(0, level);
|
||
token_o.map = [startLine, state.line];
|
||
|
||
const token_i = state.push('inline', '', 0);
|
||
token_i.content = state.src.slice(pos, max).trim();
|
||
token_i.map = [startLine, state.line];
|
||
token_i.children = [];
|
||
|
||
const token_c = state.push('heading_close', 'h' + String(level), -1);
|
||
token_c.markup = '########'.slice(0, level);
|
||
|
||
return true
|
||
}
|
||
|
||
// lheading (---, ===)
|
||
|
||
function lheading (state, startLine, endLine/*, silent */) {
|
||
const terminatorRules = state.md.block.ruler.getRules('paragraph');
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
|
||
|
||
const oldParentType = state.parentType;
|
||
state.parentType = 'paragraph'; // use paragraph to match terminatorRules
|
||
|
||
// jump line-by-line until empty one or EOF
|
||
let level = 0;
|
||
let marker;
|
||
let nextLine = startLine + 1;
|
||
|
||
for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
|
||
// this would be a code block normally, but after paragraph
|
||
// it's considered a lazy continuation regardless of what's there
|
||
if (state.sCount[nextLine] - state.blkIndent > 3) { continue }
|
||
|
||
//
|
||
// Check for underline in setext header
|
||
//
|
||
if (state.sCount[nextLine] >= state.blkIndent) {
|
||
let pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
const max = state.eMarks[nextLine];
|
||
|
||
if (pos < max) {
|
||
marker = state.src.charCodeAt(pos);
|
||
|
||
if (marker === 0x2D/* - */ || marker === 0x3D/* = */) {
|
||
pos = state.skipChars(pos, marker);
|
||
pos = state.skipSpaces(pos);
|
||
|
||
if (pos >= max) {
|
||
level = (marker === 0x3D/* = */ ? 1 : 2);
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// quirk for blockquotes, this line should already be checked by that rule
|
||
if (state.sCount[nextLine] < 0) { continue }
|
||
|
||
// Some tags can terminate paragraph without empty line.
|
||
let terminate = false;
|
||
for (let i = 0, l = terminatorRules.length; i < l; i++) {
|
||
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
||
terminate = true;
|
||
break
|
||
}
|
||
}
|
||
if (terminate) { break }
|
||
}
|
||
|
||
if (!level) {
|
||
// Didn't find valid underline
|
||
return false
|
||
}
|
||
|
||
const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
|
||
|
||
state.line = nextLine + 1;
|
||
|
||
const token_o = state.push('heading_open', 'h' + String(level), 1);
|
||
token_o.markup = String.fromCharCode(marker);
|
||
token_o.map = [startLine, state.line];
|
||
|
||
const token_i = state.push('inline', '', 0);
|
||
token_i.content = content;
|
||
token_i.map = [startLine, state.line - 1];
|
||
token_i.children = [];
|
||
|
||
const token_c = state.push('heading_close', 'h' + String(level), -1);
|
||
token_c.markup = String.fromCharCode(marker);
|
||
|
||
state.parentType = oldParentType;
|
||
|
||
return true
|
||
}
|
||
|
||
// Paragraph
|
||
|
||
function paragraph (state, startLine, endLine) {
|
||
const terminatorRules = state.md.block.ruler.getRules('paragraph');
|
||
const oldParentType = state.parentType;
|
||
let nextLine = startLine + 1;
|
||
state.parentType = 'paragraph';
|
||
|
||
// jump line-by-line until empty one or EOF
|
||
for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
|
||
// this would be a code block normally, but after paragraph
|
||
// it's considered a lazy continuation regardless of what's there
|
||
if (state.sCount[nextLine] - state.blkIndent > 3) { continue }
|
||
|
||
// quirk for blockquotes, this line should already be checked by that rule
|
||
if (state.sCount[nextLine] < 0) { continue }
|
||
|
||
// Some tags can terminate paragraph without empty line.
|
||
let terminate = false;
|
||
for (let i = 0, l = terminatorRules.length; i < l; i++) {
|
||
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
||
terminate = true;
|
||
break
|
||
}
|
||
}
|
||
if (terminate) { break }
|
||
}
|
||
|
||
const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
|
||
|
||
state.line = nextLine;
|
||
|
||
const token_o = state.push('paragraph_open', 'p', 1);
|
||
token_o.map = [startLine, state.line];
|
||
|
||
const token_i = state.push('inline', '', 0);
|
||
token_i.content = content;
|
||
token_i.map = [startLine, state.line];
|
||
token_i.children = [];
|
||
|
||
state.push('paragraph_close', 'p', -1);
|
||
|
||
state.parentType = oldParentType;
|
||
|
||
return true
|
||
}
|
||
|
||
/** internal
|
||
* class ParserBlock
|
||
*
|
||
* Block-level tokenizer.
|
||
**/
|
||
|
||
|
||
const _rules$1 = [
|
||
// First 2 params - rule name & source. Secondary array - list of rules,
|
||
// which can be terminated by this one.
|
||
['table', table, ['paragraph', 'reference']],
|
||
['code', code],
|
||
['fence', fence, ['paragraph', 'reference', 'blockquote', 'list']],
|
||
['blockquote', blockquote, ['paragraph', 'reference', 'blockquote', 'list']],
|
||
['hr', hr, ['paragraph', 'reference', 'blockquote', 'list']],
|
||
['list', list, ['paragraph', 'reference', 'blockquote']],
|
||
['reference', reference],
|
||
['html_block', html_block, ['paragraph', 'reference', 'blockquote']],
|
||
['heading', heading, ['paragraph', 'reference', 'blockquote']],
|
||
['lheading', lheading],
|
||
['paragraph', paragraph]
|
||
];
|
||
|
||
/**
|
||
* new ParserBlock()
|
||
**/
|
||
function ParserBlock () {
|
||
/**
|
||
* ParserBlock#ruler -> Ruler
|
||
*
|
||
* [[Ruler]] instance. Keep configuration of block rules.
|
||
**/
|
||
this.ruler = new Ruler();
|
||
|
||
for (let i = 0; i < _rules$1.length; i++) {
|
||
this.ruler.push(_rules$1[i][0], _rules$1[i][1], { alt: (_rules$1[i][2] || []).slice() });
|
||
}
|
||
}
|
||
|
||
// Generate tokens for input range
|
||
//
|
||
ParserBlock.prototype.tokenize = function (state, startLine, endLine) {
|
||
const rules = this.ruler.getRules('');
|
||
const len = rules.length;
|
||
const maxNesting = state.md.options.maxNesting;
|
||
let line = startLine;
|
||
let hasEmptyLines = false;
|
||
|
||
while (line < endLine) {
|
||
state.line = line = state.skipEmptyLines(line);
|
||
if (line >= endLine) { break }
|
||
|
||
// Termination condition for nested calls.
|
||
// Nested calls currently used for blockquotes & lists
|
||
if (state.sCount[line] < state.blkIndent) { break }
|
||
|
||
// If nesting level exceeded - skip tail to the end. That's not ordinary
|
||
// situation and we should not care about content.
|
||
if (state.level >= maxNesting) {
|
||
state.line = endLine;
|
||
break
|
||
}
|
||
|
||
// Try all possible rules.
|
||
// On success, rule should:
|
||
//
|
||
// - update `state.line`
|
||
// - update `state.tokens`
|
||
// - return true
|
||
const prevLine = state.line;
|
||
let ok = false;
|
||
|
||
for (let i = 0; i < len; i++) {
|
||
ok = rules[i](state, line, endLine, false);
|
||
if (ok) {
|
||
if (prevLine >= state.line) {
|
||
throw new Error("block rule didn't increment state.line")
|
||
}
|
||
break
|
||
}
|
||
}
|
||
|
||
// this can only happen if user disables paragraph rule
|
||
if (!ok) throw new Error('none of the block rules matched')
|
||
|
||
// set state.tight if we had an empty line before current tag
|
||
// i.e. latest empty line should not count
|
||
state.tight = !hasEmptyLines;
|
||
|
||
// paragraph might "eat" one newline after it in nested lists
|
||
if (state.isEmpty(state.line - 1)) {
|
||
hasEmptyLines = true;
|
||
}
|
||
|
||
line = state.line;
|
||
|
||
if (line < endLine && state.isEmpty(line)) {
|
||
hasEmptyLines = true;
|
||
line++;
|
||
state.line = line;
|
||
}
|
||
}
|
||
};
|
||
|
||
/**
|
||
* ParserBlock.parse(str, md, env, outTokens)
|
||
*
|
||
* Process input string and push block tokens into `outTokens`
|
||
**/
|
||
ParserBlock.prototype.parse = function (src, md, env, outTokens) {
|
||
if (!src) { return }
|
||
|
||
const state = new this.State(src, md, env, outTokens);
|
||
|
||
this.tokenize(state, state.line, state.lineMax);
|
||
};
|
||
|
||
ParserBlock.prototype.State = StateBlock;
|
||
|
||
// Inline parser state
|
||
|
||
|
||
function StateInline (src, md, env, outTokens) {
|
||
this.src = src;
|
||
this.env = env;
|
||
this.md = md;
|
||
this.tokens = outTokens;
|
||
this.tokens_meta = Array(outTokens.length);
|
||
|
||
this.pos = 0;
|
||
this.posMax = this.src.length;
|
||
this.level = 0;
|
||
this.pending = '';
|
||
this.pendingLevel = 0;
|
||
|
||
// Stores { start: end } pairs. Useful for backtrack
|
||
// optimization of pairs parse (emphasis, strikes).
|
||
this.cache = {};
|
||
|
||
// List of emphasis-like delimiters for current tag
|
||
this.delimiters = [];
|
||
|
||
// Stack of delimiter lists for upper level tags
|
||
this._prev_delimiters = [];
|
||
|
||
// backtick length => last seen position
|
||
this.backticks = {};
|
||
this.backticksScanned = false;
|
||
|
||
// Counter used to disable inline linkify-it execution
|
||
// inside <a> and markdown links
|
||
this.linkLevel = 0;
|
||
}
|
||
|
||
// Flush pending text
|
||
//
|
||
StateInline.prototype.pushPending = function () {
|
||
const token = new Token('text', '', 0);
|
||
token.content = this.pending;
|
||
token.level = this.pendingLevel;
|
||
this.tokens.push(token);
|
||
this.pending = '';
|
||
return token
|
||
};
|
||
|
||
// Push new token to "stream".
|
||
// If pending text exists - flush it as text token
|
||
//
|
||
StateInline.prototype.push = function (type, tag, nesting) {
|
||
if (this.pending) {
|
||
this.pushPending();
|
||
}
|
||
|
||
const token = new Token(type, tag, nesting);
|
||
let token_meta = null;
|
||
|
||
if (nesting < 0) {
|
||
// closing tag
|
||
this.level--;
|
||
this.delimiters = this._prev_delimiters.pop();
|
||
}
|
||
|
||
token.level = this.level;
|
||
|
||
if (nesting > 0) {
|
||
// opening tag
|
||
this.level++;
|
||
this._prev_delimiters.push(this.delimiters);
|
||
this.delimiters = [];
|
||
token_meta = { delimiters: this.delimiters };
|
||
}
|
||
|
||
this.pendingLevel = this.level;
|
||
this.tokens.push(token);
|
||
this.tokens_meta.push(token_meta);
|
||
return token
|
||
};
|
||
|
||
// Scan a sequence of emphasis-like markers, and determine whether
|
||
// it can start an emphasis sequence or end an emphasis sequence.
|
||
//
|
||
// - start - position to scan from (it should point at a valid marker);
|
||
// - canSplitWord - determine if these markers can be found inside a word
|
||
//
|
||
StateInline.prototype.scanDelims = function (start, canSplitWord) {
|
||
let can_open, can_close;
|
||
let left_flanking = true;
|
||
let right_flanking = true;
|
||
const max = this.posMax;
|
||
const marker = this.src.charCodeAt(start);
|
||
|
||
// treat beginning of the line as a whitespace
|
||
const lastChar = start > 0 ? this.src.charCodeAt(start - 1) : 0x20;
|
||
|
||
let pos = start;
|
||
while (pos < max && this.src.charCodeAt(pos) === marker) { pos++; }
|
||
|
||
const count = pos - start;
|
||
|
||
// treat end of the line as a whitespace
|
||
const nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20;
|
||
|
||
const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));
|
||
const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));
|
||
|
||
const isLastWhiteSpace = isWhiteSpace(lastChar);
|
||
const isNextWhiteSpace = isWhiteSpace(nextChar);
|
||
|
||
if (isNextWhiteSpace) {
|
||
left_flanking = false;
|
||
} else if (isNextPunctChar) {
|
||
if (!(isLastWhiteSpace || isLastPunctChar)) {
|
||
left_flanking = false;
|
||
}
|
||
}
|
||
|
||
if (isLastWhiteSpace) {
|
||
right_flanking = false;
|
||
} else if (isLastPunctChar) {
|
||
if (!(isNextWhiteSpace || isNextPunctChar)) {
|
||
right_flanking = false;
|
||
}
|
||
}
|
||
|
||
if (!canSplitWord) {
|
||
can_open = left_flanking && (!right_flanking || isLastPunctChar);
|
||
can_close = right_flanking && (!left_flanking || isNextPunctChar);
|
||
} else {
|
||
can_open = left_flanking;
|
||
can_close = right_flanking;
|
||
}
|
||
|
||
return { can_open, can_close, length: count }
|
||
};
|
||
|
||
// re-export Token class to use in block rules
|
||
StateInline.prototype.Token = Token;
|
||
|
||
// Skip text characters for text token, place those to pending buffer
|
||
// and increment current pos
|
||
|
||
// Rule to skip pure text
|
||
// '{}$%@~+=:' reserved for extentions
|
||
|
||
// !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, or ~
|
||
|
||
// !!!! Don't confuse with "Markdown ASCII Punctuation" chars
|
||
// http://spec.commonmark.org/0.15/#ascii-punctuation-character
|
||
function isTerminatorChar (ch) {
|
||
switch (ch) {
|
||
case 0x0A/* \n */:
|
||
case 0x21/* ! */:
|
||
case 0x23/* # */:
|
||
case 0x24/* $ */:
|
||
case 0x25/* % */:
|
||
case 0x26/* & */:
|
||
case 0x2A/* * */:
|
||
case 0x2B/* + */:
|
||
case 0x2D/* - */:
|
||
case 0x3A/* : */:
|
||
case 0x3C/* < */:
|
||
case 0x3D/* = */:
|
||
case 0x3E/* > */:
|
||
case 0x40/* @ */:
|
||
case 0x5B/* [ */:
|
||
case 0x5C/* \ */:
|
||
case 0x5D/* ] */:
|
||
case 0x5E/* ^ */:
|
||
case 0x5F/* _ */:
|
||
case 0x60/* ` */:
|
||
case 0x7B/* { */:
|
||
case 0x7D/* } */:
|
||
case 0x7E/* ~ */:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
function text$1 (state, silent) {
|
||
let pos = state.pos;
|
||
|
||
while (pos < state.posMax && !isTerminatorChar(state.src.charCodeAt(pos))) {
|
||
pos++;
|
||
}
|
||
|
||
if (pos === state.pos) { return false }
|
||
|
||
if (!silent) { state.pending += state.src.slice(state.pos, pos); }
|
||
|
||
state.pos = pos;
|
||
|
||
return true
|
||
}
|
||
|
||
// Alternative implementation, for memory.
|
||
//
|
||
// It costs 10% of performance, but allows extend terminators list, if place it
|
||
// to `ParcerInline` property. Probably, will switch to it sometime, such
|
||
// flexibility required.
|
||
|
||
/*
|
||
var TERMINATOR_RE = /[\n!#$%&*+\-:<=>@[\\\]^_`{}~]/;
|
||
|
||
module.exports = function text(state, silent) {
|
||
var pos = state.pos,
|
||
idx = state.src.slice(pos).search(TERMINATOR_RE);
|
||
|
||
// first char is terminator -> empty text
|
||
if (idx === 0) { return false; }
|
||
|
||
// no terminator -> text till end of string
|
||
if (idx < 0) {
|
||
if (!silent) { state.pending += state.src.slice(pos); }
|
||
state.pos = state.src.length;
|
||
return true;
|
||
}
|
||
|
||
if (!silent) { state.pending += state.src.slice(pos, pos + idx); }
|
||
|
||
state.pos += idx;
|
||
|
||
return true;
|
||
}; */
|
||
|
||
// Process links like https://example.org/
|
||
|
||
// RFC3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
|
||
const SCHEME_RE = /(?:^|[^a-z0-9.+-])([a-z][a-z0-9.+-]*)$/i;
|
||
|
||
function linkify (state, silent) {
|
||
if (!state.md.options.linkify) return false
|
||
if (state.linkLevel > 0) return false
|
||
|
||
const pos = state.pos;
|
||
const max = state.posMax;
|
||
|
||
if (pos + 3 > max) return false
|
||
if (state.src.charCodeAt(pos) !== 0x3A/* : */) return false
|
||
if (state.src.charCodeAt(pos + 1) !== 0x2F/* / */) return false
|
||
if (state.src.charCodeAt(pos + 2) !== 0x2F/* / */) return false
|
||
|
||
const match = state.pending.match(SCHEME_RE);
|
||
if (!match) return false
|
||
|
||
const proto = match[1];
|
||
|
||
const link = state.md.linkify.matchAtStart(state.src.slice(pos - proto.length));
|
||
if (!link) return false
|
||
|
||
let url = link.url;
|
||
|
||
// invalid link, but still detected by linkify somehow;
|
||
// need to check to prevent infinite loop below
|
||
if (url.length <= proto.length) return false
|
||
|
||
// disallow '*' at the end of the link (conflicts with emphasis)
|
||
url = url.replace(/\*+$/, '');
|
||
|
||
const fullUrl = state.md.normalizeLink(url);
|
||
if (!state.md.validateLink(fullUrl)) return false
|
||
|
||
if (!silent) {
|
||
state.pending = state.pending.slice(0, -proto.length);
|
||
|
||
const token_o = state.push('link_open', 'a', 1);
|
||
token_o.attrs = [['href', fullUrl]];
|
||
token_o.markup = 'linkify';
|
||
token_o.info = 'auto';
|
||
|
||
const token_t = state.push('text', '', 0);
|
||
token_t.content = state.md.normalizeLinkText(url);
|
||
|
||
const token_c = state.push('link_close', 'a', -1);
|
||
token_c.markup = 'linkify';
|
||
token_c.info = 'auto';
|
||
}
|
||
|
||
state.pos += url.length - proto.length;
|
||
return true
|
||
}
|
||
|
||
// Proceess '\n'
|
||
|
||
|
||
function newline (state, silent) {
|
||
let pos = state.pos;
|
||
|
||
if (state.src.charCodeAt(pos) !== 0x0A/* \n */) { return false }
|
||
|
||
const pmax = state.pending.length - 1;
|
||
const max = state.posMax;
|
||
|
||
// ' \n' -> hardbreak
|
||
// Lookup in pending chars is bad practice! Don't copy to other rules!
|
||
// Pending string is stored in concat mode, indexed lookups will cause
|
||
// convertion to flat mode.
|
||
if (!silent) {
|
||
if (pmax >= 0 && state.pending.charCodeAt(pmax) === 0x20) {
|
||
if (pmax >= 1 && state.pending.charCodeAt(pmax - 1) === 0x20) {
|
||
// Find whitespaces tail of pending chars.
|
||
let ws = pmax - 1;
|
||
while (ws >= 1 && state.pending.charCodeAt(ws - 1) === 0x20) ws--;
|
||
|
||
state.pending = state.pending.slice(0, ws);
|
||
state.push('hardbreak', 'br', 0);
|
||
} else {
|
||
state.pending = state.pending.slice(0, -1);
|
||
state.push('softbreak', 'br', 0);
|
||
}
|
||
} else {
|
||
state.push('softbreak', 'br', 0);
|
||
}
|
||
}
|
||
|
||
pos++;
|
||
|
||
// skip heading spaces for next line
|
||
while (pos < max && isSpace(state.src.charCodeAt(pos))) { pos++; }
|
||
|
||
state.pos = pos;
|
||
return true
|
||
}
|
||
|
||
// Process escaped chars and hardbreaks
|
||
|
||
|
||
const ESCAPED = [];
|
||
|
||
for (let i = 0; i < 256; i++) { ESCAPED.push(0); }
|
||
|
||
'\\!"#$%&\'()*+,./:;<=>?@[]^_`{|}~-'
|
||
.split('').forEach(function (ch) { ESCAPED[ch.charCodeAt(0)] = 1; });
|
||
|
||
function escape$3 (state, silent) {
|
||
let pos = state.pos;
|
||
const max = state.posMax;
|
||
|
||
if (state.src.charCodeAt(pos) !== 0x5C/* \ */) return false
|
||
pos++;
|
||
|
||
// '\' at the end of the inline block
|
||
if (pos >= max) return false
|
||
|
||
let ch1 = state.src.charCodeAt(pos);
|
||
|
||
if (ch1 === 0x0A) {
|
||
if (!silent) {
|
||
state.push('hardbreak', 'br', 0);
|
||
}
|
||
|
||
pos++;
|
||
// skip leading whitespaces from next line
|
||
while (pos < max) {
|
||
ch1 = state.src.charCodeAt(pos);
|
||
if (!isSpace(ch1)) break
|
||
pos++;
|
||
}
|
||
|
||
state.pos = pos;
|
||
return true
|
||
}
|
||
|
||
let escapedStr = state.src[pos];
|
||
|
||
if (ch1 >= 0xD800 && ch1 <= 0xDBFF && pos + 1 < max) {
|
||
const ch2 = state.src.charCodeAt(pos + 1);
|
||
|
||
if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) {
|
||
escapedStr += state.src[pos + 1];
|
||
pos++;
|
||
}
|
||
}
|
||
|
||
const origStr = '\\' + escapedStr;
|
||
|
||
if (!silent) {
|
||
const token = state.push('text_special', '', 0);
|
||
|
||
if (ch1 < 256 && ESCAPED[ch1] !== 0) {
|
||
token.content = escapedStr;
|
||
} else {
|
||
token.content = origStr;
|
||
}
|
||
|
||
token.markup = origStr;
|
||
token.info = 'escape';
|
||
}
|
||
|
||
state.pos = pos + 1;
|
||
return true
|
||
}
|
||
|
||
// Parse backticks
|
||
|
||
function backtick (state, silent) {
|
||
let pos = state.pos;
|
||
const ch = state.src.charCodeAt(pos);
|
||
|
||
if (ch !== 0x60/* ` */) { return false }
|
||
|
||
const start = pos;
|
||
pos++;
|
||
const max = state.posMax;
|
||
|
||
// scan marker length
|
||
while (pos < max && state.src.charCodeAt(pos) === 0x60/* ` */) { pos++; }
|
||
|
||
const marker = state.src.slice(start, pos);
|
||
const openerLength = marker.length;
|
||
|
||
if (state.backticksScanned && (state.backticks[openerLength] || 0) <= start) {
|
||
if (!silent) state.pending += marker;
|
||
state.pos += openerLength;
|
||
return true
|
||
}
|
||
|
||
let matchEnd = pos;
|
||
let matchStart;
|
||
|
||
// Nothing found in the cache, scan until the end of the line (or until marker is found)
|
||
while ((matchStart = state.src.indexOf('`', matchEnd)) !== -1) {
|
||
matchEnd = matchStart + 1;
|
||
|
||
// scan marker length
|
||
while (matchEnd < max && state.src.charCodeAt(matchEnd) === 0x60/* ` */) { matchEnd++; }
|
||
|
||
const closerLength = matchEnd - matchStart;
|
||
|
||
if (closerLength === openerLength) {
|
||
// Found matching closer length.
|
||
if (!silent) {
|
||
const token = state.push('code_inline', 'code', 0);
|
||
token.markup = marker;
|
||
token.content = state.src.slice(pos, matchStart)
|
||
.replace(/\n/g, ' ')
|
||
.replace(/^ (.+) $/, '$1');
|
||
}
|
||
state.pos = matchEnd;
|
||
return true
|
||
}
|
||
|
||
// Some different length found, put it in cache as upper limit of where closer can be found
|
||
state.backticks[closerLength] = matchStart;
|
||
}
|
||
|
||
// Scanned through the end, didn't find anything
|
||
state.backticksScanned = true;
|
||
|
||
if (!silent) state.pending += marker;
|
||
state.pos += openerLength;
|
||
return true
|
||
}
|
||
|
||
// ~~strike through~~
|
||
//
|
||
|
||
// Insert each marker as a separate text token, and add it to delimiter list
|
||
//
|
||
function strikethrough_tokenize (state, silent) {
|
||
const start = state.pos;
|
||
const marker = state.src.charCodeAt(start);
|
||
|
||
if (silent) { return false }
|
||
|
||
if (marker !== 0x7E/* ~ */) { return false }
|
||
|
||
const scanned = state.scanDelims(state.pos, true);
|
||
let len = scanned.length;
|
||
const ch = String.fromCharCode(marker);
|
||
|
||
if (len < 2) { return false }
|
||
|
||
let token;
|
||
|
||
if (len % 2) {
|
||
token = state.push('text', '', 0);
|
||
token.content = ch;
|
||
len--;
|
||
}
|
||
|
||
for (let i = 0; i < len; i += 2) {
|
||
token = state.push('text', '', 0);
|
||
token.content = ch + ch;
|
||
|
||
state.delimiters.push({
|
||
marker,
|
||
length: 0, // disable "rule of 3" length checks meant for emphasis
|
||
token: state.tokens.length - 1,
|
||
end: -1,
|
||
open: scanned.can_open,
|
||
close: scanned.can_close
|
||
});
|
||
}
|
||
|
||
state.pos += scanned.length;
|
||
|
||
return true
|
||
}
|
||
|
||
function postProcess$1 (state, delimiters) {
|
||
let token;
|
||
const loneMarkers = [];
|
||
const max = delimiters.length;
|
||
|
||
for (let i = 0; i < max; i++) {
|
||
const startDelim = delimiters[i];
|
||
|
||
if (startDelim.marker !== 0x7E/* ~ */) {
|
||
continue
|
||
}
|
||
|
||
if (startDelim.end === -1) {
|
||
continue
|
||
}
|
||
|
||
const endDelim = delimiters[startDelim.end];
|
||
|
||
token = state.tokens[startDelim.token];
|
||
token.type = 's_open';
|
||
token.tag = 's';
|
||
token.nesting = 1;
|
||
token.markup = '~~';
|
||
token.content = '';
|
||
|
||
token = state.tokens[endDelim.token];
|
||
token.type = 's_close';
|
||
token.tag = 's';
|
||
token.nesting = -1;
|
||
token.markup = '~~';
|
||
token.content = '';
|
||
|
||
if (state.tokens[endDelim.token - 1].type === 'text' &&
|
||
state.tokens[endDelim.token - 1].content === '~') {
|
||
loneMarkers.push(endDelim.token - 1);
|
||
}
|
||
}
|
||
|
||
// If a marker sequence has an odd number of characters, it's splitted
|
||
// like this: `~~~~~` -> `~` + `~~` + `~~`, leaving one marker at the
|
||
// start of the sequence.
|
||
//
|
||
// So, we have to move all those markers after subsequent s_close tags.
|
||
//
|
||
while (loneMarkers.length) {
|
||
const i = loneMarkers.pop();
|
||
let j = i + 1;
|
||
|
||
while (j < state.tokens.length && state.tokens[j].type === 's_close') {
|
||
j++;
|
||
}
|
||
|
||
j--;
|
||
|
||
if (i !== j) {
|
||
token = state.tokens[j];
|
||
state.tokens[j] = state.tokens[i];
|
||
state.tokens[i] = token;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Walk through delimiter list and replace text tokens with tags
|
||
//
|
||
function strikethrough_postProcess (state) {
|
||
const tokens_meta = state.tokens_meta;
|
||
const max = state.tokens_meta.length;
|
||
|
||
postProcess$1(state, state.delimiters);
|
||
|
||
for (let curr = 0; curr < max; curr++) {
|
||
if (tokens_meta[curr] && tokens_meta[curr].delimiters) {
|
||
postProcess$1(state, tokens_meta[curr].delimiters);
|
||
}
|
||
}
|
||
}
|
||
|
||
var r_strikethrough = {
|
||
tokenize: strikethrough_tokenize,
|
||
postProcess: strikethrough_postProcess
|
||
};
|
||
|
||
// Process *this* and _that_
|
||
//
|
||
|
||
// Insert each marker as a separate text token, and add it to delimiter list
|
||
//
|
||
function emphasis_tokenize (state, silent) {
|
||
const start = state.pos;
|
||
const marker = state.src.charCodeAt(start);
|
||
|
||
if (silent) { return false }
|
||
|
||
if (marker !== 0x5F /* _ */ && marker !== 0x2A /* * */) { return false }
|
||
|
||
const scanned = state.scanDelims(state.pos, marker === 0x2A);
|
||
|
||
for (let i = 0; i < scanned.length; i++) {
|
||
const token = state.push('text', '', 0);
|
||
token.content = String.fromCharCode(marker);
|
||
|
||
state.delimiters.push({
|
||
// Char code of the starting marker (number).
|
||
//
|
||
marker,
|
||
|
||
// Total length of these series of delimiters.
|
||
//
|
||
length: scanned.length,
|
||
|
||
// A position of the token this delimiter corresponds to.
|
||
//
|
||
token: state.tokens.length - 1,
|
||
|
||
// If this delimiter is matched as a valid opener, `end` will be
|
||
// equal to its position, otherwise it's `-1`.
|
||
//
|
||
end: -1,
|
||
|
||
// Boolean flags that determine if this delimiter could open or close
|
||
// an emphasis.
|
||
//
|
||
open: scanned.can_open,
|
||
close: scanned.can_close
|
||
});
|
||
}
|
||
|
||
state.pos += scanned.length;
|
||
|
||
return true
|
||
}
|
||
|
||
function postProcess (state, delimiters) {
|
||
const max = delimiters.length;
|
||
|
||
for (let i = max - 1; i >= 0; i--) {
|
||
const startDelim = delimiters[i];
|
||
|
||
if (startDelim.marker !== 0x5F/* _ */ && startDelim.marker !== 0x2A/* * */) {
|
||
continue
|
||
}
|
||
|
||
// Process only opening markers
|
||
if (startDelim.end === -1) {
|
||
continue
|
||
}
|
||
|
||
const endDelim = delimiters[startDelim.end];
|
||
|
||
// If the previous delimiter has the same marker and is adjacent to this one,
|
||
// merge those into one strong delimiter.
|
||
//
|
||
// `<em><em>whatever</em></em>` -> `<strong>whatever</strong>`
|
||
//
|
||
const isStrong = i > 0 &&
|
||
delimiters[i - 1].end === startDelim.end + 1 &&
|
||
// check that first two markers match and adjacent
|
||
delimiters[i - 1].marker === startDelim.marker &&
|
||
delimiters[i - 1].token === startDelim.token - 1 &&
|
||
// check that last two markers are adjacent (we can safely assume they match)
|
||
delimiters[startDelim.end + 1].token === endDelim.token + 1;
|
||
|
||
const ch = String.fromCharCode(startDelim.marker);
|
||
|
||
const token_o = state.tokens[startDelim.token];
|
||
token_o.type = isStrong ? 'strong_open' : 'em_open';
|
||
token_o.tag = isStrong ? 'strong' : 'em';
|
||
token_o.nesting = 1;
|
||
token_o.markup = isStrong ? ch + ch : ch;
|
||
token_o.content = '';
|
||
|
||
const token_c = state.tokens[endDelim.token];
|
||
token_c.type = isStrong ? 'strong_close' : 'em_close';
|
||
token_c.tag = isStrong ? 'strong' : 'em';
|
||
token_c.nesting = -1;
|
||
token_c.markup = isStrong ? ch + ch : ch;
|
||
token_c.content = '';
|
||
|
||
if (isStrong) {
|
||
state.tokens[delimiters[i - 1].token].content = '';
|
||
state.tokens[delimiters[startDelim.end + 1].token].content = '';
|
||
i--;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Walk through delimiter list and replace text tokens with tags
|
||
//
|
||
function emphasis_post_process (state) {
|
||
const tokens_meta = state.tokens_meta;
|
||
const max = state.tokens_meta.length;
|
||
|
||
postProcess(state, state.delimiters);
|
||
|
||
for (let curr = 0; curr < max; curr++) {
|
||
if (tokens_meta[curr] && tokens_meta[curr].delimiters) {
|
||
postProcess(state, tokens_meta[curr].delimiters);
|
||
}
|
||
}
|
||
}
|
||
|
||
var r_emphasis = {
|
||
tokenize: emphasis_tokenize,
|
||
postProcess: emphasis_post_process
|
||
};
|
||
|
||
// Process [link](<to> "stuff")
|
||
|
||
|
||
function link (state, silent) {
|
||
let code, label, res, ref;
|
||
let href = '';
|
||
let title = '';
|
||
let start = state.pos;
|
||
let parseReference = true;
|
||
|
||
if (state.src.charCodeAt(state.pos) !== 0x5B/* [ */) { return false }
|
||
|
||
const oldPos = state.pos;
|
||
const max = state.posMax;
|
||
const labelStart = state.pos + 1;
|
||
const labelEnd = state.md.helpers.parseLinkLabel(state, state.pos, true);
|
||
|
||
// parser failed to find ']', so it's not a valid link
|
||
if (labelEnd < 0) { return false }
|
||
|
||
let pos = labelEnd + 1;
|
||
if (pos < max && state.src.charCodeAt(pos) === 0x28/* ( */) {
|
||
//
|
||
// Inline link
|
||
//
|
||
|
||
// might have found a valid shortcut link, disable reference parsing
|
||
parseReference = false;
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^ skipping these spaces
|
||
pos++;
|
||
for (; pos < max; pos++) {
|
||
code = state.src.charCodeAt(pos);
|
||
if (!isSpace(code) && code !== 0x0A) { break }
|
||
}
|
||
if (pos >= max) { return false }
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^^^^^ parsing link destination
|
||
start = pos;
|
||
res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax);
|
||
if (res.ok) {
|
||
href = state.md.normalizeLink(res.str);
|
||
if (state.md.validateLink(href)) {
|
||
pos = res.pos;
|
||
} else {
|
||
href = '';
|
||
}
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^ skipping these spaces
|
||
start = pos;
|
||
for (; pos < max; pos++) {
|
||
code = state.src.charCodeAt(pos);
|
||
if (!isSpace(code) && code !== 0x0A) { break }
|
||
}
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^^^^^^ parsing link title
|
||
res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax);
|
||
if (pos < max && start !== pos && res.ok) {
|
||
title = res.str;
|
||
pos = res.pos;
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^ skipping these spaces
|
||
for (; pos < max; pos++) {
|
||
code = state.src.charCodeAt(pos);
|
||
if (!isSpace(code) && code !== 0x0A) { break }
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pos >= max || state.src.charCodeAt(pos) !== 0x29/* ) */) {
|
||
// parsing a valid shortcut link failed, fallback to reference
|
||
parseReference = true;
|
||
}
|
||
pos++;
|
||
}
|
||
|
||
if (parseReference) {
|
||
//
|
||
// Link reference
|
||
//
|
||
if (typeof state.env.references === 'undefined') { return false }
|
||
|
||
if (pos < max && state.src.charCodeAt(pos) === 0x5B/* [ */) {
|
||
start = pos + 1;
|
||
pos = state.md.helpers.parseLinkLabel(state, pos);
|
||
if (pos >= 0) {
|
||
label = state.src.slice(start, pos++);
|
||
} else {
|
||
pos = labelEnd + 1;
|
||
}
|
||
} else {
|
||
pos = labelEnd + 1;
|
||
}
|
||
|
||
// covers label === '' and label === undefined
|
||
// (collapsed reference link and shortcut reference link respectively)
|
||
if (!label) { label = state.src.slice(labelStart, labelEnd); }
|
||
|
||
ref = state.env.references[normalizeReference(label)];
|
||
if (!ref) {
|
||
state.pos = oldPos;
|
||
return false
|
||
}
|
||
href = ref.href;
|
||
title = ref.title;
|
||
}
|
||
|
||
//
|
||
// We found the end of the link, and know for a fact it's a valid link;
|
||
// so all that's left to do is to call tokenizer.
|
||
//
|
||
if (!silent) {
|
||
state.pos = labelStart;
|
||
state.posMax = labelEnd;
|
||
|
||
const token_o = state.push('link_open', 'a', 1);
|
||
const attrs = [['href', href]];
|
||
token_o.attrs = attrs;
|
||
if (title) {
|
||
attrs.push(['title', title]);
|
||
}
|
||
|
||
state.linkLevel++;
|
||
state.md.inline.tokenize(state);
|
||
state.linkLevel--;
|
||
|
||
state.push('link_close', 'a', -1);
|
||
}
|
||
|
||
state.pos = pos;
|
||
state.posMax = max;
|
||
return true
|
||
}
|
||
|
||
// Process 
|
||
|
||
|
||
function image (state, silent) {
|
||
let code, content, label, pos, ref, res, title, start;
|
||
let href = '';
|
||
const oldPos = state.pos;
|
||
const max = state.posMax;
|
||
|
||
if (state.src.charCodeAt(state.pos) !== 0x21/* ! */) { return false }
|
||
if (state.src.charCodeAt(state.pos + 1) !== 0x5B/* [ */) { return false }
|
||
|
||
const labelStart = state.pos + 2;
|
||
const labelEnd = state.md.helpers.parseLinkLabel(state, state.pos + 1, false);
|
||
|
||
// parser failed to find ']', so it's not a valid link
|
||
if (labelEnd < 0) { return false }
|
||
|
||
pos = labelEnd + 1;
|
||
if (pos < max && state.src.charCodeAt(pos) === 0x28/* ( */) {
|
||
//
|
||
// Inline link
|
||
//
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^ skipping these spaces
|
||
pos++;
|
||
for (; pos < max; pos++) {
|
||
code = state.src.charCodeAt(pos);
|
||
if (!isSpace(code) && code !== 0x0A) { break }
|
||
}
|
||
if (pos >= max) { return false }
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^^^^^ parsing link destination
|
||
start = pos;
|
||
res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax);
|
||
if (res.ok) {
|
||
href = state.md.normalizeLink(res.str);
|
||
if (state.md.validateLink(href)) {
|
||
pos = res.pos;
|
||
} else {
|
||
href = '';
|
||
}
|
||
}
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^ skipping these spaces
|
||
start = pos;
|
||
for (; pos < max; pos++) {
|
||
code = state.src.charCodeAt(pos);
|
||
if (!isSpace(code) && code !== 0x0A) { break }
|
||
}
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^^^^^^ parsing link title
|
||
res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax);
|
||
if (pos < max && start !== pos && res.ok) {
|
||
title = res.str;
|
||
pos = res.pos;
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^ skipping these spaces
|
||
for (; pos < max; pos++) {
|
||
code = state.src.charCodeAt(pos);
|
||
if (!isSpace(code) && code !== 0x0A) { break }
|
||
}
|
||
} else {
|
||
title = '';
|
||
}
|
||
|
||
if (pos >= max || state.src.charCodeAt(pos) !== 0x29/* ) */) {
|
||
state.pos = oldPos;
|
||
return false
|
||
}
|
||
pos++;
|
||
} else {
|
||
//
|
||
// Link reference
|
||
//
|
||
if (typeof state.env.references === 'undefined') { return false }
|
||
|
||
if (pos < max && state.src.charCodeAt(pos) === 0x5B/* [ */) {
|
||
start = pos + 1;
|
||
pos = state.md.helpers.parseLinkLabel(state, pos);
|
||
if (pos >= 0) {
|
||
label = state.src.slice(start, pos++);
|
||
} else {
|
||
pos = labelEnd + 1;
|
||
}
|
||
} else {
|
||
pos = labelEnd + 1;
|
||
}
|
||
|
||
// covers label === '' and label === undefined
|
||
// (collapsed reference link and shortcut reference link respectively)
|
||
if (!label) { label = state.src.slice(labelStart, labelEnd); }
|
||
|
||
ref = state.env.references[normalizeReference(label)];
|
||
if (!ref) {
|
||
state.pos = oldPos;
|
||
return false
|
||
}
|
||
href = ref.href;
|
||
title = ref.title;
|
||
}
|
||
|
||
//
|
||
// We found the end of the link, and know for a fact it's a valid link;
|
||
// so all that's left to do is to call tokenizer.
|
||
//
|
||
if (!silent) {
|
||
content = state.src.slice(labelStart, labelEnd);
|
||
|
||
const tokens = [];
|
||
state.md.inline.parse(
|
||
content,
|
||
state.md,
|
||
state.env,
|
||
tokens
|
||
);
|
||
|
||
const token = state.push('image', 'img', 0);
|
||
const attrs = [['src', href], ['alt', '']];
|
||
token.attrs = attrs;
|
||
token.children = tokens;
|
||
token.content = content;
|
||
|
||
if (title) {
|
||
attrs.push(['title', title]);
|
||
}
|
||
}
|
||
|
||
state.pos = pos;
|
||
state.posMax = max;
|
||
return true
|
||
}
|
||
|
||
// Process autolinks '<protocol:...>'
|
||
|
||
/* eslint max-len:0 */
|
||
const EMAIL_RE = /^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/;
|
||
/* eslint-disable-next-line no-control-regex */
|
||
const AUTOLINK_RE = /^([a-zA-Z][a-zA-Z0-9+.-]{1,31}):([^<>\x00-\x20]*)$/;
|
||
|
||
function autolink (state, silent) {
|
||
let pos = state.pos;
|
||
|
||
if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false }
|
||
|
||
const start = state.pos;
|
||
const max = state.posMax;
|
||
|
||
for (;;) {
|
||
if (++pos >= max) return false
|
||
|
||
const ch = state.src.charCodeAt(pos);
|
||
|
||
if (ch === 0x3C /* < */) return false
|
||
if (ch === 0x3E /* > */) break
|
||
}
|
||
|
||
const url = state.src.slice(start + 1, pos);
|
||
|
||
if (AUTOLINK_RE.test(url)) {
|
||
const fullUrl = state.md.normalizeLink(url);
|
||
if (!state.md.validateLink(fullUrl)) { return false }
|
||
|
||
if (!silent) {
|
||
const token_o = state.push('link_open', 'a', 1);
|
||
token_o.attrs = [['href', fullUrl]];
|
||
token_o.markup = 'autolink';
|
||
token_o.info = 'auto';
|
||
|
||
const token_t = state.push('text', '', 0);
|
||
token_t.content = state.md.normalizeLinkText(url);
|
||
|
||
const token_c = state.push('link_close', 'a', -1);
|
||
token_c.markup = 'autolink';
|
||
token_c.info = 'auto';
|
||
}
|
||
|
||
state.pos += url.length + 2;
|
||
return true
|
||
}
|
||
|
||
if (EMAIL_RE.test(url)) {
|
||
const fullUrl = state.md.normalizeLink('mailto:' + url);
|
||
if (!state.md.validateLink(fullUrl)) { return false }
|
||
|
||
if (!silent) {
|
||
const token_o = state.push('link_open', 'a', 1);
|
||
token_o.attrs = [['href', fullUrl]];
|
||
token_o.markup = 'autolink';
|
||
token_o.info = 'auto';
|
||
|
||
const token_t = state.push('text', '', 0);
|
||
token_t.content = state.md.normalizeLinkText(url);
|
||
|
||
const token_c = state.push('link_close', 'a', -1);
|
||
token_c.markup = 'autolink';
|
||
token_c.info = 'auto';
|
||
}
|
||
|
||
state.pos += url.length + 2;
|
||
return true
|
||
}
|
||
|
||
return false
|
||
}
|
||
|
||
// Process html tags
|
||
|
||
|
||
function isLinkOpen (str) {
|
||
return /^<a[>\s]/i.test(str)
|
||
}
|
||
function isLinkClose (str) {
|
||
return /^<\/a\s*>/i.test(str)
|
||
}
|
||
|
||
function isLetter (ch) {
|
||
/* eslint no-bitwise:0 */
|
||
const lc = ch | 0x20; // to lower case
|
||
return (lc >= 0x61/* a */) && (lc <= 0x7a/* z */)
|
||
}
|
||
|
||
function html_inline (state, silent) {
|
||
if (!state.md.options.html) { return false }
|
||
|
||
// Check start
|
||
const max = state.posMax;
|
||
const pos = state.pos;
|
||
if (state.src.charCodeAt(pos) !== 0x3C/* < */ ||
|
||
pos + 2 >= max) {
|
||
return false
|
||
}
|
||
|
||
// Quick fail on second char
|
||
const ch = state.src.charCodeAt(pos + 1);
|
||
if (ch !== 0x21/* ! */ &&
|
||
ch !== 0x3F/* ? */ &&
|
||
ch !== 0x2F/* / */ &&
|
||
!isLetter(ch)) {
|
||
return false
|
||
}
|
||
|
||
const match = state.src.slice(pos).match(HTML_TAG_RE);
|
||
if (!match) { return false }
|
||
|
||
if (!silent) {
|
||
const token = state.push('html_inline', '', 0);
|
||
token.content = match[0];
|
||
|
||
if (isLinkOpen(token.content)) state.linkLevel++;
|
||
if (isLinkClose(token.content)) state.linkLevel--;
|
||
}
|
||
state.pos += match[0].length;
|
||
return true
|
||
}
|
||
|
||
// Process html entity - {, ¯, ", ...
|
||
|
||
|
||
const DIGITAL_RE = /^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i;
|
||
const NAMED_RE = /^&([a-z][a-z0-9]{1,31});/i;
|
||
|
||
function entity (state, silent) {
|
||
const pos = state.pos;
|
||
const max = state.posMax;
|
||
|
||
if (state.src.charCodeAt(pos) !== 0x26/* & */) return false
|
||
|
||
if (pos + 1 >= max) return false
|
||
|
||
const ch = state.src.charCodeAt(pos + 1);
|
||
|
||
if (ch === 0x23 /* # */) {
|
||
const match = state.src.slice(pos).match(DIGITAL_RE);
|
||
if (match) {
|
||
if (!silent) {
|
||
const code = match[1][0].toLowerCase() === 'x' ? parseInt(match[1].slice(1), 16) : parseInt(match[1], 10);
|
||
|
||
const token = state.push('text_special', '', 0);
|
||
token.content = isValidEntityCode(code) ? fromCodePoint(code) : fromCodePoint(0xFFFD);
|
||
token.markup = match[0];
|
||
token.info = 'entity';
|
||
}
|
||
state.pos += match[0].length;
|
||
return true
|
||
}
|
||
} else {
|
||
const match = state.src.slice(pos).match(NAMED_RE);
|
||
if (match) {
|
||
const decoded = decodeHTML(match[0]);
|
||
if (decoded !== match[0]) {
|
||
if (!silent) {
|
||
const token = state.push('text_special', '', 0);
|
||
token.content = decoded;
|
||
token.markup = match[0];
|
||
token.info = 'entity';
|
||
}
|
||
state.pos += match[0].length;
|
||
return true
|
||
}
|
||
}
|
||
}
|
||
|
||
return false
|
||
}
|
||
|
||
// For each opening emphasis-like marker find a matching closing one
|
||
//
|
||
|
||
function processDelimiters (delimiters) {
|
||
const openersBottom = {};
|
||
const max = delimiters.length;
|
||
|
||
if (!max) return
|
||
|
||
// headerIdx is the first delimiter of the current (where closer is) delimiter run
|
||
let headerIdx = 0;
|
||
let lastTokenIdx = -2; // needs any value lower than -1
|
||
const jumps = [];
|
||
|
||
for (let closerIdx = 0; closerIdx < max; closerIdx++) {
|
||
const closer = delimiters[closerIdx];
|
||
|
||
jumps.push(0);
|
||
|
||
// markers belong to same delimiter run if:
|
||
// - they have adjacent tokens
|
||
// - AND markers are the same
|
||
//
|
||
if (delimiters[headerIdx].marker !== closer.marker || lastTokenIdx !== closer.token - 1) {
|
||
headerIdx = closerIdx;
|
||
}
|
||
|
||
lastTokenIdx = closer.token;
|
||
|
||
// Length is only used for emphasis-specific "rule of 3",
|
||
// if it's not defined (in strikethrough or 3rd party plugins),
|
||
// we can default it to 0 to disable those checks.
|
||
//
|
||
closer.length = closer.length || 0;
|
||
|
||
if (!closer.close) continue
|
||
|
||
// Previously calculated lower bounds (previous fails)
|
||
// for each marker, each delimiter length modulo 3,
|
||
// and for whether this closer can be an opener;
|
||
// https://github.com/commonmark/cmark/commit/34250e12ccebdc6372b8b49c44fab57c72443460
|
||
/* eslint-disable-next-line no-prototype-builtins */
|
||
if (!openersBottom.hasOwnProperty(closer.marker)) {
|
||
openersBottom[closer.marker] = [-1, -1, -1, -1, -1, -1];
|
||
}
|
||
|
||
const minOpenerIdx = openersBottom[closer.marker][(closer.open ? 3 : 0) + (closer.length % 3)];
|
||
|
||
let openerIdx = headerIdx - jumps[headerIdx] - 1;
|
||
|
||
let newMinOpenerIdx = openerIdx;
|
||
|
||
for (; openerIdx > minOpenerIdx; openerIdx -= jumps[openerIdx] + 1) {
|
||
const opener = delimiters[openerIdx];
|
||
|
||
if (opener.marker !== closer.marker) continue
|
||
|
||
if (opener.open && opener.end < 0) {
|
||
let isOddMatch = false;
|
||
|
||
// from spec:
|
||
//
|
||
// If one of the delimiters can both open and close emphasis, then the
|
||
// sum of the lengths of the delimiter runs containing the opening and
|
||
// closing delimiters must not be a multiple of 3 unless both lengths
|
||
// are multiples of 3.
|
||
//
|
||
if (opener.close || closer.open) {
|
||
if ((opener.length + closer.length) % 3 === 0) {
|
||
if (opener.length % 3 !== 0 || closer.length % 3 !== 0) {
|
||
isOddMatch = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!isOddMatch) {
|
||
// If previous delimiter cannot be an opener, we can safely skip
|
||
// the entire sequence in future checks. This is required to make
|
||
// sure algorithm has linear complexity (see *_*_*_*_*_... case).
|
||
//
|
||
const lastJump = openerIdx > 0 && !delimiters[openerIdx - 1].open
|
||
? jumps[openerIdx - 1] + 1
|
||
: 0;
|
||
|
||
jumps[closerIdx] = closerIdx - openerIdx + lastJump;
|
||
jumps[openerIdx] = lastJump;
|
||
|
||
closer.open = false;
|
||
opener.end = closerIdx;
|
||
opener.close = false;
|
||
newMinOpenerIdx = -1;
|
||
// treat next token as start of run,
|
||
// it optimizes skips in **<...>**a**<...>** pathological case
|
||
lastTokenIdx = -2;
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
if (newMinOpenerIdx !== -1) {
|
||
// If match for this delimiter run failed, we want to set lower bound for
|
||
// future lookups. This is required to make sure algorithm has linear
|
||
// complexity.
|
||
//
|
||
// See details here:
|
||
// https://github.com/commonmark/cmark/issues/178#issuecomment-270417442
|
||
//
|
||
openersBottom[closer.marker][(closer.open ? 3 : 0) + ((closer.length || 0) % 3)] = newMinOpenerIdx;
|
||
}
|
||
}
|
||
}
|
||
|
||
function link_pairs (state) {
|
||
const tokens_meta = state.tokens_meta;
|
||
const max = state.tokens_meta.length;
|
||
|
||
processDelimiters(state.delimiters);
|
||
|
||
for (let curr = 0; curr < max; curr++) {
|
||
if (tokens_meta[curr] && tokens_meta[curr].delimiters) {
|
||
processDelimiters(tokens_meta[curr].delimiters);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Clean up tokens after emphasis and strikethrough postprocessing:
|
||
// merge adjacent text nodes into one and re-calculate all token levels
|
||
//
|
||
// This is necessary because initially emphasis delimiter markers (*, _, ~)
|
||
// are treated as their own separate text tokens. Then emphasis rule either
|
||
// leaves them as text (needed to merge with adjacent text) or turns them
|
||
// into opening/closing tags (which messes up levels inside).
|
||
//
|
||
|
||
function fragments_join (state) {
|
||
let curr, last;
|
||
let level = 0;
|
||
const tokens = state.tokens;
|
||
const max = state.tokens.length;
|
||
|
||
for (curr = last = 0; curr < max; curr++) {
|
||
// re-calculate levels after emphasis/strikethrough turns some text nodes
|
||
// into opening/closing tags
|
||
if (tokens[curr].nesting < 0) level--; // closing tag
|
||
tokens[curr].level = level;
|
||
if (tokens[curr].nesting > 0) level++; // opening tag
|
||
|
||
if (tokens[curr].type === 'text' &&
|
||
curr + 1 < max &&
|
||
tokens[curr + 1].type === 'text') {
|
||
// collapse two adjacent text nodes
|
||
tokens[curr + 1].content = tokens[curr].content + tokens[curr + 1].content;
|
||
} else {
|
||
if (curr !== last) { tokens[last] = tokens[curr]; }
|
||
|
||
last++;
|
||
}
|
||
}
|
||
|
||
if (curr !== last) {
|
||
tokens.length = last;
|
||
}
|
||
}
|
||
|
||
/** internal
|
||
* class ParserInline
|
||
*
|
||
* Tokenizes paragraph content.
|
||
**/
|
||
|
||
|
||
// Parser rules
|
||
|
||
const _rules = [
|
||
['text', text$1],
|
||
['linkify', linkify],
|
||
['newline', newline],
|
||
['escape', escape$3],
|
||
['backticks', backtick],
|
||
['strikethrough', r_strikethrough.tokenize],
|
||
['emphasis', r_emphasis.tokenize],
|
||
['link', link],
|
||
['image', image],
|
||
['autolink', autolink],
|
||
['html_inline', html_inline],
|
||
['entity', entity]
|
||
];
|
||
|
||
// `rule2` ruleset was created specifically for emphasis/strikethrough
|
||
// post-processing and may be changed in the future.
|
||
//
|
||
// Don't use this for anything except pairs (plugins working with `balance_pairs`).
|
||
//
|
||
const _rules2 = [
|
||
['balance_pairs', link_pairs],
|
||
['strikethrough', r_strikethrough.postProcess],
|
||
['emphasis', r_emphasis.postProcess],
|
||
// rules for pairs separate '**' into its own text tokens, which may be left unused,
|
||
// rule below merges unused segments back with the rest of the text
|
||
['fragments_join', fragments_join]
|
||
];
|
||
|
||
/**
|
||
* new ParserInline()
|
||
**/
|
||
function ParserInline () {
|
||
/**
|
||
* ParserInline#ruler -> Ruler
|
||
*
|
||
* [[Ruler]] instance. Keep configuration of inline rules.
|
||
**/
|
||
this.ruler = new Ruler();
|
||
|
||
for (let i = 0; i < _rules.length; i++) {
|
||
this.ruler.push(_rules[i][0], _rules[i][1]);
|
||
}
|
||
|
||
/**
|
||
* ParserInline#ruler2 -> Ruler
|
||
*
|
||
* [[Ruler]] instance. Second ruler used for post-processing
|
||
* (e.g. in emphasis-like rules).
|
||
**/
|
||
this.ruler2 = new Ruler();
|
||
|
||
for (let i = 0; i < _rules2.length; i++) {
|
||
this.ruler2.push(_rules2[i][0], _rules2[i][1]);
|
||
}
|
||
}
|
||
|
||
// Skip single token by running all rules in validation mode;
|
||
// returns `true` if any rule reported success
|
||
//
|
||
ParserInline.prototype.skipToken = function (state) {
|
||
const pos = state.pos;
|
||
const rules = this.ruler.getRules('');
|
||
const len = rules.length;
|
||
const maxNesting = state.md.options.maxNesting;
|
||
const cache = state.cache;
|
||
|
||
if (typeof cache[pos] !== 'undefined') {
|
||
state.pos = cache[pos];
|
||
return
|
||
}
|
||
|
||
let ok = false;
|
||
|
||
if (state.level < maxNesting) {
|
||
for (let i = 0; i < len; i++) {
|
||
// Increment state.level and decrement it later to limit recursion.
|
||
// It's harmless to do here, because no tokens are created. But ideally,
|
||
// we'd need a separate private state variable for this purpose.
|
||
//
|
||
state.level++;
|
||
ok = rules[i](state, true);
|
||
state.level--;
|
||
|
||
if (ok) {
|
||
if (pos >= state.pos) { throw new Error("inline rule didn't increment state.pos") }
|
||
break
|
||
}
|
||
}
|
||
} else {
|
||
// Too much nesting, just skip until the end of the paragraph.
|
||
//
|
||
// NOTE: this will cause links to behave incorrectly in the following case,
|
||
// when an amount of `[` is exactly equal to `maxNesting + 1`:
|
||
//
|
||
// [[[[[[[[[[[[[[[[[[[[[foo]()
|
||
//
|
||
// TODO: remove this workaround when CM standard will allow nested links
|
||
// (we can replace it by preventing links from being parsed in
|
||
// validation mode)
|
||
//
|
||
state.pos = state.posMax;
|
||
}
|
||
|
||
if (!ok) { state.pos++; }
|
||
cache[pos] = state.pos;
|
||
};
|
||
|
||
// Generate tokens for input range
|
||
//
|
||
ParserInline.prototype.tokenize = function (state) {
|
||
const rules = this.ruler.getRules('');
|
||
const len = rules.length;
|
||
const end = state.posMax;
|
||
const maxNesting = state.md.options.maxNesting;
|
||
|
||
while (state.pos < end) {
|
||
// Try all possible rules.
|
||
// On success, rule should:
|
||
//
|
||
// - update `state.pos`
|
||
// - update `state.tokens`
|
||
// - return true
|
||
const prevPos = state.pos;
|
||
let ok = false;
|
||
|
||
if (state.level < maxNesting) {
|
||
for (let i = 0; i < len; i++) {
|
||
ok = rules[i](state, false);
|
||
if (ok) {
|
||
if (prevPos >= state.pos) { throw new Error("inline rule didn't increment state.pos") }
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
if (ok) {
|
||
if (state.pos >= end) { break }
|
||
continue
|
||
}
|
||
|
||
state.pending += state.src[state.pos++];
|
||
}
|
||
|
||
if (state.pending) {
|
||
state.pushPending();
|
||
}
|
||
};
|
||
|
||
/**
|
||
* ParserInline.parse(str, md, env, outTokens)
|
||
*
|
||
* Process input string and push inline tokens into `outTokens`
|
||
**/
|
||
ParserInline.prototype.parse = function (str, md, env, outTokens) {
|
||
const state = new this.State(str, md, env, outTokens);
|
||
|
||
this.tokenize(state);
|
||
|
||
const rules = this.ruler2.getRules('');
|
||
const len = rules.length;
|
||
|
||
for (let i = 0; i < len; i++) {
|
||
rules[i](state);
|
||
}
|
||
};
|
||
|
||
ParserInline.prototype.State = StateInline;
|
||
|
||
function reFactory (opts) {
|
||
const re = {};
|
||
opts = opts || {};
|
||
|
||
re.src_Any = Any.source;
|
||
re.src_Cc = Cc.source;
|
||
re.src_Z = Z$1.source;
|
||
re.src_P = P$1.source;
|
||
|
||
// \p{\Z\P\Cc\CF} (white spaces + control + format + punctuation)
|
||
re.src_ZPCc = [re.src_Z, re.src_P, re.src_Cc].join('|');
|
||
|
||
// \p{\Z\Cc} (white spaces + control)
|
||
re.src_ZCc = [re.src_Z, re.src_Cc].join('|');
|
||
|
||
// Experimental. List of chars, completely prohibited in links
|
||
// because can separate it from other part of text
|
||
const text_separators = '[><\uff5c]';
|
||
|
||
// All possible word characters (everything without punctuation, spaces & controls)
|
||
// Defined via punctuation & spaces to save space
|
||
// Should be something like \p{\L\N\S\M} (\w but without `_`)
|
||
re.src_pseudo_letter = '(?:(?!' + text_separators + '|' + re.src_ZPCc + ')' + re.src_Any + ')';
|
||
// The same as abothe but without [0-9]
|
||
// var src_pseudo_letter_non_d = '(?:(?![0-9]|' + src_ZPCc + ')' + src_Any + ')';
|
||
|
||
re.src_ip4 =
|
||
|
||
'(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)';
|
||
|
||
// Prohibit any of "@/[]()" in user/pass to avoid wrong domain fetch.
|
||
re.src_auth = '(?:(?:(?!' + re.src_ZCc + '|[@/\\[\\]()]).)+@)?';
|
||
|
||
re.src_port =
|
||
|
||
'(?::(?:6(?:[0-4]\\d{3}|5(?:[0-4]\\d{2}|5(?:[0-2]\\d|3[0-5])))|[1-5]?\\d{1,4}))?';
|
||
|
||
re.src_host_terminator =
|
||
|
||
'(?=$|' + text_separators + '|' + re.src_ZPCc + ')' +
|
||
'(?!' + (opts['---'] ? '-(?!--)|' : '-|') + '_|:\\d|\\.-|\\.(?!$|' + re.src_ZPCc + '))';
|
||
|
||
re.src_path =
|
||
|
||
'(?:' +
|
||
'[/?#]' +
|
||
'(?:' +
|
||
'(?!' + re.src_ZCc + '|' + text_separators + '|[()[\\]{}.,"\'?!\\-;]).|' +
|
||
'\\[(?:(?!' + re.src_ZCc + '|\\]).)*\\]|' +
|
||
'\\((?:(?!' + re.src_ZCc + '|[)]).)*\\)|' +
|
||
'\\{(?:(?!' + re.src_ZCc + '|[}]).)*\\}|' +
|
||
'\\"(?:(?!' + re.src_ZCc + '|["]).)+\\"|' +
|
||
"\\'(?:(?!" + re.src_ZCc + "|[']).)+\\'|" +
|
||
|
||
// allow `I'm_king` if no pair found
|
||
"\\'(?=" + re.src_pseudo_letter + '|[-])|' +
|
||
|
||
// google has many dots in "google search" links (#66, #81).
|
||
// github has ... in commit range links,
|
||
// Restrict to
|
||
// - english
|
||
// - percent-encoded
|
||
// - parts of file path
|
||
// - params separator
|
||
// until more examples found.
|
||
'\\.{2,}[a-zA-Z0-9%/&]|' +
|
||
|
||
'\\.(?!' + re.src_ZCc + '|[.]|$)|' +
|
||
(opts['---']
|
||
? '\\-(?!--(?:[^-]|$))(?:-*)|' // `---` => long dash, terminate
|
||
: '\\-+|'
|
||
) +
|
||
// allow `,,,` in paths
|
||
',(?!' + re.src_ZCc + '|$)|' +
|
||
|
||
// allow `;` if not followed by space-like char
|
||
';(?!' + re.src_ZCc + '|$)|' +
|
||
|
||
// allow `!!!` in paths, but not at the end
|
||
'\\!+(?!' + re.src_ZCc + '|[!]|$)|' +
|
||
|
||
'\\?(?!' + re.src_ZCc + '|[?]|$)' +
|
||
')+' +
|
||
'|\\/' +
|
||
')?';
|
||
|
||
// Allow anything in markdown spec, forbid quote (") at the first position
|
||
// because emails enclosed in quotes are far more common
|
||
re.src_email_name =
|
||
|
||
'[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]*';
|
||
|
||
re.src_xn =
|
||
|
||
'xn--[a-z0-9\\-]{1,59}';
|
||
|
||
// More to read about domain names
|
||
// http://serverfault.com/questions/638260/
|
||
|
||
re.src_domain_root =
|
||
|
||
// Allow letters & digits (http://test1)
|
||
'(?:' +
|
||
re.src_xn +
|
||
'|' +
|
||
re.src_pseudo_letter + '{1,63}' +
|
||
')';
|
||
|
||
re.src_domain =
|
||
|
||
'(?:' +
|
||
re.src_xn +
|
||
'|' +
|
||
'(?:' + re.src_pseudo_letter + ')' +
|
||
'|' +
|
||
'(?:' + re.src_pseudo_letter + '(?:-|' + re.src_pseudo_letter + '){0,61}' + re.src_pseudo_letter + ')' +
|
||
')';
|
||
|
||
re.src_host =
|
||
|
||
'(?:' +
|
||
// Don't need IP check, because digits are already allowed in normal domain names
|
||
// src_ip4 +
|
||
// '|' +
|
||
'(?:(?:(?:' + re.src_domain + ')\\.)*' + re.src_domain/* _root */ + ')' +
|
||
')';
|
||
|
||
re.tpl_host_fuzzy =
|
||
|
||
'(?:' +
|
||
re.src_ip4 +
|
||
'|' +
|
||
'(?:(?:(?:' + re.src_domain + ')\\.)+(?:%TLDS%))' +
|
||
')';
|
||
|
||
re.tpl_host_no_ip_fuzzy =
|
||
|
||
'(?:(?:(?:' + re.src_domain + ')\\.)+(?:%TLDS%))';
|
||
|
||
re.src_host_strict =
|
||
|
||
re.src_host + re.src_host_terminator;
|
||
|
||
re.tpl_host_fuzzy_strict =
|
||
|
||
re.tpl_host_fuzzy + re.src_host_terminator;
|
||
|
||
re.src_host_port_strict =
|
||
|
||
re.src_host + re.src_port + re.src_host_terminator;
|
||
|
||
re.tpl_host_port_fuzzy_strict =
|
||
|
||
re.tpl_host_fuzzy + re.src_port + re.src_host_terminator;
|
||
|
||
re.tpl_host_port_no_ip_fuzzy_strict =
|
||
|
||
re.tpl_host_no_ip_fuzzy + re.src_port + re.src_host_terminator;
|
||
|
||
//
|
||
// Main rules
|
||
//
|
||
|
||
// Rude test fuzzy links by host, for quick deny
|
||
re.tpl_host_fuzzy_test =
|
||
|
||
'localhost|www\\.|\\.\\d{1,3}\\.|(?:\\.(?:%TLDS%)(?:' + re.src_ZPCc + '|>|$))';
|
||
|
||
re.tpl_email_fuzzy =
|
||
|
||
'(^|' + text_separators + '|"|\\(|' + re.src_ZCc + ')' +
|
||
'(' + re.src_email_name + '@' + re.tpl_host_fuzzy_strict + ')';
|
||
|
||
re.tpl_link_fuzzy =
|
||
// Fuzzy link can't be prepended with .:/\- and non punctuation.
|
||
// but can start with > (markdown blockquote)
|
||
'(^|(?![.:/\\-_@])(?:[$+<=>^`|\uff5c]|' + re.src_ZPCc + '))' +
|
||
'((?![$+<=>^`|\uff5c])' + re.tpl_host_port_fuzzy_strict + re.src_path + ')';
|
||
|
||
re.tpl_link_no_ip_fuzzy =
|
||
// Fuzzy link can't be prepended with .:/\- and non punctuation.
|
||
// but can start with > (markdown blockquote)
|
||
'(^|(?![.:/\\-_@])(?:[$+<=>^`|\uff5c]|' + re.src_ZPCc + '))' +
|
||
'((?![$+<=>^`|\uff5c])' + re.tpl_host_port_no_ip_fuzzy_strict + re.src_path + ')';
|
||
|
||
return re
|
||
}
|
||
|
||
//
|
||
// Helpers
|
||
//
|
||
|
||
// Merge objects
|
||
//
|
||
function assign (obj /* from1, from2, from3, ... */) {
|
||
const sources = Array.prototype.slice.call(arguments, 1);
|
||
|
||
sources.forEach(function (source) {
|
||
if (!source) { return }
|
||
|
||
Object.keys(source).forEach(function (key) {
|
||
obj[key] = source[key];
|
||
});
|
||
});
|
||
|
||
return obj
|
||
}
|
||
|
||
function _class (obj) { return Object.prototype.toString.call(obj) }
|
||
function isString (obj) { return _class(obj) === '[object String]' }
|
||
function isObject (obj) { return _class(obj) === '[object Object]' }
|
||
function isRegExp (obj) { return _class(obj) === '[object RegExp]' }
|
||
function isFunction (obj) { return _class(obj) === '[object Function]' }
|
||
|
||
function escapeRE (str) { return str.replace(/[.?*+^$[\]\\(){}|-]/g, '\\$&') }
|
||
|
||
//
|
||
|
||
const defaultOptions$1 = {
|
||
fuzzyLink: true,
|
||
fuzzyEmail: true,
|
||
fuzzyIP: false
|
||
};
|
||
|
||
function isOptionsObj (obj) {
|
||
return Object.keys(obj || {}).reduce(function (acc, k) {
|
||
/* eslint-disable-next-line no-prototype-builtins */
|
||
return acc || defaultOptions$1.hasOwnProperty(k)
|
||
}, false)
|
||
}
|
||
|
||
const defaultSchemas = {
|
||
'http:': {
|
||
validate: function (text, pos, self) {
|
||
const tail = text.slice(pos);
|
||
|
||
if (!self.re.http) {
|
||
// compile lazily, because "host"-containing variables can change on tlds update.
|
||
self.re.http = new RegExp(
|
||
'^\\/\\/' + self.re.src_auth + self.re.src_host_port_strict + self.re.src_path, 'i'
|
||
);
|
||
}
|
||
if (self.re.http.test(tail)) {
|
||
return tail.match(self.re.http)[0].length
|
||
}
|
||
return 0
|
||
}
|
||
},
|
||
'https:': 'http:',
|
||
'ftp:': 'http:',
|
||
'//': {
|
||
validate: function (text, pos, self) {
|
||
const tail = text.slice(pos);
|
||
|
||
if (!self.re.no_http) {
|
||
// compile lazily, because "host"-containing variables can change on tlds update.
|
||
self.re.no_http = new RegExp(
|
||
'^' +
|
||
self.re.src_auth +
|
||
// Don't allow single-level domains, because of false positives like '//test'
|
||
// with code comments
|
||
'(?:localhost|(?:(?:' + self.re.src_domain + ')\\.)+' + self.re.src_domain_root + ')' +
|
||
self.re.src_port +
|
||
self.re.src_host_terminator +
|
||
self.re.src_path,
|
||
|
||
'i'
|
||
);
|
||
}
|
||
|
||
if (self.re.no_http.test(tail)) {
|
||
// should not be `://` & `///`, that protects from errors in protocol name
|
||
if (pos >= 3 && text[pos - 3] === ':') { return 0 }
|
||
if (pos >= 3 && text[pos - 3] === '/') { return 0 }
|
||
return tail.match(self.re.no_http)[0].length
|
||
}
|
||
return 0
|
||
}
|
||
},
|
||
'mailto:': {
|
||
validate: function (text, pos, self) {
|
||
const tail = text.slice(pos);
|
||
|
||
if (!self.re.mailto) {
|
||
self.re.mailto = new RegExp(
|
||
'^' + self.re.src_email_name + '@' + self.re.src_host_strict, 'i'
|
||
);
|
||
}
|
||
if (self.re.mailto.test(tail)) {
|
||
return tail.match(self.re.mailto)[0].length
|
||
}
|
||
return 0
|
||
}
|
||
}
|
||
};
|
||
|
||
// RE pattern for 2-character tlds (autogenerated by ./support/tlds_2char_gen.js)
|
||
/* eslint-disable-next-line max-len */
|
||
const tlds_2ch_src_re = 'a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]';
|
||
|
||
// DON'T try to make PRs with changes. Extend TLDs with LinkifyIt.tlds() instead
|
||
const tlds_default = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'.split('|');
|
||
|
||
function resetScanCache (self) {
|
||
self.__index__ = -1;
|
||
self.__text_cache__ = '';
|
||
}
|
||
|
||
function createValidator (re) {
|
||
return function (text, pos) {
|
||
const tail = text.slice(pos);
|
||
|
||
if (re.test(tail)) {
|
||
return tail.match(re)[0].length
|
||
}
|
||
return 0
|
||
}
|
||
}
|
||
|
||
function createNormalizer () {
|
||
return function (match, self) {
|
||
self.normalize(match);
|
||
}
|
||
}
|
||
|
||
// Schemas compiler. Build regexps.
|
||
//
|
||
function compile (self) {
|
||
// Load & clone RE patterns.
|
||
const re = self.re = reFactory(self.__opts__);
|
||
|
||
// Define dynamic patterns
|
||
const tlds = self.__tlds__.slice();
|
||
|
||
self.onCompile();
|
||
|
||
if (!self.__tlds_replaced__) {
|
||
tlds.push(tlds_2ch_src_re);
|
||
}
|
||
tlds.push(re.src_xn);
|
||
|
||
re.src_tlds = tlds.join('|');
|
||
|
||
function untpl (tpl) { return tpl.replace('%TLDS%', re.src_tlds) }
|
||
|
||
re.email_fuzzy = RegExp(untpl(re.tpl_email_fuzzy), 'i');
|
||
re.link_fuzzy = RegExp(untpl(re.tpl_link_fuzzy), 'i');
|
||
re.link_no_ip_fuzzy = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'i');
|
||
re.host_fuzzy_test = RegExp(untpl(re.tpl_host_fuzzy_test), 'i');
|
||
|
||
//
|
||
// Compile each schema
|
||
//
|
||
|
||
const aliases = [];
|
||
|
||
self.__compiled__ = {}; // Reset compiled data
|
||
|
||
function schemaError (name, val) {
|
||
throw new Error('(LinkifyIt) Invalid schema "' + name + '": ' + val)
|
||
}
|
||
|
||
Object.keys(self.__schemas__).forEach(function (name) {
|
||
const val = self.__schemas__[name];
|
||
|
||
// skip disabled methods
|
||
if (val === null) { return }
|
||
|
||
const compiled = { validate: null, link: null };
|
||
|
||
self.__compiled__[name] = compiled;
|
||
|
||
if (isObject(val)) {
|
||
if (isRegExp(val.validate)) {
|
||
compiled.validate = createValidator(val.validate);
|
||
} else if (isFunction(val.validate)) {
|
||
compiled.validate = val.validate;
|
||
} else {
|
||
schemaError(name, val);
|
||
}
|
||
|
||
if (isFunction(val.normalize)) {
|
||
compiled.normalize = val.normalize;
|
||
} else if (!val.normalize) {
|
||
compiled.normalize = createNormalizer();
|
||
} else {
|
||
schemaError(name, val);
|
||
}
|
||
|
||
return
|
||
}
|
||
|
||
if (isString(val)) {
|
||
aliases.push(name);
|
||
return
|
||
}
|
||
|
||
schemaError(name, val);
|
||
});
|
||
|
||
//
|
||
// Compile postponed aliases
|
||
//
|
||
|
||
aliases.forEach(function (alias) {
|
||
if (!self.__compiled__[self.__schemas__[alias]]) {
|
||
// Silently fail on missed schemas to avoid errons on disable.
|
||
// schemaError(alias, self.__schemas__[alias]);
|
||
return
|
||
}
|
||
|
||
self.__compiled__[alias].validate =
|
||
self.__compiled__[self.__schemas__[alias]].validate;
|
||
self.__compiled__[alias].normalize =
|
||
self.__compiled__[self.__schemas__[alias]].normalize;
|
||
});
|
||
|
||
//
|
||
// Fake record for guessed links
|
||
//
|
||
self.__compiled__[''] = { validate: null, normalize: createNormalizer() };
|
||
|
||
//
|
||
// Build schema condition
|
||
//
|
||
const slist = Object.keys(self.__compiled__)
|
||
.filter(function (name) {
|
||
// Filter disabled & fake schemas
|
||
return name.length > 0 && self.__compiled__[name]
|
||
})
|
||
.map(escapeRE)
|
||
.join('|');
|
||
// (?!_) cause 1.5x slowdown
|
||
self.re.schema_test = RegExp('(^|(?!_)(?:[><\uff5c]|' + re.src_ZPCc + '))(' + slist + ')', 'i');
|
||
self.re.schema_search = RegExp('(^|(?!_)(?:[><\uff5c]|' + re.src_ZPCc + '))(' + slist + ')', 'ig');
|
||
self.re.schema_at_start = RegExp('^' + self.re.schema_search.source, 'i');
|
||
|
||
self.re.pretest = RegExp(
|
||
'(' + self.re.schema_test.source + ')|(' + self.re.host_fuzzy_test.source + ')|@',
|
||
'i'
|
||
);
|
||
|
||
//
|
||
// Cleanup
|
||
//
|
||
|
||
resetScanCache(self);
|
||
}
|
||
|
||
/**
|
||
* class Match
|
||
*
|
||
* Match result. Single element of array, returned by [[LinkifyIt#match]]
|
||
**/
|
||
function Match (self, shift) {
|
||
const start = self.__index__;
|
||
const end = self.__last_index__;
|
||
const text = self.__text_cache__.slice(start, end);
|
||
|
||
/**
|
||
* Match#schema -> String
|
||
*
|
||
* Prefix (protocol) for matched string.
|
||
**/
|
||
this.schema = self.__schema__.toLowerCase();
|
||
/**
|
||
* Match#index -> Number
|
||
*
|
||
* First position of matched string.
|
||
**/
|
||
this.index = start + shift;
|
||
/**
|
||
* Match#lastIndex -> Number
|
||
*
|
||
* Next position after matched string.
|
||
**/
|
||
this.lastIndex = end + shift;
|
||
/**
|
||
* Match#raw -> String
|
||
*
|
||
* Matched string.
|
||
**/
|
||
this.raw = text;
|
||
/**
|
||
* Match#text -> String
|
||
*
|
||
* Notmalized text of matched string.
|
||
**/
|
||
this.text = text;
|
||
/**
|
||
* Match#url -> String
|
||
*
|
||
* Normalized url of matched string.
|
||
**/
|
||
this.url = text;
|
||
}
|
||
|
||
function createMatch (self, shift) {
|
||
const match = new Match(self, shift);
|
||
|
||
self.__compiled__[match.schema].normalize(match, self);
|
||
|
||
return match
|
||
}
|
||
|
||
/**
|
||
* class LinkifyIt
|
||
**/
|
||
|
||
/**
|
||
* new LinkifyIt(schemas, options)
|
||
* - schemas (Object): Optional. Additional schemas to validate (prefix/validator)
|
||
* - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false }
|
||
*
|
||
* Creates new linkifier instance with optional additional schemas.
|
||
* Can be called without `new` keyword for convenience.
|
||
*
|
||
* By default understands:
|
||
*
|
||
* - `http(s)://...` , `ftp://...`, `mailto:...` & `//...` links
|
||
* - "fuzzy" links and emails (example.com, foo@bar.com).
|
||
*
|
||
* `schemas` is an object, where each key/value describes protocol/rule:
|
||
*
|
||
* - __key__ - link prefix (usually, protocol name with `:` at the end, `skype:`
|
||
* for example). `linkify-it` makes shure that prefix is not preceeded with
|
||
* alphanumeric char and symbols. Only whitespaces and punctuation allowed.
|
||
* - __value__ - rule to check tail after link prefix
|
||
* - _String_ - just alias to existing rule
|
||
* - _Object_
|
||
* - _validate_ - validator function (should return matched length on success),
|
||
* or `RegExp`.
|
||
* - _normalize_ - optional function to normalize text & url of matched result
|
||
* (for example, for @twitter mentions).
|
||
*
|
||
* `options`:
|
||
*
|
||
* - __fuzzyLink__ - recognige URL-s without `http(s):` prefix. Default `true`.
|
||
* - __fuzzyIP__ - allow IPs in fuzzy links above. Can conflict with some texts
|
||
* like version numbers. Default `false`.
|
||
* - __fuzzyEmail__ - recognize emails without `mailto:` prefix.
|
||
*
|
||
**/
|
||
function LinkifyIt (schemas, options) {
|
||
if (!(this instanceof LinkifyIt)) {
|
||
return new LinkifyIt(schemas, options)
|
||
}
|
||
|
||
if (!options) {
|
||
if (isOptionsObj(schemas)) {
|
||
options = schemas;
|
||
schemas = {};
|
||
}
|
||
}
|
||
|
||
this.__opts__ = assign({}, defaultOptions$1, options);
|
||
|
||
// Cache last tested result. Used to skip repeating steps on next `match` call.
|
||
this.__index__ = -1;
|
||
this.__last_index__ = -1; // Next scan position
|
||
this.__schema__ = '';
|
||
this.__text_cache__ = '';
|
||
|
||
this.__schemas__ = assign({}, defaultSchemas, schemas);
|
||
this.__compiled__ = {};
|
||
|
||
this.__tlds__ = tlds_default;
|
||
this.__tlds_replaced__ = false;
|
||
|
||
this.re = {};
|
||
|
||
compile(this);
|
||
}
|
||
|
||
/** chainable
|
||
* LinkifyIt#add(schema, definition)
|
||
* - schema (String): rule name (fixed pattern prefix)
|
||
* - definition (String|RegExp|Object): schema definition
|
||
*
|
||
* Add new rule definition. See constructor description for details.
|
||
**/
|
||
LinkifyIt.prototype.add = function add (schema, definition) {
|
||
this.__schemas__[schema] = definition;
|
||
compile(this);
|
||
return this
|
||
};
|
||
|
||
/** chainable
|
||
* LinkifyIt#set(options)
|
||
* - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false }
|
||
*
|
||
* Set recognition options for links without schema.
|
||
**/
|
||
LinkifyIt.prototype.set = function set (options) {
|
||
this.__opts__ = assign(this.__opts__, options);
|
||
return this
|
||
};
|
||
|
||
/**
|
||
* LinkifyIt#test(text) -> Boolean
|
||
*
|
||
* Searches linkifiable pattern and returns `true` on success or `false` on fail.
|
||
**/
|
||
LinkifyIt.prototype.test = function test (text) {
|
||
// Reset scan cache
|
||
this.__text_cache__ = text;
|
||
this.__index__ = -1;
|
||
|
||
if (!text.length) { return false }
|
||
|
||
let m, ml, me, len, shift, next, re, tld_pos, at_pos;
|
||
|
||
// try to scan for link with schema - that's the most simple rule
|
||
if (this.re.schema_test.test(text)) {
|
||
re = this.re.schema_search;
|
||
re.lastIndex = 0;
|
||
while ((m = re.exec(text)) !== null) {
|
||
len = this.testSchemaAt(text, m[2], re.lastIndex);
|
||
if (len) {
|
||
this.__schema__ = m[2];
|
||
this.__index__ = m.index + m[1].length;
|
||
this.__last_index__ = m.index + m[0].length + len;
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
if (this.__opts__.fuzzyLink && this.__compiled__['http:']) {
|
||
// guess schemaless links
|
||
tld_pos = text.search(this.re.host_fuzzy_test);
|
||
if (tld_pos >= 0) {
|
||
// if tld is located after found link - no need to check fuzzy pattern
|
||
if (this.__index__ < 0 || tld_pos < this.__index__) {
|
||
if ((ml = text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy)) !== null) {
|
||
shift = ml.index + ml[1].length;
|
||
|
||
if (this.__index__ < 0 || shift < this.__index__) {
|
||
this.__schema__ = '';
|
||
this.__index__ = shift;
|
||
this.__last_index__ = ml.index + ml[0].length;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) {
|
||
// guess schemaless emails
|
||
at_pos = text.indexOf('@');
|
||
if (at_pos >= 0) {
|
||
// We can't skip this check, because this cases are possible:
|
||
// 192.168.1.1@gmail.com, my.in@example.com
|
||
if ((me = text.match(this.re.email_fuzzy)) !== null) {
|
||
shift = me.index + me[1].length;
|
||
next = me.index + me[0].length;
|
||
|
||
if (this.__index__ < 0 || shift < this.__index__ ||
|
||
(shift === this.__index__ && next > this.__last_index__)) {
|
||
this.__schema__ = 'mailto:';
|
||
this.__index__ = shift;
|
||
this.__last_index__ = next;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return this.__index__ >= 0
|
||
};
|
||
|
||
/**
|
||
* LinkifyIt#pretest(text) -> Boolean
|
||
*
|
||
* Very quick check, that can give false positives. Returns true if link MAY BE
|
||
* can exists. Can be used for speed optimization, when you need to check that
|
||
* link NOT exists.
|
||
**/
|
||
LinkifyIt.prototype.pretest = function pretest (text) {
|
||
return this.re.pretest.test(text)
|
||
};
|
||
|
||
/**
|
||
* LinkifyIt#testSchemaAt(text, name, position) -> Number
|
||
* - text (String): text to scan
|
||
* - name (String): rule (schema) name
|
||
* - position (Number): text offset to check from
|
||
*
|
||
* Similar to [[LinkifyIt#test]] but checks only specific protocol tail exactly
|
||
* at given position. Returns length of found pattern (0 on fail).
|
||
**/
|
||
LinkifyIt.prototype.testSchemaAt = function testSchemaAt (text, schema, pos) {
|
||
// If not supported schema check requested - terminate
|
||
if (!this.__compiled__[schema.toLowerCase()]) {
|
||
return 0
|
||
}
|
||
return this.__compiled__[schema.toLowerCase()].validate(text, pos, this)
|
||
};
|
||
|
||
/**
|
||
* LinkifyIt#match(text) -> Array|null
|
||
*
|
||
* Returns array of found link descriptions or `null` on fail. We strongly
|
||
* recommend to use [[LinkifyIt#test]] first, for best speed.
|
||
*
|
||
* ##### Result match description
|
||
*
|
||
* - __schema__ - link schema, can be empty for fuzzy links, or `//` for
|
||
* protocol-neutral links.
|
||
* - __index__ - offset of matched text
|
||
* - __lastIndex__ - index of next char after mathch end
|
||
* - __raw__ - matched text
|
||
* - __text__ - normalized text
|
||
* - __url__ - link, generated from matched text
|
||
**/
|
||
LinkifyIt.prototype.match = function match (text) {
|
||
const result = [];
|
||
let shift = 0;
|
||
|
||
// Try to take previous element from cache, if .test() called before
|
||
if (this.__index__ >= 0 && this.__text_cache__ === text) {
|
||
result.push(createMatch(this, shift));
|
||
shift = this.__last_index__;
|
||
}
|
||
|
||
// Cut head if cache was used
|
||
let tail = shift ? text.slice(shift) : text;
|
||
|
||
// Scan string until end reached
|
||
while (this.test(tail)) {
|
||
result.push(createMatch(this, shift));
|
||
|
||
tail = tail.slice(this.__last_index__);
|
||
shift += this.__last_index__;
|
||
}
|
||
|
||
if (result.length) {
|
||
return result
|
||
}
|
||
|
||
return null
|
||
};
|
||
|
||
/**
|
||
* LinkifyIt#matchAtStart(text) -> Match|null
|
||
*
|
||
* Returns fully-formed (not fuzzy) link if it starts at the beginning
|
||
* of the string, and null otherwise.
|
||
**/
|
||
LinkifyIt.prototype.matchAtStart = function matchAtStart (text) {
|
||
// Reset scan cache
|
||
this.__text_cache__ = text;
|
||
this.__index__ = -1;
|
||
|
||
if (!text.length) return null
|
||
|
||
const m = this.re.schema_at_start.exec(text);
|
||
if (!m) return null
|
||
|
||
const len = this.testSchemaAt(text, m[2], m[0].length);
|
||
if (!len) return null
|
||
|
||
this.__schema__ = m[2];
|
||
this.__index__ = m.index + m[1].length;
|
||
this.__last_index__ = m.index + m[0].length + len;
|
||
|
||
return createMatch(this, 0)
|
||
};
|
||
|
||
/** chainable
|
||
* LinkifyIt#tlds(list [, keepOld]) -> this
|
||
* - list (Array): list of tlds
|
||
* - keepOld (Boolean): merge with current list if `true` (`false` by default)
|
||
*
|
||
* Load (or merge) new tlds list. Those are user for fuzzy links (without prefix)
|
||
* to avoid false positives. By default this algorythm used:
|
||
*
|
||
* - hostname with any 2-letter root zones are ok.
|
||
* - biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф
|
||
* are ok.
|
||
* - encoded (`xn--...`) root zones are ok.
|
||
*
|
||
* If list is replaced, then exact match for 2-chars root zones will be checked.
|
||
**/
|
||
LinkifyIt.prototype.tlds = function tlds (list, keepOld) {
|
||
list = Array.isArray(list) ? list : [list];
|
||
|
||
if (!keepOld) {
|
||
this.__tlds__ = list.slice();
|
||
this.__tlds_replaced__ = true;
|
||
compile(this);
|
||
return this
|
||
}
|
||
|
||
this.__tlds__ = this.__tlds__.concat(list)
|
||
.sort()
|
||
.filter(function (el, idx, arr) {
|
||
return el !== arr[idx - 1]
|
||
})
|
||
.reverse();
|
||
|
||
compile(this);
|
||
return this
|
||
};
|
||
|
||
/**
|
||
* LinkifyIt#normalize(match)
|
||
*
|
||
* Default normalizer (if schema does not define it's own).
|
||
**/
|
||
LinkifyIt.prototype.normalize = function normalize (match) {
|
||
// Do minimal possible changes by default. Need to collect feedback prior
|
||
// to move forward https://github.com/markdown-it/linkify-it/issues/1
|
||
|
||
if (!match.schema) { match.url = 'http://' + match.url; }
|
||
|
||
if (match.schema === 'mailto:' && !/^mailto:/i.test(match.url)) {
|
||
match.url = 'mailto:' + match.url;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* LinkifyIt#onCompile()
|
||
*
|
||
* Override to modify basic RegExp-s.
|
||
**/
|
||
LinkifyIt.prototype.onCompile = function onCompile () {
|
||
};
|
||
|
||
/** Highest positive signed 32-bit float value */
|
||
const maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1
|
||
|
||
/** Bootstring parameters */
|
||
const base = 36;
|
||
const tMin = 1;
|
||
const tMax = 26;
|
||
const skew = 38;
|
||
const damp = 700;
|
||
const initialBias = 72;
|
||
const initialN = 128; // 0x80
|
||
const delimiter = '-'; // '\x2D'
|
||
|
||
/** Regular expressions */
|
||
const regexPunycode = /^xn--/;
|
||
const regexNonASCII = /[^\0-\x7F]/; // Note: U+007F DEL is excluded too.
|
||
const regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g; // RFC 3490 separators
|
||
|
||
/** Error messages */
|
||
const errors$1 = {
|
||
'overflow': 'Overflow: input needs wider integers to process',
|
||
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
|
||
'invalid-input': 'Invalid input'
|
||
};
|
||
|
||
/** Convenience shortcuts */
|
||
const baseMinusTMin = base - tMin;
|
||
const floor = Math.floor;
|
||
const stringFromCharCode = String.fromCharCode;
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* A generic error utility function.
|
||
* @private
|
||
* @param {String} type The error type.
|
||
* @returns {Error} Throws a `RangeError` with the applicable error message.
|
||
*/
|
||
function error(type) {
|
||
throw new RangeError(errors$1[type]);
|
||
}
|
||
|
||
/**
|
||
* A generic `Array#map` utility function.
|
||
* @private
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} callback The function that gets called for every array
|
||
* item.
|
||
* @returns {Array} A new array of values returned by the callback function.
|
||
*/
|
||
function map$1(array, callback) {
|
||
const result = [];
|
||
let length = array.length;
|
||
while (length--) {
|
||
result[length] = callback(array[length]);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* A simple `Array#map`-like wrapper to work with domain name strings or email
|
||
* addresses.
|
||
* @private
|
||
* @param {String} domain The domain name or email address.
|
||
* @param {Function} callback The function that gets called for every
|
||
* character.
|
||
* @returns {String} A new string of characters returned by the callback
|
||
* function.
|
||
*/
|
||
function mapDomain(domain, callback) {
|
||
const parts = domain.split('@');
|
||
let result = '';
|
||
if (parts.length > 1) {
|
||
// In email addresses, only the domain name should be punycoded. Leave
|
||
// the local part (i.e. everything up to `@`) intact.
|
||
result = parts[0] + '@';
|
||
domain = parts[1];
|
||
}
|
||
// Avoid `split(regex)` for IE8 compatibility. See #17.
|
||
domain = domain.replace(regexSeparators, '\x2E');
|
||
const labels = domain.split('.');
|
||
const encoded = map$1(labels, callback).join('.');
|
||
return result + encoded;
|
||
}
|
||
|
||
/**
|
||
* Creates an array containing the numeric code points of each Unicode
|
||
* character in the string. While JavaScript uses UCS-2 internally,
|
||
* this function will convert a pair of surrogate halves (each of which
|
||
* UCS-2 exposes as separate characters) into a single code point,
|
||
* matching UTF-16.
|
||
* @see `punycode.ucs2.encode`
|
||
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
||
* @memberOf punycode.ucs2
|
||
* @name decode
|
||
* @param {String} string The Unicode input string (UCS-2).
|
||
* @returns {Array} The new array of code points.
|
||
*/
|
||
function ucs2decode(string) {
|
||
const output = [];
|
||
let counter = 0;
|
||
const length = string.length;
|
||
while (counter < length) {
|
||
const value = string.charCodeAt(counter++);
|
||
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
|
||
// It's a high surrogate, and there is a next character.
|
||
const extra = string.charCodeAt(counter++);
|
||
if ((extra & 0xFC00) == 0xDC00) { // Low surrogate.
|
||
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
|
||
} else {
|
||
// It's an unmatched surrogate; only append this code unit, in case the
|
||
// next code unit is the high surrogate of a surrogate pair.
|
||
output.push(value);
|
||
counter--;
|
||
}
|
||
} else {
|
||
output.push(value);
|
||
}
|
||
}
|
||
return output;
|
||
}
|
||
|
||
/**
|
||
* Creates a string based on an array of numeric code points.
|
||
* @see `punycode.ucs2.decode`
|
||
* @memberOf punycode.ucs2
|
||
* @name encode
|
||
* @param {Array} codePoints The array of numeric code points.
|
||
* @returns {String} The new Unicode string (UCS-2).
|
||
*/
|
||
const ucs2encode = codePoints => String.fromCodePoint(...codePoints);
|
||
|
||
/**
|
||
* Converts a basic code point into a digit/integer.
|
||
* @see `digitToBasic()`
|
||
* @private
|
||
* @param {Number} codePoint The basic numeric code point value.
|
||
* @returns {Number} The numeric value of a basic code point (for use in
|
||
* representing integers) in the range `0` to `base - 1`, or `base` if
|
||
* the code point does not represent a value.
|
||
*/
|
||
const basicToDigit = function(codePoint) {
|
||
if (codePoint >= 0x30 && codePoint < 0x3A) {
|
||
return 26 + (codePoint - 0x30);
|
||
}
|
||
if (codePoint >= 0x41 && codePoint < 0x5B) {
|
||
return codePoint - 0x41;
|
||
}
|
||
if (codePoint >= 0x61 && codePoint < 0x7B) {
|
||
return codePoint - 0x61;
|
||
}
|
||
return base;
|
||
};
|
||
|
||
/**
|
||
* Converts a digit/integer into a basic code point.
|
||
* @see `basicToDigit()`
|
||
* @private
|
||
* @param {Number} digit The numeric value of a basic code point.
|
||
* @returns {Number} The basic code point whose value (when used for
|
||
* representing integers) is `digit`, which needs to be in the range
|
||
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
|
||
* used; else, the lowercase form is used. The behavior is undefined
|
||
* if `flag` is non-zero and `digit` has no uppercase form.
|
||
*/
|
||
const digitToBasic = function(digit, flag) {
|
||
// 0..25 map to ASCII a..z or A..Z
|
||
// 26..35 map to ASCII 0..9
|
||
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
|
||
};
|
||
|
||
/**
|
||
* Bias adaptation function as per section 3.4 of RFC 3492.
|
||
* https://tools.ietf.org/html/rfc3492#section-3.4
|
||
* @private
|
||
*/
|
||
const adapt = function(delta, numPoints, firstTime) {
|
||
let k = 0;
|
||
delta = firstTime ? floor(delta / damp) : delta >> 1;
|
||
delta += floor(delta / numPoints);
|
||
for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
|
||
delta = floor(delta / baseMinusTMin);
|
||
}
|
||
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
|
||
};
|
||
|
||
/**
|
||
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
|
||
* symbols.
|
||
* @memberOf punycode
|
||
* @param {String} input The Punycode string of ASCII-only symbols.
|
||
* @returns {String} The resulting string of Unicode symbols.
|
||
*/
|
||
const decode = function(input) {
|
||
// Don't use UCS-2.
|
||
const output = [];
|
||
const inputLength = input.length;
|
||
let i = 0;
|
||
let n = initialN;
|
||
let bias = initialBias;
|
||
|
||
// Handle the basic code points: let `basic` be the number of input code
|
||
// points before the last delimiter, or `0` if there is none, then copy
|
||
// the first basic code points to the output.
|
||
|
||
let basic = input.lastIndexOf(delimiter);
|
||
if (basic < 0) {
|
||
basic = 0;
|
||
}
|
||
|
||
for (let j = 0; j < basic; ++j) {
|
||
// if it's not a basic code point
|
||
if (input.charCodeAt(j) >= 0x80) {
|
||
error('not-basic');
|
||
}
|
||
output.push(input.charCodeAt(j));
|
||
}
|
||
|
||
// Main decoding loop: start just after the last delimiter if any basic code
|
||
// points were copied; start at the beginning otherwise.
|
||
|
||
for (let index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
|
||
|
||
// `index` is the index of the next character to be consumed.
|
||
// Decode a generalized variable-length integer into `delta`,
|
||
// which gets added to `i`. The overflow checking is easier
|
||
// if we increase `i` as we go, then subtract off its starting
|
||
// value at the end to obtain `delta`.
|
||
const oldi = i;
|
||
for (let w = 1, k = base; /* no condition */; k += base) {
|
||
|
||
if (index >= inputLength) {
|
||
error('invalid-input');
|
||
}
|
||
|
||
const digit = basicToDigit(input.charCodeAt(index++));
|
||
|
||
if (digit >= base) {
|
||
error('invalid-input');
|
||
}
|
||
if (digit > floor((maxInt - i) / w)) {
|
||
error('overflow');
|
||
}
|
||
|
||
i += digit * w;
|
||
const t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
|
||
|
||
if (digit < t) {
|
||
break;
|
||
}
|
||
|
||
const baseMinusT = base - t;
|
||
if (w > floor(maxInt / baseMinusT)) {
|
||
error('overflow');
|
||
}
|
||
|
||
w *= baseMinusT;
|
||
|
||
}
|
||
|
||
const out = output.length + 1;
|
||
bias = adapt(i - oldi, out, oldi == 0);
|
||
|
||
// `i` was supposed to wrap around from `out` to `0`,
|
||
// incrementing `n` each time, so we'll fix that now:
|
||
if (floor(i / out) > maxInt - n) {
|
||
error('overflow');
|
||
}
|
||
|
||
n += floor(i / out);
|
||
i %= out;
|
||
|
||
// Insert `n` at position `i` of the output.
|
||
output.splice(i++, 0, n);
|
||
|
||
}
|
||
|
||
return String.fromCodePoint(...output);
|
||
};
|
||
|
||
/**
|
||
* Converts a string of Unicode symbols (e.g. a domain name label) to a
|
||
* Punycode string of ASCII-only symbols.
|
||
* @memberOf punycode
|
||
* @param {String} input The string of Unicode symbols.
|
||
* @returns {String} The resulting Punycode string of ASCII-only symbols.
|
||
*/
|
||
const encode = function(input) {
|
||
const output = [];
|
||
|
||
// Convert the input in UCS-2 to an array of Unicode code points.
|
||
input = ucs2decode(input);
|
||
|
||
// Cache the length.
|
||
const inputLength = input.length;
|
||
|
||
// Initialize the state.
|
||
let n = initialN;
|
||
let delta = 0;
|
||
let bias = initialBias;
|
||
|
||
// Handle the basic code points.
|
||
for (const currentValue of input) {
|
||
if (currentValue < 0x80) {
|
||
output.push(stringFromCharCode(currentValue));
|
||
}
|
||
}
|
||
|
||
const basicLength = output.length;
|
||
let handledCPCount = basicLength;
|
||
|
||
// `handledCPCount` is the number of code points that have been handled;
|
||
// `basicLength` is the number of basic code points.
|
||
|
||
// Finish the basic string with a delimiter unless it's empty.
|
||
if (basicLength) {
|
||
output.push(delimiter);
|
||
}
|
||
|
||
// Main encoding loop:
|
||
while (handledCPCount < inputLength) {
|
||
|
||
// All non-basic code points < n have been handled already. Find the next
|
||
// larger one:
|
||
let m = maxInt;
|
||
for (const currentValue of input) {
|
||
if (currentValue >= n && currentValue < m) {
|
||
m = currentValue;
|
||
}
|
||
}
|
||
|
||
// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
|
||
// but guard against overflow.
|
||
const handledCPCountPlusOne = handledCPCount + 1;
|
||
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
|
||
error('overflow');
|
||
}
|
||
|
||
delta += (m - n) * handledCPCountPlusOne;
|
||
n = m;
|
||
|
||
for (const currentValue of input) {
|
||
if (currentValue < n && ++delta > maxInt) {
|
||
error('overflow');
|
||
}
|
||
if (currentValue === n) {
|
||
// Represent delta as a generalized variable-length integer.
|
||
let q = delta;
|
||
for (let k = base; /* no condition */; k += base) {
|
||
const t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
|
||
if (q < t) {
|
||
break;
|
||
}
|
||
const qMinusT = q - t;
|
||
const baseMinusT = base - t;
|
||
output.push(
|
||
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
|
||
);
|
||
q = floor(qMinusT / baseMinusT);
|
||
}
|
||
|
||
output.push(stringFromCharCode(digitToBasic(q, 0)));
|
||
bias = adapt(delta, handledCPCountPlusOne, handledCPCount === basicLength);
|
||
delta = 0;
|
||
++handledCPCount;
|
||
}
|
||
}
|
||
|
||
++delta;
|
||
++n;
|
||
|
||
}
|
||
return output.join('');
|
||
};
|
||
|
||
/**
|
||
* Converts a Punycode string representing a domain name or an email address
|
||
* to Unicode. Only the Punycoded parts of the input will be converted, i.e.
|
||
* it doesn't matter if you call it on a string that has already been
|
||
* converted to Unicode.
|
||
* @memberOf punycode
|
||
* @param {String} input The Punycoded domain name or email address to
|
||
* convert to Unicode.
|
||
* @returns {String} The Unicode representation of the given Punycode
|
||
* string.
|
||
*/
|
||
const toUnicode = function(input) {
|
||
return mapDomain(input, function(string) {
|
||
return regexPunycode.test(string)
|
||
? decode(string.slice(4).toLowerCase())
|
||
: string;
|
||
});
|
||
};
|
||
|
||
/**
|
||
* Converts a Unicode string representing a domain name or an email address to
|
||
* Punycode. Only the non-ASCII parts of the domain name will be converted,
|
||
* i.e. it doesn't matter if you call it with a domain that's already in
|
||
* ASCII.
|
||
* @memberOf punycode
|
||
* @param {String} input The domain name or email address to convert, as a
|
||
* Unicode string.
|
||
* @returns {String} The Punycode representation of the given domain name or
|
||
* email address.
|
||
*/
|
||
const toASCII = function(input) {
|
||
return mapDomain(input, function(string) {
|
||
return regexNonASCII.test(string)
|
||
? 'xn--' + encode(string)
|
||
: string;
|
||
});
|
||
};
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
/** Define the public API */
|
||
const punycode = {
|
||
/**
|
||
* A string representing the current Punycode.js version number.
|
||
* @memberOf punycode
|
||
* @type String
|
||
*/
|
||
'version': '2.3.1',
|
||
/**
|
||
* An object of methods to convert from JavaScript's internal character
|
||
* representation (UCS-2) to Unicode code points, and back.
|
||
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
||
* @memberOf punycode
|
||
* @type Object
|
||
*/
|
||
'ucs2': {
|
||
'decode': ucs2decode,
|
||
'encode': ucs2encode
|
||
},
|
||
'decode': decode,
|
||
'encode': encode,
|
||
'toASCII': toASCII,
|
||
'toUnicode': toUnicode
|
||
};
|
||
|
||
// markdown-it default options
|
||
|
||
var cfg_default = {
|
||
options: {
|
||
// Enable HTML tags in source
|
||
html: false,
|
||
|
||
// Use '/' to close single tags (<br />)
|
||
xhtmlOut: false,
|
||
|
||
// Convert '\n' in paragraphs into <br>
|
||
breaks: false,
|
||
|
||
// CSS language prefix for fenced blocks
|
||
langPrefix: 'language-',
|
||
|
||
// autoconvert URL-like texts to links
|
||
linkify: false,
|
||
|
||
// Enable some language-neutral replacements + quotes beautification
|
||
typographer: false,
|
||
|
||
// Double + single quotes replacement pairs, when typographer enabled,
|
||
// and smartquotes on. Could be either a String or an Array.
|
||
//
|
||
// For example, you can use '«»„“' for Russian, '„“‚‘' for German,
|
||
// and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp).
|
||
quotes: '\u201c\u201d\u2018\u2019', /* “”‘’ */
|
||
|
||
// Highlighter function. Should return escaped HTML,
|
||
// or '' if the source string is not changed and should be escaped externaly.
|
||
// If result starts with <pre... internal wrapper is skipped.
|
||
//
|
||
// function (/*str, lang*/) { return ''; }
|
||
//
|
||
highlight: null,
|
||
|
||
// Internal protection, recursion limit
|
||
maxNesting: 100
|
||
},
|
||
|
||
components: {
|
||
core: {},
|
||
block: {},
|
||
inline: {}
|
||
}
|
||
};
|
||
|
||
// "Zero" preset, with nothing enabled. Useful for manual configuring of simple
|
||
// modes. For example, to parse bold/italic only.
|
||
|
||
var cfg_zero = {
|
||
options: {
|
||
// Enable HTML tags in source
|
||
html: false,
|
||
|
||
// Use '/' to close single tags (<br />)
|
||
xhtmlOut: false,
|
||
|
||
// Convert '\n' in paragraphs into <br>
|
||
breaks: false,
|
||
|
||
// CSS language prefix for fenced blocks
|
||
langPrefix: 'language-',
|
||
|
||
// autoconvert URL-like texts to links
|
||
linkify: false,
|
||
|
||
// Enable some language-neutral replacements + quotes beautification
|
||
typographer: false,
|
||
|
||
// Double + single quotes replacement pairs, when typographer enabled,
|
||
// and smartquotes on. Could be either a String or an Array.
|
||
//
|
||
// For example, you can use '«»„“' for Russian, '„“‚‘' for German,
|
||
// and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp).
|
||
quotes: '\u201c\u201d\u2018\u2019', /* “”‘’ */
|
||
|
||
// Highlighter function. Should return escaped HTML,
|
||
// or '' if the source string is not changed and should be escaped externaly.
|
||
// If result starts with <pre... internal wrapper is skipped.
|
||
//
|
||
// function (/*str, lang*/) { return ''; }
|
||
//
|
||
highlight: null,
|
||
|
||
// Internal protection, recursion limit
|
||
maxNesting: 20
|
||
},
|
||
|
||
components: {
|
||
|
||
core: {
|
||
rules: [
|
||
'normalize',
|
||
'block',
|
||
'inline',
|
||
'text_join'
|
||
]
|
||
},
|
||
|
||
block: {
|
||
rules: [
|
||
'paragraph'
|
||
]
|
||
},
|
||
|
||
inline: {
|
||
rules: [
|
||
'text'
|
||
],
|
||
rules2: [
|
||
'balance_pairs',
|
||
'fragments_join'
|
||
]
|
||
}
|
||
}
|
||
};
|
||
|
||
// Commonmark default options
|
||
|
||
var cfg_commonmark = {
|
||
options: {
|
||
// Enable HTML tags in source
|
||
html: true,
|
||
|
||
// Use '/' to close single tags (<br />)
|
||
xhtmlOut: true,
|
||
|
||
// Convert '\n' in paragraphs into <br>
|
||
breaks: false,
|
||
|
||
// CSS language prefix for fenced blocks
|
||
langPrefix: 'language-',
|
||
|
||
// autoconvert URL-like texts to links
|
||
linkify: false,
|
||
|
||
// Enable some language-neutral replacements + quotes beautification
|
||
typographer: false,
|
||
|
||
// Double + single quotes replacement pairs, when typographer enabled,
|
||
// and smartquotes on. Could be either a String or an Array.
|
||
//
|
||
// For example, you can use '«»„“' for Russian, '„“‚‘' for German,
|
||
// and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp).
|
||
quotes: '\u201c\u201d\u2018\u2019', /* “”‘’ */
|
||
|
||
// Highlighter function. Should return escaped HTML,
|
||
// or '' if the source string is not changed and should be escaped externaly.
|
||
// If result starts with <pre... internal wrapper is skipped.
|
||
//
|
||
// function (/*str, lang*/) { return ''; }
|
||
//
|
||
highlight: null,
|
||
|
||
// Internal protection, recursion limit
|
||
maxNesting: 20
|
||
},
|
||
|
||
components: {
|
||
|
||
core: {
|
||
rules: [
|
||
'normalize',
|
||
'block',
|
||
'inline',
|
||
'text_join'
|
||
]
|
||
},
|
||
|
||
block: {
|
||
rules: [
|
||
'blockquote',
|
||
'code',
|
||
'fence',
|
||
'heading',
|
||
'hr',
|
||
'html_block',
|
||
'lheading',
|
||
'list',
|
||
'reference',
|
||
'paragraph'
|
||
]
|
||
},
|
||
|
||
inline: {
|
||
rules: [
|
||
'autolink',
|
||
'backticks',
|
||
'emphasis',
|
||
'entity',
|
||
'escape',
|
||
'html_inline',
|
||
'image',
|
||
'link',
|
||
'newline',
|
||
'text'
|
||
],
|
||
rules2: [
|
||
'balance_pairs',
|
||
'emphasis',
|
||
'fragments_join'
|
||
]
|
||
}
|
||
}
|
||
};
|
||
|
||
// Main parser class
|
||
|
||
|
||
const config = {
|
||
default: cfg_default,
|
||
zero: cfg_zero,
|
||
commonmark: cfg_commonmark
|
||
};
|
||
|
||
//
|
||
// This validator can prohibit more than really needed to prevent XSS. It's a
|
||
// tradeoff to keep code simple and to be secure by default.
|
||
//
|
||
// If you need different setup - override validator method as you wish. Or
|
||
// replace it with dummy function and use external sanitizer.
|
||
//
|
||
|
||
const BAD_PROTO_RE = /^(vbscript|javascript|file|data):/;
|
||
const GOOD_DATA_RE = /^data:image\/(gif|png|jpeg|webp);/;
|
||
|
||
function validateLink (url) {
|
||
// url should be normalized at this point, and existing entities are decoded
|
||
const str = url.trim().toLowerCase();
|
||
|
||
return BAD_PROTO_RE.test(str) ? GOOD_DATA_RE.test(str) : true
|
||
}
|
||
|
||
const RECODE_HOSTNAME_FOR = ['http:', 'https:', 'mailto:'];
|
||
|
||
function normalizeLink (url) {
|
||
const parsed = urlParse(url, true);
|
||
|
||
if (parsed.hostname) {
|
||
// Encode hostnames in urls like:
|
||
// `http://host/`, `https://host/`, `mailto:user@host`, `//host/`
|
||
//
|
||
// We don't encode unknown schemas, because it's likely that we encode
|
||
// something we shouldn't (e.g. `skype:name` treated as `skype:host`)
|
||
//
|
||
if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) {
|
||
try {
|
||
parsed.hostname = punycode.toASCII(parsed.hostname);
|
||
} catch (er) { /**/ }
|
||
}
|
||
}
|
||
|
||
return encode$1(format$1(parsed))
|
||
}
|
||
|
||
function normalizeLinkText (url) {
|
||
const parsed = urlParse(url, true);
|
||
|
||
if (parsed.hostname) {
|
||
// Encode hostnames in urls like:
|
||
// `http://host/`, `https://host/`, `mailto:user@host`, `//host/`
|
||
//
|
||
// We don't encode unknown schemas, because it's likely that we encode
|
||
// something we shouldn't (e.g. `skype:name` treated as `skype:host`)
|
||
//
|
||
if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) {
|
||
try {
|
||
parsed.hostname = punycode.toUnicode(parsed.hostname);
|
||
} catch (er) { /**/ }
|
||
}
|
||
}
|
||
|
||
// add '%' to exclude list because of https://github.com/markdown-it/markdown-it/issues/720
|
||
return decode$1(format$1(parsed), decode$1.defaultChars + '%')
|
||
}
|
||
|
||
/**
|
||
* class MarkdownIt
|
||
*
|
||
* Main parser/renderer class.
|
||
*
|
||
* ##### Usage
|
||
*
|
||
* ```javascript
|
||
* // node.js, "classic" way:
|
||
* var MarkdownIt = require('markdown-it'),
|
||
* md = new MarkdownIt();
|
||
* var result = md.render('# markdown-it rulezz!');
|
||
*
|
||
* // node.js, the same, but with sugar:
|
||
* var md = require('markdown-it')();
|
||
* var result = md.render('# markdown-it rulezz!');
|
||
*
|
||
* // browser without AMD, added to "window" on script load
|
||
* // Note, there are no dash.
|
||
* var md = window.markdownit();
|
||
* var result = md.render('# markdown-it rulezz!');
|
||
* ```
|
||
*
|
||
* Single line rendering, without paragraph wrap:
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
* var result = md.renderInline('__markdown-it__ rulezz!');
|
||
* ```
|
||
**/
|
||
|
||
/**
|
||
* new MarkdownIt([presetName, options])
|
||
* - presetName (String): optional, `commonmark` / `zero`
|
||
* - options (Object)
|
||
*
|
||
* Creates parser instanse with given config. Can be called without `new`.
|
||
*
|
||
* ##### presetName
|
||
*
|
||
* MarkdownIt provides named presets as a convenience to quickly
|
||
* enable/disable active syntax rules and options for common use cases.
|
||
*
|
||
* - ["commonmark"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/commonmark.js) -
|
||
* configures parser to strict [CommonMark](http://commonmark.org/) mode.
|
||
* - [default](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/default.js) -
|
||
* similar to GFM, used when no preset name given. Enables all available rules,
|
||
* but still without html, typographer & autolinker.
|
||
* - ["zero"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/zero.js) -
|
||
* all rules disabled. Useful to quickly setup your config via `.enable()`.
|
||
* For example, when you need only `bold` and `italic` markup and nothing else.
|
||
*
|
||
* ##### options:
|
||
*
|
||
* - __html__ - `false`. Set `true` to enable HTML tags in source. Be careful!
|
||
* That's not safe! You may need external sanitizer to protect output from XSS.
|
||
* It's better to extend features via plugins, instead of enabling HTML.
|
||
* - __xhtmlOut__ - `false`. Set `true` to add '/' when closing single tags
|
||
* (`<br />`). This is needed only for full CommonMark compatibility. In real
|
||
* world you will need HTML output.
|
||
* - __breaks__ - `false`. Set `true` to convert `\n` in paragraphs into `<br>`.
|
||
* - __langPrefix__ - `language-`. CSS language class prefix for fenced blocks.
|
||
* Can be useful for external highlighters.
|
||
* - __linkify__ - `false`. Set `true` to autoconvert URL-like text to links.
|
||
* - __typographer__ - `false`. Set `true` to enable [some language-neutral
|
||
* replacement](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.js) +
|
||
* quotes beautification (smartquotes).
|
||
* - __quotes__ - `“”‘’`, String or Array. Double + single quotes replacement
|
||
* pairs, when typographer enabled and smartquotes on. For example, you can
|
||
* use `'«»„“'` for Russian, `'„“‚‘'` for German, and
|
||
* `['«\xA0', '\xA0»', '‹\xA0', '\xA0›']` for French (including nbsp).
|
||
* - __highlight__ - `null`. Highlighter function for fenced code blocks.
|
||
* Highlighter `function (str, lang)` should return escaped HTML. It can also
|
||
* return empty string if the source was not changed and should be escaped
|
||
* externaly. If result starts with <pre... internal wrapper is skipped.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* // commonmark mode
|
||
* var md = require('markdown-it')('commonmark');
|
||
*
|
||
* // default mode
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* // enable everything
|
||
* var md = require('markdown-it')({
|
||
* html: true,
|
||
* linkify: true,
|
||
* typographer: true
|
||
* });
|
||
* ```
|
||
*
|
||
* ##### Syntax highlighting
|
||
*
|
||
* ```js
|
||
* var hljs = require('highlight.js') // https://highlightjs.org/
|
||
*
|
||
* var md = require('markdown-it')({
|
||
* highlight: function (str, lang) {
|
||
* if (lang && hljs.getLanguage(lang)) {
|
||
* try {
|
||
* return hljs.highlight(str, { language: lang, ignoreIllegals: true }).value;
|
||
* } catch (__) {}
|
||
* }
|
||
*
|
||
* return ''; // use external default escaping
|
||
* }
|
||
* });
|
||
* ```
|
||
*
|
||
* Or with full wrapper override (if you need assign class to `<pre>` or `<code>`):
|
||
*
|
||
* ```javascript
|
||
* var hljs = require('highlight.js') // https://highlightjs.org/
|
||
*
|
||
* // Actual default values
|
||
* var md = require('markdown-it')({
|
||
* highlight: function (str, lang) {
|
||
* if (lang && hljs.getLanguage(lang)) {
|
||
* try {
|
||
* return '<pre><code class="hljs">' +
|
||
* hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
|
||
* '</code></pre>';
|
||
* } catch (__) {}
|
||
* }
|
||
*
|
||
* return '<pre><code class="hljs">' + md.utils.escapeHtml(str) + '</code></pre>';
|
||
* }
|
||
* });
|
||
* ```
|
||
*
|
||
**/
|
||
function MarkdownIt (presetName, options) {
|
||
if (!(this instanceof MarkdownIt)) {
|
||
return new MarkdownIt(presetName, options)
|
||
}
|
||
|
||
if (!options) {
|
||
if (!isString$1(presetName)) {
|
||
options = presetName || {};
|
||
presetName = 'default';
|
||
}
|
||
}
|
||
|
||
/**
|
||
* MarkdownIt#inline -> ParserInline
|
||
*
|
||
* Instance of [[ParserInline]]. You may need it to add new rules when
|
||
* writing plugins. For simple rules control use [[MarkdownIt.disable]] and
|
||
* [[MarkdownIt.enable]].
|
||
**/
|
||
this.inline = new ParserInline();
|
||
|
||
/**
|
||
* MarkdownIt#block -> ParserBlock
|
||
*
|
||
* Instance of [[ParserBlock]]. You may need it to add new rules when
|
||
* writing plugins. For simple rules control use [[MarkdownIt.disable]] and
|
||
* [[MarkdownIt.enable]].
|
||
**/
|
||
this.block = new ParserBlock();
|
||
|
||
/**
|
||
* MarkdownIt#core -> Core
|
||
*
|
||
* Instance of [[Core]] chain executor. You may need it to add new rules when
|
||
* writing plugins. For simple rules control use [[MarkdownIt.disable]] and
|
||
* [[MarkdownIt.enable]].
|
||
**/
|
||
this.core = new Core();
|
||
|
||
/**
|
||
* MarkdownIt#renderer -> Renderer
|
||
*
|
||
* Instance of [[Renderer]]. Use it to modify output look. Or to add rendering
|
||
* rules for new token types, generated by plugins.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* function myToken(tokens, idx, options, env, self) {
|
||
* //...
|
||
* return result;
|
||
* };
|
||
*
|
||
* md.renderer.rules['my_token'] = myToken
|
||
* ```
|
||
*
|
||
* See [[Renderer]] docs and [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js).
|
||
**/
|
||
this.renderer = new Renderer();
|
||
|
||
/**
|
||
* MarkdownIt#linkify -> LinkifyIt
|
||
*
|
||
* [linkify-it](https://github.com/markdown-it/linkify-it) instance.
|
||
* Used by [linkify](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/linkify.js)
|
||
* rule.
|
||
**/
|
||
this.linkify = new LinkifyIt();
|
||
|
||
/**
|
||
* MarkdownIt#validateLink(url) -> Boolean
|
||
*
|
||
* Link validation function. CommonMark allows too much in links. By default
|
||
* we disable `javascript:`, `vbscript:`, `file:` schemas, and almost all `data:...` schemas
|
||
* except some embedded image types.
|
||
*
|
||
* You can change this behaviour:
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
* // enable everything
|
||
* md.validateLink = function () { return true; }
|
||
* ```
|
||
**/
|
||
this.validateLink = validateLink;
|
||
|
||
/**
|
||
* MarkdownIt#normalizeLink(url) -> String
|
||
*
|
||
* Function used to encode link url to a machine-readable format,
|
||
* which includes url-encoding, punycode, etc.
|
||
**/
|
||
this.normalizeLink = normalizeLink;
|
||
|
||
/**
|
||
* MarkdownIt#normalizeLinkText(url) -> String
|
||
*
|
||
* Function used to decode link url to a human-readable format`
|
||
**/
|
||
this.normalizeLinkText = normalizeLinkText;
|
||
|
||
// Expose utils & helpers for easy acces from plugins
|
||
|
||
/**
|
||
* MarkdownIt#utils -> utils
|
||
*
|
||
* Assorted utility functions, useful to write plugins. See details
|
||
* [here](https://github.com/markdown-it/markdown-it/blob/master/lib/common/utils.mjs).
|
||
**/
|
||
this.utils = utils$3;
|
||
|
||
/**
|
||
* MarkdownIt#helpers -> helpers
|
||
*
|
||
* Link components parser functions, useful to write plugins. See details
|
||
* [here](https://github.com/markdown-it/markdown-it/blob/master/lib/helpers).
|
||
**/
|
||
this.helpers = assign$1({}, helpers);
|
||
|
||
this.options = {};
|
||
this.configure(presetName);
|
||
|
||
if (options) { this.set(options); }
|
||
}
|
||
|
||
/** chainable
|
||
* MarkdownIt.set(options)
|
||
*
|
||
* Set parser options (in the same format as in constructor). Probably, you
|
||
* will never need it, but you can change options after constructor call.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')()
|
||
* .set({ html: true, breaks: true })
|
||
* .set({ typographer, true });
|
||
* ```
|
||
*
|
||
* __Note:__ To achieve the best possible performance, don't modify a
|
||
* `markdown-it` instance options on the fly. If you need multiple configurations
|
||
* it's best to create multiple instances and initialize each with separate
|
||
* config.
|
||
**/
|
||
MarkdownIt.prototype.set = function (options) {
|
||
assign$1(this.options, options);
|
||
return this
|
||
};
|
||
|
||
/** chainable, internal
|
||
* MarkdownIt.configure(presets)
|
||
*
|
||
* Batch load of all options and compenent settings. This is internal method,
|
||
* and you probably will not need it. But if you will - see available presets
|
||
* and data structure [here](https://github.com/markdown-it/markdown-it/tree/master/lib/presets)
|
||
*
|
||
* We strongly recommend to use presets instead of direct config loads. That
|
||
* will give better compatibility with next versions.
|
||
**/
|
||
MarkdownIt.prototype.configure = function (presets) {
|
||
const self = this;
|
||
|
||
if (isString$1(presets)) {
|
||
const presetName = presets;
|
||
presets = config[presetName];
|
||
if (!presets) { throw new Error('Wrong `markdown-it` preset "' + presetName + '", check name') }
|
||
}
|
||
|
||
if (!presets) { throw new Error('Wrong `markdown-it` preset, can\'t be empty') }
|
||
|
||
if (presets.options) { self.set(presets.options); }
|
||
|
||
if (presets.components) {
|
||
Object.keys(presets.components).forEach(function (name) {
|
||
if (presets.components[name].rules) {
|
||
self[name].ruler.enableOnly(presets.components[name].rules);
|
||
}
|
||
if (presets.components[name].rules2) {
|
||
self[name].ruler2.enableOnly(presets.components[name].rules2);
|
||
}
|
||
});
|
||
}
|
||
return this
|
||
};
|
||
|
||
/** chainable
|
||
* MarkdownIt.enable(list, ignoreInvalid)
|
||
* - list (String|Array): rule name or list of rule names to enable
|
||
* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
|
||
*
|
||
* Enable list or rules. It will automatically find appropriate components,
|
||
* containing rules with given names. If rule not found, and `ignoreInvalid`
|
||
* not set - throws exception.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')()
|
||
* .enable(['sub', 'sup'])
|
||
* .disable('smartquotes');
|
||
* ```
|
||
**/
|
||
MarkdownIt.prototype.enable = function (list, ignoreInvalid) {
|
||
let result = [];
|
||
|
||
if (!Array.isArray(list)) { list = [list]; }
|
||
|
||
['core', 'block', 'inline'].forEach(function (chain) {
|
||
result = result.concat(this[chain].ruler.enable(list, true));
|
||
}, this);
|
||
|
||
result = result.concat(this.inline.ruler2.enable(list, true));
|
||
|
||
const missed = list.filter(function (name) { return result.indexOf(name) < 0 });
|
||
|
||
if (missed.length && !ignoreInvalid) {
|
||
throw new Error('MarkdownIt. Failed to enable unknown rule(s): ' + missed)
|
||
}
|
||
|
||
return this
|
||
};
|
||
|
||
/** chainable
|
||
* MarkdownIt.disable(list, ignoreInvalid)
|
||
* - list (String|Array): rule name or list of rule names to disable.
|
||
* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
|
||
*
|
||
* The same as [[MarkdownIt.enable]], but turn specified rules off.
|
||
**/
|
||
MarkdownIt.prototype.disable = function (list, ignoreInvalid) {
|
||
let result = [];
|
||
|
||
if (!Array.isArray(list)) { list = [list]; }
|
||
|
||
['core', 'block', 'inline'].forEach(function (chain) {
|
||
result = result.concat(this[chain].ruler.disable(list, true));
|
||
}, this);
|
||
|
||
result = result.concat(this.inline.ruler2.disable(list, true));
|
||
|
||
const missed = list.filter(function (name) { return result.indexOf(name) < 0 });
|
||
|
||
if (missed.length && !ignoreInvalid) {
|
||
throw new Error('MarkdownIt. Failed to disable unknown rule(s): ' + missed)
|
||
}
|
||
return this
|
||
};
|
||
|
||
/** chainable
|
||
* MarkdownIt.use(plugin, params)
|
||
*
|
||
* Load specified plugin with given params into current parser instance.
|
||
* It's just a sugar to call `plugin(md, params)` with curring.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var iterator = require('markdown-it-for-inline');
|
||
* var md = require('markdown-it')()
|
||
* .use(iterator, 'foo_replace', 'text', function (tokens, idx) {
|
||
* tokens[idx].content = tokens[idx].content.replace(/foo/g, 'bar');
|
||
* });
|
||
* ```
|
||
**/
|
||
MarkdownIt.prototype.use = function (plugin /*, params, ... */) {
|
||
const args = [this].concat(Array.prototype.slice.call(arguments, 1));
|
||
plugin.apply(plugin, args);
|
||
return this
|
||
};
|
||
|
||
/** internal
|
||
* MarkdownIt.parse(src, env) -> Array
|
||
* - src (String): source string
|
||
* - env (Object): environment sandbox
|
||
*
|
||
* Parse input string and return list of block tokens (special token type
|
||
* "inline" will contain list of inline tokens). You should not call this
|
||
* method directly, until you write custom renderer (for example, to produce
|
||
* AST).
|
||
*
|
||
* `env` is used to pass data between "distributed" rules and return additional
|
||
* metadata like reference info, needed for the renderer. It also can be used to
|
||
* inject data in specific cases. Usually, you will be ok to pass `{}`,
|
||
* and then pass updated object to renderer.
|
||
**/
|
||
MarkdownIt.prototype.parse = function (src, env) {
|
||
if (typeof src !== 'string') {
|
||
throw new Error('Input data should be a String')
|
||
}
|
||
|
||
const state = new this.core.State(src, this, env);
|
||
|
||
this.core.process(state);
|
||
|
||
return state.tokens
|
||
};
|
||
|
||
/**
|
||
* MarkdownIt.render(src [, env]) -> String
|
||
* - src (String): source string
|
||
* - env (Object): environment sandbox
|
||
*
|
||
* Render markdown string into html. It does all magic for you :).
|
||
*
|
||
* `env` can be used to inject additional metadata (`{}` by default).
|
||
* But you will not need it with high probability. See also comment
|
||
* in [[MarkdownIt.parse]].
|
||
**/
|
||
MarkdownIt.prototype.render = function (src, env) {
|
||
env = env || {};
|
||
|
||
return this.renderer.render(this.parse(src, env), this.options, env)
|
||
};
|
||
|
||
/** internal
|
||
* MarkdownIt.parseInline(src, env) -> Array
|
||
* - src (String): source string
|
||
* - env (Object): environment sandbox
|
||
*
|
||
* The same as [[MarkdownIt.parse]] but skip all block rules. It returns the
|
||
* block tokens list with the single `inline` element, containing parsed inline
|
||
* tokens in `children` property. Also updates `env` object.
|
||
**/
|
||
MarkdownIt.prototype.parseInline = function (src, env) {
|
||
const state = new this.core.State(src, this, env);
|
||
|
||
state.inlineMode = true;
|
||
this.core.process(state);
|
||
|
||
return state.tokens
|
||
};
|
||
|
||
/**
|
||
* MarkdownIt.renderInline(src [, env]) -> String
|
||
* - src (String): source string
|
||
* - env (Object): environment sandbox
|
||
*
|
||
* Similar to [[MarkdownIt.render]] but for single paragraph content. Result
|
||
* will NOT be wrapped into `<p>` tags.
|
||
**/
|
||
MarkdownIt.prototype.renderInline = function (src, env) {
|
||
env = env || {};
|
||
|
||
return this.renderer.render(this.parseInline(src, env), this.options, env)
|
||
};
|
||
|
||
var e=!1,n={false:"push",true:"unshift",after:"push",before:"unshift"},t={isPermalinkSymbol:!0};function r$1(r,a,i,l){var o;if(!e){var c="Using deprecated markdown-it-anchor permalink option, see https://github.com/valeriangalliat/markdown-it-anchor#permalinks";"object"==typeof process&&process&&process.emitWarning?process.emitWarning(c):console.warn(c),e=!0;}var s=[Object.assign(new i.Token("link_open","a",1),{attrs:[].concat(a.permalinkClass?[["class",a.permalinkClass]]:[],[["href",a.permalinkHref(r,i)]],Object.entries(a.permalinkAttrs(r,i)))}),Object.assign(new i.Token("html_block","",0),{content:a.permalinkSymbol,meta:t}),new i.Token("link_close","a",-1)];a.permalinkSpace&&i.tokens[l+1].children[n[a.permalinkBefore]](Object.assign(new i.Token("text","",0),{content:" "})),(o=i.tokens[l+1].children)[n[a.permalinkBefore]].apply(o,s);}function a$1(e){return "#"+e}function i(e){return {}}var l={class:"header-anchor",symbol:"#",renderHref:a$1,renderAttrs:i};function o$1(e){function n(t){return t=Object.assign({},n.defaults,t),function(n,r,a,i){return e(n,t,r,a,i)}}return n.defaults=Object.assign({},l),n.renderPermalinkImpl=e,n}var c$1=o$1(function(e,r,a,i,l){var o,c=[Object.assign(new i.Token("link_open","a",1),{attrs:[].concat(r.class?[["class",r.class]]:[],[["href",r.renderHref(e,i)]],r.ariaHidden?[["aria-hidden","true"]]:[],Object.entries(r.renderAttrs(e,i)))}),Object.assign(new i.Token("html_inline","",0),{content:r.symbol,meta:t}),new i.Token("link_close","a",-1)];if(r.space){var s="string"==typeof r.space?r.space:" ";i.tokens[l+1].children[n[r.placement]](Object.assign(new i.Token("string"==typeof r.space?"html_inline":"text","",0),{content:s}));}(o=i.tokens[l+1].children)[n[r.placement]].apply(o,c);});Object.assign(c$1.defaults,{space:!0,placement:"after",ariaHidden:!1});var s=o$1(c$1.renderPermalinkImpl);s.defaults=Object.assign({},c$1.defaults,{ariaHidden:!0});var u=o$1(function(e,n,t,r,a){var i=[Object.assign(new r.Token("link_open","a",1),{attrs:[].concat(n.class?[["class",n.class]]:[],[["href",n.renderHref(e,r)]],Object.entries(n.renderAttrs(e,r)))})].concat(n.safariReaderFix?[new r.Token("span_open","span",1)]:[],r.tokens[a+1].children,n.safariReaderFix?[new r.Token("span_close","span",-1)]:[],[new r.Token("link_close","a",-1)]);r.tokens[a+1]=Object.assign(new r.Token("inline","",0),{children:i});});Object.assign(u.defaults,{safariReaderFix:!1});var d$1=o$1(function(e,r,a,i,l){var o;if(!["visually-hidden","aria-label","aria-describedby","aria-labelledby"].includes(r.style))throw new Error("`permalink.linkAfterHeader` called with unknown style option `"+r.style+"`");if(!["aria-describedby","aria-labelledby"].includes(r.style)&&!r.assistiveText)throw new Error("`permalink.linkAfterHeader` called without the `assistiveText` option in `"+r.style+"` style");if("visually-hidden"===r.style&&!r.visuallyHiddenClass)throw new Error("`permalink.linkAfterHeader` called without the `visuallyHiddenClass` option in `visually-hidden` style");var c=i.tokens[l+1].children.filter(function(e){return "text"===e.type||"code_inline"===e.type}).reduce(function(e,n){return e+n.content},""),s=[],u=[];if(r.class&&u.push(["class",r.class]),u.push(["href",r.renderHref(e,i)]),u.push.apply(u,Object.entries(r.renderAttrs(e,i))),"visually-hidden"===r.style){if(s.push(Object.assign(new i.Token("span_open","span",1),{attrs:[["class",r.visuallyHiddenClass]]}),Object.assign(new i.Token("text","",0),{content:r.assistiveText(c)}),new i.Token("span_close","span",-1)),r.space){var d="string"==typeof r.space?r.space:" ";s[n[r.placement]](Object.assign(new i.Token("string"==typeof r.space?"html_inline":"text","",0),{content:d}));}s[n[r.placement]](Object.assign(new i.Token("span_open","span",1),{attrs:[["aria-hidden","true"]]}),Object.assign(new i.Token("html_inline","",0),{content:r.symbol,meta:t}),new i.Token("span_close","span",-1));}else s.push(Object.assign(new i.Token("html_inline","",0),{content:r.symbol,meta:t}));"aria-label"===r.style?u.push(["aria-label",r.assistiveText(c)]):["aria-describedby","aria-labelledby"].includes(r.style)&&u.push([r.style,e]);var f=[Object.assign(new i.Token("link_open","a",1),{attrs:u})].concat(s,[new i.Token("link_close","a",-1)]);(o=i.tokens).splice.apply(o,[l+3,0].concat(f)),r.wrapper&&(i.tokens.splice(l,0,Object.assign(new i.Token("html_block","",0),{content:r.wrapper[0]+"\n"})),i.tokens.splice(l+3+f.length+1,0,Object.assign(new i.Token("html_block","",0),{content:r.wrapper[1]+"\n"})));});function f(e,n,t,r){var a=e,i=r;if(t&&Object.prototype.hasOwnProperty.call(n,a))throw new Error("User defined `id` attribute `"+e+"` is not unique. Please fix it in your Markdown to continue.");for(;Object.prototype.hasOwnProperty.call(n,a);)a=e+"-"+i,i+=1;return n[a]=!0,a}function p$1(e,n){n=Object.assign({},p$1.defaults,n),e.core.ruler.push("anchor",function(e){for(var t,a={},i=e.tokens,l=Array.isArray(n.level)?(t=n.level,function(e){return t.includes(e)}):function(e){return function(n){return n>=e}}(n.level),o=0;o<i.length;o++){var c=i[o];if("heading_open"===c.type&&l(Number(c.tag.substr(1)))){var s=n.getTokensText(i[o+1].children),u=c.attrGet("id");u=null==u?f(n.slugify(s),a,!1,n.uniqueSlugStartIndex):f(u,a,!0,n.uniqueSlugStartIndex),c.attrSet("id",u),!1!==n.tabIndex&&c.attrSet("tabindex",""+n.tabIndex),"function"==typeof n.permalink?n.permalink(u,n,e,o):(n.permalink||n.renderPermalink&&n.renderPermalink!==r$1)&&n.renderPermalink(u,n,e,o),o=i.indexOf(c),n.callback&&n.callback(c,{slug:u,title:s});}}});}Object.assign(d$1.defaults,{style:"visually-hidden",space:!0,placement:"after",wrapper:null}),p$1.permalink={__proto__:null,legacy:r$1,renderHref:a$1,renderAttrs:i,makePermalink:o$1,linkInsideHeader:c$1,ariaHidden:s,headerLink:u,linkAfterHeader:d$1},p$1.defaults={level:1,slugify:function(e){return encodeURIComponent(String(e).trim().toLowerCase().replace(/\s+/g,"-"))},uniqueSlugStartIndex:1,tabIndex:"-1",getTokensText:function(e){return e.filter(function(e){return ["text","code_inline"].includes(e.type)}).map(function(e){return e.content}).join("")},permalink:!1,renderPermalink:r$1,permalinkClass:s.defaults.class,permalinkSpace:s.defaults.space,permalinkSymbol:"¶",permalinkBefore:"before"===s.defaults.placement,permalinkHref:s.defaults.renderHref,permalinkAttrs:s.defaults.renderAttrs},p$1.default=p$1;
|
||
|
||
var utils$2 = {};
|
||
|
||
/**
|
||
* parse {.class #id key=val} strings
|
||
* @param {string} str: string to parse
|
||
* @param {int} start: where to start parsing (including {)
|
||
* @returns {2d array}: [['key', 'val'], ['class', 'red']]
|
||
*/
|
||
|
||
utils$2.getAttrs = function (str, start, options) {
|
||
// not tab, line feed, form feed, space, solidus, greater than sign, quotation mark, apostrophe and equals sign
|
||
const allowedKeyChars = /[^\t\n\f />"'=]/;
|
||
const pairSeparator = ' ';
|
||
const keySeparator = '=';
|
||
const classChar = '.';
|
||
const idChar = '#';
|
||
|
||
const attrs = [];
|
||
let key = '';
|
||
let value = '';
|
||
let parsingKey = true;
|
||
let valueInsideQuotes = false;
|
||
|
||
// read inside {}
|
||
// start + left delimiter length to avoid beginning {
|
||
// breaks when } is found or end of string
|
||
for (let i = start + options.leftDelimiter.length; i < str.length; i++) {
|
||
if (str.slice(i, i + options.rightDelimiter.length) === options.rightDelimiter) {
|
||
if (key !== '') { attrs.push([key, value]); }
|
||
break;
|
||
}
|
||
const char_ = str.charAt(i);
|
||
|
||
// switch to reading value if equal sign
|
||
if (char_ === keySeparator && parsingKey) {
|
||
parsingKey = false;
|
||
continue;
|
||
}
|
||
|
||
// {.class} {..css-module}
|
||
if (char_ === classChar && key === '') {
|
||
if (str.charAt(i + 1) === classChar) {
|
||
key = 'css-module';
|
||
i += 1;
|
||
} else {
|
||
key = 'class';
|
||
}
|
||
parsingKey = false;
|
||
continue;
|
||
}
|
||
|
||
// {#id}
|
||
if (char_ === idChar && key === '') {
|
||
key = 'id';
|
||
parsingKey = false;
|
||
continue;
|
||
}
|
||
|
||
// {value="inside quotes"}
|
||
if (char_ === '"' && value === '' && !valueInsideQuotes) {
|
||
valueInsideQuotes = true;
|
||
continue;
|
||
}
|
||
if (char_ === '"' && valueInsideQuotes) {
|
||
valueInsideQuotes = false;
|
||
continue;
|
||
}
|
||
|
||
// read next key/value pair
|
||
if ((char_ === pairSeparator && !valueInsideQuotes)) {
|
||
if (key === '') {
|
||
// beginning or ending space: { .red } vs {.red}
|
||
continue;
|
||
}
|
||
attrs.push([key, value]);
|
||
key = '';
|
||
value = '';
|
||
parsingKey = true;
|
||
continue;
|
||
}
|
||
|
||
// continue if character not allowed
|
||
if (parsingKey && char_.search(allowedKeyChars) === -1) {
|
||
continue;
|
||
}
|
||
|
||
// no other conditions met; append to key/value
|
||
if (parsingKey) {
|
||
key += char_;
|
||
continue;
|
||
}
|
||
value += char_;
|
||
}
|
||
|
||
if (options.allowedAttributes && options.allowedAttributes.length) {
|
||
const allowedAttributes = options.allowedAttributes;
|
||
|
||
return attrs.filter(function (attrPair) {
|
||
const attr = attrPair[0];
|
||
|
||
function isAllowedAttribute (allowedAttribute) {
|
||
return (attr === allowedAttribute
|
||
|| (allowedAttribute instanceof RegExp && allowedAttribute.test(attr))
|
||
);
|
||
}
|
||
|
||
return allowedAttributes.some(isAllowedAttribute);
|
||
});
|
||
|
||
}
|
||
return attrs;
|
||
|
||
};
|
||
|
||
/**
|
||
* add attributes from [['key', 'val']] list
|
||
* @param {array} attrs: [['key', 'val']]
|
||
* @param {token} token: which token to add attributes
|
||
* @returns token
|
||
*/
|
||
utils$2.addAttrs = function (attrs, token) {
|
||
for (let j = 0, l = attrs.length; j < l; ++j) {
|
||
const key = attrs[j][0];
|
||
if (key === 'class') {
|
||
token.attrJoin('class', attrs[j][1]);
|
||
} else if (key === 'css-module') {
|
||
token.attrJoin('css-module', attrs[j][1]);
|
||
} else {
|
||
token.attrPush(attrs[j]);
|
||
}
|
||
}
|
||
return token;
|
||
};
|
||
|
||
/**
|
||
* Does string have properly formatted curly?
|
||
*
|
||
* start: '{.a} asdf'
|
||
* end: 'asdf {.a}'
|
||
* only: '{.a}'
|
||
*
|
||
* @param {string} where to expect {} curly. start, end or only.
|
||
* @return {function(string)} Function which testes if string has curly.
|
||
*/
|
||
utils$2.hasDelimiters = function (where, options) {
|
||
|
||
if (!where) {
|
||
throw new Error('Parameter `where` not passed. Should be "start", "end" or "only".');
|
||
}
|
||
|
||
/**
|
||
* @param {string} str
|
||
* @return {boolean}
|
||
*/
|
||
return function (str) {
|
||
// we need minimum three chars, for example {b}
|
||
const minCurlyLength = options.leftDelimiter.length + 1 + options.rightDelimiter.length;
|
||
if (!str || typeof str !== 'string' || str.length < minCurlyLength) {
|
||
return false;
|
||
}
|
||
|
||
function validCurlyLength (curly) {
|
||
const isClass = curly.charAt(options.leftDelimiter.length) === '.';
|
||
const isId = curly.charAt(options.leftDelimiter.length) === '#';
|
||
return (isClass || isId)
|
||
? curly.length >= (minCurlyLength + 1)
|
||
: curly.length >= minCurlyLength;
|
||
}
|
||
|
||
let start, end, slice, nextChar;
|
||
const rightDelimiterMinimumShift = minCurlyLength - options.rightDelimiter.length;
|
||
switch (where) {
|
||
case 'start':
|
||
// first char should be {, } found in char 2 or more
|
||
slice = str.slice(0, options.leftDelimiter.length);
|
||
start = slice === options.leftDelimiter ? 0 : -1;
|
||
end = start === -1 ? -1 : str.indexOf(options.rightDelimiter, rightDelimiterMinimumShift);
|
||
// check if next character is not one of the delimiters
|
||
nextChar = str.charAt(end + options.rightDelimiter.length);
|
||
if (nextChar && options.rightDelimiter.indexOf(nextChar) !== -1) {
|
||
end = -1;
|
||
}
|
||
break;
|
||
|
||
case 'end':
|
||
// last char should be }
|
||
start = str.lastIndexOf(options.leftDelimiter);
|
||
end = start === -1 ? -1 : str.indexOf(options.rightDelimiter, start + rightDelimiterMinimumShift);
|
||
end = end === str.length - options.rightDelimiter.length ? end : -1;
|
||
break;
|
||
|
||
case 'only':
|
||
// '{.a}'
|
||
slice = str.slice(0, options.leftDelimiter.length);
|
||
start = slice === options.leftDelimiter ? 0 : -1;
|
||
slice = str.slice(str.length - options.rightDelimiter.length);
|
||
end = slice === options.rightDelimiter ? str.length - options.rightDelimiter.length : -1;
|
||
break;
|
||
|
||
default:
|
||
throw new Error(`Unexpected case ${where}, expected 'start', 'end' or 'only'`);
|
||
}
|
||
|
||
return start !== -1 && end !== -1 && validCurlyLength(str.substring(start, end + options.rightDelimiter.length));
|
||
};
|
||
};
|
||
|
||
/**
|
||
* Removes last curly from string.
|
||
*/
|
||
utils$2.removeDelimiter = function (str, options) {
|
||
const start = escapeRegExp(options.leftDelimiter);
|
||
const end = escapeRegExp(options.rightDelimiter);
|
||
|
||
const curly = new RegExp(
|
||
'[ \\n]?' + start + '[^' + start + end + ']+' + end + '$'
|
||
);
|
||
const pos = str.search(curly);
|
||
|
||
return pos !== -1 ? str.slice(0, pos) : str;
|
||
};
|
||
|
||
/**
|
||
* Escapes special characters in string s such that the string
|
||
* can be used in `new RegExp`. For example "[" becomes "\\[".
|
||
*
|
||
* @param {string} s Regex string.
|
||
* @return {string} Escaped string.
|
||
*/
|
||
function escapeRegExp (s) {
|
||
return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
||
}
|
||
utils$2.escapeRegExp = escapeRegExp;
|
||
|
||
/**
|
||
* find corresponding opening block
|
||
*/
|
||
utils$2.getMatchingOpeningToken = function (tokens, i) {
|
||
if (tokens[i].type === 'softbreak') {
|
||
return false;
|
||
}
|
||
// non closing blocks, example img
|
||
if (tokens[i].nesting === 0) {
|
||
return tokens[i];
|
||
}
|
||
|
||
const level = tokens[i].level;
|
||
const type = tokens[i].type.replace('_close', '_open');
|
||
|
||
for (; i >= 0; --i) {
|
||
if (tokens[i].type === type && tokens[i].level === level) {
|
||
return tokens[i];
|
||
}
|
||
}
|
||
|
||
return false;
|
||
};
|
||
|
||
|
||
/**
|
||
* from https://github.com/markdown-it/markdown-it/blob/master/lib/common/utils.js
|
||
*/
|
||
const HTML_ESCAPE_TEST_RE = /[&<>"]/;
|
||
const HTML_ESCAPE_REPLACE_RE = /[&<>"]/g;
|
||
const HTML_REPLACEMENTS = {
|
||
'&': '&',
|
||
'<': '<',
|
||
'>': '>',
|
||
'"': '"'
|
||
};
|
||
|
||
function replaceUnsafeChar(ch) {
|
||
return HTML_REPLACEMENTS[ch];
|
||
}
|
||
|
||
utils$2.escapeHtml = function (str) {
|
||
if (HTML_ESCAPE_TEST_RE.test(str)) {
|
||
return str.replace(HTML_ESCAPE_REPLACE_RE, replaceUnsafeChar);
|
||
}
|
||
return str;
|
||
};
|
||
|
||
/**
|
||
* If a pattern matches the token stream,
|
||
* then run transform.
|
||
*/
|
||
|
||
const utils$1 = utils$2;
|
||
|
||
var patterns = options => {
|
||
const __hr = new RegExp('^ {0,3}[-*_]{3,} ?'
|
||
+ utils$1.escapeRegExp(options.leftDelimiter)
|
||
+ '[^' + utils$1.escapeRegExp(options.rightDelimiter) + ']');
|
||
|
||
return ([
|
||
{
|
||
/**
|
||
* ```python {.cls}
|
||
* for i in range(10):
|
||
* print(i)
|
||
* ```
|
||
*/
|
||
name: 'fenced code blocks',
|
||
tests: [
|
||
{
|
||
shift: 0,
|
||
block: true,
|
||
info: utils$1.hasDelimiters('end', options)
|
||
}
|
||
],
|
||
transform: (tokens, i) => {
|
||
const token = tokens[i];
|
||
const start = token.info.lastIndexOf(options.leftDelimiter);
|
||
const attrs = utils$1.getAttrs(token.info, start, options);
|
||
utils$1.addAttrs(attrs, token);
|
||
token.info = utils$1.removeDelimiter(token.info, options);
|
||
}
|
||
}, {
|
||
/**
|
||
* bla `click()`{.c} {.d}
|
||
*
|
||
* differs from 'inline attributes' as it does
|
||
* not have a closing tag (nesting: -1)
|
||
*/
|
||
name: 'inline nesting 0',
|
||
tests: [
|
||
{
|
||
shift: 0,
|
||
type: 'inline',
|
||
children: [
|
||
{
|
||
shift: -1,
|
||
type: (str) => str === 'image' || str === 'code_inline'
|
||
}, {
|
||
shift: 0,
|
||
type: 'text',
|
||
content: utils$1.hasDelimiters('start', options)
|
||
}
|
||
]
|
||
}
|
||
],
|
||
transform: (tokens, i, j) => {
|
||
const token = tokens[i].children[j];
|
||
const endChar = token.content.indexOf(options.rightDelimiter);
|
||
const attrToken = tokens[i].children[j - 1];
|
||
const attrs = utils$1.getAttrs(token.content, 0, options);
|
||
utils$1.addAttrs(attrs, attrToken);
|
||
if (token.content.length === (endChar + options.rightDelimiter.length)) {
|
||
tokens[i].children.splice(j, 1);
|
||
} else {
|
||
token.content = token.content.slice(endChar + options.rightDelimiter.length);
|
||
}
|
||
}
|
||
}, {
|
||
/**
|
||
* | h1 |
|
||
* | -- |
|
||
* | c1 |
|
||
*
|
||
* {.c}
|
||
*/
|
||
name: 'tables',
|
||
tests: [
|
||
{
|
||
// let this token be i, such that for-loop continues at
|
||
// next token after tokens.splice
|
||
shift: 0,
|
||
type: 'table_close'
|
||
}, {
|
||
shift: 1,
|
||
type: 'paragraph_open'
|
||
}, {
|
||
shift: 2,
|
||
type: 'inline',
|
||
content: utils$1.hasDelimiters('only', options)
|
||
}
|
||
],
|
||
transform: (tokens, i) => {
|
||
const token = tokens[i + 2];
|
||
const tableOpen = utils$1.getMatchingOpeningToken(tokens, i);
|
||
const attrs = utils$1.getAttrs(token.content, 0, options);
|
||
// add attributes
|
||
utils$1.addAttrs(attrs, tableOpen);
|
||
// remove <p>{.c}</p>
|
||
tokens.splice(i + 1, 3);
|
||
}
|
||
}, {
|
||
/**
|
||
* *emphasis*{.with attrs=1}
|
||
*/
|
||
name: 'inline attributes',
|
||
tests: [
|
||
{
|
||
shift: 0,
|
||
type: 'inline',
|
||
children: [
|
||
{
|
||
shift: -1,
|
||
nesting: -1 // closing inline tag, </em>{.a}
|
||
}, {
|
||
shift: 0,
|
||
type: 'text',
|
||
content: utils$1.hasDelimiters('start', options)
|
||
}
|
||
]
|
||
}
|
||
],
|
||
transform: (tokens, i, j) => {
|
||
const token = tokens[i].children[j];
|
||
const content = token.content;
|
||
const attrs = utils$1.getAttrs(content, 0, options);
|
||
const openingToken = utils$1.getMatchingOpeningToken(tokens[i].children, j - 1);
|
||
utils$1.addAttrs(attrs, openingToken);
|
||
token.content = content.slice(content.indexOf(options.rightDelimiter) + options.rightDelimiter.length);
|
||
}
|
||
}, {
|
||
/**
|
||
* - item
|
||
* {.a}
|
||
*/
|
||
name: 'list softbreak',
|
||
tests: [
|
||
{
|
||
shift: -2,
|
||
type: 'list_item_open'
|
||
}, {
|
||
shift: 0,
|
||
type: 'inline',
|
||
children: [
|
||
{
|
||
position: -2,
|
||
type: 'softbreak'
|
||
}, {
|
||
position: -1,
|
||
type: 'text',
|
||
content: utils$1.hasDelimiters('only', options)
|
||
}
|
||
]
|
||
}
|
||
],
|
||
transform: (tokens, i, j) => {
|
||
const token = tokens[i].children[j];
|
||
const content = token.content;
|
||
const attrs = utils$1.getAttrs(content, 0, options);
|
||
let ii = i - 2;
|
||
while (tokens[ii - 1] &&
|
||
tokens[ii - 1].type !== 'ordered_list_open' &&
|
||
tokens[ii - 1].type !== 'bullet_list_open') { ii--; }
|
||
utils$1.addAttrs(attrs, tokens[ii - 1]);
|
||
tokens[i].children = tokens[i].children.slice(0, -2);
|
||
}
|
||
}, {
|
||
/**
|
||
* - nested list
|
||
* - with double \n
|
||
* {.a} <-- apply to nested ul
|
||
*
|
||
* {.b} <-- apply to root <ul>
|
||
*/
|
||
name: 'list double softbreak',
|
||
tests: [
|
||
{
|
||
// let this token be i = 0 so that we can erase
|
||
// the <p>{.a}</p> tokens below
|
||
shift: 0,
|
||
type: (str) =>
|
||
str === 'bullet_list_close' ||
|
||
str === 'ordered_list_close'
|
||
}, {
|
||
shift: 1,
|
||
type: 'paragraph_open'
|
||
}, {
|
||
shift: 2,
|
||
type: 'inline',
|
||
content: utils$1.hasDelimiters('only', options),
|
||
children: (arr) => arr.length === 1
|
||
}, {
|
||
shift: 3,
|
||
type: 'paragraph_close'
|
||
}
|
||
],
|
||
transform: (tokens, i) => {
|
||
const token = tokens[i + 2];
|
||
const content = token.content;
|
||
const attrs = utils$1.getAttrs(content, 0, options);
|
||
const openingToken = utils$1.getMatchingOpeningToken(tokens, i);
|
||
utils$1.addAttrs(attrs, openingToken);
|
||
tokens.splice(i + 1, 3);
|
||
}
|
||
}, {
|
||
/**
|
||
* - end of {.list-item}
|
||
*/
|
||
name: 'list item end',
|
||
tests: [
|
||
{
|
||
shift: -2,
|
||
type: 'list_item_open'
|
||
}, {
|
||
shift: 0,
|
||
type: 'inline',
|
||
children: [
|
||
{
|
||
position: -1,
|
||
type: 'text',
|
||
content: utils$1.hasDelimiters('end', options)
|
||
}
|
||
]
|
||
}
|
||
],
|
||
transform: (tokens, i, j) => {
|
||
const token = tokens[i].children[j];
|
||
const content = token.content;
|
||
const attrs = utils$1.getAttrs(content, content.lastIndexOf(options.leftDelimiter), options);
|
||
utils$1.addAttrs(attrs, tokens[i - 2]);
|
||
const trimmed = content.slice(0, content.lastIndexOf(options.leftDelimiter));
|
||
token.content = last$1(trimmed) !== ' ' ?
|
||
trimmed : trimmed.slice(0, -1);
|
||
}
|
||
}, {
|
||
/**
|
||
* something with softbreak
|
||
* {.cls}
|
||
*/
|
||
name: '\n{.a} softbreak then curly in start',
|
||
tests: [
|
||
{
|
||
shift: 0,
|
||
type: 'inline',
|
||
children: [
|
||
{
|
||
position: -2,
|
||
type: 'softbreak'
|
||
}, {
|
||
position: -1,
|
||
type: 'text',
|
||
content: utils$1.hasDelimiters('only', options)
|
||
}
|
||
]
|
||
}
|
||
],
|
||
transform: (tokens, i, j) => {
|
||
const token = tokens[i].children[j];
|
||
const attrs = utils$1.getAttrs(token.content, 0, options);
|
||
// find last closing tag
|
||
let ii = i + 1;
|
||
while (tokens[ii + 1] && tokens[ii + 1].nesting === -1) { ii++; }
|
||
const openingToken = utils$1.getMatchingOpeningToken(tokens, ii);
|
||
utils$1.addAttrs(attrs, openingToken);
|
||
tokens[i].children = tokens[i].children.slice(0, -2);
|
||
}
|
||
}, {
|
||
/**
|
||
* horizontal rule --- {#id}
|
||
*/
|
||
name: 'horizontal rule',
|
||
tests: [
|
||
{
|
||
shift: 0,
|
||
type: 'paragraph_open'
|
||
},
|
||
{
|
||
shift: 1,
|
||
type: 'inline',
|
||
children: (arr) => arr.length === 1,
|
||
content: (str) => str.match(__hr) !== null,
|
||
},
|
||
{
|
||
shift: 2,
|
||
type: 'paragraph_close'
|
||
}
|
||
],
|
||
transform: (tokens, i) => {
|
||
const token = tokens[i];
|
||
token.type = 'hr';
|
||
token.tag = 'hr';
|
||
token.nesting = 0;
|
||
const content = tokens[i + 1].content;
|
||
const start = content.lastIndexOf(options.leftDelimiter);
|
||
const attrs = utils$1.getAttrs(content, start, options);
|
||
utils$1.addAttrs(attrs, token);
|
||
token.markup = content;
|
||
tokens.splice(i + 1, 2);
|
||
}
|
||
}, {
|
||
/**
|
||
* end of {.block}
|
||
*/
|
||
name: 'end of block',
|
||
tests: [
|
||
{
|
||
shift: 0,
|
||
type: 'inline',
|
||
children: [
|
||
{
|
||
position: -1,
|
||
content: utils$1.hasDelimiters('end', options),
|
||
type: (t) => t !== 'code_inline' && t !== 'math_inline'
|
||
}
|
||
]
|
||
}
|
||
],
|
||
transform: (tokens, i, j) => {
|
||
const token = tokens[i].children[j];
|
||
const content = token.content;
|
||
const attrs = utils$1.getAttrs(content, content.lastIndexOf(options.leftDelimiter), options);
|
||
let ii = i + 1;
|
||
while (tokens[ii + 1] && tokens[ii + 1].nesting === -1) { ii++; }
|
||
const openingToken = utils$1.getMatchingOpeningToken(tokens, ii);
|
||
utils$1.addAttrs(attrs, openingToken);
|
||
const trimmed = content.slice(0, content.lastIndexOf(options.leftDelimiter));
|
||
token.content = last$1(trimmed) !== ' ' ?
|
||
trimmed : trimmed.slice(0, -1);
|
||
}
|
||
}
|
||
]);
|
||
};
|
||
|
||
// get last element of array or string
|
||
function last$1(arr) {
|
||
return arr.slice(-1)[0];
|
||
}
|
||
|
||
const patternsConfig = patterns;
|
||
|
||
const defaultOptions = {
|
||
leftDelimiter: '{',
|
||
rightDelimiter: '}',
|
||
allowedAttributes: []
|
||
};
|
||
|
||
var markdownItAttrs = function attributes(md, options_) {
|
||
let options = Object.assign({}, defaultOptions);
|
||
options = Object.assign(options, options_);
|
||
|
||
const patterns = patternsConfig(options);
|
||
|
||
function curlyAttrs(state) {
|
||
const tokens = state.tokens;
|
||
|
||
for (let i = 0; i < tokens.length; i++) {
|
||
for (let p = 0; p < patterns.length; p++) {
|
||
const pattern = patterns[p];
|
||
let j = null; // position of child with offset 0
|
||
const match = pattern.tests.every(t => {
|
||
const res = test(tokens, i, t);
|
||
if (res.j !== null) { j = res.j; }
|
||
return res.match;
|
||
});
|
||
if (match) {
|
||
pattern.transform(tokens, i, j);
|
||
if (pattern.name === 'inline attributes' || pattern.name === 'inline nesting 0') {
|
||
// retry, may be several inline attributes
|
||
p--;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
md.core.ruler.before('linkify', 'curly_attributes', curlyAttrs);
|
||
};
|
||
|
||
/**
|
||
* Test if t matches token stream.
|
||
*
|
||
* @param {array} tokens
|
||
* @param {number} i
|
||
* @param {object} t Test to match.
|
||
* @return {object} { match: true|false, j: null|number }
|
||
*/
|
||
function test(tokens, i, t) {
|
||
const res = {
|
||
match: false,
|
||
j: null // position of child
|
||
};
|
||
|
||
const ii = t.shift !== undefined
|
||
? i + t.shift
|
||
: t.position;
|
||
|
||
if (t.shift !== undefined && ii < 0) {
|
||
// we should never shift to negative indexes (rolling around to back of array)
|
||
return res;
|
||
}
|
||
|
||
const token = get(tokens, ii); // supports negative ii
|
||
|
||
|
||
if (token === undefined) { return res; }
|
||
|
||
for (const key of Object.keys(t)) {
|
||
if (key === 'shift' || key === 'position') { continue; }
|
||
|
||
if (token[key] === undefined) { return res; }
|
||
|
||
if (key === 'children' && isArrayOfObjects(t.children)) {
|
||
if (token.children.length === 0) {
|
||
return res;
|
||
}
|
||
let match;
|
||
const childTests = t.children;
|
||
const children = token.children;
|
||
if (childTests.every(tt => tt.position !== undefined)) {
|
||
// positions instead of shifts, do not loop all children
|
||
match = childTests.every(tt => test(children, tt.position, tt).match);
|
||
if (match) {
|
||
// we may need position of child in transform
|
||
const j = last(childTests).position;
|
||
res.j = j >= 0 ? j : children.length + j;
|
||
}
|
||
} else {
|
||
for (let j = 0; j < children.length; j++) {
|
||
match = childTests.every(tt => test(children, j, tt).match);
|
||
if (match) {
|
||
res.j = j;
|
||
// all tests true, continue with next key of pattern t
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (match === false) { return res; }
|
||
|
||
continue;
|
||
}
|
||
|
||
switch (typeof t[key]) {
|
||
case 'boolean':
|
||
case 'number':
|
||
case 'string':
|
||
if (token[key] !== t[key]) { return res; }
|
||
break;
|
||
case 'function':
|
||
if (!t[key](token[key])) { return res; }
|
||
break;
|
||
case 'object':
|
||
if (isArrayOfFunctions(t[key])) {
|
||
const r = t[key].every(tt => tt(token[key]));
|
||
if (r === false) { return res; }
|
||
break;
|
||
}
|
||
// fall through for objects !== arrays of functions
|
||
default:
|
||
throw new Error(`Unknown type of pattern test (key: ${key}). Test should be of type boolean, number, string, function or array of functions.`);
|
||
}
|
||
}
|
||
|
||
// no tests returned false -> all tests returns true
|
||
res.match = true;
|
||
return res;
|
||
}
|
||
|
||
function isArrayOfObjects(arr) {
|
||
return Array.isArray(arr) && arr.length && arr.every(i => typeof i === 'object');
|
||
}
|
||
|
||
function isArrayOfFunctions(arr) {
|
||
return Array.isArray(arr) && arr.length && arr.every(i => typeof i === 'function');
|
||
}
|
||
|
||
/**
|
||
* Get n item of array. Supports negative n, where -1 is last
|
||
* element in array.
|
||
* @param {array} arr
|
||
* @param {number} n
|
||
*/
|
||
function get(arr, n) {
|
||
return n >= 0 ? arr[n] : arr[arr.length + n];
|
||
}
|
||
|
||
// get last element of array, safe - returns {} if not found
|
||
function last(arr) {
|
||
return arr.slice(-1)[0] || {};
|
||
}
|
||
|
||
var attrsPlugin = /*@__PURE__*/getDefaultExportFromCjs(markdownItAttrs);
|
||
|
||
function emoji_html (tokens, idx /*, options, env */) {
|
||
return tokens[idx].content
|
||
}
|
||
|
||
// Emojies & shortcuts replacement logic.
|
||
//
|
||
// Note: In theory, it could be faster to parse :smile: in inline chain and
|
||
// leave only shortcuts here. But, who care...
|
||
//
|
||
function create_rule (md, emojies, shortcuts, scanRE, replaceRE) {
|
||
const arrayReplaceAt = md.utils.arrayReplaceAt;
|
||
const ucm = md.utils.lib.ucmicro;
|
||
const has = md.utils.has;
|
||
const ZPCc = new RegExp([ucm.Z.source, ucm.P.source, ucm.Cc.source].join('|'));
|
||
|
||
function splitTextToken (text, level, Token) {
|
||
let last_pos = 0;
|
||
const nodes = [];
|
||
|
||
text.replace(replaceRE, function (match, offset, src) {
|
||
let emoji_name;
|
||
// Validate emoji name
|
||
if (has(shortcuts, match)) {
|
||
// replace shortcut with full name
|
||
emoji_name = shortcuts[match];
|
||
|
||
// Don't allow letters before any shortcut (as in no ":/" in http://)
|
||
if (offset > 0 && !ZPCc.test(src[offset - 1])) return
|
||
|
||
// Don't allow letters after any shortcut
|
||
if (offset + match.length < src.length && !ZPCc.test(src[offset + match.length])) {
|
||
return
|
||
}
|
||
} else {
|
||
emoji_name = match.slice(1, -1);
|
||
}
|
||
|
||
// Add new tokens to pending list
|
||
if (offset > last_pos) {
|
||
const token = new Token('text', '', 0);
|
||
token.content = text.slice(last_pos, offset);
|
||
nodes.push(token);
|
||
}
|
||
|
||
const token = new Token('emoji', '', 0);
|
||
token.markup = emoji_name;
|
||
token.content = emojies[emoji_name];
|
||
nodes.push(token);
|
||
|
||
last_pos = offset + match.length;
|
||
});
|
||
|
||
if (last_pos < text.length) {
|
||
const token = new Token('text', '', 0);
|
||
token.content = text.slice(last_pos);
|
||
nodes.push(token);
|
||
}
|
||
|
||
return nodes
|
||
}
|
||
|
||
return function emoji_replace (state) {
|
||
let token;
|
||
const blockTokens = state.tokens;
|
||
let autolinkLevel = 0;
|
||
|
||
for (let j = 0, l = blockTokens.length; j < l; j++) {
|
||
if (blockTokens[j].type !== 'inline') { continue }
|
||
let tokens = blockTokens[j].children;
|
||
|
||
// We scan from the end, to keep position when new tags added.
|
||
// Use reversed logic in links start/end match
|
||
for (let i = tokens.length - 1; i >= 0; i--) {
|
||
token = tokens[i];
|
||
|
||
if (token.type === 'link_open' || token.type === 'link_close') {
|
||
if (token.info === 'auto') { autolinkLevel -= token.nesting; }
|
||
}
|
||
|
||
if (token.type === 'text' && autolinkLevel === 0 && scanRE.test(token.content)) {
|
||
// replace current node
|
||
blockTokens[j].children = tokens = arrayReplaceAt(
|
||
tokens, i, splitTextToken(token.content, token.level, state.Token)
|
||
);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Convert input options to more useable format
|
||
// and compile search regexp
|
||
|
||
function quoteRE (str) {
|
||
return str.replace(/[.?*+^$[\]\\(){}|-]/g, '\\$&')
|
||
}
|
||
|
||
function normalize_opts (options) {
|
||
let emojies = options.defs;
|
||
|
||
// Filter emojies by whitelist, if needed
|
||
if (options.enabled.length) {
|
||
emojies = Object.keys(emojies).reduce((acc, key) => {
|
||
if (options.enabled.indexOf(key) >= 0) acc[key] = emojies[key];
|
||
return acc
|
||
}, {});
|
||
}
|
||
|
||
// Flatten shortcuts to simple object: { alias: emoji_name }
|
||
const shortcuts = Object.keys(options.shortcuts).reduce((acc, key) => {
|
||
// Skip aliases for filtered emojies, to reduce regexp
|
||
if (!emojies[key]) return acc
|
||
|
||
if (Array.isArray(options.shortcuts[key])) {
|
||
options.shortcuts[key].forEach(alias => { acc[alias] = key; });
|
||
return acc
|
||
}
|
||
|
||
acc[options.shortcuts[key]] = key;
|
||
return acc
|
||
}, {});
|
||
|
||
const keys = Object.keys(emojies);
|
||
let names;
|
||
|
||
// If no definitions are given, return empty regex to avoid replacements with 'undefined'.
|
||
if (keys.length === 0) {
|
||
names = '^$';
|
||
} else {
|
||
// Compile regexp
|
||
names = keys
|
||
.map(name => { return `:${name}:` })
|
||
.concat(Object.keys(shortcuts))
|
||
.sort()
|
||
.reverse()
|
||
.map(name => { return quoteRE(name) })
|
||
.join('|');
|
||
}
|
||
const scanRE = RegExp(names);
|
||
const replaceRE = RegExp(names, 'g');
|
||
|
||
return {
|
||
defs: emojies,
|
||
shortcuts,
|
||
scanRE,
|
||
replaceRE
|
||
}
|
||
}
|
||
|
||
function emoji_plugin$1 (md, options) {
|
||
const defaults = {
|
||
defs: {},
|
||
shortcuts: {},
|
||
enabled: []
|
||
};
|
||
|
||
const opts = normalize_opts(md.utils.assign({}, defaults, options || {}));
|
||
|
||
md.renderer.rules.emoji = emoji_html;
|
||
|
||
md.core.ruler.after(
|
||
'linkify',
|
||
'emoji',
|
||
create_rule(md, opts.defs, opts.shortcuts, opts.scanRE, opts.replaceRE)
|
||
);
|
||
}
|
||
|
||
// Emoticons -> Emoji mapping.
|
||
//
|
||
// (!) Some patterns skipped, to avoid collisions
|
||
// without increase matcher complicity. Than can change in future.
|
||
//
|
||
// Places to look for more emoticons info:
|
||
//
|
||
// - http://en.wikipedia.org/wiki/List_of_emoticons#Western
|
||
// - https://github.com/wooorm/emoticon/blob/master/Support.md
|
||
// - http://factoryjoe.com/projects/emoticons/
|
||
//
|
||
|
||
/* eslint-disable key-spacing */
|
||
|
||
var emojies_shortcuts = {
|
||
angry: ['>:(', '>:-('],
|
||
blush: [':")', ':-")'],
|
||
broken_heart: ['</3', '<\\3'],
|
||
// :\ and :-\ not used because of conflict with markdown escaping
|
||
confused: [':/', ':-/'], // twemoji shows question
|
||
cry: [":'(", ":'-(", ':,(', ':,-('],
|
||
frowning: [':(', ':-('],
|
||
heart: ['<3'],
|
||
imp: [']:(', ']:-('],
|
||
innocent: ['o:)', 'O:)', 'o:-)', 'O:-)', '0:)', '0:-)'],
|
||
joy: [":')", ":'-)", ':,)', ':,-)', ":'D", ":'-D", ':,D', ':,-D'],
|
||
kissing: [':*', ':-*'],
|
||
laughing: ['x-)', 'X-)'],
|
||
neutral_face: [':|', ':-|'],
|
||
open_mouth: [':o', ':-o', ':O', ':-O'],
|
||
rage: [':@', ':-@'],
|
||
smile: [':D', ':-D'],
|
||
smiley: [':)', ':-)'],
|
||
smiling_imp: [']:)', ']:-)'],
|
||
sob: [":,'(", ":,'-(", ';(', ';-('],
|
||
stuck_out_tongue: [':P', ':-P'],
|
||
sunglasses: ['8-)', 'B-)'],
|
||
sweat: [',:(', ',:-('],
|
||
sweat_smile: [',:)', ',:-)'],
|
||
unamused: [':s', ':-S', ':z', ':-Z', ':$', ':-$'],
|
||
wink: [';)', ';-)']
|
||
};
|
||
|
||
// Generated, don't edit
|
||
var emojies_defs = {
|
||
"100": "💯",
|
||
"1234": "🔢",
|
||
"grinning": "😀",
|
||
"smiley": "😃",
|
||
"smile": "😄",
|
||
"grin": "😁",
|
||
"laughing": "😆",
|
||
"satisfied": "😆",
|
||
"sweat_smile": "😅",
|
||
"rofl": "🤣",
|
||
"joy": "😂",
|
||
"slightly_smiling_face": "🙂",
|
||
"upside_down_face": "🙃",
|
||
"melting_face": "🫠",
|
||
"wink": "😉",
|
||
"blush": "😊",
|
||
"innocent": "😇",
|
||
"smiling_face_with_three_hearts": "🥰",
|
||
"heart_eyes": "😍",
|
||
"star_struck": "🤩",
|
||
"kissing_heart": "😘",
|
||
"kissing": "😗",
|
||
"relaxed": "☺️",
|
||
"kissing_closed_eyes": "😚",
|
||
"kissing_smiling_eyes": "😙",
|
||
"smiling_face_with_tear": "🥲",
|
||
"yum": "😋",
|
||
"stuck_out_tongue": "😛",
|
||
"stuck_out_tongue_winking_eye": "😜",
|
||
"zany_face": "🤪",
|
||
"stuck_out_tongue_closed_eyes": "😝",
|
||
"money_mouth_face": "🤑",
|
||
"hugs": "🤗",
|
||
"hand_over_mouth": "🤭",
|
||
"face_with_open_eyes_and_hand_over_mouth": "🫢",
|
||
"face_with_peeking_eye": "🫣",
|
||
"shushing_face": "🤫",
|
||
"thinking": "🤔",
|
||
"saluting_face": "🫡",
|
||
"zipper_mouth_face": "🤐",
|
||
"raised_eyebrow": "🤨",
|
||
"neutral_face": "😐",
|
||
"expressionless": "😑",
|
||
"no_mouth": "😶",
|
||
"dotted_line_face": "🫥",
|
||
"face_in_clouds": "😶🌫️",
|
||
"smirk": "😏",
|
||
"unamused": "😒",
|
||
"roll_eyes": "🙄",
|
||
"grimacing": "😬",
|
||
"face_exhaling": "😮💨",
|
||
"lying_face": "🤥",
|
||
"shaking_face": "🫨",
|
||
"relieved": "😌",
|
||
"pensive": "😔",
|
||
"sleepy": "😪",
|
||
"drooling_face": "🤤",
|
||
"sleeping": "😴",
|
||
"mask": "😷",
|
||
"face_with_thermometer": "🤒",
|
||
"face_with_head_bandage": "🤕",
|
||
"nauseated_face": "🤢",
|
||
"vomiting_face": "🤮",
|
||
"sneezing_face": "🤧",
|
||
"hot_face": "🥵",
|
||
"cold_face": "🥶",
|
||
"woozy_face": "🥴",
|
||
"dizzy_face": "😵",
|
||
"face_with_spiral_eyes": "😵💫",
|
||
"exploding_head": "🤯",
|
||
"cowboy_hat_face": "🤠",
|
||
"partying_face": "🥳",
|
||
"disguised_face": "🥸",
|
||
"sunglasses": "😎",
|
||
"nerd_face": "🤓",
|
||
"monocle_face": "🧐",
|
||
"confused": "😕",
|
||
"face_with_diagonal_mouth": "🫤",
|
||
"worried": "😟",
|
||
"slightly_frowning_face": "🙁",
|
||
"frowning_face": "☹️",
|
||
"open_mouth": "😮",
|
||
"hushed": "😯",
|
||
"astonished": "😲",
|
||
"flushed": "😳",
|
||
"pleading_face": "🥺",
|
||
"face_holding_back_tears": "🥹",
|
||
"frowning": "😦",
|
||
"anguished": "😧",
|
||
"fearful": "😨",
|
||
"cold_sweat": "😰",
|
||
"disappointed_relieved": "😥",
|
||
"cry": "😢",
|
||
"sob": "😭",
|
||
"scream": "😱",
|
||
"confounded": "😖",
|
||
"persevere": "😣",
|
||
"disappointed": "😞",
|
||
"sweat": "😓",
|
||
"weary": "😩",
|
||
"tired_face": "😫",
|
||
"yawning_face": "🥱",
|
||
"triumph": "😤",
|
||
"rage": "😡",
|
||
"pout": "😡",
|
||
"angry": "😠",
|
||
"cursing_face": "🤬",
|
||
"smiling_imp": "😈",
|
||
"imp": "👿",
|
||
"skull": "💀",
|
||
"skull_and_crossbones": "☠️",
|
||
"hankey": "💩",
|
||
"poop": "💩",
|
||
"shit": "💩",
|
||
"clown_face": "🤡",
|
||
"japanese_ogre": "👹",
|
||
"japanese_goblin": "👺",
|
||
"ghost": "👻",
|
||
"alien": "👽",
|
||
"space_invader": "👾",
|
||
"robot": "🤖",
|
||
"smiley_cat": "😺",
|
||
"smile_cat": "😸",
|
||
"joy_cat": "😹",
|
||
"heart_eyes_cat": "😻",
|
||
"smirk_cat": "😼",
|
||
"kissing_cat": "😽",
|
||
"scream_cat": "🙀",
|
||
"crying_cat_face": "😿",
|
||
"pouting_cat": "😾",
|
||
"see_no_evil": "🙈",
|
||
"hear_no_evil": "🙉",
|
||
"speak_no_evil": "🙊",
|
||
"love_letter": "💌",
|
||
"cupid": "💘",
|
||
"gift_heart": "💝",
|
||
"sparkling_heart": "💖",
|
||
"heartpulse": "💗",
|
||
"heartbeat": "💓",
|
||
"revolving_hearts": "💞",
|
||
"two_hearts": "💕",
|
||
"heart_decoration": "💟",
|
||
"heavy_heart_exclamation": "❣️",
|
||
"broken_heart": "💔",
|
||
"heart_on_fire": "❤️🔥",
|
||
"mending_heart": "❤️🩹",
|
||
"heart": "❤️",
|
||
"pink_heart": "🩷",
|
||
"orange_heart": "🧡",
|
||
"yellow_heart": "💛",
|
||
"green_heart": "💚",
|
||
"blue_heart": "💙",
|
||
"light_blue_heart": "🩵",
|
||
"purple_heart": "💜",
|
||
"brown_heart": "🤎",
|
||
"black_heart": "🖤",
|
||
"grey_heart": "🩶",
|
||
"white_heart": "🤍",
|
||
"kiss": "💋",
|
||
"anger": "💢",
|
||
"boom": "💥",
|
||
"collision": "💥",
|
||
"dizzy": "💫",
|
||
"sweat_drops": "💦",
|
||
"dash": "💨",
|
||
"hole": "🕳️",
|
||
"speech_balloon": "💬",
|
||
"eye_speech_bubble": "👁️🗨️",
|
||
"left_speech_bubble": "🗨️",
|
||
"right_anger_bubble": "🗯️",
|
||
"thought_balloon": "💭",
|
||
"zzz": "💤",
|
||
"wave": "👋",
|
||
"raised_back_of_hand": "🤚",
|
||
"raised_hand_with_fingers_splayed": "🖐️",
|
||
"hand": "✋",
|
||
"raised_hand": "✋",
|
||
"vulcan_salute": "🖖",
|
||
"rightwards_hand": "🫱",
|
||
"leftwards_hand": "🫲",
|
||
"palm_down_hand": "🫳",
|
||
"palm_up_hand": "🫴",
|
||
"leftwards_pushing_hand": "🫷",
|
||
"rightwards_pushing_hand": "🫸",
|
||
"ok_hand": "👌",
|
||
"pinched_fingers": "🤌",
|
||
"pinching_hand": "🤏",
|
||
"v": "✌️",
|
||
"crossed_fingers": "🤞",
|
||
"hand_with_index_finger_and_thumb_crossed": "🫰",
|
||
"love_you_gesture": "🤟",
|
||
"metal": "🤘",
|
||
"call_me_hand": "🤙",
|
||
"point_left": "👈",
|
||
"point_right": "👉",
|
||
"point_up_2": "👆",
|
||
"middle_finger": "🖕",
|
||
"fu": "🖕",
|
||
"point_down": "👇",
|
||
"point_up": "☝️",
|
||
"index_pointing_at_the_viewer": "🫵",
|
||
"+1": "👍",
|
||
"thumbsup": "👍",
|
||
"-1": "👎",
|
||
"thumbsdown": "👎",
|
||
"fist_raised": "✊",
|
||
"fist": "✊",
|
||
"fist_oncoming": "👊",
|
||
"facepunch": "👊",
|
||
"punch": "👊",
|
||
"fist_left": "🤛",
|
||
"fist_right": "🤜",
|
||
"clap": "👏",
|
||
"raised_hands": "🙌",
|
||
"heart_hands": "🫶",
|
||
"open_hands": "👐",
|
||
"palms_up_together": "🤲",
|
||
"handshake": "🤝",
|
||
"pray": "🙏",
|
||
"writing_hand": "✍️",
|
||
"nail_care": "💅",
|
||
"selfie": "🤳",
|
||
"muscle": "💪",
|
||
"mechanical_arm": "🦾",
|
||
"mechanical_leg": "🦿",
|
||
"leg": "🦵",
|
||
"foot": "🦶",
|
||
"ear": "👂",
|
||
"ear_with_hearing_aid": "🦻",
|
||
"nose": "👃",
|
||
"brain": "🧠",
|
||
"anatomical_heart": "🫀",
|
||
"lungs": "🫁",
|
||
"tooth": "🦷",
|
||
"bone": "🦴",
|
||
"eyes": "👀",
|
||
"eye": "👁️",
|
||
"tongue": "👅",
|
||
"lips": "👄",
|
||
"biting_lip": "🫦",
|
||
"baby": "👶",
|
||
"child": "🧒",
|
||
"boy": "👦",
|
||
"girl": "👧",
|
||
"adult": "🧑",
|
||
"blond_haired_person": "👱",
|
||
"man": "👨",
|
||
"bearded_person": "🧔",
|
||
"man_beard": "🧔♂️",
|
||
"woman_beard": "🧔♀️",
|
||
"red_haired_man": "👨🦰",
|
||
"curly_haired_man": "👨🦱",
|
||
"white_haired_man": "👨🦳",
|
||
"bald_man": "👨🦲",
|
||
"woman": "👩",
|
||
"red_haired_woman": "👩🦰",
|
||
"person_red_hair": "🧑🦰",
|
||
"curly_haired_woman": "👩🦱",
|
||
"person_curly_hair": "🧑🦱",
|
||
"white_haired_woman": "👩🦳",
|
||
"person_white_hair": "🧑🦳",
|
||
"bald_woman": "👩🦲",
|
||
"person_bald": "🧑🦲",
|
||
"blond_haired_woman": "👱♀️",
|
||
"blonde_woman": "👱♀️",
|
||
"blond_haired_man": "👱♂️",
|
||
"older_adult": "🧓",
|
||
"older_man": "👴",
|
||
"older_woman": "👵",
|
||
"frowning_person": "🙍",
|
||
"frowning_man": "🙍♂️",
|
||
"frowning_woman": "🙍♀️",
|
||
"pouting_face": "🙎",
|
||
"pouting_man": "🙎♂️",
|
||
"pouting_woman": "🙎♀️",
|
||
"no_good": "🙅",
|
||
"no_good_man": "🙅♂️",
|
||
"ng_man": "🙅♂️",
|
||
"no_good_woman": "🙅♀️",
|
||
"ng_woman": "🙅♀️",
|
||
"ok_person": "🙆",
|
||
"ok_man": "🙆♂️",
|
||
"ok_woman": "🙆♀️",
|
||
"tipping_hand_person": "💁",
|
||
"information_desk_person": "💁",
|
||
"tipping_hand_man": "💁♂️",
|
||
"sassy_man": "💁♂️",
|
||
"tipping_hand_woman": "💁♀️",
|
||
"sassy_woman": "💁♀️",
|
||
"raising_hand": "🙋",
|
||
"raising_hand_man": "🙋♂️",
|
||
"raising_hand_woman": "🙋♀️",
|
||
"deaf_person": "🧏",
|
||
"deaf_man": "🧏♂️",
|
||
"deaf_woman": "🧏♀️",
|
||
"bow": "🙇",
|
||
"bowing_man": "🙇♂️",
|
||
"bowing_woman": "🙇♀️",
|
||
"facepalm": "🤦",
|
||
"man_facepalming": "🤦♂️",
|
||
"woman_facepalming": "🤦♀️",
|
||
"shrug": "🤷",
|
||
"man_shrugging": "🤷♂️",
|
||
"woman_shrugging": "🤷♀️",
|
||
"health_worker": "🧑⚕️",
|
||
"man_health_worker": "👨⚕️",
|
||
"woman_health_worker": "👩⚕️",
|
||
"student": "🧑🎓",
|
||
"man_student": "👨🎓",
|
||
"woman_student": "👩🎓",
|
||
"teacher": "🧑🏫",
|
||
"man_teacher": "👨🏫",
|
||
"woman_teacher": "👩🏫",
|
||
"judge": "🧑⚖️",
|
||
"man_judge": "👨⚖️",
|
||
"woman_judge": "👩⚖️",
|
||
"farmer": "🧑🌾",
|
||
"man_farmer": "👨🌾",
|
||
"woman_farmer": "👩🌾",
|
||
"cook": "🧑🍳",
|
||
"man_cook": "👨🍳",
|
||
"woman_cook": "👩🍳",
|
||
"mechanic": "🧑🔧",
|
||
"man_mechanic": "👨🔧",
|
||
"woman_mechanic": "👩🔧",
|
||
"factory_worker": "🧑🏭",
|
||
"man_factory_worker": "👨🏭",
|
||
"woman_factory_worker": "👩🏭",
|
||
"office_worker": "🧑💼",
|
||
"man_office_worker": "👨💼",
|
||
"woman_office_worker": "👩💼",
|
||
"scientist": "🧑🔬",
|
||
"man_scientist": "👨🔬",
|
||
"woman_scientist": "👩🔬",
|
||
"technologist": "🧑💻",
|
||
"man_technologist": "👨💻",
|
||
"woman_technologist": "👩💻",
|
||
"singer": "🧑🎤",
|
||
"man_singer": "👨🎤",
|
||
"woman_singer": "👩🎤",
|
||
"artist": "🧑🎨",
|
||
"man_artist": "👨🎨",
|
||
"woman_artist": "👩🎨",
|
||
"pilot": "🧑✈️",
|
||
"man_pilot": "👨✈️",
|
||
"woman_pilot": "👩✈️",
|
||
"astronaut": "🧑🚀",
|
||
"man_astronaut": "👨🚀",
|
||
"woman_astronaut": "👩🚀",
|
||
"firefighter": "🧑🚒",
|
||
"man_firefighter": "👨🚒",
|
||
"woman_firefighter": "👩🚒",
|
||
"police_officer": "👮",
|
||
"cop": "👮",
|
||
"policeman": "👮♂️",
|
||
"policewoman": "👮♀️",
|
||
"detective": "🕵️",
|
||
"male_detective": "🕵️♂️",
|
||
"female_detective": "🕵️♀️",
|
||
"guard": "💂",
|
||
"guardsman": "💂♂️",
|
||
"guardswoman": "💂♀️",
|
||
"ninja": "🥷",
|
||
"construction_worker": "👷",
|
||
"construction_worker_man": "👷♂️",
|
||
"construction_worker_woman": "👷♀️",
|
||
"person_with_crown": "🫅",
|
||
"prince": "🤴",
|
||
"princess": "👸",
|
||
"person_with_turban": "👳",
|
||
"man_with_turban": "👳♂️",
|
||
"woman_with_turban": "👳♀️",
|
||
"man_with_gua_pi_mao": "👲",
|
||
"woman_with_headscarf": "🧕",
|
||
"person_in_tuxedo": "🤵",
|
||
"man_in_tuxedo": "🤵♂️",
|
||
"woman_in_tuxedo": "🤵♀️",
|
||
"person_with_veil": "👰",
|
||
"man_with_veil": "👰♂️",
|
||
"woman_with_veil": "👰♀️",
|
||
"bride_with_veil": "👰♀️",
|
||
"pregnant_woman": "🤰",
|
||
"pregnant_man": "🫃",
|
||
"pregnant_person": "🫄",
|
||
"breast_feeding": "🤱",
|
||
"woman_feeding_baby": "👩🍼",
|
||
"man_feeding_baby": "👨🍼",
|
||
"person_feeding_baby": "🧑🍼",
|
||
"angel": "👼",
|
||
"santa": "🎅",
|
||
"mrs_claus": "🤶",
|
||
"mx_claus": "🧑🎄",
|
||
"superhero": "🦸",
|
||
"superhero_man": "🦸♂️",
|
||
"superhero_woman": "🦸♀️",
|
||
"supervillain": "🦹",
|
||
"supervillain_man": "🦹♂️",
|
||
"supervillain_woman": "🦹♀️",
|
||
"mage": "🧙",
|
||
"mage_man": "🧙♂️",
|
||
"mage_woman": "🧙♀️",
|
||
"fairy": "🧚",
|
||
"fairy_man": "🧚♂️",
|
||
"fairy_woman": "🧚♀️",
|
||
"vampire": "🧛",
|
||
"vampire_man": "🧛♂️",
|
||
"vampire_woman": "🧛♀️",
|
||
"merperson": "🧜",
|
||
"merman": "🧜♂️",
|
||
"mermaid": "🧜♀️",
|
||
"elf": "🧝",
|
||
"elf_man": "🧝♂️",
|
||
"elf_woman": "🧝♀️",
|
||
"genie": "🧞",
|
||
"genie_man": "🧞♂️",
|
||
"genie_woman": "🧞♀️",
|
||
"zombie": "🧟",
|
||
"zombie_man": "🧟♂️",
|
||
"zombie_woman": "🧟♀️",
|
||
"troll": "🧌",
|
||
"massage": "💆",
|
||
"massage_man": "💆♂️",
|
||
"massage_woman": "💆♀️",
|
||
"haircut": "💇",
|
||
"haircut_man": "💇♂️",
|
||
"haircut_woman": "💇♀️",
|
||
"walking": "🚶",
|
||
"walking_man": "🚶♂️",
|
||
"walking_woman": "🚶♀️",
|
||
"standing_person": "🧍",
|
||
"standing_man": "🧍♂️",
|
||
"standing_woman": "🧍♀️",
|
||
"kneeling_person": "🧎",
|
||
"kneeling_man": "🧎♂️",
|
||
"kneeling_woman": "🧎♀️",
|
||
"person_with_probing_cane": "🧑🦯",
|
||
"man_with_probing_cane": "👨🦯",
|
||
"woman_with_probing_cane": "👩🦯",
|
||
"person_in_motorized_wheelchair": "🧑🦼",
|
||
"man_in_motorized_wheelchair": "👨🦼",
|
||
"woman_in_motorized_wheelchair": "👩🦼",
|
||
"person_in_manual_wheelchair": "🧑🦽",
|
||
"man_in_manual_wheelchair": "👨🦽",
|
||
"woman_in_manual_wheelchair": "👩🦽",
|
||
"runner": "🏃",
|
||
"running": "🏃",
|
||
"running_man": "🏃♂️",
|
||
"running_woman": "🏃♀️",
|
||
"woman_dancing": "💃",
|
||
"dancer": "💃",
|
||
"man_dancing": "🕺",
|
||
"business_suit_levitating": "🕴️",
|
||
"dancers": "👯",
|
||
"dancing_men": "👯♂️",
|
||
"dancing_women": "👯♀️",
|
||
"sauna_person": "🧖",
|
||
"sauna_man": "🧖♂️",
|
||
"sauna_woman": "🧖♀️",
|
||
"climbing": "🧗",
|
||
"climbing_man": "🧗♂️",
|
||
"climbing_woman": "🧗♀️",
|
||
"person_fencing": "🤺",
|
||
"horse_racing": "🏇",
|
||
"skier": "⛷️",
|
||
"snowboarder": "🏂",
|
||
"golfing": "🏌️",
|
||
"golfing_man": "🏌️♂️",
|
||
"golfing_woman": "🏌️♀️",
|
||
"surfer": "🏄",
|
||
"surfing_man": "🏄♂️",
|
||
"surfing_woman": "🏄♀️",
|
||
"rowboat": "🚣",
|
||
"rowing_man": "🚣♂️",
|
||
"rowing_woman": "🚣♀️",
|
||
"swimmer": "🏊",
|
||
"swimming_man": "🏊♂️",
|
||
"swimming_woman": "🏊♀️",
|
||
"bouncing_ball_person": "⛹️",
|
||
"bouncing_ball_man": "⛹️♂️",
|
||
"basketball_man": "⛹️♂️",
|
||
"bouncing_ball_woman": "⛹️♀️",
|
||
"basketball_woman": "⛹️♀️",
|
||
"weight_lifting": "🏋️",
|
||
"weight_lifting_man": "🏋️♂️",
|
||
"weight_lifting_woman": "🏋️♀️",
|
||
"bicyclist": "🚴",
|
||
"biking_man": "🚴♂️",
|
||
"biking_woman": "🚴♀️",
|
||
"mountain_bicyclist": "🚵",
|
||
"mountain_biking_man": "🚵♂️",
|
||
"mountain_biking_woman": "🚵♀️",
|
||
"cartwheeling": "🤸",
|
||
"man_cartwheeling": "🤸♂️",
|
||
"woman_cartwheeling": "🤸♀️",
|
||
"wrestling": "🤼",
|
||
"men_wrestling": "🤼♂️",
|
||
"women_wrestling": "🤼♀️",
|
||
"water_polo": "🤽",
|
||
"man_playing_water_polo": "🤽♂️",
|
||
"woman_playing_water_polo": "🤽♀️",
|
||
"handball_person": "🤾",
|
||
"man_playing_handball": "🤾♂️",
|
||
"woman_playing_handball": "🤾♀️",
|
||
"juggling_person": "🤹",
|
||
"man_juggling": "🤹♂️",
|
||
"woman_juggling": "🤹♀️",
|
||
"lotus_position": "🧘",
|
||
"lotus_position_man": "🧘♂️",
|
||
"lotus_position_woman": "🧘♀️",
|
||
"bath": "🛀",
|
||
"sleeping_bed": "🛌",
|
||
"people_holding_hands": "🧑🤝🧑",
|
||
"two_women_holding_hands": "👭",
|
||
"couple": "👫",
|
||
"two_men_holding_hands": "👬",
|
||
"couplekiss": "💏",
|
||
"couplekiss_man_woman": "👩❤️💋👨",
|
||
"couplekiss_man_man": "👨❤️💋👨",
|
||
"couplekiss_woman_woman": "👩❤️💋👩",
|
||
"couple_with_heart": "💑",
|
||
"couple_with_heart_woman_man": "👩❤️👨",
|
||
"couple_with_heart_man_man": "👨❤️👨",
|
||
"couple_with_heart_woman_woman": "👩❤️👩",
|
||
"family": "👪",
|
||
"family_man_woman_boy": "👨👩👦",
|
||
"family_man_woman_girl": "👨👩👧",
|
||
"family_man_woman_girl_boy": "👨👩👧👦",
|
||
"family_man_woman_boy_boy": "👨👩👦👦",
|
||
"family_man_woman_girl_girl": "👨👩👧👧",
|
||
"family_man_man_boy": "👨👨👦",
|
||
"family_man_man_girl": "👨👨👧",
|
||
"family_man_man_girl_boy": "👨👨👧👦",
|
||
"family_man_man_boy_boy": "👨👨👦👦",
|
||
"family_man_man_girl_girl": "👨👨👧👧",
|
||
"family_woman_woman_boy": "👩👩👦",
|
||
"family_woman_woman_girl": "👩👩👧",
|
||
"family_woman_woman_girl_boy": "👩👩👧👦",
|
||
"family_woman_woman_boy_boy": "👩👩👦👦",
|
||
"family_woman_woman_girl_girl": "👩👩👧👧",
|
||
"family_man_boy": "👨👦",
|
||
"family_man_boy_boy": "👨👦👦",
|
||
"family_man_girl": "👨👧",
|
||
"family_man_girl_boy": "👨👧👦",
|
||
"family_man_girl_girl": "👨👧👧",
|
||
"family_woman_boy": "👩👦",
|
||
"family_woman_boy_boy": "👩👦👦",
|
||
"family_woman_girl": "👩👧",
|
||
"family_woman_girl_boy": "👩👧👦",
|
||
"family_woman_girl_girl": "👩👧👧",
|
||
"speaking_head": "🗣️",
|
||
"bust_in_silhouette": "👤",
|
||
"busts_in_silhouette": "👥",
|
||
"people_hugging": "🫂",
|
||
"footprints": "👣",
|
||
"monkey_face": "🐵",
|
||
"monkey": "🐒",
|
||
"gorilla": "🦍",
|
||
"orangutan": "🦧",
|
||
"dog": "🐶",
|
||
"dog2": "🐕",
|
||
"guide_dog": "🦮",
|
||
"service_dog": "🐕🦺",
|
||
"poodle": "🐩",
|
||
"wolf": "🐺",
|
||
"fox_face": "🦊",
|
||
"raccoon": "🦝",
|
||
"cat": "🐱",
|
||
"cat2": "🐈",
|
||
"black_cat": "🐈⬛",
|
||
"lion": "🦁",
|
||
"tiger": "🐯",
|
||
"tiger2": "🐅",
|
||
"leopard": "🐆",
|
||
"horse": "🐴",
|
||
"moose": "🫎",
|
||
"donkey": "🫏",
|
||
"racehorse": "🐎",
|
||
"unicorn": "🦄",
|
||
"zebra": "🦓",
|
||
"deer": "🦌",
|
||
"bison": "🦬",
|
||
"cow": "🐮",
|
||
"ox": "🐂",
|
||
"water_buffalo": "🐃",
|
||
"cow2": "🐄",
|
||
"pig": "🐷",
|
||
"pig2": "🐖",
|
||
"boar": "🐗",
|
||
"pig_nose": "🐽",
|
||
"ram": "🐏",
|
||
"sheep": "🐑",
|
||
"goat": "🐐",
|
||
"dromedary_camel": "🐪",
|
||
"camel": "🐫",
|
||
"llama": "🦙",
|
||
"giraffe": "🦒",
|
||
"elephant": "🐘",
|
||
"mammoth": "🦣",
|
||
"rhinoceros": "🦏",
|
||
"hippopotamus": "🦛",
|
||
"mouse": "🐭",
|
||
"mouse2": "🐁",
|
||
"rat": "🐀",
|
||
"hamster": "🐹",
|
||
"rabbit": "🐰",
|
||
"rabbit2": "🐇",
|
||
"chipmunk": "🐿️",
|
||
"beaver": "🦫",
|
||
"hedgehog": "🦔",
|
||
"bat": "🦇",
|
||
"bear": "🐻",
|
||
"polar_bear": "🐻❄️",
|
||
"koala": "🐨",
|
||
"panda_face": "🐼",
|
||
"sloth": "🦥",
|
||
"otter": "🦦",
|
||
"skunk": "🦨",
|
||
"kangaroo": "🦘",
|
||
"badger": "🦡",
|
||
"feet": "🐾",
|
||
"paw_prints": "🐾",
|
||
"turkey": "🦃",
|
||
"chicken": "🐔",
|
||
"rooster": "🐓",
|
||
"hatching_chick": "🐣",
|
||
"baby_chick": "🐤",
|
||
"hatched_chick": "🐥",
|
||
"bird": "🐦",
|
||
"penguin": "🐧",
|
||
"dove": "🕊️",
|
||
"eagle": "🦅",
|
||
"duck": "🦆",
|
||
"swan": "🦢",
|
||
"owl": "🦉",
|
||
"dodo": "🦤",
|
||
"feather": "🪶",
|
||
"flamingo": "🦩",
|
||
"peacock": "🦚",
|
||
"parrot": "🦜",
|
||
"wing": "🪽",
|
||
"black_bird": "🐦⬛",
|
||
"goose": "🪿",
|
||
"frog": "🐸",
|
||
"crocodile": "🐊",
|
||
"turtle": "🐢",
|
||
"lizard": "🦎",
|
||
"snake": "🐍",
|
||
"dragon_face": "🐲",
|
||
"dragon": "🐉",
|
||
"sauropod": "🦕",
|
||
"t-rex": "🦖",
|
||
"whale": "🐳",
|
||
"whale2": "🐋",
|
||
"dolphin": "🐬",
|
||
"flipper": "🐬",
|
||
"seal": "🦭",
|
||
"fish": "🐟",
|
||
"tropical_fish": "🐠",
|
||
"blowfish": "🐡",
|
||
"shark": "🦈",
|
||
"octopus": "🐙",
|
||
"shell": "🐚",
|
||
"coral": "🪸",
|
||
"jellyfish": "🪼",
|
||
"snail": "🐌",
|
||
"butterfly": "🦋",
|
||
"bug": "🐛",
|
||
"ant": "🐜",
|
||
"bee": "🐝",
|
||
"honeybee": "🐝",
|
||
"beetle": "🪲",
|
||
"lady_beetle": "🐞",
|
||
"cricket": "🦗",
|
||
"cockroach": "🪳",
|
||
"spider": "🕷️",
|
||
"spider_web": "🕸️",
|
||
"scorpion": "🦂",
|
||
"mosquito": "🦟",
|
||
"fly": "🪰",
|
||
"worm": "🪱",
|
||
"microbe": "🦠",
|
||
"bouquet": "💐",
|
||
"cherry_blossom": "🌸",
|
||
"white_flower": "💮",
|
||
"lotus": "🪷",
|
||
"rosette": "🏵️",
|
||
"rose": "🌹",
|
||
"wilted_flower": "🥀",
|
||
"hibiscus": "🌺",
|
||
"sunflower": "🌻",
|
||
"blossom": "🌼",
|
||
"tulip": "🌷",
|
||
"hyacinth": "🪻",
|
||
"seedling": "🌱",
|
||
"potted_plant": "🪴",
|
||
"evergreen_tree": "🌲",
|
||
"deciduous_tree": "🌳",
|
||
"palm_tree": "🌴",
|
||
"cactus": "🌵",
|
||
"ear_of_rice": "🌾",
|
||
"herb": "🌿",
|
||
"shamrock": "☘️",
|
||
"four_leaf_clover": "🍀",
|
||
"maple_leaf": "🍁",
|
||
"fallen_leaf": "🍂",
|
||
"leaves": "🍃",
|
||
"empty_nest": "🪹",
|
||
"nest_with_eggs": "🪺",
|
||
"mushroom": "🍄",
|
||
"grapes": "🍇",
|
||
"melon": "🍈",
|
||
"watermelon": "🍉",
|
||
"tangerine": "🍊",
|
||
"orange": "🍊",
|
||
"mandarin": "🍊",
|
||
"lemon": "🍋",
|
||
"banana": "🍌",
|
||
"pineapple": "🍍",
|
||
"mango": "🥭",
|
||
"apple": "🍎",
|
||
"green_apple": "🍏",
|
||
"pear": "🍐",
|
||
"peach": "🍑",
|
||
"cherries": "🍒",
|
||
"strawberry": "🍓",
|
||
"blueberries": "🫐",
|
||
"kiwi_fruit": "🥝",
|
||
"tomato": "🍅",
|
||
"olive": "🫒",
|
||
"coconut": "🥥",
|
||
"avocado": "🥑",
|
||
"eggplant": "🍆",
|
||
"potato": "🥔",
|
||
"carrot": "🥕",
|
||
"corn": "🌽",
|
||
"hot_pepper": "🌶️",
|
||
"bell_pepper": "🫑",
|
||
"cucumber": "🥒",
|
||
"leafy_green": "🥬",
|
||
"broccoli": "🥦",
|
||
"garlic": "🧄",
|
||
"onion": "🧅",
|
||
"peanuts": "🥜",
|
||
"beans": "🫘",
|
||
"chestnut": "🌰",
|
||
"ginger_root": "🫚",
|
||
"pea_pod": "🫛",
|
||
"bread": "🍞",
|
||
"croissant": "🥐",
|
||
"baguette_bread": "🥖",
|
||
"flatbread": "🫓",
|
||
"pretzel": "🥨",
|
||
"bagel": "🥯",
|
||
"pancakes": "🥞",
|
||
"waffle": "🧇",
|
||
"cheese": "🧀",
|
||
"meat_on_bone": "🍖",
|
||
"poultry_leg": "🍗",
|
||
"cut_of_meat": "🥩",
|
||
"bacon": "🥓",
|
||
"hamburger": "🍔",
|
||
"fries": "🍟",
|
||
"pizza": "🍕",
|
||
"hotdog": "🌭",
|
||
"sandwich": "🥪",
|
||
"taco": "🌮",
|
||
"burrito": "🌯",
|
||
"tamale": "🫔",
|
||
"stuffed_flatbread": "🥙",
|
||
"falafel": "🧆",
|
||
"egg": "🥚",
|
||
"fried_egg": "🍳",
|
||
"shallow_pan_of_food": "🥘",
|
||
"stew": "🍲",
|
||
"fondue": "🫕",
|
||
"bowl_with_spoon": "🥣",
|
||
"green_salad": "🥗",
|
||
"popcorn": "🍿",
|
||
"butter": "🧈",
|
||
"salt": "🧂",
|
||
"canned_food": "🥫",
|
||
"bento": "🍱",
|
||
"rice_cracker": "🍘",
|
||
"rice_ball": "🍙",
|
||
"rice": "🍚",
|
||
"curry": "🍛",
|
||
"ramen": "🍜",
|
||
"spaghetti": "🍝",
|
||
"sweet_potato": "🍠",
|
||
"oden": "🍢",
|
||
"sushi": "🍣",
|
||
"fried_shrimp": "🍤",
|
||
"fish_cake": "🍥",
|
||
"moon_cake": "🥮",
|
||
"dango": "🍡",
|
||
"dumpling": "🥟",
|
||
"fortune_cookie": "🥠",
|
||
"takeout_box": "🥡",
|
||
"crab": "🦀",
|
||
"lobster": "🦞",
|
||
"shrimp": "🦐",
|
||
"squid": "🦑",
|
||
"oyster": "🦪",
|
||
"icecream": "🍦",
|
||
"shaved_ice": "🍧",
|
||
"ice_cream": "🍨",
|
||
"doughnut": "🍩",
|
||
"cookie": "🍪",
|
||
"birthday": "🎂",
|
||
"cake": "🍰",
|
||
"cupcake": "🧁",
|
||
"pie": "🥧",
|
||
"chocolate_bar": "🍫",
|
||
"candy": "🍬",
|
||
"lollipop": "🍭",
|
||
"custard": "🍮",
|
||
"honey_pot": "🍯",
|
||
"baby_bottle": "🍼",
|
||
"milk_glass": "🥛",
|
||
"coffee": "☕",
|
||
"teapot": "🫖",
|
||
"tea": "🍵",
|
||
"sake": "🍶",
|
||
"champagne": "🍾",
|
||
"wine_glass": "🍷",
|
||
"cocktail": "🍸",
|
||
"tropical_drink": "🍹",
|
||
"beer": "🍺",
|
||
"beers": "🍻",
|
||
"clinking_glasses": "🥂",
|
||
"tumbler_glass": "🥃",
|
||
"pouring_liquid": "🫗",
|
||
"cup_with_straw": "🥤",
|
||
"bubble_tea": "🧋",
|
||
"beverage_box": "🧃",
|
||
"mate": "🧉",
|
||
"ice_cube": "🧊",
|
||
"chopsticks": "🥢",
|
||
"plate_with_cutlery": "🍽️",
|
||
"fork_and_knife": "🍴",
|
||
"spoon": "🥄",
|
||
"hocho": "🔪",
|
||
"knife": "🔪",
|
||
"jar": "🫙",
|
||
"amphora": "🏺",
|
||
"earth_africa": "🌍",
|
||
"earth_americas": "🌎",
|
||
"earth_asia": "🌏",
|
||
"globe_with_meridians": "🌐",
|
||
"world_map": "🗺️",
|
||
"japan": "🗾",
|
||
"compass": "🧭",
|
||
"mountain_snow": "🏔️",
|
||
"mountain": "⛰️",
|
||
"volcano": "🌋",
|
||
"mount_fuji": "🗻",
|
||
"camping": "🏕️",
|
||
"beach_umbrella": "🏖️",
|
||
"desert": "🏜️",
|
||
"desert_island": "🏝️",
|
||
"national_park": "🏞️",
|
||
"stadium": "🏟️",
|
||
"classical_building": "🏛️",
|
||
"building_construction": "🏗️",
|
||
"bricks": "🧱",
|
||
"rock": "🪨",
|
||
"wood": "🪵",
|
||
"hut": "🛖",
|
||
"houses": "🏘️",
|
||
"derelict_house": "🏚️",
|
||
"house": "🏠",
|
||
"house_with_garden": "🏡",
|
||
"office": "🏢",
|
||
"post_office": "🏣",
|
||
"european_post_office": "🏤",
|
||
"hospital": "🏥",
|
||
"bank": "🏦",
|
||
"hotel": "🏨",
|
||
"love_hotel": "🏩",
|
||
"convenience_store": "🏪",
|
||
"school": "🏫",
|
||
"department_store": "🏬",
|
||
"factory": "🏭",
|
||
"japanese_castle": "🏯",
|
||
"european_castle": "🏰",
|
||
"wedding": "💒",
|
||
"tokyo_tower": "🗼",
|
||
"statue_of_liberty": "🗽",
|
||
"church": "⛪",
|
||
"mosque": "🕌",
|
||
"hindu_temple": "🛕",
|
||
"synagogue": "🕍",
|
||
"shinto_shrine": "⛩️",
|
||
"kaaba": "🕋",
|
||
"fountain": "⛲",
|
||
"tent": "⛺",
|
||
"foggy": "🌁",
|
||
"night_with_stars": "🌃",
|
||
"cityscape": "🏙️",
|
||
"sunrise_over_mountains": "🌄",
|
||
"sunrise": "🌅",
|
||
"city_sunset": "🌆",
|
||
"city_sunrise": "🌇",
|
||
"bridge_at_night": "🌉",
|
||
"hotsprings": "♨️",
|
||
"carousel_horse": "🎠",
|
||
"playground_slide": "🛝",
|
||
"ferris_wheel": "🎡",
|
||
"roller_coaster": "🎢",
|
||
"barber": "💈",
|
||
"circus_tent": "🎪",
|
||
"steam_locomotive": "🚂",
|
||
"railway_car": "🚃",
|
||
"bullettrain_side": "🚄",
|
||
"bullettrain_front": "🚅",
|
||
"train2": "🚆",
|
||
"metro": "🚇",
|
||
"light_rail": "🚈",
|
||
"station": "🚉",
|
||
"tram": "🚊",
|
||
"monorail": "🚝",
|
||
"mountain_railway": "🚞",
|
||
"train": "🚋",
|
||
"bus": "🚌",
|
||
"oncoming_bus": "🚍",
|
||
"trolleybus": "🚎",
|
||
"minibus": "🚐",
|
||
"ambulance": "🚑",
|
||
"fire_engine": "🚒",
|
||
"police_car": "🚓",
|
||
"oncoming_police_car": "🚔",
|
||
"taxi": "🚕",
|
||
"oncoming_taxi": "🚖",
|
||
"car": "🚗",
|
||
"red_car": "🚗",
|
||
"oncoming_automobile": "🚘",
|
||
"blue_car": "🚙",
|
||
"pickup_truck": "🛻",
|
||
"truck": "🚚",
|
||
"articulated_lorry": "🚛",
|
||
"tractor": "🚜",
|
||
"racing_car": "🏎️",
|
||
"motorcycle": "🏍️",
|
||
"motor_scooter": "🛵",
|
||
"manual_wheelchair": "🦽",
|
||
"motorized_wheelchair": "🦼",
|
||
"auto_rickshaw": "🛺",
|
||
"bike": "🚲",
|
||
"kick_scooter": "🛴",
|
||
"skateboard": "🛹",
|
||
"roller_skate": "🛼",
|
||
"busstop": "🚏",
|
||
"motorway": "🛣️",
|
||
"railway_track": "🛤️",
|
||
"oil_drum": "🛢️",
|
||
"fuelpump": "⛽",
|
||
"wheel": "🛞",
|
||
"rotating_light": "🚨",
|
||
"traffic_light": "🚥",
|
||
"vertical_traffic_light": "🚦",
|
||
"stop_sign": "🛑",
|
||
"construction": "🚧",
|
||
"anchor": "⚓",
|
||
"ring_buoy": "🛟",
|
||
"boat": "⛵",
|
||
"sailboat": "⛵",
|
||
"canoe": "🛶",
|
||
"speedboat": "🚤",
|
||
"passenger_ship": "🛳️",
|
||
"ferry": "⛴️",
|
||
"motor_boat": "🛥️",
|
||
"ship": "🚢",
|
||
"airplane": "✈️",
|
||
"small_airplane": "🛩️",
|
||
"flight_departure": "🛫",
|
||
"flight_arrival": "🛬",
|
||
"parachute": "🪂",
|
||
"seat": "💺",
|
||
"helicopter": "🚁",
|
||
"suspension_railway": "🚟",
|
||
"mountain_cableway": "🚠",
|
||
"aerial_tramway": "🚡",
|
||
"artificial_satellite": "🛰️",
|
||
"rocket": "🚀",
|
||
"flying_saucer": "🛸",
|
||
"bellhop_bell": "🛎️",
|
||
"luggage": "🧳",
|
||
"hourglass": "⌛",
|
||
"hourglass_flowing_sand": "⏳",
|
||
"watch": "⌚",
|
||
"alarm_clock": "⏰",
|
||
"stopwatch": "⏱️",
|
||
"timer_clock": "⏲️",
|
||
"mantelpiece_clock": "🕰️",
|
||
"clock12": "🕛",
|
||
"clock1230": "🕧",
|
||
"clock1": "🕐",
|
||
"clock130": "🕜",
|
||
"clock2": "🕑",
|
||
"clock230": "🕝",
|
||
"clock3": "🕒",
|
||
"clock330": "🕞",
|
||
"clock4": "🕓",
|
||
"clock430": "🕟",
|
||
"clock5": "🕔",
|
||
"clock530": "🕠",
|
||
"clock6": "🕕",
|
||
"clock630": "🕡",
|
||
"clock7": "🕖",
|
||
"clock730": "🕢",
|
||
"clock8": "🕗",
|
||
"clock830": "🕣",
|
||
"clock9": "🕘",
|
||
"clock930": "🕤",
|
||
"clock10": "🕙",
|
||
"clock1030": "🕥",
|
||
"clock11": "🕚",
|
||
"clock1130": "🕦",
|
||
"new_moon": "🌑",
|
||
"waxing_crescent_moon": "🌒",
|
||
"first_quarter_moon": "🌓",
|
||
"moon": "🌔",
|
||
"waxing_gibbous_moon": "🌔",
|
||
"full_moon": "🌕",
|
||
"waning_gibbous_moon": "🌖",
|
||
"last_quarter_moon": "🌗",
|
||
"waning_crescent_moon": "🌘",
|
||
"crescent_moon": "🌙",
|
||
"new_moon_with_face": "🌚",
|
||
"first_quarter_moon_with_face": "🌛",
|
||
"last_quarter_moon_with_face": "🌜",
|
||
"thermometer": "🌡️",
|
||
"sunny": "☀️",
|
||
"full_moon_with_face": "🌝",
|
||
"sun_with_face": "🌞",
|
||
"ringed_planet": "🪐",
|
||
"star": "⭐",
|
||
"star2": "🌟",
|
||
"stars": "🌠",
|
||
"milky_way": "🌌",
|
||
"cloud": "☁️",
|
||
"partly_sunny": "⛅",
|
||
"cloud_with_lightning_and_rain": "⛈️",
|
||
"sun_behind_small_cloud": "🌤️",
|
||
"sun_behind_large_cloud": "🌥️",
|
||
"sun_behind_rain_cloud": "🌦️",
|
||
"cloud_with_rain": "🌧️",
|
||
"cloud_with_snow": "🌨️",
|
||
"cloud_with_lightning": "🌩️",
|
||
"tornado": "🌪️",
|
||
"fog": "🌫️",
|
||
"wind_face": "🌬️",
|
||
"cyclone": "🌀",
|
||
"rainbow": "🌈",
|
||
"closed_umbrella": "🌂",
|
||
"open_umbrella": "☂️",
|
||
"umbrella": "☔",
|
||
"parasol_on_ground": "⛱️",
|
||
"zap": "⚡",
|
||
"snowflake": "❄️",
|
||
"snowman_with_snow": "☃️",
|
||
"snowman": "⛄",
|
||
"comet": "☄️",
|
||
"fire": "🔥",
|
||
"droplet": "💧",
|
||
"ocean": "🌊",
|
||
"jack_o_lantern": "🎃",
|
||
"christmas_tree": "🎄",
|
||
"fireworks": "🎆",
|
||
"sparkler": "🎇",
|
||
"firecracker": "🧨",
|
||
"sparkles": "✨",
|
||
"balloon": "🎈",
|
||
"tada": "🎉",
|
||
"confetti_ball": "🎊",
|
||
"tanabata_tree": "🎋",
|
||
"bamboo": "🎍",
|
||
"dolls": "🎎",
|
||
"flags": "🎏",
|
||
"wind_chime": "🎐",
|
||
"rice_scene": "🎑",
|
||
"red_envelope": "🧧",
|
||
"ribbon": "🎀",
|
||
"gift": "🎁",
|
||
"reminder_ribbon": "🎗️",
|
||
"tickets": "🎟️",
|
||
"ticket": "🎫",
|
||
"medal_military": "🎖️",
|
||
"trophy": "🏆",
|
||
"medal_sports": "🏅",
|
||
"1st_place_medal": "🥇",
|
||
"2nd_place_medal": "🥈",
|
||
"3rd_place_medal": "🥉",
|
||
"soccer": "⚽",
|
||
"baseball": "⚾",
|
||
"softball": "🥎",
|
||
"basketball": "🏀",
|
||
"volleyball": "🏐",
|
||
"football": "🏈",
|
||
"rugby_football": "🏉",
|
||
"tennis": "🎾",
|
||
"flying_disc": "🥏",
|
||
"bowling": "🎳",
|
||
"cricket_game": "🏏",
|
||
"field_hockey": "🏑",
|
||
"ice_hockey": "🏒",
|
||
"lacrosse": "🥍",
|
||
"ping_pong": "🏓",
|
||
"badminton": "🏸",
|
||
"boxing_glove": "🥊",
|
||
"martial_arts_uniform": "🥋",
|
||
"goal_net": "🥅",
|
||
"golf": "⛳",
|
||
"ice_skate": "⛸️",
|
||
"fishing_pole_and_fish": "🎣",
|
||
"diving_mask": "🤿",
|
||
"running_shirt_with_sash": "🎽",
|
||
"ski": "🎿",
|
||
"sled": "🛷",
|
||
"curling_stone": "🥌",
|
||
"dart": "🎯",
|
||
"yo_yo": "🪀",
|
||
"kite": "🪁",
|
||
"gun": "🔫",
|
||
"8ball": "🎱",
|
||
"crystal_ball": "🔮",
|
||
"magic_wand": "🪄",
|
||
"video_game": "🎮",
|
||
"joystick": "🕹️",
|
||
"slot_machine": "🎰",
|
||
"game_die": "🎲",
|
||
"jigsaw": "🧩",
|
||
"teddy_bear": "🧸",
|
||
"pinata": "🪅",
|
||
"mirror_ball": "🪩",
|
||
"nesting_dolls": "🪆",
|
||
"spades": "♠️",
|
||
"hearts": "♥️",
|
||
"diamonds": "♦️",
|
||
"clubs": "♣️",
|
||
"chess_pawn": "♟️",
|
||
"black_joker": "🃏",
|
||
"mahjong": "🀄",
|
||
"flower_playing_cards": "🎴",
|
||
"performing_arts": "🎭",
|
||
"framed_picture": "🖼️",
|
||
"art": "🎨",
|
||
"thread": "🧵",
|
||
"sewing_needle": "🪡",
|
||
"yarn": "🧶",
|
||
"knot": "🪢",
|
||
"eyeglasses": "👓",
|
||
"dark_sunglasses": "🕶️",
|
||
"goggles": "🥽",
|
||
"lab_coat": "🥼",
|
||
"safety_vest": "🦺",
|
||
"necktie": "👔",
|
||
"shirt": "👕",
|
||
"tshirt": "👕",
|
||
"jeans": "👖",
|
||
"scarf": "🧣",
|
||
"gloves": "🧤",
|
||
"coat": "🧥",
|
||
"socks": "🧦",
|
||
"dress": "👗",
|
||
"kimono": "👘",
|
||
"sari": "🥻",
|
||
"one_piece_swimsuit": "🩱",
|
||
"swim_brief": "🩲",
|
||
"shorts": "🩳",
|
||
"bikini": "👙",
|
||
"womans_clothes": "👚",
|
||
"folding_hand_fan": "🪭",
|
||
"purse": "👛",
|
||
"handbag": "👜",
|
||
"pouch": "👝",
|
||
"shopping": "🛍️",
|
||
"school_satchel": "🎒",
|
||
"thong_sandal": "🩴",
|
||
"mans_shoe": "👞",
|
||
"shoe": "👞",
|
||
"athletic_shoe": "👟",
|
||
"hiking_boot": "🥾",
|
||
"flat_shoe": "🥿",
|
||
"high_heel": "👠",
|
||
"sandal": "👡",
|
||
"ballet_shoes": "🩰",
|
||
"boot": "👢",
|
||
"hair_pick": "🪮",
|
||
"crown": "👑",
|
||
"womans_hat": "👒",
|
||
"tophat": "🎩",
|
||
"mortar_board": "🎓",
|
||
"billed_cap": "🧢",
|
||
"military_helmet": "🪖",
|
||
"rescue_worker_helmet": "⛑️",
|
||
"prayer_beads": "📿",
|
||
"lipstick": "💄",
|
||
"ring": "💍",
|
||
"gem": "💎",
|
||
"mute": "🔇",
|
||
"speaker": "🔈",
|
||
"sound": "🔉",
|
||
"loud_sound": "🔊",
|
||
"loudspeaker": "📢",
|
||
"mega": "📣",
|
||
"postal_horn": "📯",
|
||
"bell": "🔔",
|
||
"no_bell": "🔕",
|
||
"musical_score": "🎼",
|
||
"musical_note": "🎵",
|
||
"notes": "🎶",
|
||
"studio_microphone": "🎙️",
|
||
"level_slider": "🎚️",
|
||
"control_knobs": "🎛️",
|
||
"microphone": "🎤",
|
||
"headphones": "🎧",
|
||
"radio": "📻",
|
||
"saxophone": "🎷",
|
||
"accordion": "🪗",
|
||
"guitar": "🎸",
|
||
"musical_keyboard": "🎹",
|
||
"trumpet": "🎺",
|
||
"violin": "🎻",
|
||
"banjo": "🪕",
|
||
"drum": "🥁",
|
||
"long_drum": "🪘",
|
||
"maracas": "🪇",
|
||
"flute": "🪈",
|
||
"iphone": "📱",
|
||
"calling": "📲",
|
||
"phone": "☎️",
|
||
"telephone": "☎️",
|
||
"telephone_receiver": "📞",
|
||
"pager": "📟",
|
||
"fax": "📠",
|
||
"battery": "🔋",
|
||
"low_battery": "🪫",
|
||
"electric_plug": "🔌",
|
||
"computer": "💻",
|
||
"desktop_computer": "🖥️",
|
||
"printer": "🖨️",
|
||
"keyboard": "⌨️",
|
||
"computer_mouse": "🖱️",
|
||
"trackball": "🖲️",
|
||
"minidisc": "💽",
|
||
"floppy_disk": "💾",
|
||
"cd": "💿",
|
||
"dvd": "📀",
|
||
"abacus": "🧮",
|
||
"movie_camera": "🎥",
|
||
"film_strip": "🎞️",
|
||
"film_projector": "📽️",
|
||
"clapper": "🎬",
|
||
"tv": "📺",
|
||
"camera": "📷",
|
||
"camera_flash": "📸",
|
||
"video_camera": "📹",
|
||
"vhs": "📼",
|
||
"mag": "🔍",
|
||
"mag_right": "🔎",
|
||
"candle": "🕯️",
|
||
"bulb": "💡",
|
||
"flashlight": "🔦",
|
||
"izakaya_lantern": "🏮",
|
||
"lantern": "🏮",
|
||
"diya_lamp": "🪔",
|
||
"notebook_with_decorative_cover": "📔",
|
||
"closed_book": "📕",
|
||
"book": "📖",
|
||
"open_book": "📖",
|
||
"green_book": "📗",
|
||
"blue_book": "📘",
|
||
"orange_book": "📙",
|
||
"books": "📚",
|
||
"notebook": "📓",
|
||
"ledger": "📒",
|
||
"page_with_curl": "📃",
|
||
"scroll": "📜",
|
||
"page_facing_up": "📄",
|
||
"newspaper": "📰",
|
||
"newspaper_roll": "🗞️",
|
||
"bookmark_tabs": "📑",
|
||
"bookmark": "🔖",
|
||
"label": "🏷️",
|
||
"moneybag": "💰",
|
||
"coin": "🪙",
|
||
"yen": "💴",
|
||
"dollar": "💵",
|
||
"euro": "💶",
|
||
"pound": "💷",
|
||
"money_with_wings": "💸",
|
||
"credit_card": "💳",
|
||
"receipt": "🧾",
|
||
"chart": "💹",
|
||
"envelope": "✉️",
|
||
"email": "📧",
|
||
"e-mail": "📧",
|
||
"incoming_envelope": "📨",
|
||
"envelope_with_arrow": "📩",
|
||
"outbox_tray": "📤",
|
||
"inbox_tray": "📥",
|
||
"package": "📦",
|
||
"mailbox": "📫",
|
||
"mailbox_closed": "📪",
|
||
"mailbox_with_mail": "📬",
|
||
"mailbox_with_no_mail": "📭",
|
||
"postbox": "📮",
|
||
"ballot_box": "🗳️",
|
||
"pencil2": "✏️",
|
||
"black_nib": "✒️",
|
||
"fountain_pen": "🖋️",
|
||
"pen": "🖊️",
|
||
"paintbrush": "🖌️",
|
||
"crayon": "🖍️",
|
||
"memo": "📝",
|
||
"pencil": "📝",
|
||
"briefcase": "💼",
|
||
"file_folder": "📁",
|
||
"open_file_folder": "📂",
|
||
"card_index_dividers": "🗂️",
|
||
"date": "📅",
|
||
"calendar": "📆",
|
||
"spiral_notepad": "🗒️",
|
||
"spiral_calendar": "🗓️",
|
||
"card_index": "📇",
|
||
"chart_with_upwards_trend": "📈",
|
||
"chart_with_downwards_trend": "📉",
|
||
"bar_chart": "📊",
|
||
"clipboard": "📋",
|
||
"pushpin": "📌",
|
||
"round_pushpin": "📍",
|
||
"paperclip": "📎",
|
||
"paperclips": "🖇️",
|
||
"straight_ruler": "📏",
|
||
"triangular_ruler": "📐",
|
||
"scissors": "✂️",
|
||
"card_file_box": "🗃️",
|
||
"file_cabinet": "🗄️",
|
||
"wastebasket": "🗑️",
|
||
"lock": "🔒",
|
||
"unlock": "🔓",
|
||
"lock_with_ink_pen": "🔏",
|
||
"closed_lock_with_key": "🔐",
|
||
"key": "🔑",
|
||
"old_key": "🗝️",
|
||
"hammer": "🔨",
|
||
"axe": "🪓",
|
||
"pick": "⛏️",
|
||
"hammer_and_pick": "⚒️",
|
||
"hammer_and_wrench": "🛠️",
|
||
"dagger": "🗡️",
|
||
"crossed_swords": "⚔️",
|
||
"bomb": "💣",
|
||
"boomerang": "🪃",
|
||
"bow_and_arrow": "🏹",
|
||
"shield": "🛡️",
|
||
"carpentry_saw": "🪚",
|
||
"wrench": "🔧",
|
||
"screwdriver": "🪛",
|
||
"nut_and_bolt": "🔩",
|
||
"gear": "⚙️",
|
||
"clamp": "🗜️",
|
||
"balance_scale": "⚖️",
|
||
"probing_cane": "🦯",
|
||
"link": "🔗",
|
||
"chains": "⛓️",
|
||
"hook": "🪝",
|
||
"toolbox": "🧰",
|
||
"magnet": "🧲",
|
||
"ladder": "🪜",
|
||
"alembic": "⚗️",
|
||
"test_tube": "🧪",
|
||
"petri_dish": "🧫",
|
||
"dna": "🧬",
|
||
"microscope": "🔬",
|
||
"telescope": "🔭",
|
||
"satellite": "📡",
|
||
"syringe": "💉",
|
||
"drop_of_blood": "🩸",
|
||
"pill": "💊",
|
||
"adhesive_bandage": "🩹",
|
||
"crutch": "🩼",
|
||
"stethoscope": "🩺",
|
||
"x_ray": "🩻",
|
||
"door": "🚪",
|
||
"elevator": "🛗",
|
||
"mirror": "🪞",
|
||
"window": "🪟",
|
||
"bed": "🛏️",
|
||
"couch_and_lamp": "🛋️",
|
||
"chair": "🪑",
|
||
"toilet": "🚽",
|
||
"plunger": "🪠",
|
||
"shower": "🚿",
|
||
"bathtub": "🛁",
|
||
"mouse_trap": "🪤",
|
||
"razor": "🪒",
|
||
"lotion_bottle": "🧴",
|
||
"safety_pin": "🧷",
|
||
"broom": "🧹",
|
||
"basket": "🧺",
|
||
"roll_of_paper": "🧻",
|
||
"bucket": "🪣",
|
||
"soap": "🧼",
|
||
"bubbles": "🫧",
|
||
"toothbrush": "🪥",
|
||
"sponge": "🧽",
|
||
"fire_extinguisher": "🧯",
|
||
"shopping_cart": "🛒",
|
||
"smoking": "🚬",
|
||
"coffin": "⚰️",
|
||
"headstone": "🪦",
|
||
"funeral_urn": "⚱️",
|
||
"nazar_amulet": "🧿",
|
||
"hamsa": "🪬",
|
||
"moyai": "🗿",
|
||
"placard": "🪧",
|
||
"identification_card": "🪪",
|
||
"atm": "🏧",
|
||
"put_litter_in_its_place": "🚮",
|
||
"potable_water": "🚰",
|
||
"wheelchair": "♿",
|
||
"mens": "🚹",
|
||
"womens": "🚺",
|
||
"restroom": "🚻",
|
||
"baby_symbol": "🚼",
|
||
"wc": "🚾",
|
||
"passport_control": "🛂",
|
||
"customs": "🛃",
|
||
"baggage_claim": "🛄",
|
||
"left_luggage": "🛅",
|
||
"warning": "⚠️",
|
||
"children_crossing": "🚸",
|
||
"no_entry": "⛔",
|
||
"no_entry_sign": "🚫",
|
||
"no_bicycles": "🚳",
|
||
"no_smoking": "🚭",
|
||
"do_not_litter": "🚯",
|
||
"non-potable_water": "🚱",
|
||
"no_pedestrians": "🚷",
|
||
"no_mobile_phones": "📵",
|
||
"underage": "🔞",
|
||
"radioactive": "☢️",
|
||
"biohazard": "☣️",
|
||
"arrow_up": "⬆️",
|
||
"arrow_upper_right": "↗️",
|
||
"arrow_right": "➡️",
|
||
"arrow_lower_right": "↘️",
|
||
"arrow_down": "⬇️",
|
||
"arrow_lower_left": "↙️",
|
||
"arrow_left": "⬅️",
|
||
"arrow_upper_left": "↖️",
|
||
"arrow_up_down": "↕️",
|
||
"left_right_arrow": "↔️",
|
||
"leftwards_arrow_with_hook": "↩️",
|
||
"arrow_right_hook": "↪️",
|
||
"arrow_heading_up": "⤴️",
|
||
"arrow_heading_down": "⤵️",
|
||
"arrows_clockwise": "🔃",
|
||
"arrows_counterclockwise": "🔄",
|
||
"back": "🔙",
|
||
"end": "🔚",
|
||
"on": "🔛",
|
||
"soon": "🔜",
|
||
"top": "🔝",
|
||
"place_of_worship": "🛐",
|
||
"atom_symbol": "⚛️",
|
||
"om": "🕉️",
|
||
"star_of_david": "✡️",
|
||
"wheel_of_dharma": "☸️",
|
||
"yin_yang": "☯️",
|
||
"latin_cross": "✝️",
|
||
"orthodox_cross": "☦️",
|
||
"star_and_crescent": "☪️",
|
||
"peace_symbol": "☮️",
|
||
"menorah": "🕎",
|
||
"six_pointed_star": "🔯",
|
||
"khanda": "🪯",
|
||
"aries": "♈",
|
||
"taurus": "♉",
|
||
"gemini": "♊",
|
||
"cancer": "♋",
|
||
"leo": "♌",
|
||
"virgo": "♍",
|
||
"libra": "♎",
|
||
"scorpius": "♏",
|
||
"sagittarius": "♐",
|
||
"capricorn": "♑",
|
||
"aquarius": "♒",
|
||
"pisces": "♓",
|
||
"ophiuchus": "⛎",
|
||
"twisted_rightwards_arrows": "🔀",
|
||
"repeat": "🔁",
|
||
"repeat_one": "🔂",
|
||
"arrow_forward": "▶️",
|
||
"fast_forward": "⏩",
|
||
"next_track_button": "⏭️",
|
||
"play_or_pause_button": "⏯️",
|
||
"arrow_backward": "◀️",
|
||
"rewind": "⏪",
|
||
"previous_track_button": "⏮️",
|
||
"arrow_up_small": "🔼",
|
||
"arrow_double_up": "⏫",
|
||
"arrow_down_small": "🔽",
|
||
"arrow_double_down": "⏬",
|
||
"pause_button": "⏸️",
|
||
"stop_button": "⏹️",
|
||
"record_button": "⏺️",
|
||
"eject_button": "⏏️",
|
||
"cinema": "🎦",
|
||
"low_brightness": "🔅",
|
||
"high_brightness": "🔆",
|
||
"signal_strength": "📶",
|
||
"wireless": "🛜",
|
||
"vibration_mode": "📳",
|
||
"mobile_phone_off": "📴",
|
||
"female_sign": "♀️",
|
||
"male_sign": "♂️",
|
||
"transgender_symbol": "⚧️",
|
||
"heavy_multiplication_x": "✖️",
|
||
"heavy_plus_sign": "➕",
|
||
"heavy_minus_sign": "➖",
|
||
"heavy_division_sign": "➗",
|
||
"heavy_equals_sign": "🟰",
|
||
"infinity": "♾️",
|
||
"bangbang": "‼️",
|
||
"interrobang": "⁉️",
|
||
"question": "❓",
|
||
"grey_question": "❔",
|
||
"grey_exclamation": "❕",
|
||
"exclamation": "❗",
|
||
"heavy_exclamation_mark": "❗",
|
||
"wavy_dash": "〰️",
|
||
"currency_exchange": "💱",
|
||
"heavy_dollar_sign": "💲",
|
||
"medical_symbol": "⚕️",
|
||
"recycle": "♻️",
|
||
"fleur_de_lis": "⚜️",
|
||
"trident": "🔱",
|
||
"name_badge": "📛",
|
||
"beginner": "🔰",
|
||
"o": "⭕",
|
||
"white_check_mark": "✅",
|
||
"ballot_box_with_check": "☑️",
|
||
"heavy_check_mark": "✔️",
|
||
"x": "❌",
|
||
"negative_squared_cross_mark": "❎",
|
||
"curly_loop": "➰",
|
||
"loop": "➿",
|
||
"part_alternation_mark": "〽️",
|
||
"eight_spoked_asterisk": "✳️",
|
||
"eight_pointed_black_star": "✴️",
|
||
"sparkle": "❇️",
|
||
"copyright": "©️",
|
||
"registered": "®️",
|
||
"tm": "™️",
|
||
"hash": "#️⃣",
|
||
"asterisk": "*️⃣",
|
||
"zero": "0️⃣",
|
||
"one": "1️⃣",
|
||
"two": "2️⃣",
|
||
"three": "3️⃣",
|
||
"four": "4️⃣",
|
||
"five": "5️⃣",
|
||
"six": "6️⃣",
|
||
"seven": "7️⃣",
|
||
"eight": "8️⃣",
|
||
"nine": "9️⃣",
|
||
"keycap_ten": "🔟",
|
||
"capital_abcd": "🔠",
|
||
"abcd": "🔡",
|
||
"symbols": "🔣",
|
||
"abc": "🔤",
|
||
"a": "🅰️",
|
||
"ab": "🆎",
|
||
"b": "🅱️",
|
||
"cl": "🆑",
|
||
"cool": "🆒",
|
||
"free": "🆓",
|
||
"information_source": "ℹ️",
|
||
"id": "🆔",
|
||
"m": "Ⓜ️",
|
||
"new": "🆕",
|
||
"ng": "🆖",
|
||
"o2": "🅾️",
|
||
"ok": "🆗",
|
||
"parking": "🅿️",
|
||
"sos": "🆘",
|
||
"up": "🆙",
|
||
"vs": "🆚",
|
||
"koko": "🈁",
|
||
"sa": "🈂️",
|
||
"ideograph_advantage": "🉐",
|
||
"accept": "🉑",
|
||
"congratulations": "㊗️",
|
||
"secret": "㊙️",
|
||
"u6e80": "🈵",
|
||
"red_circle": "🔴",
|
||
"orange_circle": "🟠",
|
||
"yellow_circle": "🟡",
|
||
"green_circle": "🟢",
|
||
"large_blue_circle": "🔵",
|
||
"purple_circle": "🟣",
|
||
"brown_circle": "🟤",
|
||
"black_circle": "⚫",
|
||
"white_circle": "⚪",
|
||
"red_square": "🟥",
|
||
"orange_square": "🟧",
|
||
"yellow_square": "🟨",
|
||
"green_square": "🟩",
|
||
"blue_square": "🟦",
|
||
"purple_square": "🟪",
|
||
"brown_square": "🟫",
|
||
"black_large_square": "⬛",
|
||
"white_large_square": "⬜",
|
||
"black_medium_square": "◼️",
|
||
"white_medium_square": "◻️",
|
||
"black_medium_small_square": "◾",
|
||
"white_medium_small_square": "◽",
|
||
"black_small_square": "▪️",
|
||
"white_small_square": "▫️",
|
||
"large_orange_diamond": "🔶",
|
||
"large_blue_diamond": "🔷",
|
||
"small_orange_diamond": "🔸",
|
||
"small_blue_diamond": "🔹",
|
||
"small_red_triangle": "🔺",
|
||
"small_red_triangle_down": "🔻",
|
||
"diamond_shape_with_a_dot_inside": "💠",
|
||
"radio_button": "🔘",
|
||
"white_square_button": "🔳",
|
||
"black_square_button": "🔲",
|
||
"checkered_flag": "🏁",
|
||
"triangular_flag_on_post": "🚩",
|
||
"crossed_flags": "🎌",
|
||
"black_flag": "🏴",
|
||
"white_flag": "🏳️",
|
||
"rainbow_flag": "🏳️🌈",
|
||
"transgender_flag": "🏳️⚧️",
|
||
"pirate_flag": "🏴☠️",
|
||
"ascension_island": "🇦🇨",
|
||
"andorra": "🇦🇩",
|
||
"united_arab_emirates": "🇦🇪",
|
||
"afghanistan": "🇦🇫",
|
||
"antigua_barbuda": "🇦🇬",
|
||
"anguilla": "🇦🇮",
|
||
"albania": "🇦🇱",
|
||
"armenia": "🇦🇲",
|
||
"angola": "🇦🇴",
|
||
"antarctica": "🇦🇶",
|
||
"argentina": "🇦🇷",
|
||
"american_samoa": "🇦🇸",
|
||
"austria": "🇦🇹",
|
||
"australia": "🇦🇺",
|
||
"aruba": "🇦🇼",
|
||
"aland_islands": "🇦🇽",
|
||
"azerbaijan": "🇦🇿",
|
||
"bosnia_herzegovina": "🇧🇦",
|
||
"barbados": "🇧🇧",
|
||
"bangladesh": "🇧🇩",
|
||
"belgium": "🇧🇪",
|
||
"burkina_faso": "🇧🇫",
|
||
"bulgaria": "🇧🇬",
|
||
"bahrain": "🇧🇭",
|
||
"burundi": "🇧🇮",
|
||
"benin": "🇧🇯",
|
||
"st_barthelemy": "🇧🇱",
|
||
"bermuda": "🇧🇲",
|
||
"brunei": "🇧🇳",
|
||
"bolivia": "🇧🇴",
|
||
"caribbean_netherlands": "🇧🇶",
|
||
"brazil": "🇧🇷",
|
||
"bahamas": "🇧🇸",
|
||
"bhutan": "🇧🇹",
|
||
"bouvet_island": "🇧🇻",
|
||
"botswana": "🇧🇼",
|
||
"belarus": "🇧🇾",
|
||
"belize": "🇧🇿",
|
||
"canada": "🇨🇦",
|
||
"cocos_islands": "🇨🇨",
|
||
"congo_kinshasa": "🇨🇩",
|
||
"central_african_republic": "🇨🇫",
|
||
"congo_brazzaville": "🇨🇬",
|
||
"switzerland": "🇨🇭",
|
||
"cote_divoire": "🇨🇮",
|
||
"cook_islands": "🇨🇰",
|
||
"chile": "🇨🇱",
|
||
"cameroon": "🇨🇲",
|
||
"cn": "🇨🇳",
|
||
"colombia": "🇨🇴",
|
||
"clipperton_island": "🇨🇵",
|
||
"costa_rica": "🇨🇷",
|
||
"cuba": "🇨🇺",
|
||
"cape_verde": "🇨🇻",
|
||
"curacao": "🇨🇼",
|
||
"christmas_island": "🇨🇽",
|
||
"cyprus": "🇨🇾",
|
||
"czech_republic": "🇨🇿",
|
||
"de": "🇩🇪",
|
||
"diego_garcia": "🇩🇬",
|
||
"djibouti": "🇩🇯",
|
||
"denmark": "🇩🇰",
|
||
"dominica": "🇩🇲",
|
||
"dominican_republic": "🇩🇴",
|
||
"algeria": "🇩🇿",
|
||
"ceuta_melilla": "🇪🇦",
|
||
"ecuador": "🇪🇨",
|
||
"estonia": "🇪🇪",
|
||
"egypt": "🇪🇬",
|
||
"western_sahara": "🇪🇭",
|
||
"eritrea": "🇪🇷",
|
||
"es": "🇪🇸",
|
||
"ethiopia": "🇪🇹",
|
||
"eu": "🇪🇺",
|
||
"european_union": "🇪🇺",
|
||
"finland": "🇫🇮",
|
||
"fiji": "🇫🇯",
|
||
"falkland_islands": "🇫🇰",
|
||
"micronesia": "🇫🇲",
|
||
"faroe_islands": "🇫🇴",
|
||
"fr": "🇫🇷",
|
||
"gabon": "🇬🇦",
|
||
"gb": "🇬🇧",
|
||
"uk": "🇬🇧",
|
||
"grenada": "🇬🇩",
|
||
"georgia": "🇬🇪",
|
||
"french_guiana": "🇬🇫",
|
||
"guernsey": "🇬🇬",
|
||
"ghana": "🇬🇭",
|
||
"gibraltar": "🇬🇮",
|
||
"greenland": "🇬🇱",
|
||
"gambia": "🇬🇲",
|
||
"guinea": "🇬🇳",
|
||
"guadeloupe": "🇬🇵",
|
||
"equatorial_guinea": "🇬🇶",
|
||
"greece": "🇬🇷",
|
||
"south_georgia_south_sandwich_islands": "🇬🇸",
|
||
"guatemala": "🇬🇹",
|
||
"guam": "🇬🇺",
|
||
"guinea_bissau": "🇬🇼",
|
||
"guyana": "🇬🇾",
|
||
"hong_kong": "🇭🇰",
|
||
"heard_mcdonald_islands": "🇭🇲",
|
||
"honduras": "🇭🇳",
|
||
"croatia": "🇭🇷",
|
||
"haiti": "🇭🇹",
|
||
"hungary": "🇭🇺",
|
||
"canary_islands": "🇮🇨",
|
||
"indonesia": "🇮🇩",
|
||
"ireland": "🇮🇪",
|
||
"israel": "🇮🇱",
|
||
"isle_of_man": "🇮🇲",
|
||
"india": "🇮🇳",
|
||
"british_indian_ocean_territory": "🇮🇴",
|
||
"iraq": "🇮🇶",
|
||
"iran": "🇮🇷",
|
||
"iceland": "🇮🇸",
|
||
"it": "🇮🇹",
|
||
"jersey": "🇯🇪",
|
||
"jamaica": "🇯🇲",
|
||
"jordan": "🇯🇴",
|
||
"jp": "🇯🇵",
|
||
"kenya": "🇰🇪",
|
||
"kyrgyzstan": "🇰🇬",
|
||
"cambodia": "🇰🇭",
|
||
"kiribati": "🇰🇮",
|
||
"comoros": "🇰🇲",
|
||
"st_kitts_nevis": "🇰🇳",
|
||
"north_korea": "🇰🇵",
|
||
"kr": "🇰🇷",
|
||
"kuwait": "🇰🇼",
|
||
"cayman_islands": "🇰🇾",
|
||
"kazakhstan": "🇰🇿",
|
||
"laos": "🇱🇦",
|
||
"lebanon": "🇱🇧",
|
||
"st_lucia": "🇱🇨",
|
||
"liechtenstein": "🇱🇮",
|
||
"sri_lanka": "🇱🇰",
|
||
"liberia": "🇱🇷",
|
||
"lesotho": "🇱🇸",
|
||
"lithuania": "🇱🇹",
|
||
"luxembourg": "🇱🇺",
|
||
"latvia": "🇱🇻",
|
||
"libya": "🇱🇾",
|
||
"morocco": "🇲🇦",
|
||
"monaco": "🇲🇨",
|
||
"moldova": "🇲🇩",
|
||
"montenegro": "🇲🇪",
|
||
"st_martin": "🇲🇫",
|
||
"madagascar": "🇲🇬",
|
||
"marshall_islands": "🇲🇭",
|
||
"macedonia": "🇲🇰",
|
||
"mali": "🇲🇱",
|
||
"myanmar": "🇲🇲",
|
||
"mongolia": "🇲🇳",
|
||
"macau": "🇲🇴",
|
||
"northern_mariana_islands": "🇲🇵",
|
||
"martinique": "🇲🇶",
|
||
"mauritania": "🇲🇷",
|
||
"montserrat": "🇲🇸",
|
||
"malta": "🇲🇹",
|
||
"mauritius": "🇲🇺",
|
||
"maldives": "🇲🇻",
|
||
"malawi": "🇲🇼",
|
||
"mexico": "🇲🇽",
|
||
"malaysia": "🇲🇾",
|
||
"mozambique": "🇲🇿",
|
||
"namibia": "🇳🇦",
|
||
"new_caledonia": "🇳🇨",
|
||
"niger": "🇳🇪",
|
||
"norfolk_island": "🇳🇫",
|
||
"nigeria": "🇳🇬",
|
||
"nicaragua": "🇳🇮",
|
||
"netherlands": "🇳🇱",
|
||
"norway": "🇳🇴",
|
||
"nepal": "🇳🇵",
|
||
"nauru": "🇳🇷",
|
||
"niue": "🇳🇺",
|
||
"new_zealand": "🇳🇿",
|
||
"oman": "🇴🇲",
|
||
"panama": "🇵🇦",
|
||
"peru": "🇵🇪",
|
||
"french_polynesia": "🇵🇫",
|
||
"papua_new_guinea": "🇵🇬",
|
||
"philippines": "🇵🇭",
|
||
"pakistan": "🇵🇰",
|
||
"poland": "🇵🇱",
|
||
"st_pierre_miquelon": "🇵🇲",
|
||
"pitcairn_islands": "🇵🇳",
|
||
"puerto_rico": "🇵🇷",
|
||
"palestinian_territories": "🇵🇸",
|
||
"portugal": "🇵🇹",
|
||
"palau": "🇵🇼",
|
||
"paraguay": "🇵🇾",
|
||
"qatar": "🇶🇦",
|
||
"reunion": "🇷🇪",
|
||
"romania": "🇷🇴",
|
||
"serbia": "🇷🇸",
|
||
"ru": "🇷🇺",
|
||
"rwanda": "🇷🇼",
|
||
"saudi_arabia": "🇸🇦",
|
||
"solomon_islands": "🇸🇧",
|
||
"seychelles": "🇸🇨",
|
||
"sudan": "🇸🇩",
|
||
"sweden": "🇸🇪",
|
||
"singapore": "🇸🇬",
|
||
"st_helena": "🇸🇭",
|
||
"slovenia": "🇸🇮",
|
||
"svalbard_jan_mayen": "🇸🇯",
|
||
"slovakia": "🇸🇰",
|
||
"sierra_leone": "🇸🇱",
|
||
"san_marino": "🇸🇲",
|
||
"senegal": "🇸🇳",
|
||
"somalia": "🇸🇴",
|
||
"suriname": "🇸🇷",
|
||
"south_sudan": "🇸🇸",
|
||
"sao_tome_principe": "🇸🇹",
|
||
"el_salvador": "🇸🇻",
|
||
"sint_maarten": "🇸🇽",
|
||
"syria": "🇸🇾",
|
||
"swaziland": "🇸🇿",
|
||
"tristan_da_cunha": "🇹🇦",
|
||
"turks_caicos_islands": "🇹🇨",
|
||
"chad": "🇹🇩",
|
||
"french_southern_territories": "🇹🇫",
|
||
"togo": "🇹🇬",
|
||
"thailand": "🇹🇭",
|
||
"tajikistan": "🇹🇯",
|
||
"tokelau": "🇹🇰",
|
||
"timor_leste": "🇹🇱",
|
||
"turkmenistan": "🇹🇲",
|
||
"tunisia": "🇹🇳",
|
||
"tonga": "🇹🇴",
|
||
"tr": "🇹🇷",
|
||
"trinidad_tobago": "🇹🇹",
|
||
"tuvalu": "🇹🇻",
|
||
"taiwan": "🇹🇼",
|
||
"tanzania": "🇹🇿",
|
||
"ukraine": "🇺🇦",
|
||
"uganda": "🇺🇬",
|
||
"us_outlying_islands": "🇺🇲",
|
||
"united_nations": "🇺🇳",
|
||
"us": "🇺🇸",
|
||
"uruguay": "🇺🇾",
|
||
"uzbekistan": "🇺🇿",
|
||
"vatican_city": "🇻🇦",
|
||
"st_vincent_grenadines": "🇻🇨",
|
||
"venezuela": "🇻🇪",
|
||
"british_virgin_islands": "🇻🇬",
|
||
"us_virgin_islands": "🇻🇮",
|
||
"vietnam": "🇻🇳",
|
||
"vanuatu": "🇻🇺",
|
||
"wallis_futuna": "🇼🇫",
|
||
"samoa": "🇼🇸",
|
||
"kosovo": "🇽🇰",
|
||
"yemen": "🇾🇪",
|
||
"mayotte": "🇾🇹",
|
||
"south_africa": "🇿🇦",
|
||
"zambia": "🇿🇲",
|
||
"zimbabwe": "🇿🇼",
|
||
"england": "🏴",
|
||
"scotland": "🏴",
|
||
"wales": "🏴"
|
||
};
|
||
|
||
function emoji_plugin (md, options) {
|
||
const defaults = {
|
||
defs: emojies_defs,
|
||
shortcuts: emojies_shortcuts,
|
||
enabled: []
|
||
};
|
||
|
||
const opts = md.utils.assign({}, defaults, options || {});
|
||
|
||
emoji_plugin$1(md, opts);
|
||
}
|
||
|
||
// Process block-level custom containers
|
||
//
|
||
function container_plugin (md, name, options) {
|
||
// Second param may be useful if you decide
|
||
// to increase minimal allowed marker length
|
||
function validateDefault (params/*, markup */) {
|
||
return params.trim().split(' ', 2)[0] === name
|
||
}
|
||
|
||
function renderDefault (tokens, idx, _options, env, slf) {
|
||
// add a class to the opening tag
|
||
if (tokens[idx].nesting === 1) {
|
||
tokens[idx].attrJoin('class', name);
|
||
}
|
||
|
||
return slf.renderToken(tokens, idx, _options, env, slf)
|
||
}
|
||
|
||
options = options || {};
|
||
|
||
const min_markers = 3;
|
||
const marker_str = options.marker || ':';
|
||
const marker_char = marker_str.charCodeAt(0);
|
||
const marker_len = marker_str.length;
|
||
const validate = options.validate || validateDefault;
|
||
const render = options.render || renderDefault;
|
||
|
||
function container (state, startLine, endLine, silent) {
|
||
let pos;
|
||
let auto_closed = false;
|
||
let start = state.bMarks[startLine] + state.tShift[startLine];
|
||
let max = state.eMarks[startLine];
|
||
|
||
// Check out the first character quickly,
|
||
// this should filter out most of non-containers
|
||
//
|
||
if (marker_char !== state.src.charCodeAt(start)) { return false }
|
||
|
||
// Check out the rest of the marker string
|
||
//
|
||
for (pos = start + 1; pos <= max; pos++) {
|
||
if (marker_str[(pos - start) % marker_len] !== state.src[pos]) {
|
||
break
|
||
}
|
||
}
|
||
|
||
const marker_count = Math.floor((pos - start) / marker_len);
|
||
if (marker_count < min_markers) { return false }
|
||
pos -= (pos - start) % marker_len;
|
||
|
||
const markup = state.src.slice(start, pos);
|
||
const params = state.src.slice(pos, max);
|
||
if (!validate(params, markup)) { return false }
|
||
|
||
// Since start is found, we can report success here in validation mode
|
||
//
|
||
if (silent) { return true }
|
||
|
||
// Search for the end of the block
|
||
//
|
||
let nextLine = startLine;
|
||
|
||
for (;;) {
|
||
nextLine++;
|
||
if (nextLine >= endLine) {
|
||
// unclosed block should be autoclosed by end of document.
|
||
// also block seems to be autoclosed by end of parent
|
||
break
|
||
}
|
||
|
||
start = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
max = state.eMarks[nextLine];
|
||
|
||
if (start < max && state.sCount[nextLine] < state.blkIndent) {
|
||
// non-empty line with negative indent should stop the list:
|
||
// - ```
|
||
// test
|
||
break
|
||
}
|
||
|
||
if (marker_char !== state.src.charCodeAt(start)) { continue }
|
||
|
||
if (state.sCount[nextLine] - state.blkIndent >= 4) {
|
||
// closing fence should be indented less than 4 spaces
|
||
continue
|
||
}
|
||
|
||
for (pos = start + 1; pos <= max; pos++) {
|
||
if (marker_str[(pos - start) % marker_len] !== state.src[pos]) {
|
||
break
|
||
}
|
||
}
|
||
|
||
// closing code fence must be at least as long as the opening one
|
||
if (Math.floor((pos - start) / marker_len) < marker_count) { continue }
|
||
|
||
// make sure tail has spaces only
|
||
pos -= (pos - start) % marker_len;
|
||
pos = state.skipSpaces(pos);
|
||
|
||
if (pos < max) { continue }
|
||
|
||
// found!
|
||
auto_closed = true;
|
||
break
|
||
}
|
||
|
||
const old_parent = state.parentType;
|
||
const old_line_max = state.lineMax;
|
||
state.parentType = 'container';
|
||
|
||
// this will prevent lazy continuations from ever going past our end marker
|
||
state.lineMax = nextLine;
|
||
|
||
const token_o = state.push('container_' + name + '_open', 'div', 1);
|
||
token_o.markup = markup;
|
||
token_o.block = true;
|
||
token_o.info = params;
|
||
token_o.map = [startLine, nextLine];
|
||
|
||
state.md.block.tokenize(state, startLine + 1, nextLine);
|
||
|
||
const token_c = state.push('container_' + name + '_close', 'div', -1);
|
||
token_c.markup = state.src.slice(start, pos);
|
||
token_c.block = true;
|
||
|
||
state.parentType = old_parent;
|
||
state.lineMax = old_line_max;
|
||
state.line = nextLine + (auto_closed ? 1 : 0);
|
||
|
||
return true
|
||
}
|
||
|
||
md.block.ruler.before('fence', 'container_' + name, container, {
|
||
alt: ['paragraph', 'reference', 'blockquote', 'list']
|
||
});
|
||
md.renderer.rules['container_' + name + '_open'] = render;
|
||
md.renderer.rules['container_' + name + '_close'] = render;
|
||
}
|
||
|
||
const urlAlphabet =
|
||
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict';
|
||
|
||
const POOL_SIZE_MULTIPLIER = 128;
|
||
let pool, poolOffset;
|
||
function fillPool(bytes) {
|
||
if (!pool || pool.length < bytes) {
|
||
pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
|
||
webcrypto.getRandomValues(pool);
|
||
poolOffset = 0;
|
||
} else if (poolOffset + bytes > pool.length) {
|
||
webcrypto.getRandomValues(pool);
|
||
poolOffset = 0;
|
||
}
|
||
poolOffset += bytes;
|
||
}
|
||
function random(bytes) {
|
||
fillPool((bytes -= 0));
|
||
return pool.subarray(poolOffset - bytes, poolOffset)
|
||
}
|
||
function customRandom(alphabet, defaultSize, getRandom) {
|
||
let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1;
|
||
let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length);
|
||
return (size = defaultSize) => {
|
||
let id = '';
|
||
while (true) {
|
||
let bytes = getRandom(step);
|
||
let i = step;
|
||
while (i--) {
|
||
id += alphabet[bytes[i] & mask] || '';
|
||
if (id.length === size) return id
|
||
}
|
||
}
|
||
}
|
||
}
|
||
function customAlphabet(alphabet, size = 21) {
|
||
return customRandom(alphabet, size, random)
|
||
}
|
||
function nanoid$1(size = 21) {
|
||
fillPool((size -= 0));
|
||
let id = '';
|
||
for (let i = poolOffset - size; i < poolOffset; i++) {
|
||
id += urlAlphabet[pool[i] & 63];
|
||
}
|
||
return id
|
||
}
|
||
|
||
function preWrapperPlugin(md, options) {
|
||
const fence = md.renderer.rules.fence;
|
||
md.renderer.rules.fence = (...args) => {
|
||
const [tokens, idx] = args;
|
||
const token = tokens[idx];
|
||
token.info = token.info.replace(/\[.*\]/, "");
|
||
const active = / active( |$)/.test(token.info) ? " active" : "";
|
||
token.info = token.info.replace(/ active$/, "").replace(/ active /, " ");
|
||
const lang = extractLang(token.info);
|
||
const rawCode = fence(...args);
|
||
return `<div class="language-${lang}${getAdaptiveThemeMarker(
|
||
options
|
||
)}${active}"><button title="Copy Code" class="copy"></button><span class="lang">${lang}</span>${rawCode}</div>`;
|
||
};
|
||
}
|
||
function getAdaptiveThemeMarker(options) {
|
||
return options.hasSingleTheme ? "" : " vp-adaptive-theme";
|
||
}
|
||
function extractTitle(info, html = false) {
|
||
if (html) {
|
||
return info.replace(/<!--[^]*?-->/g, "").match(/data-title="(.*?)"/)?.[1] || "";
|
||
}
|
||
return info.match(/\[(.*)\]/)?.[1] || extractLang(info) || "txt";
|
||
}
|
||
function extractLang(info) {
|
||
return info.trim().replace(/=(\d*)/, "").replace(/:(no-)?line-numbers({| |$|=\d*).*/, "").replace(/(-vue|{| ).*$/, "").replace(/^vue-html$/, "template").replace(/^ansi$/, "");
|
||
}
|
||
|
||
const containerPlugin = (md, options, containerOptions) => {
|
||
md.use(...createContainer("tip", containerOptions?.tipLabel || "TIP", md)).use(...createContainer("info", containerOptions?.infoLabel || "INFO", md)).use(
|
||
...createContainer(
|
||
"warning",
|
||
containerOptions?.warningLabel || "WARNING",
|
||
md
|
||
)
|
||
).use(
|
||
...createContainer(
|
||
"danger",
|
||
containerOptions?.dangerLabel || "DANGER",
|
||
md
|
||
)
|
||
).use(
|
||
...createContainer(
|
||
"details",
|
||
containerOptions?.detailsLabel || "Details",
|
||
md
|
||
)
|
||
).use(container_plugin, "v-pre", {
|
||
render: (tokens, idx) => tokens[idx].nesting === 1 ? `<div v-pre>
|
||
` : `</div>
|
||
`
|
||
}).use(container_plugin, "raw", {
|
||
render: (tokens, idx) => tokens[idx].nesting === 1 ? `<div class="vp-raw">
|
||
` : `</div>
|
||
`
|
||
}).use(...createCodeGroup(options));
|
||
};
|
||
function createContainer(klass, defaultTitle, md) {
|
||
return [
|
||
container_plugin,
|
||
klass,
|
||
{
|
||
render(tokens, idx, _options, env) {
|
||
const token = tokens[idx];
|
||
const info = token.info.trim().slice(klass.length).trim();
|
||
const attrs = md.renderer.renderAttrs(token);
|
||
if (token.nesting === 1) {
|
||
const title = md.renderInline(info || defaultTitle, {
|
||
references: env.references
|
||
});
|
||
if (klass === "details")
|
||
return `<details class="${klass} custom-block"${attrs}><summary>${title}</summary>
|
||
`;
|
||
return `<div class="${klass} custom-block"${attrs}><p class="custom-block-title">${title}</p>
|
||
`;
|
||
} else
|
||
return klass === "details" ? `</details>
|
||
` : `</div>
|
||
`;
|
||
}
|
||
}
|
||
];
|
||
}
|
||
function createCodeGroup(options) {
|
||
return [
|
||
container_plugin,
|
||
"code-group",
|
||
{
|
||
render(tokens, idx) {
|
||
if (tokens[idx].nesting === 1) {
|
||
const name = nanoid$1(5);
|
||
let tabs = "";
|
||
let checked = 'checked="checked"';
|
||
for (let i = idx + 1; !(tokens[i].nesting === -1 && tokens[i].type === "container_code-group_close"); ++i) {
|
||
const isHtml = tokens[i].type === "html_block";
|
||
if (tokens[i].type === "fence" && tokens[i].tag === "code" || isHtml) {
|
||
const title = extractTitle(
|
||
isHtml ? tokens[i].content : tokens[i].info,
|
||
isHtml
|
||
);
|
||
if (title) {
|
||
const id = nanoid$1(7);
|
||
tabs += `<input type="radio" name="group-${name}" id="tab-${id}" ${checked}><label for="tab-${id}">${title}</label>`;
|
||
if (checked && !isHtml)
|
||
tokens[i].info += " active";
|
||
checked = "";
|
||
}
|
||
}
|
||
}
|
||
return `<div class="vp-code-group${getAdaptiveThemeMarker(
|
||
options
|
||
)}"><div class="tabs">${tabs}</div><div class="blocks">
|
||
`;
|
||
}
|
||
return `</div></div>
|
||
`;
|
||
}
|
||
}
|
||
];
|
||
}
|
||
|
||
const nanoid = customAlphabet("abcdefghijklmnopqrstuvwxyz", 10);
|
||
const attrsToLines = (attrs) => {
|
||
attrs = attrs.replace(/^(?:\[.*?\])?.*?([\d,-]+).*/, "$1").trim();
|
||
const result = [];
|
||
if (!attrs) {
|
||
return [];
|
||
}
|
||
attrs.split(",").map((v) => v.split("-").map((v2) => parseInt(v2, 10))).forEach(([start, end]) => {
|
||
if (start && end) {
|
||
result.push(
|
||
...Array.from({ length: end - start + 1 }, (_, i) => start + i)
|
||
);
|
||
} else {
|
||
result.push(start);
|
||
}
|
||
});
|
||
return result.map((v) => ({
|
||
line: v,
|
||
classes: ["highlighted"]
|
||
}));
|
||
};
|
||
async function highlight(theme, options, logger = console) {
|
||
const {
|
||
defaultHighlightLang: defaultLang = "",
|
||
codeTransformers: userTransformers = []
|
||
} = options;
|
||
const highlighter = await getHighlighter({
|
||
themes: typeof theme === "object" && "light" in theme && "dark" in theme ? [theme.light, theme.dark] : [theme],
|
||
langs: [...Object.keys(bundledLanguages), ...options.languages || []],
|
||
langAlias: options.languageAlias
|
||
});
|
||
await options?.shikijiSetup?.(highlighter);
|
||
const transformers = [
|
||
transformerNotationDiff(),
|
||
transformerNotationFocus({
|
||
classActiveLine: "has-focus",
|
||
classActivePre: "has-focused-lines"
|
||
}),
|
||
transformerNotationHighlight(),
|
||
transformerNotationErrorLevel(),
|
||
{
|
||
name: "vitepress:add-class",
|
||
pre(node) {
|
||
addClassToHast(node, "vp-code");
|
||
}
|
||
},
|
||
{
|
||
name: "vitepress:clean-up",
|
||
pre(node) {
|
||
delete node.properties.tabindex;
|
||
delete node.properties.style;
|
||
}
|
||
}
|
||
];
|
||
const vueRE = /-vue$/;
|
||
const lineNoStartRE = /=(\d*)/;
|
||
const lineNoRE = /:(no-)?line-numbers(=\d*)?$/;
|
||
const mustacheRE = /\{\{.*?\}\}/g;
|
||
return (str, lang, attrs) => {
|
||
const vPre = vueRE.test(lang) ? "" : "v-pre";
|
||
lang = lang.replace(lineNoStartRE, "").replace(lineNoRE, "").replace(vueRE, "").toLowerCase() || defaultLang;
|
||
if (lang) {
|
||
const langLoaded = highlighter.getLoadedLanguages().includes(lang);
|
||
if (!langLoaded && !isPlaintext(lang) && !isSpecialLang(lang)) {
|
||
logger.warn(
|
||
c$2.yellow(
|
||
`
|
||
The language '${lang}' is not loaded, falling back to '${defaultLang || "txt"}' for syntax highlighting.`
|
||
)
|
||
);
|
||
lang = defaultLang;
|
||
}
|
||
}
|
||
const lineOptions = attrsToLines(attrs);
|
||
const mustaches = /* @__PURE__ */ new Map();
|
||
const removeMustache = (s) => {
|
||
if (vPre)
|
||
return s;
|
||
return s.replace(mustacheRE, (match) => {
|
||
let marker = mustaches.get(match);
|
||
if (!marker) {
|
||
marker = nanoid();
|
||
mustaches.set(match, marker);
|
||
}
|
||
return marker;
|
||
});
|
||
};
|
||
const restoreMustache = (s) => {
|
||
mustaches.forEach((marker, match) => {
|
||
s = s.replaceAll(marker, match);
|
||
});
|
||
return s;
|
||
};
|
||
str = removeMustache(str).trimEnd();
|
||
const highlighted = highlighter.codeToHtml(str, {
|
||
lang,
|
||
transformers: [
|
||
...transformers,
|
||
transformerCompactLineOptions(lineOptions),
|
||
{
|
||
name: "vitepress:v-pre",
|
||
pre(node) {
|
||
if (vPre)
|
||
node.properties["v-pre"] = "";
|
||
}
|
||
},
|
||
{
|
||
name: "vitepress:empty-line",
|
||
pre(hast) {
|
||
hast.children.forEach((code) => {
|
||
if (code.type === "element" && code.tagName === "code") {
|
||
code.children.forEach((span) => {
|
||
if (span.type === "element" && span.tagName === "span" && Array.isArray(span.properties.class) && span.properties.class.includes("line") && span.children.length === 0) {
|
||
span.children.push({
|
||
type: "element",
|
||
tagName: "wbr",
|
||
properties: {},
|
||
children: []
|
||
});
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
},
|
||
...userTransformers
|
||
],
|
||
meta: { __raw: attrs },
|
||
...typeof theme === "object" && "light" in theme && "dark" in theme ? { themes: theme, defaultColor: false } : { theme }
|
||
});
|
||
return restoreMustache(highlighted);
|
||
};
|
||
}
|
||
|
||
const RE = /{([\d,-]+)}/;
|
||
const highlightLinePlugin = (md) => {
|
||
const fence = md.renderer.rules.fence;
|
||
md.renderer.rules.fence = (...args) => {
|
||
const [tokens, idx] = args;
|
||
const token = tokens[idx];
|
||
const attr = token.attrs && token.attrs[0];
|
||
let lines = null;
|
||
if (!attr) {
|
||
const rawInfo = token.info;
|
||
if (!rawInfo || !RE.test(rawInfo)) {
|
||
return fence(...args);
|
||
}
|
||
const langName = rawInfo.replace(RE, "").trim();
|
||
token.info = langName;
|
||
lines = RE.exec(rawInfo)[1];
|
||
}
|
||
if (!lines) {
|
||
lines = attr[0];
|
||
if (!lines || !/[\d,-]+/.test(lines)) {
|
||
return fence(...args);
|
||
}
|
||
}
|
||
token.info += " " + lines;
|
||
return fence(...args);
|
||
};
|
||
};
|
||
|
||
const imagePlugin = (md, { lazyLoading } = {}) => {
|
||
const imageRule = md.renderer.rules.image;
|
||
md.renderer.rules.image = (tokens, idx, options, env, self) => {
|
||
const token = tokens[idx];
|
||
let url = token.attrGet("src");
|
||
if (url && !EXTERNAL_URL_RE.test(url)) {
|
||
if (!/^\.?\//.test(url))
|
||
url = "./" + url;
|
||
token.attrSet("src", decodeURIComponent(url));
|
||
}
|
||
if (lazyLoading) {
|
||
token.attrSet("loading", "lazy");
|
||
}
|
||
return imageRule(tokens, idx, options, env, self);
|
||
};
|
||
};
|
||
|
||
const lineNumberPlugin = (md, enable = false) => {
|
||
const fence = md.renderer.rules.fence;
|
||
md.renderer.rules.fence = (...args) => {
|
||
const rawCode = fence(...args);
|
||
const [tokens, idx] = args;
|
||
const info = tokens[idx].info;
|
||
if (!enable && !/:line-numbers($| |=)/.test(info) || enable && /:no-line-numbers($| )/.test(info)) {
|
||
return rawCode;
|
||
}
|
||
let startLineNumber = 1;
|
||
const matchStartLineNumber = info.match(/=(\d*)/);
|
||
if (matchStartLineNumber && matchStartLineNumber[1]) {
|
||
startLineNumber = parseInt(matchStartLineNumber[1]);
|
||
}
|
||
const code = rawCode.slice(
|
||
rawCode.indexOf("<code>"),
|
||
rawCode.indexOf("</code>")
|
||
);
|
||
const lines = code.split("\n");
|
||
const lineNumbersCode = [...Array(lines.length)].map(
|
||
(_, index) => `<span class="line-number">${index + startLineNumber}</span><br>`
|
||
).join("");
|
||
const lineNumbersWrapperCode = `<div class="line-numbers-wrapper" aria-hidden="true">${lineNumbersCode}</div>`;
|
||
const finalCode = rawCode.replace(/<\/div>$/, `${lineNumbersWrapperCode}</div>`).replace(/"(language-[^"]*?)"/, '"$1 line-numbers-mode"');
|
||
return finalCode;
|
||
};
|
||
};
|
||
|
||
const indexRE = /(^|.*\/)index.md(#?.*)$/i;
|
||
const linkPlugin = (md, externalAttrs, base) => {
|
||
md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
|
||
const token = tokens[idx];
|
||
const hrefIndex = token.attrIndex("href");
|
||
if (hrefIndex >= 0) {
|
||
const hrefAttr = token.attrs[hrefIndex];
|
||
const url = hrefAttr[1];
|
||
if (isExternal(url)) {
|
||
Object.entries(externalAttrs).forEach(([key, val]) => {
|
||
token.attrSet(key, val);
|
||
});
|
||
if (url.replace(EXTERNAL_URL_RE, "").startsWith("//localhost:")) {
|
||
pushLink(url, env);
|
||
}
|
||
hrefAttr[1] = url;
|
||
} else {
|
||
const { pathname, protocol } = new URL$1(url, "http://a.com");
|
||
if (
|
||
// skip internal anchor links
|
||
!url.startsWith("#") && // skip mail/custom protocol links
|
||
protocol.startsWith("http") && // skip links to files (other than html/md)
|
||
treatAsHtml(pathname)
|
||
) {
|
||
normalizeHref(hrefAttr, env);
|
||
} else if (url.startsWith("#")) {
|
||
hrefAttr[1] = decodeURI(hrefAttr[1]);
|
||
}
|
||
if (hrefAttr[1].startsWith("/")) {
|
||
hrefAttr[1] = `${base}${hrefAttr[1]}`.replace(/\/+/g, "/");
|
||
}
|
||
}
|
||
}
|
||
return self.renderToken(tokens, idx, options);
|
||
};
|
||
function normalizeHref(hrefAttr, env) {
|
||
let url = hrefAttr[1];
|
||
const indexMatch = url.match(indexRE);
|
||
if (indexMatch) {
|
||
const [, path, hash] = indexMatch;
|
||
url = path + hash;
|
||
} else {
|
||
let cleanUrl = url.replace(/[?#].*$/, "");
|
||
if (cleanUrl.endsWith(".md")) {
|
||
cleanUrl = cleanUrl.replace(/\.md$/, env.cleanUrls ? "" : ".html");
|
||
}
|
||
if (!env.cleanUrls && !cleanUrl.endsWith(".html") && !cleanUrl.endsWith("/")) {
|
||
cleanUrl += ".html";
|
||
}
|
||
const parsed = new URL$1(url, "http://a.com");
|
||
url = cleanUrl + parsed.search + parsed.hash;
|
||
}
|
||
if (!url.startsWith("/") && !/^\.\//.test(url)) {
|
||
url = "./" + url;
|
||
}
|
||
pushLink(url.replace(/\.html$/, ""), env);
|
||
hrefAttr[1] = decodeURI(url);
|
||
}
|
||
function pushLink(link, env) {
|
||
const links = env.links || (env.links = []);
|
||
links.push(link);
|
||
}
|
||
};
|
||
|
||
const rawPathRegexp = /^(.+?(?:(?:\.([a-z0-9]+))?))(?:(#[\w-]+))?(?: ?(?:{(\d+(?:[,-]\d+)*)? ?(\S+)?}))? ?(?:\[(.+)\])?$/;
|
||
function rawPathToToken(rawPath) {
|
||
const [
|
||
filepath = "",
|
||
extension = "",
|
||
region = "",
|
||
lines = "",
|
||
lang = "",
|
||
rawTitle = ""
|
||
] = (rawPathRegexp.exec(rawPath) || []).slice(1);
|
||
const title = rawTitle || filepath.split("/").pop() || "";
|
||
return { filepath, extension, region, lines, lang, title };
|
||
}
|
||
function dedent(text) {
|
||
const lines = text.split("\n");
|
||
const minIndentLength = lines.reduce((acc, line) => {
|
||
for (let i = 0; i < line.length; i++) {
|
||
if (line[i] !== " " && line[i] !== " ")
|
||
return Math.min(i, acc);
|
||
}
|
||
return acc;
|
||
}, Infinity);
|
||
if (minIndentLength < Infinity) {
|
||
return lines.map((x) => x.slice(minIndentLength)).join("\n");
|
||
}
|
||
return text;
|
||
}
|
||
function testLine(line, regexp, regionName, end = false) {
|
||
const [full, tag, name] = regexp.exec(line.trim()) || [];
|
||
return full && tag && name === regionName && tag.match(end ? /^[Ee]nd ?[rR]egion$/ : /^[rR]egion$/);
|
||
}
|
||
function findRegion(lines, regionName) {
|
||
const regionRegexps = [
|
||
/^\/\/ ?#?((?:end)?region) ([\w*-]+)$/,
|
||
// javascript, typescript, java
|
||
/^\/\* ?#((?:end)?region) ([\w*-]+) ?\*\/$/,
|
||
// css, less, scss
|
||
/^#pragma ((?:end)?region) ([\w*-]+)$/,
|
||
// C, C++
|
||
/^<!-- #?((?:end)?region) ([\w*-]+) -->$/,
|
||
// HTML, markdown
|
||
/^#((?:End )Region) ([\w*-]+)$/,
|
||
// Visual Basic
|
||
/^::#((?:end)region) ([\w*-]+)$/,
|
||
// Bat
|
||
/^# ?((?:end)?region) ([\w*-]+)$/
|
||
// C#, PHP, Powershell, Python, perl & misc
|
||
];
|
||
let regexp = null;
|
||
let start = -1;
|
||
for (const [lineId, line] of lines.entries()) {
|
||
if (regexp === null) {
|
||
for (const reg of regionRegexps) {
|
||
if (testLine(line, reg, regionName)) {
|
||
start = lineId + 1;
|
||
regexp = reg;
|
||
break;
|
||
}
|
||
}
|
||
} else if (testLine(line, regexp, regionName, true)) {
|
||
return { start, end: lineId, regexp };
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
const snippetPlugin = (md, srcDir) => {
|
||
const parser = (state, startLine, endLine, silent) => {
|
||
const CH = "<".charCodeAt(0);
|
||
const pos = state.bMarks[startLine] + state.tShift[startLine];
|
||
const max = state.eMarks[startLine];
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) {
|
||
return false;
|
||
}
|
||
for (let i = 0; i < 3; ++i) {
|
||
const ch = state.src.charCodeAt(pos + i);
|
||
if (ch !== CH || pos + i >= max)
|
||
return false;
|
||
}
|
||
if (silent) {
|
||
return true;
|
||
}
|
||
const start = pos + 3;
|
||
const end = state.skipSpacesBack(max, pos);
|
||
const rawPath = state.src.slice(start, end).trim().replace(/^@/, srcDir).trim();
|
||
const { filepath, extension, region, lines, lang, title } = rawPathToToken(rawPath);
|
||
state.line = startLine + 1;
|
||
const token = state.push("fence", "code", 0);
|
||
token.info = `${lang || extension}${lines ? `{${lines}}` : ""}${title ? `[${title}]` : ""}`;
|
||
const { realPath, path: _path } = state.env;
|
||
const resolvedPath = path$q.resolve(path$q.dirname(realPath ?? _path), filepath);
|
||
token.src = [resolvedPath, region.slice(1)];
|
||
token.markup = "```";
|
||
token.map = [startLine, startLine + 1];
|
||
return true;
|
||
};
|
||
const fence = md.renderer.rules.fence;
|
||
md.renderer.rules.fence = (...args) => {
|
||
const [tokens, idx, , { includes }] = args;
|
||
const token = tokens[idx];
|
||
const [src, regionName] = token.src ?? [];
|
||
if (!src)
|
||
return fence(...args);
|
||
if (includes) {
|
||
includes.push(src);
|
||
}
|
||
const isAFile = fs$a.statSync(src).isFile();
|
||
if (!fs$a.existsSync(src) || !isAFile) {
|
||
token.content = isAFile ? `Code snippet path not found: ${src}` : `Invalid code snippet option`;
|
||
token.info = "";
|
||
return fence(...args);
|
||
}
|
||
let content = fs$a.readFileSync(src, "utf8");
|
||
if (regionName) {
|
||
const lines = content.split(/\r?\n/);
|
||
const region = findRegion(lines, regionName);
|
||
if (region) {
|
||
content = dedent(
|
||
lines.slice(region.start, region.end).filter((line) => !region.regexp.test(line.trim())).join("\n")
|
||
);
|
||
}
|
||
}
|
||
token.content = content;
|
||
return fence(...args);
|
||
};
|
||
md.block.ruler.before("fence", "snippet", parser);
|
||
};
|
||
|
||
const createMarkdownRenderer = async (srcDir, options = {}, base = "/", logger = console) => {
|
||
const theme = options.theme ?? { light: "github-light", dark: "github-dark" };
|
||
const hasSingleTheme = typeof theme === "string" || "name" in theme;
|
||
const md = MarkdownIt({
|
||
html: true,
|
||
linkify: true,
|
||
highlight: options.highlight || await highlight(theme, options, logger),
|
||
...options
|
||
});
|
||
md.linkify.set({ fuzzyLink: false });
|
||
if (options.preConfig) {
|
||
options.preConfig(md);
|
||
}
|
||
md.use(componentPlugin, { ...options.component }).use(highlightLinePlugin).use(preWrapperPlugin, { hasSingleTheme }).use(snippetPlugin, srcDir).use(containerPlugin, { hasSingleTheme }, options.container).use(imagePlugin, options.image).use(
|
||
linkPlugin,
|
||
{ target: "_blank", rel: "noreferrer", ...options.externalLinks },
|
||
base
|
||
).use(lineNumberPlugin, options.lineNumbers);
|
||
if (!options.attrs?.disable) {
|
||
md.use(attrsPlugin, options.attrs);
|
||
}
|
||
md.use(emoji_plugin, { ...options.emoji });
|
||
md.use(p$1, {
|
||
slugify,
|
||
permalink: p$1.permalink.linkInsideHeader({
|
||
symbol: "​",
|
||
renderAttrs: (slug, state) => {
|
||
const idx = state.tokens.findIndex((token) => {
|
||
const attrs = token.attrs;
|
||
const id = attrs?.find((attr) => attr[0] === "id");
|
||
return id && slug === id[1];
|
||
});
|
||
const title = state.tokens[idx + 1].content;
|
||
return {
|
||
"aria-label": `Permalink to "${title}"`
|
||
};
|
||
}
|
||
}),
|
||
...options.anchor
|
||
}).use(frontmatterPlugin, {
|
||
...options.frontmatter
|
||
});
|
||
if (options.headers) {
|
||
md.use(headersPlugin, {
|
||
level: [2, 3, 4, 5, 6],
|
||
slugify,
|
||
...typeof options.headers === "boolean" ? void 0 : options.headers
|
||
});
|
||
}
|
||
md.use(sfcPlugin, {
|
||
...options.sfc
|
||
}).use(titlePlugin).use(tocPlugin, {
|
||
...options.toc
|
||
});
|
||
if (options.math) {
|
||
try {
|
||
const mathPlugin = await import('markdown-it-mathjax3');
|
||
md.use(mathPlugin.default ?? mathPlugin, {
|
||
...typeof options.math === "boolean" ? {} : options.math
|
||
});
|
||
} catch (error) {
|
||
throw new Error(
|
||
"You need to install `markdown-it-mathjax3` to use math support."
|
||
);
|
||
}
|
||
}
|
||
if (options.config) {
|
||
options.config(md);
|
||
}
|
||
return md;
|
||
};
|
||
|
||
var crossSpawn = {exports: {}};
|
||
|
||
var mode;
|
||
var hasRequiredMode;
|
||
|
||
function requireMode () {
|
||
if (hasRequiredMode) return mode;
|
||
hasRequiredMode = 1;
|
||
mode = isexe;
|
||
isexe.sync = sync;
|
||
|
||
var fs = fs__default;
|
||
|
||
function isexe (path, options, cb) {
|
||
fs.stat(path, function (er, stat) {
|
||
cb(er, er ? false : checkStat(stat, options));
|
||
});
|
||
}
|
||
|
||
function sync (path, options) {
|
||
return checkStat(fs.statSync(path), options)
|
||
}
|
||
|
||
function checkStat (stat, options) {
|
||
return stat.isFile() && checkMode(stat, options)
|
||
}
|
||
|
||
function checkMode (stat, options) {
|
||
var mod = stat.mode;
|
||
var uid = stat.uid;
|
||
var gid = stat.gid;
|
||
|
||
var myUid = options.uid !== undefined ?
|
||
options.uid : process.getuid && process.getuid();
|
||
var myGid = options.gid !== undefined ?
|
||
options.gid : process.getgid && process.getgid();
|
||
|
||
var u = parseInt('100', 8);
|
||
var g = parseInt('010', 8);
|
||
var o = parseInt('001', 8);
|
||
var ug = u | g;
|
||
|
||
var ret = (mod & o) ||
|
||
(mod & g) && gid === myGid ||
|
||
(mod & u) && uid === myUid ||
|
||
(mod & ug) && myUid === 0;
|
||
|
||
return ret
|
||
}
|
||
return mode;
|
||
}
|
||
|
||
var windows;
|
||
var hasRequiredWindows;
|
||
|
||
function requireWindows () {
|
||
if (hasRequiredWindows) return windows;
|
||
hasRequiredWindows = 1;
|
||
windows = isexe;
|
||
isexe.sync = sync;
|
||
|
||
var fs = fs__default;
|
||
|
||
function checkPathExt (path, options) {
|
||
var pathext = options.pathExt !== undefined ?
|
||
options.pathExt : process.env.PATHEXT;
|
||
|
||
if (!pathext) {
|
||
return true
|
||
}
|
||
|
||
pathext = pathext.split(';');
|
||
if (pathext.indexOf('') !== -1) {
|
||
return true
|
||
}
|
||
for (var i = 0; i < pathext.length; i++) {
|
||
var p = pathext[i].toLowerCase();
|
||
if (p && path.substr(-p.length).toLowerCase() === p) {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
function checkStat (stat, path, options) {
|
||
if (!stat.isSymbolicLink() && !stat.isFile()) {
|
||
return false
|
||
}
|
||
return checkPathExt(path, options)
|
||
}
|
||
|
||
function isexe (path, options, cb) {
|
||
fs.stat(path, function (er, stat) {
|
||
cb(er, er ? false : checkStat(stat, path, options));
|
||
});
|
||
}
|
||
|
||
function sync (path, options) {
|
||
return checkStat(fs.statSync(path), path, options)
|
||
}
|
||
return windows;
|
||
}
|
||
|
||
var core;
|
||
if (process.platform === 'win32' || commonjsGlobal.TESTING_WINDOWS) {
|
||
core = requireWindows();
|
||
} else {
|
||
core = requireMode();
|
||
}
|
||
|
||
var isexe_1 = isexe$1;
|
||
isexe$1.sync = sync;
|
||
|
||
function isexe$1 (path, options, cb) {
|
||
if (typeof options === 'function') {
|
||
cb = options;
|
||
options = {};
|
||
}
|
||
|
||
if (!cb) {
|
||
if (typeof Promise !== 'function') {
|
||
throw new TypeError('callback not provided')
|
||
}
|
||
|
||
return new Promise(function (resolve, reject) {
|
||
isexe$1(path, options || {}, function (er, is) {
|
||
if (er) {
|
||
reject(er);
|
||
} else {
|
||
resolve(is);
|
||
}
|
||
});
|
||
})
|
||
}
|
||
|
||
core(path, options || {}, function (er, is) {
|
||
// ignore EACCES because that just means we aren't allowed to run it
|
||
if (er) {
|
||
if (er.code === 'EACCES' || options && options.ignoreErrors) {
|
||
er = null;
|
||
is = false;
|
||
}
|
||
}
|
||
cb(er, is);
|
||
});
|
||
}
|
||
|
||
function sync (path, options) {
|
||
// my kingdom for a filtered catch
|
||
try {
|
||
return core.sync(path, options || {})
|
||
} catch (er) {
|
||
if (options && options.ignoreErrors || er.code === 'EACCES') {
|
||
return false
|
||
} else {
|
||
throw er
|
||
}
|
||
}
|
||
}
|
||
|
||
const isWindows = process.platform === 'win32' ||
|
||
process.env.OSTYPE === 'cygwin' ||
|
||
process.env.OSTYPE === 'msys';
|
||
|
||
const path$2 = path$q;
|
||
const COLON = isWindows ? ';' : ':';
|
||
const isexe = isexe_1;
|
||
|
||
const getNotFoundError = (cmd) =>
|
||
Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' });
|
||
|
||
const getPathInfo = (cmd, opt) => {
|
||
const colon = opt.colon || COLON;
|
||
|
||
// If it has a slash, then we don't bother searching the pathenv.
|
||
// just check the file itself, and that's it.
|
||
const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? ['']
|
||
: (
|
||
[
|
||
// windows always checks the cwd first
|
||
...(isWindows ? [process.cwd()] : []),
|
||
...(opt.path || process.env.PATH ||
|
||
/* istanbul ignore next: very unusual */ '').split(colon),
|
||
]
|
||
);
|
||
const pathExtExe = isWindows
|
||
? opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM'
|
||
: '';
|
||
const pathExt = isWindows ? pathExtExe.split(colon) : [''];
|
||
|
||
if (isWindows) {
|
||
if (cmd.indexOf('.') !== -1 && pathExt[0] !== '')
|
||
pathExt.unshift('');
|
||
}
|
||
|
||
return {
|
||
pathEnv,
|
||
pathExt,
|
||
pathExtExe,
|
||
}
|
||
};
|
||
|
||
const which$1 = (cmd, opt, cb) => {
|
||
if (typeof opt === 'function') {
|
||
cb = opt;
|
||
opt = {};
|
||
}
|
||
if (!opt)
|
||
opt = {};
|
||
|
||
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
||
const found = [];
|
||
|
||
const step = i => new Promise((resolve, reject) => {
|
||
if (i === pathEnv.length)
|
||
return opt.all && found.length ? resolve(found)
|
||
: reject(getNotFoundError(cmd))
|
||
|
||
const ppRaw = pathEnv[i];
|
||
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
||
|
||
const pCmd = path$2.join(pathPart, cmd);
|
||
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd
|
||
: pCmd;
|
||
|
||
resolve(subStep(p, i, 0));
|
||
});
|
||
|
||
const subStep = (p, i, ii) => new Promise((resolve, reject) => {
|
||
if (ii === pathExt.length)
|
||
return resolve(step(i + 1))
|
||
const ext = pathExt[ii];
|
||
isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
|
||
if (!er && is) {
|
||
if (opt.all)
|
||
found.push(p + ext);
|
||
else
|
||
return resolve(p + ext)
|
||
}
|
||
return resolve(subStep(p, i, ii + 1))
|
||
});
|
||
});
|
||
|
||
return cb ? step(0).then(res => cb(null, res), cb) : step(0)
|
||
};
|
||
|
||
const whichSync = (cmd, opt) => {
|
||
opt = opt || {};
|
||
|
||
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
||
const found = [];
|
||
|
||
for (let i = 0; i < pathEnv.length; i ++) {
|
||
const ppRaw = pathEnv[i];
|
||
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
||
|
||
const pCmd = path$2.join(pathPart, cmd);
|
||
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd
|
||
: pCmd;
|
||
|
||
for (let j = 0; j < pathExt.length; j ++) {
|
||
const cur = p + pathExt[j];
|
||
try {
|
||
const is = isexe.sync(cur, { pathExt: pathExtExe });
|
||
if (is) {
|
||
if (opt.all)
|
||
found.push(cur);
|
||
else
|
||
return cur
|
||
}
|
||
} catch (ex) {}
|
||
}
|
||
}
|
||
|
||
if (opt.all && found.length)
|
||
return found
|
||
|
||
if (opt.nothrow)
|
||
return null
|
||
|
||
throw getNotFoundError(cmd)
|
||
};
|
||
|
||
var which_1 = which$1;
|
||
which$1.sync = whichSync;
|
||
|
||
var pathKey$1 = {exports: {}};
|
||
|
||
const pathKey = (options = {}) => {
|
||
const environment = options.env || process.env;
|
||
const platform = options.platform || process.platform;
|
||
|
||
if (platform !== 'win32') {
|
||
return 'PATH';
|
||
}
|
||
|
||
return Object.keys(environment).reverse().find(key => key.toUpperCase() === 'PATH') || 'Path';
|
||
};
|
||
|
||
pathKey$1.exports = pathKey;
|
||
// TODO: Remove this for the next major release
|
||
pathKey$1.exports.default = pathKey;
|
||
|
||
var pathKeyExports = pathKey$1.exports;
|
||
|
||
const path$1 = path$q;
|
||
const which = which_1;
|
||
const getPathKey = pathKeyExports;
|
||
|
||
function resolveCommandAttempt(parsed, withoutPathExt) {
|
||
const env = parsed.options.env || process.env;
|
||
const cwd = process.cwd();
|
||
const hasCustomCwd = parsed.options.cwd != null;
|
||
// Worker threads do not have process.chdir()
|
||
const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined && !process.chdir.disabled;
|
||
|
||
// If a custom `cwd` was specified, we need to change the process cwd
|
||
// because `which` will do stat calls but does not support a custom cwd
|
||
if (shouldSwitchCwd) {
|
||
try {
|
||
process.chdir(parsed.options.cwd);
|
||
} catch (err) {
|
||
/* Empty */
|
||
}
|
||
}
|
||
|
||
let resolved;
|
||
|
||
try {
|
||
resolved = which.sync(parsed.command, {
|
||
path: env[getPathKey({ env })],
|
||
pathExt: withoutPathExt ? path$1.delimiter : undefined,
|
||
});
|
||
} catch (e) {
|
||
/* Empty */
|
||
} finally {
|
||
if (shouldSwitchCwd) {
|
||
process.chdir(cwd);
|
||
}
|
||
}
|
||
|
||
// If we successfully resolved, ensure that an absolute path is returned
|
||
// Note that when a custom `cwd` was used, we need to resolve to an absolute path based on it
|
||
if (resolved) {
|
||
resolved = path$1.resolve(hasCustomCwd ? parsed.options.cwd : '', resolved);
|
||
}
|
||
|
||
return resolved;
|
||
}
|
||
|
||
function resolveCommand$1(parsed) {
|
||
return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
|
||
}
|
||
|
||
var resolveCommand_1 = resolveCommand$1;
|
||
|
||
var _escape = {};
|
||
|
||
// See http://www.robvanderwoude.com/escapechars.php
|
||
const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
|
||
|
||
function escapeCommand(arg) {
|
||
// Escape meta chars
|
||
arg = arg.replace(metaCharsRegExp, '^$1');
|
||
|
||
return arg;
|
||
}
|
||
|
||
function escapeArgument(arg, doubleEscapeMetaChars) {
|
||
// Convert to string
|
||
arg = `${arg}`;
|
||
|
||
// Algorithm below is based on https://qntm.org/cmd
|
||
|
||
// Sequence of backslashes followed by a double quote:
|
||
// double up all the backslashes and escape the double quote
|
||
arg = arg.replace(/(\\*)"/g, '$1$1\\"');
|
||
|
||
// Sequence of backslashes followed by the end of the string
|
||
// (which will become a double quote later):
|
||
// double up all the backslashes
|
||
arg = arg.replace(/(\\*)$/, '$1$1');
|
||
|
||
// All other backslashes occur literally
|
||
|
||
// Quote the whole thing:
|
||
arg = `"${arg}"`;
|
||
|
||
// Escape meta chars
|
||
arg = arg.replace(metaCharsRegExp, '^$1');
|
||
|
||
// Double escape meta chars if necessary
|
||
if (doubleEscapeMetaChars) {
|
||
arg = arg.replace(metaCharsRegExp, '^$1');
|
||
}
|
||
|
||
return arg;
|
||
}
|
||
|
||
_escape.command = escapeCommand;
|
||
_escape.argument = escapeArgument;
|
||
|
||
var shebangRegex$1 = /^#!(.*)/;
|
||
|
||
const shebangRegex = shebangRegex$1;
|
||
|
||
var shebangCommand$1 = (string = '') => {
|
||
const match = string.match(shebangRegex);
|
||
|
||
if (!match) {
|
||
return null;
|
||
}
|
||
|
||
const [path, argument] = match[0].replace(/#! ?/, '').split(' ');
|
||
const binary = path.split('/').pop();
|
||
|
||
if (binary === 'env') {
|
||
return argument;
|
||
}
|
||
|
||
return argument ? `${binary} ${argument}` : binary;
|
||
};
|
||
|
||
const fs = fs__default;
|
||
const shebangCommand = shebangCommand$1;
|
||
|
||
function readShebang$1(command) {
|
||
// Read the first 150 bytes from the file
|
||
const size = 150;
|
||
const buffer = Buffer.alloc(size);
|
||
|
||
let fd;
|
||
|
||
try {
|
||
fd = fs.openSync(command, 'r');
|
||
fs.readSync(fd, buffer, 0, size, 0);
|
||
fs.closeSync(fd);
|
||
} catch (e) { /* Empty */ }
|
||
|
||
// Attempt to extract shebang (null is returned if not a shebang)
|
||
return shebangCommand(buffer.toString());
|
||
}
|
||
|
||
var readShebang_1 = readShebang$1;
|
||
|
||
const path = path$q;
|
||
const resolveCommand = resolveCommand_1;
|
||
const escape$2 = _escape;
|
||
const readShebang = readShebang_1;
|
||
|
||
const isWin$2 = process.platform === 'win32';
|
||
const isExecutableRegExp = /\.(?:com|exe)$/i;
|
||
const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
|
||
|
||
function detectShebang(parsed) {
|
||
parsed.file = resolveCommand(parsed);
|
||
|
||
const shebang = parsed.file && readShebang(parsed.file);
|
||
|
||
if (shebang) {
|
||
parsed.args.unshift(parsed.file);
|
||
parsed.command = shebang;
|
||
|
||
return resolveCommand(parsed);
|
||
}
|
||
|
||
return parsed.file;
|
||
}
|
||
|
||
function parseNonShell(parsed) {
|
||
if (!isWin$2) {
|
||
return parsed;
|
||
}
|
||
|
||
// Detect & add support for shebangs
|
||
const commandFile = detectShebang(parsed);
|
||
|
||
// We don't need a shell if the command filename is an executable
|
||
const needsShell = !isExecutableRegExp.test(commandFile);
|
||
|
||
// If a shell is required, use cmd.exe and take care of escaping everything correctly
|
||
// Note that `forceShell` is an hidden option used only in tests
|
||
if (parsed.options.forceShell || needsShell) {
|
||
// Need to double escape meta chars if the command is a cmd-shim located in `node_modules/.bin/`
|
||
// The cmd-shim simply calls execute the package bin file with NodeJS, proxying any argument
|
||
// Because the escape of metachars with ^ gets interpreted when the cmd.exe is first called,
|
||
// we need to double escape them
|
||
const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
|
||
|
||
// Normalize posix paths into OS compatible paths (e.g.: foo/bar -> foo\bar)
|
||
// This is necessary otherwise it will always fail with ENOENT in those cases
|
||
parsed.command = path.normalize(parsed.command);
|
||
|
||
// Escape command & arguments
|
||
parsed.command = escape$2.command(parsed.command);
|
||
parsed.args = parsed.args.map((arg) => escape$2.argument(arg, needsDoubleEscapeMetaChars));
|
||
|
||
const shellCommand = [parsed.command].concat(parsed.args).join(' ');
|
||
|
||
parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`];
|
||
parsed.command = process.env.comspec || 'cmd.exe';
|
||
parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped
|
||
}
|
||
|
||
return parsed;
|
||
}
|
||
|
||
function parse$5(command, args, options) {
|
||
// Normalize arguments, similar to nodejs
|
||
if (args && !Array.isArray(args)) {
|
||
options = args;
|
||
args = null;
|
||
}
|
||
|
||
args = args ? args.slice(0) : []; // Clone array to avoid changing the original
|
||
options = Object.assign({}, options); // Clone object to avoid changing the original
|
||
|
||
// Build our parsed object
|
||
const parsed = {
|
||
command,
|
||
args,
|
||
options,
|
||
file: undefined,
|
||
original: {
|
||
command,
|
||
args,
|
||
},
|
||
};
|
||
|
||
// Delegate further parsing to shell or non-shell
|
||
return options.shell ? parsed : parseNonShell(parsed);
|
||
}
|
||
|
||
var parse_1 = parse$5;
|
||
|
||
const isWin$1 = process.platform === 'win32';
|
||
|
||
function notFoundError(original, syscall) {
|
||
return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), {
|
||
code: 'ENOENT',
|
||
errno: 'ENOENT',
|
||
syscall: `${syscall} ${original.command}`,
|
||
path: original.command,
|
||
spawnargs: original.args,
|
||
});
|
||
}
|
||
|
||
function hookChildProcess(cp, parsed) {
|
||
if (!isWin$1) {
|
||
return;
|
||
}
|
||
|
||
const originalEmit = cp.emit;
|
||
|
||
cp.emit = function (name, arg1) {
|
||
// If emitting "exit" event and exit code is 1, we need to check if
|
||
// the command exists and emit an "error" instead
|
||
// See https://github.com/IndigoUnited/node-cross-spawn/issues/16
|
||
if (name === 'exit') {
|
||
const err = verifyENOENT(arg1, parsed);
|
||
|
||
if (err) {
|
||
return originalEmit.call(cp, 'error', err);
|
||
}
|
||
}
|
||
|
||
return originalEmit.apply(cp, arguments); // eslint-disable-line prefer-rest-params
|
||
};
|
||
}
|
||
|
||
function verifyENOENT(status, parsed) {
|
||
if (isWin$1 && status === 1 && !parsed.file) {
|
||
return notFoundError(parsed.original, 'spawn');
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function verifyENOENTSync(status, parsed) {
|
||
if (isWin$1 && status === 1 && !parsed.file) {
|
||
return notFoundError(parsed.original, 'spawnSync');
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
var enoent$1 = {
|
||
hookChildProcess,
|
||
verifyENOENT,
|
||
verifyENOENTSync,
|
||
notFoundError,
|
||
};
|
||
|
||
const cp = require$$0$8;
|
||
const parse$4 = parse_1;
|
||
const enoent = enoent$1;
|
||
|
||
function spawn(command, args, options) {
|
||
// Parse the arguments
|
||
const parsed = parse$4(command, args, options);
|
||
|
||
// Spawn the child process
|
||
const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
|
||
|
||
// Hook into child process "exit" event to emit an error if the command
|
||
// does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16
|
||
enoent.hookChildProcess(spawned, parsed);
|
||
|
||
return spawned;
|
||
}
|
||
|
||
function spawnSync(command, args, options) {
|
||
// Parse the arguments
|
||
const parsed = parse$4(command, args, options);
|
||
|
||
// Spawn the child process
|
||
const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
|
||
|
||
// Analyze if the command does not exist, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16
|
||
result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
|
||
|
||
return result;
|
||
}
|
||
|
||
crossSpawn.exports = spawn;
|
||
var spawn_1 = crossSpawn.exports.spawn = spawn;
|
||
crossSpawn.exports.sync = spawnSync;
|
||
|
||
crossSpawn.exports._parse = parse$4;
|
||
crossSpawn.exports._enoent = enoent;
|
||
|
||
const cache$2 = /* @__PURE__ */ new Map();
|
||
function getGitTimestamp(file) {
|
||
const cached = cache$2.get(file);
|
||
if (cached)
|
||
return cached;
|
||
return new Promise((resolve, reject) => {
|
||
const cwd = dirname(file);
|
||
if (!fs$a.existsSync(cwd))
|
||
return resolve(0);
|
||
const fileName = basename(file);
|
||
const child = spawn_1("git", ["log", "-1", '--pretty="%ai"', fileName], {
|
||
cwd
|
||
});
|
||
let output = "";
|
||
child.stdout.on("data", (d) => output += String(d));
|
||
child.on("close", () => {
|
||
const timestamp = +new Date(output);
|
||
cache$2.set(file, timestamp);
|
||
resolve(timestamp);
|
||
});
|
||
child.on("error", reject);
|
||
});
|
||
}
|
||
|
||
function processIncludes(srcDir, src, file, includes) {
|
||
const includesRE = /<!--\s*@include:\s*(.*?)\s*-->/g;
|
||
const rangeRE = /\{(\d*),(\d*)\}$/;
|
||
return src.replace(includesRE, (m, m1) => {
|
||
if (!m1.length)
|
||
return m;
|
||
const range = m1.match(rangeRE);
|
||
range && (m1 = m1.slice(0, -range[0].length));
|
||
const atPresent = m1[0] === "@";
|
||
try {
|
||
const includePath = atPresent ? path$q.join(srcDir, m1.slice(m1[1] === "/" ? 2 : 1)) : path$q.join(path$q.dirname(file), m1);
|
||
let content = fs$a.readFileSync(includePath, "utf-8");
|
||
if (range) {
|
||
const [, startLine, endLine] = range;
|
||
const lines = content.split(/\r?\n/);
|
||
content = lines.slice(
|
||
startLine ? parseInt(startLine, 10) - 1 : void 0,
|
||
endLine ? parseInt(endLine, 10) : void 0
|
||
).join("\n");
|
||
} else {
|
||
content = matter$1(content).content;
|
||
}
|
||
includes.push(slash(includePath));
|
||
return processIncludes(srcDir, content, includePath, includes);
|
||
} catch (error) {
|
||
return m;
|
||
}
|
||
});
|
||
}
|
||
|
||
const debug$3 = _debug("vitepress:md");
|
||
const cache$1 = new LRUCache({ max: 1024 });
|
||
function clearCache(file) {
|
||
if (!file) {
|
||
cache$1.clear();
|
||
return;
|
||
}
|
||
file = JSON.stringify({ file }).slice(1);
|
||
cache$1.find((_, key) => key.endsWith(file) && cache$1.delete(key));
|
||
}
|
||
async function createMarkdownToVueRenderFn(srcDir, options = {}, pages, isBuild = false, base = "/", includeLastUpdatedData = false, cleanUrls = false, siteConfig = null) {
|
||
const md = await createMarkdownRenderer(
|
||
srcDir,
|
||
options,
|
||
base,
|
||
siteConfig?.logger
|
||
);
|
||
pages = pages.map((p) => slash(p.replace(/\.md$/, "")));
|
||
return async (src, file, publicDir) => {
|
||
const fileOrig = file;
|
||
const alias = siteConfig?.rewrites.map[file] || // virtual dynamic path file
|
||
siteConfig?.rewrites.map[file.slice(srcDir.length + 1)];
|
||
file = alias ? path$q.join(srcDir, alias) : file;
|
||
const relativePath = slash(path$q.relative(srcDir, file));
|
||
const cacheKey = JSON.stringify({ src, file: fileOrig });
|
||
if (isBuild || options.cache !== false) {
|
||
const cached = cache$1.get(cacheKey);
|
||
if (cached) {
|
||
debug$3(`[cache hit] ${relativePath}`);
|
||
return cached;
|
||
}
|
||
}
|
||
const start = Date.now();
|
||
let params;
|
||
src = src.replace(
|
||
/^__VP_PARAMS_START([^]+?)__VP_PARAMS_END__/,
|
||
(_, paramsString) => {
|
||
params = JSON.parse(paramsString);
|
||
return "";
|
||
}
|
||
);
|
||
let includes = [];
|
||
src = processIncludes(srcDir, src, fileOrig, includes);
|
||
const env = {
|
||
path: file,
|
||
relativePath,
|
||
cleanUrls,
|
||
includes,
|
||
realPath: fileOrig
|
||
};
|
||
const html = md.render(src, env);
|
||
const {
|
||
frontmatter = {},
|
||
headers = [],
|
||
links = [],
|
||
sfcBlocks,
|
||
title = ""
|
||
} = env;
|
||
const deadLinks = [];
|
||
const recordDeadLink = (url) => {
|
||
deadLinks.push({ url, file: path$q.relative(srcDir, fileOrig) });
|
||
};
|
||
function shouldIgnoreDeadLink(url) {
|
||
if (!siteConfig?.ignoreDeadLinks) {
|
||
return false;
|
||
}
|
||
if (siteConfig.ignoreDeadLinks === true) {
|
||
return true;
|
||
}
|
||
if (siteConfig.ignoreDeadLinks === "localhostLinks") {
|
||
return url.replace(EXTERNAL_URL_RE, "").startsWith("//localhost");
|
||
}
|
||
return siteConfig.ignoreDeadLinks.some((ignore) => {
|
||
if (typeof ignore === "string") {
|
||
return url === ignore;
|
||
}
|
||
if (ignore instanceof RegExp) {
|
||
return ignore.test(url);
|
||
}
|
||
if (typeof ignore === "function") {
|
||
return ignore(url);
|
||
}
|
||
return false;
|
||
});
|
||
}
|
||
if (links) {
|
||
const dir = path$q.dirname(file);
|
||
for (let url of links) {
|
||
const { pathname } = new URL(url, "http://a.com");
|
||
if (!treatAsHtml(pathname))
|
||
continue;
|
||
url = url.replace(/[?#].*$/, "").replace(/\.(html|md)$/, "");
|
||
if (url.endsWith("/"))
|
||
url += `index`;
|
||
let resolved = decodeURIComponent(
|
||
slash(
|
||
url.startsWith("/") ? url.slice(1) : path$q.relative(srcDir, path$q.resolve(dir, url))
|
||
)
|
||
);
|
||
resolved = siteConfig?.rewrites.inv[resolved + ".md"]?.slice(0, -3) || resolved;
|
||
if (!pages.includes(resolved) && !fs$a.existsSync(path$q.resolve(dir, publicDir, `${resolved}.html`)) && !shouldIgnoreDeadLink(url)) {
|
||
recordDeadLink(url);
|
||
}
|
||
}
|
||
}
|
||
let pageData = {
|
||
title: inferTitle(md, frontmatter, title),
|
||
titleTemplate: frontmatter.titleTemplate,
|
||
description: inferDescription(frontmatter),
|
||
frontmatter,
|
||
headers,
|
||
params,
|
||
relativePath,
|
||
filePath: slash(path$q.relative(srcDir, fileOrig))
|
||
};
|
||
if (includeLastUpdatedData) {
|
||
pageData.lastUpdated = await getGitTimestamp(fileOrig);
|
||
}
|
||
if (siteConfig?.transformPageData) {
|
||
const dataToMerge = await siteConfig.transformPageData(pageData, {
|
||
siteConfig
|
||
});
|
||
if (dataToMerge) {
|
||
pageData = {
|
||
...pageData,
|
||
...dataToMerge
|
||
};
|
||
}
|
||
}
|
||
const vueSrc = [
|
||
...injectPageDataCode(
|
||
sfcBlocks?.scripts.map((item) => item.content) ?? [],
|
||
pageData
|
||
),
|
||
`<template><div>${html}</div></template>`,
|
||
...sfcBlocks?.styles.map((item) => item.content) ?? [],
|
||
...sfcBlocks?.customBlocks.map((item) => item.content) ?? []
|
||
].join("\n");
|
||
debug$3(`[render] ${file} in ${Date.now() - start}ms.`);
|
||
const result = {
|
||
vueSrc,
|
||
pageData,
|
||
deadLinks,
|
||
includes
|
||
};
|
||
if (isBuild || options.cache !== false) {
|
||
cache$1.set(cacheKey, result);
|
||
}
|
||
return result;
|
||
};
|
||
}
|
||
const scriptRE = /<\/script>/;
|
||
const scriptLangTsRE = /<\s*script[^>]*\blang=['"]ts['"][^>]*/;
|
||
const scriptSetupRE = /<\s*script[^>]*\bsetup\b[^>]*/;
|
||
const scriptClientRE$1 = /<\s*script[^>]*\bclient\b[^>]*/;
|
||
const defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/;
|
||
const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/;
|
||
function injectPageDataCode(tags, data) {
|
||
const code = `
|
||
export const __pageData = JSON.parse(${JSON.stringify(
|
||
JSON.stringify(data)
|
||
)})`;
|
||
const existingScriptIndex = tags.findIndex((tag) => {
|
||
return scriptRE.test(tag) && !scriptSetupRE.test(tag) && !scriptClientRE$1.test(tag);
|
||
});
|
||
const isUsingTS = tags.findIndex((tag) => scriptLangTsRE.test(tag)) > -1;
|
||
if (existingScriptIndex > -1) {
|
||
const tagSrc = tags[existingScriptIndex];
|
||
const hasDefaultExport = defaultExportRE.test(tagSrc) || namedDefaultExportRE.test(tagSrc);
|
||
tags[existingScriptIndex] = tagSrc.replace(
|
||
scriptRE,
|
||
code + (hasDefaultExport ? `` : `
|
||
export default {name:${JSON.stringify(data.relativePath)}}`) + `<\/script>`
|
||
);
|
||
} else {
|
||
tags.unshift(
|
||
`<script ${isUsingTS ? 'lang="ts"' : ""}>${code}
|
||
export default {name:${JSON.stringify(
|
||
data.relativePath
|
||
)}}<\/script>`
|
||
);
|
||
}
|
||
return tags;
|
||
}
|
||
const inferTitle = (md, frontmatter, title) => {
|
||
if (typeof frontmatter.title === "string") {
|
||
const titleToken = md.parseInline(frontmatter.title, {})[0];
|
||
if (titleToken) {
|
||
return resolveTitleFromToken(titleToken, {
|
||
shouldAllowHtml: false,
|
||
shouldEscapeText: false
|
||
});
|
||
}
|
||
}
|
||
return title;
|
||
};
|
||
const inferDescription = (frontmatter) => {
|
||
const { description, head } = frontmatter;
|
||
if (description !== void 0) {
|
||
return description;
|
||
}
|
||
return head && getHeadMetaContent(head, "description") || "";
|
||
};
|
||
const getHeadMetaContent = (head, name) => {
|
||
if (!head || !head.length) {
|
||
return void 0;
|
||
}
|
||
const meta = head.find(([tag, attrs = {}]) => {
|
||
return tag === "meta" && attrs.name === name && attrs.content;
|
||
});
|
||
return meta && meta[1].content;
|
||
};
|
||
|
||
function serializeFunctions(value, key) {
|
||
if (Array.isArray(value)) {
|
||
return value.map((v) => serializeFunctions(v));
|
||
} else if (typeof value === "object" && value !== null) {
|
||
return Object.keys(value).reduce((acc, key2) => {
|
||
if (key2[0] === "_")
|
||
return acc;
|
||
acc[key2] = serializeFunctions(value[key2], key2);
|
||
return acc;
|
||
}, {});
|
||
} else if (typeof value === "function") {
|
||
let serialized = value.toString();
|
||
if (key && (serialized.startsWith(key) || serialized.startsWith("async " + key))) {
|
||
serialized = serialized.replace(key, "function");
|
||
}
|
||
return `_vp-fn_${serialized}`;
|
||
} else {
|
||
return value;
|
||
}
|
||
}
|
||
const deserializeFunctions = 'function deserializeFunctions(r){return Array.isArray(r)?r.map(deserializeFunctions):typeof r=="object"&&r!==null?Object.keys(r).reduce((t,n)=>(t[n]=deserializeFunctions(r[n]),t),{}):typeof r=="string"&&r.startsWith("_vp-fn_")?new Function(`return ${r.slice(7)}`)():r}';
|
||
|
||
const ANSI_BACKGROUND_OFFSET = 10;
|
||
|
||
const wrapAnsi16 = (offset = 0) => code => `\u001B[${code + offset}m`;
|
||
|
||
const wrapAnsi256 = (offset = 0) => code => `\u001B[${38 + offset};5;${code}m`;
|
||
|
||
const wrapAnsi16m = (offset = 0) => (red, green, blue) => `\u001B[${38 + offset};2;${red};${green};${blue}m`;
|
||
|
||
const styles$1 = {
|
||
modifier: {
|
||
reset: [0, 0],
|
||
// 21 isn't widely supported and 22 does the same thing
|
||
bold: [1, 22],
|
||
dim: [2, 22],
|
||
italic: [3, 23],
|
||
underline: [4, 24],
|
||
overline: [53, 55],
|
||
inverse: [7, 27],
|
||
hidden: [8, 28],
|
||
strikethrough: [9, 29],
|
||
},
|
||
color: {
|
||
black: [30, 39],
|
||
red: [31, 39],
|
||
green: [32, 39],
|
||
yellow: [33, 39],
|
||
blue: [34, 39],
|
||
magenta: [35, 39],
|
||
cyan: [36, 39],
|
||
white: [37, 39],
|
||
|
||
// Bright color
|
||
blackBright: [90, 39],
|
||
gray: [90, 39], // Alias of `blackBright`
|
||
grey: [90, 39], // Alias of `blackBright`
|
||
redBright: [91, 39],
|
||
greenBright: [92, 39],
|
||
yellowBright: [93, 39],
|
||
blueBright: [94, 39],
|
||
magentaBright: [95, 39],
|
||
cyanBright: [96, 39],
|
||
whiteBright: [97, 39],
|
||
},
|
||
bgColor: {
|
||
bgBlack: [40, 49],
|
||
bgRed: [41, 49],
|
||
bgGreen: [42, 49],
|
||
bgYellow: [43, 49],
|
||
bgBlue: [44, 49],
|
||
bgMagenta: [45, 49],
|
||
bgCyan: [46, 49],
|
||
bgWhite: [47, 49],
|
||
|
||
// Bright color
|
||
bgBlackBright: [100, 49],
|
||
bgGray: [100, 49], // Alias of `bgBlackBright`
|
||
bgGrey: [100, 49], // Alias of `bgBlackBright`
|
||
bgRedBright: [101, 49],
|
||
bgGreenBright: [102, 49],
|
||
bgYellowBright: [103, 49],
|
||
bgBlueBright: [104, 49],
|
||
bgMagentaBright: [105, 49],
|
||
bgCyanBright: [106, 49],
|
||
bgWhiteBright: [107, 49],
|
||
},
|
||
};
|
||
|
||
Object.keys(styles$1.modifier);
|
||
const foregroundColorNames = Object.keys(styles$1.color);
|
||
const backgroundColorNames = Object.keys(styles$1.bgColor);
|
||
[...foregroundColorNames, ...backgroundColorNames];
|
||
|
||
function assembleStyles() {
|
||
const codes = new Map();
|
||
|
||
for (const [groupName, group] of Object.entries(styles$1)) {
|
||
for (const [styleName, style] of Object.entries(group)) {
|
||
styles$1[styleName] = {
|
||
open: `\u001B[${style[0]}m`,
|
||
close: `\u001B[${style[1]}m`,
|
||
};
|
||
|
||
group[styleName] = styles$1[styleName];
|
||
|
||
codes.set(style[0], style[1]);
|
||
}
|
||
|
||
Object.defineProperty(styles$1, groupName, {
|
||
value: group,
|
||
enumerable: false,
|
||
});
|
||
}
|
||
|
||
Object.defineProperty(styles$1, 'codes', {
|
||
value: codes,
|
||
enumerable: false,
|
||
});
|
||
|
||
styles$1.color.close = '\u001B[39m';
|
||
styles$1.bgColor.close = '\u001B[49m';
|
||
|
||
styles$1.color.ansi = wrapAnsi16();
|
||
styles$1.color.ansi256 = wrapAnsi256();
|
||
styles$1.color.ansi16m = wrapAnsi16m();
|
||
styles$1.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
|
||
styles$1.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
|
||
styles$1.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
|
||
|
||
// From https://github.com/Qix-/color-convert/blob/3f0e0d4e92e235796ccb17f6e85c72094a651f49/conversions.js
|
||
Object.defineProperties(styles$1, {
|
||
rgbToAnsi256: {
|
||
value(red, green, blue) {
|
||
// We use the extended greyscale palette here, with the exception of
|
||
// black and white. normal palette only has 4 greyscale shades.
|
||
if (red === green && green === blue) {
|
||
if (red < 8) {
|
||
return 16;
|
||
}
|
||
|
||
if (red > 248) {
|
||
return 231;
|
||
}
|
||
|
||
return Math.round(((red - 8) / 247) * 24) + 232;
|
||
}
|
||
|
||
return 16
|
||
+ (36 * Math.round(red / 255 * 5))
|
||
+ (6 * Math.round(green / 255 * 5))
|
||
+ Math.round(blue / 255 * 5);
|
||
},
|
||
enumerable: false,
|
||
},
|
||
hexToRgb: {
|
||
value(hex) {
|
||
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
|
||
if (!matches) {
|
||
return [0, 0, 0];
|
||
}
|
||
|
||
let [colorString] = matches;
|
||
|
||
if (colorString.length === 3) {
|
||
colorString = [...colorString].map(character => character + character).join('');
|
||
}
|
||
|
||
const integer = Number.parseInt(colorString, 16);
|
||
|
||
return [
|
||
/* eslint-disable no-bitwise */
|
||
(integer >> 16) & 0xFF,
|
||
(integer >> 8) & 0xFF,
|
||
integer & 0xFF,
|
||
/* eslint-enable no-bitwise */
|
||
];
|
||
},
|
||
enumerable: false,
|
||
},
|
||
hexToAnsi256: {
|
||
value: hex => styles$1.rgbToAnsi256(...styles$1.hexToRgb(hex)),
|
||
enumerable: false,
|
||
},
|
||
ansi256ToAnsi: {
|
||
value(code) {
|
||
if (code < 8) {
|
||
return 30 + code;
|
||
}
|
||
|
||
if (code < 16) {
|
||
return 90 + (code - 8);
|
||
}
|
||
|
||
let red;
|
||
let green;
|
||
let blue;
|
||
|
||
if (code >= 232) {
|
||
red = (((code - 232) * 10) + 8) / 255;
|
||
green = red;
|
||
blue = red;
|
||
} else {
|
||
code -= 16;
|
||
|
||
const remainder = code % 36;
|
||
|
||
red = Math.floor(code / 36) / 5;
|
||
green = Math.floor(remainder / 6) / 5;
|
||
blue = (remainder % 6) / 5;
|
||
}
|
||
|
||
const value = Math.max(red, green, blue) * 2;
|
||
|
||
if (value === 0) {
|
||
return 30;
|
||
}
|
||
|
||
// eslint-disable-next-line no-bitwise
|
||
let result = 30 + ((Math.round(blue) << 2) | (Math.round(green) << 1) | Math.round(red));
|
||
|
||
if (value === 2) {
|
||
result += 60;
|
||
}
|
||
|
||
return result;
|
||
},
|
||
enumerable: false,
|
||
},
|
||
rgbToAnsi: {
|
||
value: (red, green, blue) => styles$1.ansi256ToAnsi(styles$1.rgbToAnsi256(red, green, blue)),
|
||
enumerable: false,
|
||
},
|
||
hexToAnsi: {
|
||
value: hex => styles$1.ansi256ToAnsi(styles$1.hexToAnsi256(hex)),
|
||
enumerable: false,
|
||
},
|
||
});
|
||
|
||
return styles$1;
|
||
}
|
||
|
||
const ansiStyles = assembleStyles();
|
||
|
||
/* eslint-env browser */
|
||
|
||
const level = (() => {
|
||
|
||
if (/\b(Chrome|Chromium)\//.test(undefined)) {
|
||
return 1;
|
||
}
|
||
|
||
return 0;
|
||
})();
|
||
|
||
const colorSupport = level !== 0 && {
|
||
level,
|
||
hasBasic: true,
|
||
has256: level >= 2,
|
||
has16m: level >= 3,
|
||
};
|
||
|
||
const supportsColor = {
|
||
stdout: colorSupport,
|
||
stderr: colorSupport,
|
||
};
|
||
|
||
// TODO: When targeting Node.js 16, use `String.prototype.replaceAll`.
|
||
function stringReplaceAll(string, substring, replacer) {
|
||
let index = string.indexOf(substring);
|
||
if (index === -1) {
|
||
return string;
|
||
}
|
||
|
||
const substringLength = substring.length;
|
||
let endIndex = 0;
|
||
let returnValue = '';
|
||
do {
|
||
returnValue += string.slice(endIndex, index) + substring + replacer;
|
||
endIndex = index + substringLength;
|
||
index = string.indexOf(substring, endIndex);
|
||
} while (index !== -1);
|
||
|
||
returnValue += string.slice(endIndex);
|
||
return returnValue;
|
||
}
|
||
|
||
function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
|
||
let endIndex = 0;
|
||
let returnValue = '';
|
||
do {
|
||
const gotCR = string[index - 1] === '\r';
|
||
returnValue += string.slice(endIndex, (gotCR ? index - 1 : index)) + prefix + (gotCR ? '\r\n' : '\n') + postfix;
|
||
endIndex = index + 1;
|
||
index = string.indexOf('\n', endIndex);
|
||
} while (index !== -1);
|
||
|
||
returnValue += string.slice(endIndex);
|
||
return returnValue;
|
||
}
|
||
|
||
const {stdout: stdoutColor, stderr: stderrColor} = supportsColor;
|
||
|
||
const GENERATOR = Symbol('GENERATOR');
|
||
const STYLER = Symbol('STYLER');
|
||
const IS_EMPTY = Symbol('IS_EMPTY');
|
||
|
||
// `supportsColor.level` → `ansiStyles.color[name]` mapping
|
||
const levelMapping = [
|
||
'ansi',
|
||
'ansi',
|
||
'ansi256',
|
||
'ansi16m',
|
||
];
|
||
|
||
const styles = Object.create(null);
|
||
|
||
const applyOptions = (object, options = {}) => {
|
||
if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
|
||
throw new Error('The `level` option should be an integer from 0 to 3');
|
||
}
|
||
|
||
// Detect level if not set manually
|
||
const colorLevel = stdoutColor ? stdoutColor.level : 0;
|
||
object.level = options.level === undefined ? colorLevel : options.level;
|
||
};
|
||
|
||
const chalkFactory = options => {
|
||
const chalk = (...strings) => strings.join(' ');
|
||
applyOptions(chalk, options);
|
||
|
||
Object.setPrototypeOf(chalk, createChalk.prototype);
|
||
|
||
return chalk;
|
||
};
|
||
|
||
function createChalk(options) {
|
||
return chalkFactory(options);
|
||
}
|
||
|
||
Object.setPrototypeOf(createChalk.prototype, Function.prototype);
|
||
|
||
for (const [styleName, style] of Object.entries(ansiStyles)) {
|
||
styles[styleName] = {
|
||
get() {
|
||
const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
|
||
Object.defineProperty(this, styleName, {value: builder});
|
||
return builder;
|
||
},
|
||
};
|
||
}
|
||
|
||
styles.visible = {
|
||
get() {
|
||
const builder = createBuilder(this, this[STYLER], true);
|
||
Object.defineProperty(this, 'visible', {value: builder});
|
||
return builder;
|
||
},
|
||
};
|
||
|
||
const getModelAnsi = (model, level, type, ...arguments_) => {
|
||
if (model === 'rgb') {
|
||
if (level === 'ansi16m') {
|
||
return ansiStyles[type].ansi16m(...arguments_);
|
||
}
|
||
|
||
if (level === 'ansi256') {
|
||
return ansiStyles[type].ansi256(ansiStyles.rgbToAnsi256(...arguments_));
|
||
}
|
||
|
||
return ansiStyles[type].ansi(ansiStyles.rgbToAnsi(...arguments_));
|
||
}
|
||
|
||
if (model === 'hex') {
|
||
return getModelAnsi('rgb', level, type, ...ansiStyles.hexToRgb(...arguments_));
|
||
}
|
||
|
||
return ansiStyles[type][model](...arguments_);
|
||
};
|
||
|
||
const usedModels = ['rgb', 'hex', 'ansi256'];
|
||
|
||
for (const model of usedModels) {
|
||
styles[model] = {
|
||
get() {
|
||
const {level} = this;
|
||
return function (...arguments_) {
|
||
const styler = createStyler(getModelAnsi(model, levelMapping[level], 'color', ...arguments_), ansiStyles.color.close, this[STYLER]);
|
||
return createBuilder(this, styler, this[IS_EMPTY]);
|
||
};
|
||
},
|
||
};
|
||
|
||
const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);
|
||
styles[bgModel] = {
|
||
get() {
|
||
const {level} = this;
|
||
return function (...arguments_) {
|
||
const styler = createStyler(getModelAnsi(model, levelMapping[level], 'bgColor', ...arguments_), ansiStyles.bgColor.close, this[STYLER]);
|
||
return createBuilder(this, styler, this[IS_EMPTY]);
|
||
};
|
||
},
|
||
};
|
||
}
|
||
|
||
const proto = Object.defineProperties(() => {}, {
|
||
...styles,
|
||
level: {
|
||
enumerable: true,
|
||
get() {
|
||
return this[GENERATOR].level;
|
||
},
|
||
set(level) {
|
||
this[GENERATOR].level = level;
|
||
},
|
||
},
|
||
});
|
||
|
||
const createStyler = (open, close, parent) => {
|
||
let openAll;
|
||
let closeAll;
|
||
if (parent === undefined) {
|
||
openAll = open;
|
||
closeAll = close;
|
||
} else {
|
||
openAll = parent.openAll + open;
|
||
closeAll = close + parent.closeAll;
|
||
}
|
||
|
||
return {
|
||
open,
|
||
close,
|
||
openAll,
|
||
closeAll,
|
||
parent,
|
||
};
|
||
};
|
||
|
||
const createBuilder = (self, _styler, _isEmpty) => {
|
||
// Single argument is hot path, implicit coercion is faster than anything
|
||
// eslint-disable-next-line no-implicit-coercion
|
||
const builder = (...arguments_) => applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));
|
||
|
||
// We alter the prototype because we must return a function, but there is
|
||
// no way to create a function with a different prototype
|
||
Object.setPrototypeOf(builder, proto);
|
||
|
||
builder[GENERATOR] = self;
|
||
builder[STYLER] = _styler;
|
||
builder[IS_EMPTY] = _isEmpty;
|
||
|
||
return builder;
|
||
};
|
||
|
||
const applyStyle = (self, string) => {
|
||
if (self.level <= 0 || !string) {
|
||
return self[IS_EMPTY] ? '' : string;
|
||
}
|
||
|
||
let styler = self[STYLER];
|
||
|
||
if (styler === undefined) {
|
||
return string;
|
||
}
|
||
|
||
const {openAll, closeAll} = styler;
|
||
if (string.includes('\u001B')) {
|
||
while (styler !== undefined) {
|
||
// Replace any instances already present with a re-opening code
|
||
// otherwise only the part of the string until said closing code
|
||
// will be colored, and the rest will simply be 'plain'.
|
||
string = stringReplaceAll(string, styler.close, styler.open);
|
||
|
||
styler = styler.parent;
|
||
}
|
||
}
|
||
|
||
// We can move both next actions out of loop, because remaining actions in loop won't have
|
||
// any/visible effect on parts we add here. Close the styling before a linebreak and reopen
|
||
// after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92
|
||
const lfIndex = string.indexOf('\n');
|
||
if (lfIndex !== -1) {
|
||
string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
|
||
}
|
||
|
||
return openAll + string + closeAll;
|
||
};
|
||
|
||
Object.defineProperties(createChalk.prototype, styles);
|
||
|
||
const chalk = createChalk();
|
||
createChalk({level: stderrColor ? stderrColor.level : 0});
|
||
|
||
var onetime$2 = {exports: {}};
|
||
|
||
var mimicFn$2 = {exports: {}};
|
||
|
||
const mimicFn$1 = (to, from) => {
|
||
for (const prop of Reflect.ownKeys(from)) {
|
||
Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop));
|
||
}
|
||
|
||
return to;
|
||
};
|
||
|
||
mimicFn$2.exports = mimicFn$1;
|
||
// TODO: Remove this for the next major release
|
||
mimicFn$2.exports.default = mimicFn$1;
|
||
|
||
var mimicFnExports = mimicFn$2.exports;
|
||
|
||
const mimicFn = mimicFnExports;
|
||
|
||
const calledFunctions = new WeakMap();
|
||
|
||
const onetime = (function_, options = {}) => {
|
||
if (typeof function_ !== 'function') {
|
||
throw new TypeError('Expected a function');
|
||
}
|
||
|
||
let returnValue;
|
||
let callCount = 0;
|
||
const functionName = function_.displayName || function_.name || '<anonymous>';
|
||
|
||
const onetime = function (...arguments_) {
|
||
calledFunctions.set(onetime, ++callCount);
|
||
|
||
if (callCount === 1) {
|
||
returnValue = function_.apply(this, arguments_);
|
||
function_ = null;
|
||
} else if (options.throw === true) {
|
||
throw new Error(`Function \`${functionName}\` can only be called once`);
|
||
}
|
||
|
||
return returnValue;
|
||
};
|
||
|
||
mimicFn(onetime, function_);
|
||
calledFunctions.set(onetime, callCount);
|
||
|
||
return onetime;
|
||
};
|
||
|
||
onetime$2.exports = onetime;
|
||
// TODO: Remove this for the next major release
|
||
onetime$2.exports.default = onetime;
|
||
|
||
onetime$2.exports.callCount = function_ => {
|
||
if (!calledFunctions.has(function_)) {
|
||
throw new Error(`The given function \`${function_.name}\` is not wrapped by the \`onetime\` package`);
|
||
}
|
||
|
||
return calledFunctions.get(function_);
|
||
};
|
||
|
||
var onetimeExports = onetime$2.exports;
|
||
var onetime$1 = /*@__PURE__*/getDefaultExportFromCjs(onetimeExports);
|
||
|
||
var signalExit$1 = {exports: {}};
|
||
|
||
var signals$1 = {exports: {}};
|
||
|
||
var hasRequiredSignals;
|
||
|
||
function requireSignals () {
|
||
if (hasRequiredSignals) return signals$1.exports;
|
||
hasRequiredSignals = 1;
|
||
(function (module) {
|
||
// This is not the set of all possible signals.
|
||
//
|
||
// It IS, however, the set of all signals that trigger
|
||
// an exit on either Linux or BSD systems. Linux is a
|
||
// superset of the signal names supported on BSD, and
|
||
// the unknown signals just fail to register, so we can
|
||
// catch that easily enough.
|
||
//
|
||
// Don't bother with SIGKILL. It's uncatchable, which
|
||
// means that we can't fire any callbacks anyway.
|
||
//
|
||
// If a user does happen to register a handler on a non-
|
||
// fatal signal like SIGWINCH or something, and then
|
||
// exit, it'll end up firing `process.emit('exit')`, so
|
||
// the handler will be fired anyway.
|
||
//
|
||
// SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised
|
||
// artificially, inherently leave the process in a
|
||
// state from which it is not safe to try and enter JS
|
||
// listeners.
|
||
module.exports = [
|
||
'SIGABRT',
|
||
'SIGALRM',
|
||
'SIGHUP',
|
||
'SIGINT',
|
||
'SIGTERM'
|
||
];
|
||
|
||
if (process.platform !== 'win32') {
|
||
module.exports.push(
|
||
'SIGVTALRM',
|
||
'SIGXCPU',
|
||
'SIGXFSZ',
|
||
'SIGUSR2',
|
||
'SIGTRAP',
|
||
'SIGSYS',
|
||
'SIGQUIT',
|
||
'SIGIOT'
|
||
// should detect profiler and enable/disable accordingly.
|
||
// see #21
|
||
// 'SIGPROF'
|
||
);
|
||
}
|
||
|
||
if (process.platform === 'linux') {
|
||
module.exports.push(
|
||
'SIGIO',
|
||
'SIGPOLL',
|
||
'SIGPWR',
|
||
'SIGSTKFLT',
|
||
'SIGUNUSED'
|
||
);
|
||
}
|
||
} (signals$1));
|
||
return signals$1.exports;
|
||
}
|
||
|
||
// Note: since nyc uses this module to output coverage, any lines
|
||
// that are in the direct sync flow of nyc's outputCoverage are
|
||
// ignored, since we can never get coverage for them.
|
||
// grab a reference to node's real process object right away
|
||
var process$1 = commonjsGlobal.process;
|
||
|
||
const processOk = function (process) {
|
||
return process &&
|
||
typeof process === 'object' &&
|
||
typeof process.removeListener === 'function' &&
|
||
typeof process.emit === 'function' &&
|
||
typeof process.reallyExit === 'function' &&
|
||
typeof process.listeners === 'function' &&
|
||
typeof process.kill === 'function' &&
|
||
typeof process.pid === 'number' &&
|
||
typeof process.on === 'function'
|
||
};
|
||
|
||
// some kind of non-node environment, just no-op
|
||
/* istanbul ignore if */
|
||
if (!processOk(process$1)) {
|
||
signalExit$1.exports = function () {
|
||
return function () {}
|
||
};
|
||
} else {
|
||
var assert = require$$5;
|
||
var signals = requireSignals();
|
||
var isWin = /^win/i.test(process$1.platform);
|
||
|
||
var EE = require$$0$7;
|
||
/* istanbul ignore if */
|
||
if (typeof EE !== 'function') {
|
||
EE = EE.EventEmitter;
|
||
}
|
||
|
||
var emitter;
|
||
if (process$1.__signal_exit_emitter__) {
|
||
emitter = process$1.__signal_exit_emitter__;
|
||
} else {
|
||
emitter = process$1.__signal_exit_emitter__ = new EE();
|
||
emitter.count = 0;
|
||
emitter.emitted = {};
|
||
}
|
||
|
||
// Because this emitter is a global, we have to check to see if a
|
||
// previous version of this library failed to enable infinite listeners.
|
||
// I know what you're about to say. But literally everything about
|
||
// signal-exit is a compromise with evil. Get used to it.
|
||
if (!emitter.infinite) {
|
||
emitter.setMaxListeners(Infinity);
|
||
emitter.infinite = true;
|
||
}
|
||
|
||
signalExit$1.exports = function (cb, opts) {
|
||
/* istanbul ignore if */
|
||
if (!processOk(commonjsGlobal.process)) {
|
||
return function () {}
|
||
}
|
||
assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler');
|
||
|
||
if (loaded === false) {
|
||
load();
|
||
}
|
||
|
||
var ev = 'exit';
|
||
if (opts && opts.alwaysLast) {
|
||
ev = 'afterexit';
|
||
}
|
||
|
||
var remove = function () {
|
||
emitter.removeListener(ev, cb);
|
||
if (emitter.listeners('exit').length === 0 &&
|
||
emitter.listeners('afterexit').length === 0) {
|
||
unload();
|
||
}
|
||
};
|
||
emitter.on(ev, cb);
|
||
|
||
return remove
|
||
};
|
||
|
||
var unload = function unload () {
|
||
if (!loaded || !processOk(commonjsGlobal.process)) {
|
||
return
|
||
}
|
||
loaded = false;
|
||
|
||
signals.forEach(function (sig) {
|
||
try {
|
||
process$1.removeListener(sig, sigListeners[sig]);
|
||
} catch (er) {}
|
||
});
|
||
process$1.emit = originalProcessEmit;
|
||
process$1.reallyExit = originalProcessReallyExit;
|
||
emitter.count -= 1;
|
||
};
|
||
signalExit$1.exports.unload = unload;
|
||
|
||
var emit = function emit (event, code, signal) {
|
||
/* istanbul ignore if */
|
||
if (emitter.emitted[event]) {
|
||
return
|
||
}
|
||
emitter.emitted[event] = true;
|
||
emitter.emit(event, code, signal);
|
||
};
|
||
|
||
// { <signal>: <listener fn>, ... }
|
||
var sigListeners = {};
|
||
signals.forEach(function (sig) {
|
||
sigListeners[sig] = function listener () {
|
||
/* istanbul ignore if */
|
||
if (!processOk(commonjsGlobal.process)) {
|
||
return
|
||
}
|
||
// If there are no other listeners, an exit is coming!
|
||
// Simplest way: remove us and then re-send the signal.
|
||
// We know that this will kill the process, so we can
|
||
// safely emit now.
|
||
var listeners = process$1.listeners(sig);
|
||
if (listeners.length === emitter.count) {
|
||
unload();
|
||
emit('exit', null, sig);
|
||
/* istanbul ignore next */
|
||
emit('afterexit', null, sig);
|
||
/* istanbul ignore next */
|
||
if (isWin && sig === 'SIGHUP') {
|
||
// "SIGHUP" throws an `ENOSYS` error on Windows,
|
||
// so use a supported signal instead
|
||
sig = 'SIGINT';
|
||
}
|
||
/* istanbul ignore next */
|
||
process$1.kill(process$1.pid, sig);
|
||
}
|
||
};
|
||
});
|
||
|
||
signalExit$1.exports.signals = function () {
|
||
return signals
|
||
};
|
||
|
||
var loaded = false;
|
||
|
||
var load = function load () {
|
||
if (loaded || !processOk(commonjsGlobal.process)) {
|
||
return
|
||
}
|
||
loaded = true;
|
||
|
||
// This is the number of onSignalExit's that are in play.
|
||
// It's important so that we can count the correct number of
|
||
// listeners on signals, and don't wait for the other one to
|
||
// handle it instead of us.
|
||
emitter.count += 1;
|
||
|
||
signals = signals.filter(function (sig) {
|
||
try {
|
||
process$1.on(sig, sigListeners[sig]);
|
||
return true
|
||
} catch (er) {
|
||
return false
|
||
}
|
||
});
|
||
|
||
process$1.emit = processEmit;
|
||
process$1.reallyExit = processReallyExit;
|
||
};
|
||
signalExit$1.exports.load = load;
|
||
|
||
var originalProcessReallyExit = process$1.reallyExit;
|
||
var processReallyExit = function processReallyExit (code) {
|
||
/* istanbul ignore if */
|
||
if (!processOk(commonjsGlobal.process)) {
|
||
return
|
||
}
|
||
process$1.exitCode = code || /* istanbul ignore next */ 0;
|
||
emit('exit', process$1.exitCode, null);
|
||
/* istanbul ignore next */
|
||
emit('afterexit', process$1.exitCode, null);
|
||
/* istanbul ignore next */
|
||
originalProcessReallyExit.call(process$1, process$1.exitCode);
|
||
};
|
||
|
||
var originalProcessEmit = process$1.emit;
|
||
var processEmit = function processEmit (ev, arg) {
|
||
if (ev === 'exit' && processOk(commonjsGlobal.process)) {
|
||
/* istanbul ignore else */
|
||
if (arg !== undefined) {
|
||
process$1.exitCode = arg;
|
||
}
|
||
var ret = originalProcessEmit.apply(this, arguments);
|
||
/* istanbul ignore next */
|
||
emit('exit', process$1.exitCode, null);
|
||
/* istanbul ignore next */
|
||
emit('afterexit', process$1.exitCode, null);
|
||
/* istanbul ignore next */
|
||
return ret
|
||
} else {
|
||
return originalProcessEmit.apply(this, arguments)
|
||
}
|
||
};
|
||
}
|
||
|
||
var signalExitExports = signalExit$1.exports;
|
||
var signalExit = /*@__PURE__*/getDefaultExportFromCjs(signalExitExports);
|
||
|
||
const restoreCursor = onetime$1(() => {
|
||
signalExit(() => {
|
||
process$2.stderr.write('\u001B[?25h');
|
||
}, {alwaysLast: true});
|
||
});
|
||
|
||
let isHidden = false;
|
||
|
||
const cliCursor = {};
|
||
|
||
cliCursor.show = (writableStream = process$2.stderr) => {
|
||
if (!writableStream.isTTY) {
|
||
return;
|
||
}
|
||
|
||
isHidden = false;
|
||
writableStream.write('\u001B[?25h');
|
||
};
|
||
|
||
cliCursor.hide = (writableStream = process$2.stderr) => {
|
||
if (!writableStream.isTTY) {
|
||
return;
|
||
}
|
||
|
||
restoreCursor();
|
||
isHidden = true;
|
||
writableStream.write('\u001B[?25l');
|
||
};
|
||
|
||
cliCursor.toggle = (force, writableStream) => {
|
||
if (force !== undefined) {
|
||
isHidden = force;
|
||
}
|
||
|
||
if (isHidden) {
|
||
cliCursor.show(writableStream);
|
||
} else {
|
||
cliCursor.hide(writableStream);
|
||
}
|
||
};
|
||
|
||
var dots = {
|
||
interval: 80,
|
||
frames: [
|
||
"⠋",
|
||
"⠙",
|
||
"⠹",
|
||
"⠸",
|
||
"⠼",
|
||
"⠴",
|
||
"⠦",
|
||
"⠧",
|
||
"⠇",
|
||
"⠏"
|
||
]
|
||
};
|
||
var dots2 = {
|
||
interval: 80,
|
||
frames: [
|
||
"⣾",
|
||
"⣽",
|
||
"⣻",
|
||
"⢿",
|
||
"⡿",
|
||
"⣟",
|
||
"⣯",
|
||
"⣷"
|
||
]
|
||
};
|
||
var dots3 = {
|
||
interval: 80,
|
||
frames: [
|
||
"⠋",
|
||
"⠙",
|
||
"⠚",
|
||
"⠞",
|
||
"⠖",
|
||
"⠦",
|
||
"⠴",
|
||
"⠲",
|
||
"⠳",
|
||
"⠓"
|
||
]
|
||
};
|
||
var dots4 = {
|
||
interval: 80,
|
||
frames: [
|
||
"⠄",
|
||
"⠆",
|
||
"⠇",
|
||
"⠋",
|
||
"⠙",
|
||
"⠸",
|
||
"⠰",
|
||
"⠠",
|
||
"⠰",
|
||
"⠸",
|
||
"⠙",
|
||
"⠋",
|
||
"⠇",
|
||
"⠆"
|
||
]
|
||
};
|
||
var dots5 = {
|
||
interval: 80,
|
||
frames: [
|
||
"⠋",
|
||
"⠙",
|
||
"⠚",
|
||
"⠒",
|
||
"⠂",
|
||
"⠂",
|
||
"⠒",
|
||
"⠲",
|
||
"⠴",
|
||
"⠦",
|
||
"⠖",
|
||
"⠒",
|
||
"⠐",
|
||
"⠐",
|
||
"⠒",
|
||
"⠓",
|
||
"⠋"
|
||
]
|
||
};
|
||
var dots6 = {
|
||
interval: 80,
|
||
frames: [
|
||
"⠁",
|
||
"⠉",
|
||
"⠙",
|
||
"⠚",
|
||
"⠒",
|
||
"⠂",
|
||
"⠂",
|
||
"⠒",
|
||
"⠲",
|
||
"⠴",
|
||
"⠤",
|
||
"⠄",
|
||
"⠄",
|
||
"⠤",
|
||
"⠴",
|
||
"⠲",
|
||
"⠒",
|
||
"⠂",
|
||
"⠂",
|
||
"⠒",
|
||
"⠚",
|
||
"⠙",
|
||
"⠉",
|
||
"⠁"
|
||
]
|
||
};
|
||
var dots7 = {
|
||
interval: 80,
|
||
frames: [
|
||
"⠈",
|
||
"⠉",
|
||
"⠋",
|
||
"⠓",
|
||
"⠒",
|
||
"⠐",
|
||
"⠐",
|
||
"⠒",
|
||
"⠖",
|
||
"⠦",
|
||
"⠤",
|
||
"⠠",
|
||
"⠠",
|
||
"⠤",
|
||
"⠦",
|
||
"⠖",
|
||
"⠒",
|
||
"⠐",
|
||
"⠐",
|
||
"⠒",
|
||
"⠓",
|
||
"⠋",
|
||
"⠉",
|
||
"⠈"
|
||
]
|
||
};
|
||
var dots8 = {
|
||
interval: 80,
|
||
frames: [
|
||
"⠁",
|
||
"⠁",
|
||
"⠉",
|
||
"⠙",
|
||
"⠚",
|
||
"⠒",
|
||
"⠂",
|
||
"⠂",
|
||
"⠒",
|
||
"⠲",
|
||
"⠴",
|
||
"⠤",
|
||
"⠄",
|
||
"⠄",
|
||
"⠤",
|
||
"⠠",
|
||
"⠠",
|
||
"⠤",
|
||
"⠦",
|
||
"⠖",
|
||
"⠒",
|
||
"⠐",
|
||
"⠐",
|
||
"⠒",
|
||
"⠓",
|
||
"⠋",
|
||
"⠉",
|
||
"⠈",
|
||
"⠈"
|
||
]
|
||
};
|
||
var dots9 = {
|
||
interval: 80,
|
||
frames: [
|
||
"⢹",
|
||
"⢺",
|
||
"⢼",
|
||
"⣸",
|
||
"⣇",
|
||
"⡧",
|
||
"⡗",
|
||
"⡏"
|
||
]
|
||
};
|
||
var dots10 = {
|
||
interval: 80,
|
||
frames: [
|
||
"⢄",
|
||
"⢂",
|
||
"⢁",
|
||
"⡁",
|
||
"⡈",
|
||
"⡐",
|
||
"⡠"
|
||
]
|
||
};
|
||
var dots11 = {
|
||
interval: 100,
|
||
frames: [
|
||
"⠁",
|
||
"⠂",
|
||
"⠄",
|
||
"⡀",
|
||
"⢀",
|
||
"⠠",
|
||
"⠐",
|
||
"⠈"
|
||
]
|
||
};
|
||
var dots12 = {
|
||
interval: 80,
|
||
frames: [
|
||
"⢀⠀",
|
||
"⡀⠀",
|
||
"⠄⠀",
|
||
"⢂⠀",
|
||
"⡂⠀",
|
||
"⠅⠀",
|
||
"⢃⠀",
|
||
"⡃⠀",
|
||
"⠍⠀",
|
||
"⢋⠀",
|
||
"⡋⠀",
|
||
"⠍⠁",
|
||
"⢋⠁",
|
||
"⡋⠁",
|
||
"⠍⠉",
|
||
"⠋⠉",
|
||
"⠋⠉",
|
||
"⠉⠙",
|
||
"⠉⠙",
|
||
"⠉⠩",
|
||
"⠈⢙",
|
||
"⠈⡙",
|
||
"⢈⠩",
|
||
"⡀⢙",
|
||
"⠄⡙",
|
||
"⢂⠩",
|
||
"⡂⢘",
|
||
"⠅⡘",
|
||
"⢃⠨",
|
||
"⡃⢐",
|
||
"⠍⡐",
|
||
"⢋⠠",
|
||
"⡋⢀",
|
||
"⠍⡁",
|
||
"⢋⠁",
|
||
"⡋⠁",
|
||
"⠍⠉",
|
||
"⠋⠉",
|
||
"⠋⠉",
|
||
"⠉⠙",
|
||
"⠉⠙",
|
||
"⠉⠩",
|
||
"⠈⢙",
|
||
"⠈⡙",
|
||
"⠈⠩",
|
||
"⠀⢙",
|
||
"⠀⡙",
|
||
"⠀⠩",
|
||
"⠀⢘",
|
||
"⠀⡘",
|
||
"⠀⠨",
|
||
"⠀⢐",
|
||
"⠀⡐",
|
||
"⠀⠠",
|
||
"⠀⢀",
|
||
"⠀⡀"
|
||
]
|
||
};
|
||
var dots13 = {
|
||
interval: 80,
|
||
frames: [
|
||
"⣼",
|
||
"⣹",
|
||
"⢻",
|
||
"⠿",
|
||
"⡟",
|
||
"⣏",
|
||
"⣧",
|
||
"⣶"
|
||
]
|
||
};
|
||
var dots8Bit = {
|
||
interval: 80,
|
||
frames: [
|
||
"⠀",
|
||
"⠁",
|
||
"⠂",
|
||
"⠃",
|
||
"⠄",
|
||
"⠅",
|
||
"⠆",
|
||
"⠇",
|
||
"⡀",
|
||
"⡁",
|
||
"⡂",
|
||
"⡃",
|
||
"⡄",
|
||
"⡅",
|
||
"⡆",
|
||
"⡇",
|
||
"⠈",
|
||
"⠉",
|
||
"⠊",
|
||
"⠋",
|
||
"⠌",
|
||
"⠍",
|
||
"⠎",
|
||
"⠏",
|
||
"⡈",
|
||
"⡉",
|
||
"⡊",
|
||
"⡋",
|
||
"⡌",
|
||
"⡍",
|
||
"⡎",
|
||
"⡏",
|
||
"⠐",
|
||
"⠑",
|
||
"⠒",
|
||
"⠓",
|
||
"⠔",
|
||
"⠕",
|
||
"⠖",
|
||
"⠗",
|
||
"⡐",
|
||
"⡑",
|
||
"⡒",
|
||
"⡓",
|
||
"⡔",
|
||
"⡕",
|
||
"⡖",
|
||
"⡗",
|
||
"⠘",
|
||
"⠙",
|
||
"⠚",
|
||
"⠛",
|
||
"⠜",
|
||
"⠝",
|
||
"⠞",
|
||
"⠟",
|
||
"⡘",
|
||
"⡙",
|
||
"⡚",
|
||
"⡛",
|
||
"⡜",
|
||
"⡝",
|
||
"⡞",
|
||
"⡟",
|
||
"⠠",
|
||
"⠡",
|
||
"⠢",
|
||
"⠣",
|
||
"⠤",
|
||
"⠥",
|
||
"⠦",
|
||
"⠧",
|
||
"⡠",
|
||
"⡡",
|
||
"⡢",
|
||
"⡣",
|
||
"⡤",
|
||
"⡥",
|
||
"⡦",
|
||
"⡧",
|
||
"⠨",
|
||
"⠩",
|
||
"⠪",
|
||
"⠫",
|
||
"⠬",
|
||
"⠭",
|
||
"⠮",
|
||
"⠯",
|
||
"⡨",
|
||
"⡩",
|
||
"⡪",
|
||
"⡫",
|
||
"⡬",
|
||
"⡭",
|
||
"⡮",
|
||
"⡯",
|
||
"⠰",
|
||
"⠱",
|
||
"⠲",
|
||
"⠳",
|
||
"⠴",
|
||
"⠵",
|
||
"⠶",
|
||
"⠷",
|
||
"⡰",
|
||
"⡱",
|
||
"⡲",
|
||
"⡳",
|
||
"⡴",
|
||
"⡵",
|
||
"⡶",
|
||
"⡷",
|
||
"⠸",
|
||
"⠹",
|
||
"⠺",
|
||
"⠻",
|
||
"⠼",
|
||
"⠽",
|
||
"⠾",
|
||
"⠿",
|
||
"⡸",
|
||
"⡹",
|
||
"⡺",
|
||
"⡻",
|
||
"⡼",
|
||
"⡽",
|
||
"⡾",
|
||
"⡿",
|
||
"⢀",
|
||
"⢁",
|
||
"⢂",
|
||
"⢃",
|
||
"⢄",
|
||
"⢅",
|
||
"⢆",
|
||
"⢇",
|
||
"⣀",
|
||
"⣁",
|
||
"⣂",
|
||
"⣃",
|
||
"⣄",
|
||
"⣅",
|
||
"⣆",
|
||
"⣇",
|
||
"⢈",
|
||
"⢉",
|
||
"⢊",
|
||
"⢋",
|
||
"⢌",
|
||
"⢍",
|
||
"⢎",
|
||
"⢏",
|
||
"⣈",
|
||
"⣉",
|
||
"⣊",
|
||
"⣋",
|
||
"⣌",
|
||
"⣍",
|
||
"⣎",
|
||
"⣏",
|
||
"⢐",
|
||
"⢑",
|
||
"⢒",
|
||
"⢓",
|
||
"⢔",
|
||
"⢕",
|
||
"⢖",
|
||
"⢗",
|
||
"⣐",
|
||
"⣑",
|
||
"⣒",
|
||
"⣓",
|
||
"⣔",
|
||
"⣕",
|
||
"⣖",
|
||
"⣗",
|
||
"⢘",
|
||
"⢙",
|
||
"⢚",
|
||
"⢛",
|
||
"⢜",
|
||
"⢝",
|
||
"⢞",
|
||
"⢟",
|
||
"⣘",
|
||
"⣙",
|
||
"⣚",
|
||
"⣛",
|
||
"⣜",
|
||
"⣝",
|
||
"⣞",
|
||
"⣟",
|
||
"⢠",
|
||
"⢡",
|
||
"⢢",
|
||
"⢣",
|
||
"⢤",
|
||
"⢥",
|
||
"⢦",
|
||
"⢧",
|
||
"⣠",
|
||
"⣡",
|
||
"⣢",
|
||
"⣣",
|
||
"⣤",
|
||
"⣥",
|
||
"⣦",
|
||
"⣧",
|
||
"⢨",
|
||
"⢩",
|
||
"⢪",
|
||
"⢫",
|
||
"⢬",
|
||
"⢭",
|
||
"⢮",
|
||
"⢯",
|
||
"⣨",
|
||
"⣩",
|
||
"⣪",
|
||
"⣫",
|
||
"⣬",
|
||
"⣭",
|
||
"⣮",
|
||
"⣯",
|
||
"⢰",
|
||
"⢱",
|
||
"⢲",
|
||
"⢳",
|
||
"⢴",
|
||
"⢵",
|
||
"⢶",
|
||
"⢷",
|
||
"⣰",
|
||
"⣱",
|
||
"⣲",
|
||
"⣳",
|
||
"⣴",
|
||
"⣵",
|
||
"⣶",
|
||
"⣷",
|
||
"⢸",
|
||
"⢹",
|
||
"⢺",
|
||
"⢻",
|
||
"⢼",
|
||
"⢽",
|
||
"⢾",
|
||
"⢿",
|
||
"⣸",
|
||
"⣹",
|
||
"⣺",
|
||
"⣻",
|
||
"⣼",
|
||
"⣽",
|
||
"⣾",
|
||
"⣿"
|
||
]
|
||
};
|
||
var sand = {
|
||
interval: 80,
|
||
frames: [
|
||
"⠁",
|
||
"⠂",
|
||
"⠄",
|
||
"⡀",
|
||
"⡈",
|
||
"⡐",
|
||
"⡠",
|
||
"⣀",
|
||
"⣁",
|
||
"⣂",
|
||
"⣄",
|
||
"⣌",
|
||
"⣔",
|
||
"⣤",
|
||
"⣥",
|
||
"⣦",
|
||
"⣮",
|
||
"⣶",
|
||
"⣷",
|
||
"⣿",
|
||
"⡿",
|
||
"⠿",
|
||
"⢟",
|
||
"⠟",
|
||
"⡛",
|
||
"⠛",
|
||
"⠫",
|
||
"⢋",
|
||
"⠋",
|
||
"⠍",
|
||
"⡉",
|
||
"⠉",
|
||
"⠑",
|
||
"⠡",
|
||
"⢁"
|
||
]
|
||
};
|
||
var line = {
|
||
interval: 130,
|
||
frames: [
|
||
"-",
|
||
"\\",
|
||
"|",
|
||
"/"
|
||
]
|
||
};
|
||
var line2 = {
|
||
interval: 100,
|
||
frames: [
|
||
"⠂",
|
||
"-",
|
||
"–",
|
||
"—",
|
||
"–",
|
||
"-"
|
||
]
|
||
};
|
||
var pipe = {
|
||
interval: 100,
|
||
frames: [
|
||
"┤",
|
||
"┘",
|
||
"┴",
|
||
"└",
|
||
"├",
|
||
"┌",
|
||
"┬",
|
||
"┐"
|
||
]
|
||
};
|
||
var simpleDots = {
|
||
interval: 400,
|
||
frames: [
|
||
". ",
|
||
".. ",
|
||
"...",
|
||
" "
|
||
]
|
||
};
|
||
var simpleDotsScrolling = {
|
||
interval: 200,
|
||
frames: [
|
||
". ",
|
||
".. ",
|
||
"...",
|
||
" ..",
|
||
" .",
|
||
" "
|
||
]
|
||
};
|
||
var star = {
|
||
interval: 70,
|
||
frames: [
|
||
"✶",
|
||
"✸",
|
||
"✹",
|
||
"✺",
|
||
"✹",
|
||
"✷"
|
||
]
|
||
};
|
||
var star2 = {
|
||
interval: 80,
|
||
frames: [
|
||
"+",
|
||
"x",
|
||
"*"
|
||
]
|
||
};
|
||
var flip = {
|
||
interval: 70,
|
||
frames: [
|
||
"_",
|
||
"_",
|
||
"_",
|
||
"-",
|
||
"`",
|
||
"`",
|
||
"'",
|
||
"´",
|
||
"-",
|
||
"_",
|
||
"_",
|
||
"_"
|
||
]
|
||
};
|
||
var hamburger = {
|
||
interval: 100,
|
||
frames: [
|
||
"☱",
|
||
"☲",
|
||
"☴"
|
||
]
|
||
};
|
||
var growVertical = {
|
||
interval: 120,
|
||
frames: [
|
||
"▁",
|
||
"▃",
|
||
"▄",
|
||
"▅",
|
||
"▆",
|
||
"▇",
|
||
"▆",
|
||
"▅",
|
||
"▄",
|
||
"▃"
|
||
]
|
||
};
|
||
var growHorizontal = {
|
||
interval: 120,
|
||
frames: [
|
||
"▏",
|
||
"▎",
|
||
"▍",
|
||
"▌",
|
||
"▋",
|
||
"▊",
|
||
"▉",
|
||
"▊",
|
||
"▋",
|
||
"▌",
|
||
"▍",
|
||
"▎"
|
||
]
|
||
};
|
||
var balloon = {
|
||
interval: 140,
|
||
frames: [
|
||
" ",
|
||
".",
|
||
"o",
|
||
"O",
|
||
"@",
|
||
"*",
|
||
" "
|
||
]
|
||
};
|
||
var balloon2 = {
|
||
interval: 120,
|
||
frames: [
|
||
".",
|
||
"o",
|
||
"O",
|
||
"°",
|
||
"O",
|
||
"o",
|
||
"."
|
||
]
|
||
};
|
||
var noise = {
|
||
interval: 100,
|
||
frames: [
|
||
"▓",
|
||
"▒",
|
||
"░"
|
||
]
|
||
};
|
||
var bounce = {
|
||
interval: 120,
|
||
frames: [
|
||
"⠁",
|
||
"⠂",
|
||
"⠄",
|
||
"⠂"
|
||
]
|
||
};
|
||
var boxBounce = {
|
||
interval: 120,
|
||
frames: [
|
||
"▖",
|
||
"▘",
|
||
"▝",
|
||
"▗"
|
||
]
|
||
};
|
||
var boxBounce2 = {
|
||
interval: 100,
|
||
frames: [
|
||
"▌",
|
||
"▀",
|
||
"▐",
|
||
"▄"
|
||
]
|
||
};
|
||
var triangle = {
|
||
interval: 50,
|
||
frames: [
|
||
"◢",
|
||
"◣",
|
||
"◤",
|
||
"◥"
|
||
]
|
||
};
|
||
var binary = {
|
||
interval: 80,
|
||
frames: [
|
||
"010010",
|
||
"001100",
|
||
"100101",
|
||
"111010",
|
||
"111101",
|
||
"010111",
|
||
"101011",
|
||
"111000",
|
||
"110011",
|
||
"110101"
|
||
]
|
||
};
|
||
var arc = {
|
||
interval: 100,
|
||
frames: [
|
||
"◜",
|
||
"◠",
|
||
"◝",
|
||
"◞",
|
||
"◡",
|
||
"◟"
|
||
]
|
||
};
|
||
var circle = {
|
||
interval: 120,
|
||
frames: [
|
||
"◡",
|
||
"⊙",
|
||
"◠"
|
||
]
|
||
};
|
||
var squareCorners = {
|
||
interval: 180,
|
||
frames: [
|
||
"◰",
|
||
"◳",
|
||
"◲",
|
||
"◱"
|
||
]
|
||
};
|
||
var circleQuarters = {
|
||
interval: 120,
|
||
frames: [
|
||
"◴",
|
||
"◷",
|
||
"◶",
|
||
"◵"
|
||
]
|
||
};
|
||
var circleHalves = {
|
||
interval: 50,
|
||
frames: [
|
||
"◐",
|
||
"◓",
|
||
"◑",
|
||
"◒"
|
||
]
|
||
};
|
||
var squish = {
|
||
interval: 100,
|
||
frames: [
|
||
"╫",
|
||
"╪"
|
||
]
|
||
};
|
||
var toggle = {
|
||
interval: 250,
|
||
frames: [
|
||
"⊶",
|
||
"⊷"
|
||
]
|
||
};
|
||
var toggle2 = {
|
||
interval: 80,
|
||
frames: [
|
||
"▫",
|
||
"▪"
|
||
]
|
||
};
|
||
var toggle3 = {
|
||
interval: 120,
|
||
frames: [
|
||
"□",
|
||
"■"
|
||
]
|
||
};
|
||
var toggle4 = {
|
||
interval: 100,
|
||
frames: [
|
||
"■",
|
||
"□",
|
||
"▪",
|
||
"▫"
|
||
]
|
||
};
|
||
var toggle5 = {
|
||
interval: 100,
|
||
frames: [
|
||
"▮",
|
||
"▯"
|
||
]
|
||
};
|
||
var toggle6 = {
|
||
interval: 300,
|
||
frames: [
|
||
"ဝ",
|
||
"၀"
|
||
]
|
||
};
|
||
var toggle7 = {
|
||
interval: 80,
|
||
frames: [
|
||
"⦾",
|
||
"⦿"
|
||
]
|
||
};
|
||
var toggle8 = {
|
||
interval: 100,
|
||
frames: [
|
||
"◍",
|
||
"◌"
|
||
]
|
||
};
|
||
var toggle9 = {
|
||
interval: 100,
|
||
frames: [
|
||
"◉",
|
||
"◎"
|
||
]
|
||
};
|
||
var toggle10 = {
|
||
interval: 100,
|
||
frames: [
|
||
"㊂",
|
||
"㊀",
|
||
"㊁"
|
||
]
|
||
};
|
||
var toggle11 = {
|
||
interval: 50,
|
||
frames: [
|
||
"⧇",
|
||
"⧆"
|
||
]
|
||
};
|
||
var toggle12 = {
|
||
interval: 120,
|
||
frames: [
|
||
"☗",
|
||
"☖"
|
||
]
|
||
};
|
||
var toggle13 = {
|
||
interval: 80,
|
||
frames: [
|
||
"=",
|
||
"*",
|
||
"-"
|
||
]
|
||
};
|
||
var arrow = {
|
||
interval: 100,
|
||
frames: [
|
||
"←",
|
||
"↖",
|
||
"↑",
|
||
"↗",
|
||
"→",
|
||
"↘",
|
||
"↓",
|
||
"↙"
|
||
]
|
||
};
|
||
var arrow2 = {
|
||
interval: 80,
|
||
frames: [
|
||
"⬆️ ",
|
||
"↗️ ",
|
||
"➡️ ",
|
||
"↘️ ",
|
||
"⬇️ ",
|
||
"↙️ ",
|
||
"⬅️ ",
|
||
"↖️ "
|
||
]
|
||
};
|
||
var arrow3 = {
|
||
interval: 120,
|
||
frames: [
|
||
"▹▹▹▹▹",
|
||
"▸▹▹▹▹",
|
||
"▹▸▹▹▹",
|
||
"▹▹▸▹▹",
|
||
"▹▹▹▸▹",
|
||
"▹▹▹▹▸"
|
||
]
|
||
};
|
||
var bouncingBar = {
|
||
interval: 80,
|
||
frames: [
|
||
"[ ]",
|
||
"[= ]",
|
||
"[== ]",
|
||
"[=== ]",
|
||
"[====]",
|
||
"[ ===]",
|
||
"[ ==]",
|
||
"[ =]",
|
||
"[ ]",
|
||
"[ =]",
|
||
"[ ==]",
|
||
"[ ===]",
|
||
"[====]",
|
||
"[=== ]",
|
||
"[== ]",
|
||
"[= ]"
|
||
]
|
||
};
|
||
var bouncingBall = {
|
||
interval: 80,
|
||
frames: [
|
||
"( ● )",
|
||
"( ● )",
|
||
"( ● )",
|
||
"( ● )",
|
||
"( ●)",
|
||
"( ● )",
|
||
"( ● )",
|
||
"( ● )",
|
||
"( ● )",
|
||
"(● )"
|
||
]
|
||
};
|
||
var smiley = {
|
||
interval: 200,
|
||
frames: [
|
||
"😄 ",
|
||
"😝 "
|
||
]
|
||
};
|
||
var monkey = {
|
||
interval: 300,
|
||
frames: [
|
||
"🙈 ",
|
||
"🙈 ",
|
||
"🙉 ",
|
||
"🙊 "
|
||
]
|
||
};
|
||
var hearts = {
|
||
interval: 100,
|
||
frames: [
|
||
"💛 ",
|
||
"💙 ",
|
||
"💜 ",
|
||
"💚 ",
|
||
"❤️ "
|
||
]
|
||
};
|
||
var clock = {
|
||
interval: 100,
|
||
frames: [
|
||
"🕛 ",
|
||
"🕐 ",
|
||
"🕑 ",
|
||
"🕒 ",
|
||
"🕓 ",
|
||
"🕔 ",
|
||
"🕕 ",
|
||
"🕖 ",
|
||
"🕗 ",
|
||
"🕘 ",
|
||
"🕙 ",
|
||
"🕚 "
|
||
]
|
||
};
|
||
var earth = {
|
||
interval: 180,
|
||
frames: [
|
||
"🌍 ",
|
||
"🌎 ",
|
||
"🌏 "
|
||
]
|
||
};
|
||
var material = {
|
||
interval: 17,
|
||
frames: [
|
||
"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
|
||
"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
|
||
"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
|
||
"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
|
||
"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
|
||
"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
|
||
"███████▁▁▁▁▁▁▁▁▁▁▁▁▁",
|
||
"████████▁▁▁▁▁▁▁▁▁▁▁▁",
|
||
"█████████▁▁▁▁▁▁▁▁▁▁▁",
|
||
"█████████▁▁▁▁▁▁▁▁▁▁▁",
|
||
"██████████▁▁▁▁▁▁▁▁▁▁",
|
||
"███████████▁▁▁▁▁▁▁▁▁",
|
||
"█████████████▁▁▁▁▁▁▁",
|
||
"██████████████▁▁▁▁▁▁",
|
||
"██████████████▁▁▁▁▁▁",
|
||
"▁██████████████▁▁▁▁▁",
|
||
"▁██████████████▁▁▁▁▁",
|
||
"▁██████████████▁▁▁▁▁",
|
||
"▁▁██████████████▁▁▁▁",
|
||
"▁▁▁██████████████▁▁▁",
|
||
"▁▁▁▁█████████████▁▁▁",
|
||
"▁▁▁▁██████████████▁▁",
|
||
"▁▁▁▁██████████████▁▁",
|
||
"▁▁▁▁▁██████████████▁",
|
||
"▁▁▁▁▁██████████████▁",
|
||
"▁▁▁▁▁██████████████▁",
|
||
"▁▁▁▁▁▁██████████████",
|
||
"▁▁▁▁▁▁██████████████",
|
||
"▁▁▁▁▁▁▁█████████████",
|
||
"▁▁▁▁▁▁▁█████████████",
|
||
"▁▁▁▁▁▁▁▁████████████",
|
||
"▁▁▁▁▁▁▁▁████████████",
|
||
"▁▁▁▁▁▁▁▁▁███████████",
|
||
"▁▁▁▁▁▁▁▁▁███████████",
|
||
"▁▁▁▁▁▁▁▁▁▁██████████",
|
||
"▁▁▁▁▁▁▁▁▁▁██████████",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁████████",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁███████",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████",
|
||
"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████",
|
||
"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███",
|
||
"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███",
|
||
"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███",
|
||
"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██",
|
||
"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█",
|
||
"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█",
|
||
"██████▁▁▁▁▁▁▁▁▁▁▁▁▁█",
|
||
"████████▁▁▁▁▁▁▁▁▁▁▁▁",
|
||
"█████████▁▁▁▁▁▁▁▁▁▁▁",
|
||
"█████████▁▁▁▁▁▁▁▁▁▁▁",
|
||
"█████████▁▁▁▁▁▁▁▁▁▁▁",
|
||
"█████████▁▁▁▁▁▁▁▁▁▁▁",
|
||
"███████████▁▁▁▁▁▁▁▁▁",
|
||
"████████████▁▁▁▁▁▁▁▁",
|
||
"████████████▁▁▁▁▁▁▁▁",
|
||
"██████████████▁▁▁▁▁▁",
|
||
"██████████████▁▁▁▁▁▁",
|
||
"▁██████████████▁▁▁▁▁",
|
||
"▁██████████████▁▁▁▁▁",
|
||
"▁▁▁█████████████▁▁▁▁",
|
||
"▁▁▁▁▁████████████▁▁▁",
|
||
"▁▁▁▁▁████████████▁▁▁",
|
||
"▁▁▁▁▁▁███████████▁▁▁",
|
||
"▁▁▁▁▁▁▁▁█████████▁▁▁",
|
||
"▁▁▁▁▁▁▁▁█████████▁▁▁",
|
||
"▁▁▁▁▁▁▁▁▁█████████▁▁",
|
||
"▁▁▁▁▁▁▁▁▁█████████▁▁",
|
||
"▁▁▁▁▁▁▁▁▁▁█████████▁",
|
||
"▁▁▁▁▁▁▁▁▁▁▁████████▁",
|
||
"▁▁▁▁▁▁▁▁▁▁▁████████▁",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁███████▁",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁███████▁",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁███████",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁███████",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁",
|
||
"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁"
|
||
]
|
||
};
|
||
var moon = {
|
||
interval: 80,
|
||
frames: [
|
||
"🌑 ",
|
||
"🌒 ",
|
||
"🌓 ",
|
||
"🌔 ",
|
||
"🌕 ",
|
||
"🌖 ",
|
||
"🌗 ",
|
||
"🌘 "
|
||
]
|
||
};
|
||
var runner = {
|
||
interval: 140,
|
||
frames: [
|
||
"🚶 ",
|
||
"🏃 "
|
||
]
|
||
};
|
||
var pong = {
|
||
interval: 80,
|
||
frames: [
|
||
"▐⠂ ▌",
|
||
"▐⠈ ▌",
|
||
"▐ ⠂ ▌",
|
||
"▐ ⠠ ▌",
|
||
"▐ ⡀ ▌",
|
||
"▐ ⠠ ▌",
|
||
"▐ ⠂ ▌",
|
||
"▐ ⠈ ▌",
|
||
"▐ ⠂ ▌",
|
||
"▐ ⠠ ▌",
|
||
"▐ ⡀ ▌",
|
||
"▐ ⠠ ▌",
|
||
"▐ ⠂ ▌",
|
||
"▐ ⠈ ▌",
|
||
"▐ ⠂▌",
|
||
"▐ ⠠▌",
|
||
"▐ ⡀▌",
|
||
"▐ ⠠ ▌",
|
||
"▐ ⠂ ▌",
|
||
"▐ ⠈ ▌",
|
||
"▐ ⠂ ▌",
|
||
"▐ ⠠ ▌",
|
||
"▐ ⡀ ▌",
|
||
"▐ ⠠ ▌",
|
||
"▐ ⠂ ▌",
|
||
"▐ ⠈ ▌",
|
||
"▐ ⠂ ▌",
|
||
"▐ ⠠ ▌",
|
||
"▐ ⡀ ▌",
|
||
"▐⠠ ▌"
|
||
]
|
||
};
|
||
var shark = {
|
||
interval: 120,
|
||
frames: [
|
||
"▐|\\____________▌",
|
||
"▐_|\\___________▌",
|
||
"▐__|\\__________▌",
|
||
"▐___|\\_________▌",
|
||
"▐____|\\________▌",
|
||
"▐_____|\\_______▌",
|
||
"▐______|\\______▌",
|
||
"▐_______|\\_____▌",
|
||
"▐________|\\____▌",
|
||
"▐_________|\\___▌",
|
||
"▐__________|\\__▌",
|
||
"▐___________|\\_▌",
|
||
"▐____________|\\▌",
|
||
"▐____________/|▌",
|
||
"▐___________/|_▌",
|
||
"▐__________/|__▌",
|
||
"▐_________/|___▌",
|
||
"▐________/|____▌",
|
||
"▐_______/|_____▌",
|
||
"▐______/|______▌",
|
||
"▐_____/|_______▌",
|
||
"▐____/|________▌",
|
||
"▐___/|_________▌",
|
||
"▐__/|__________▌",
|
||
"▐_/|___________▌",
|
||
"▐/|____________▌"
|
||
]
|
||
};
|
||
var dqpb = {
|
||
interval: 100,
|
||
frames: [
|
||
"d",
|
||
"q",
|
||
"p",
|
||
"b"
|
||
]
|
||
};
|
||
var weather = {
|
||
interval: 100,
|
||
frames: [
|
||
"☀️ ",
|
||
"☀️ ",
|
||
"☀️ ",
|
||
"🌤 ",
|
||
"⛅️ ",
|
||
"🌥 ",
|
||
"☁️ ",
|
||
"🌧 ",
|
||
"🌨 ",
|
||
"🌧 ",
|
||
"🌨 ",
|
||
"🌧 ",
|
||
"🌨 ",
|
||
"⛈ ",
|
||
"🌨 ",
|
||
"🌧 ",
|
||
"🌨 ",
|
||
"☁️ ",
|
||
"🌥 ",
|
||
"⛅️ ",
|
||
"🌤 ",
|
||
"☀️ ",
|
||
"☀️ "
|
||
]
|
||
};
|
||
var christmas = {
|
||
interval: 400,
|
||
frames: [
|
||
"🌲",
|
||
"🎄"
|
||
]
|
||
};
|
||
var grenade = {
|
||
interval: 80,
|
||
frames: [
|
||
"، ",
|
||
"′ ",
|
||
" ´ ",
|
||
" ‾ ",
|
||
" ⸌",
|
||
" ⸊",
|
||
" |",
|
||
" ⁎",
|
||
" ⁕",
|
||
" ෴ ",
|
||
" ⁓",
|
||
" ",
|
||
" ",
|
||
" "
|
||
]
|
||
};
|
||
var point = {
|
||
interval: 125,
|
||
frames: [
|
||
"∙∙∙",
|
||
"●∙∙",
|
||
"∙●∙",
|
||
"∙∙●",
|
||
"∙∙∙"
|
||
]
|
||
};
|
||
var layer = {
|
||
interval: 150,
|
||
frames: [
|
||
"-",
|
||
"=",
|
||
"≡"
|
||
]
|
||
};
|
||
var betaWave = {
|
||
interval: 80,
|
||
frames: [
|
||
"ρββββββ",
|
||
"βρβββββ",
|
||
"ββρββββ",
|
||
"βββρβββ",
|
||
"ββββρββ",
|
||
"βββββρβ",
|
||
"ββββββρ"
|
||
]
|
||
};
|
||
var fingerDance = {
|
||
interval: 160,
|
||
frames: [
|
||
"🤘 ",
|
||
"🤟 ",
|
||
"🖖 ",
|
||
"✋ ",
|
||
"🤚 ",
|
||
"👆 "
|
||
]
|
||
};
|
||
var fistBump = {
|
||
interval: 80,
|
||
frames: [
|
||
"🤜 🤛 ",
|
||
"🤜 🤛 ",
|
||
"🤜 🤛 ",
|
||
" 🤜 🤛 ",
|
||
" 🤜🤛 ",
|
||
" 🤜✨🤛 ",
|
||
"🤜 ✨ 🤛 "
|
||
]
|
||
};
|
||
var soccerHeader = {
|
||
interval: 80,
|
||
frames: [
|
||
" 🧑⚽️ 🧑 ",
|
||
"🧑 ⚽️ 🧑 ",
|
||
"🧑 ⚽️ 🧑 ",
|
||
"🧑 ⚽️ 🧑 ",
|
||
"🧑 ⚽️ 🧑 ",
|
||
"🧑 ⚽️ 🧑 ",
|
||
"🧑 ⚽️🧑 ",
|
||
"🧑 ⚽️ 🧑 ",
|
||
"🧑 ⚽️ 🧑 ",
|
||
"🧑 ⚽️ 🧑 ",
|
||
"🧑 ⚽️ 🧑 ",
|
||
"🧑 ⚽️ 🧑 "
|
||
]
|
||
};
|
||
var mindblown = {
|
||
interval: 160,
|
||
frames: [
|
||
"😐 ",
|
||
"😐 ",
|
||
"😮 ",
|
||
"😮 ",
|
||
"😦 ",
|
||
"😦 ",
|
||
"😧 ",
|
||
"😧 ",
|
||
"🤯 ",
|
||
"💥 ",
|
||
"✨ ",
|
||
" ",
|
||
" ",
|
||
" "
|
||
]
|
||
};
|
||
var speaker = {
|
||
interval: 160,
|
||
frames: [
|
||
"🔈 ",
|
||
"🔉 ",
|
||
"🔊 ",
|
||
"🔉 "
|
||
]
|
||
};
|
||
var orangePulse = {
|
||
interval: 100,
|
||
frames: [
|
||
"🔸 ",
|
||
"🔶 ",
|
||
"🟠 ",
|
||
"🟠 ",
|
||
"🔶 "
|
||
]
|
||
};
|
||
var bluePulse = {
|
||
interval: 100,
|
||
frames: [
|
||
"🔹 ",
|
||
"🔷 ",
|
||
"🔵 ",
|
||
"🔵 ",
|
||
"🔷 "
|
||
]
|
||
};
|
||
var orangeBluePulse = {
|
||
interval: 100,
|
||
frames: [
|
||
"🔸 ",
|
||
"🔶 ",
|
||
"🟠 ",
|
||
"🟠 ",
|
||
"🔶 ",
|
||
"🔹 ",
|
||
"🔷 ",
|
||
"🔵 ",
|
||
"🔵 ",
|
||
"🔷 "
|
||
]
|
||
};
|
||
var timeTravel = {
|
||
interval: 100,
|
||
frames: [
|
||
"🕛 ",
|
||
"🕚 ",
|
||
"🕙 ",
|
||
"🕘 ",
|
||
"🕗 ",
|
||
"🕖 ",
|
||
"🕕 ",
|
||
"🕔 ",
|
||
"🕓 ",
|
||
"🕒 ",
|
||
"🕑 ",
|
||
"🕐 "
|
||
]
|
||
};
|
||
var aesthetic = {
|
||
interval: 80,
|
||
frames: [
|
||
"▰▱▱▱▱▱▱",
|
||
"▰▰▱▱▱▱▱",
|
||
"▰▰▰▱▱▱▱",
|
||
"▰▰▰▰▱▱▱",
|
||
"▰▰▰▰▰▱▱",
|
||
"▰▰▰▰▰▰▱",
|
||
"▰▰▰▰▰▰▰",
|
||
"▰▱▱▱▱▱▱"
|
||
]
|
||
};
|
||
var dwarfFortress = {
|
||
interval: 80,
|
||
frames: [
|
||
" ██████£££ ",
|
||
"☺██████£££ ",
|
||
"☺██████£££ ",
|
||
"☺▓█████£££ ",
|
||
"☺▓█████£££ ",
|
||
"☺▒█████£££ ",
|
||
"☺▒█████£££ ",
|
||
"☺░█████£££ ",
|
||
"☺░█████£££ ",
|
||
"☺ █████£££ ",
|
||
" ☺█████£££ ",
|
||
" ☺█████£££ ",
|
||
" ☺▓████£££ ",
|
||
" ☺▓████£££ ",
|
||
" ☺▒████£££ ",
|
||
" ☺▒████£££ ",
|
||
" ☺░████£££ ",
|
||
" ☺░████£££ ",
|
||
" ☺ ████£££ ",
|
||
" ☺████£££ ",
|
||
" ☺████£££ ",
|
||
" ☺▓███£££ ",
|
||
" ☺▓███£££ ",
|
||
" ☺▒███£££ ",
|
||
" ☺▒███£££ ",
|
||
" ☺░███£££ ",
|
||
" ☺░███£££ ",
|
||
" ☺ ███£££ ",
|
||
" ☺███£££ ",
|
||
" ☺███£££ ",
|
||
" ☺▓██£££ ",
|
||
" ☺▓██£££ ",
|
||
" ☺▒██£££ ",
|
||
" ☺▒██£££ ",
|
||
" ☺░██£££ ",
|
||
" ☺░██£££ ",
|
||
" ☺ ██£££ ",
|
||
" ☺██£££ ",
|
||
" ☺██£££ ",
|
||
" ☺▓█£££ ",
|
||
" ☺▓█£££ ",
|
||
" ☺▒█£££ ",
|
||
" ☺▒█£££ ",
|
||
" ☺░█£££ ",
|
||
" ☺░█£££ ",
|
||
" ☺ █£££ ",
|
||
" ☺█£££ ",
|
||
" ☺█£££ ",
|
||
" ☺▓£££ ",
|
||
" ☺▓£££ ",
|
||
" ☺▒£££ ",
|
||
" ☺▒£££ ",
|
||
" ☺░£££ ",
|
||
" ☺░£££ ",
|
||
" ☺ £££ ",
|
||
" ☺£££ ",
|
||
" ☺£££ ",
|
||
" ☺▓££ ",
|
||
" ☺▓££ ",
|
||
" ☺▒££ ",
|
||
" ☺▒££ ",
|
||
" ☺░££ ",
|
||
" ☺░££ ",
|
||
" ☺ ££ ",
|
||
" ☺££ ",
|
||
" ☺££ ",
|
||
" ☺▓£ ",
|
||
" ☺▓£ ",
|
||
" ☺▒£ ",
|
||
" ☺▒£ ",
|
||
" ☺░£ ",
|
||
" ☺░£ ",
|
||
" ☺ £ ",
|
||
" ☺£ ",
|
||
" ☺£ ",
|
||
" ☺▓ ",
|
||
" ☺▓ ",
|
||
" ☺▒ ",
|
||
" ☺▒ ",
|
||
" ☺░ ",
|
||
" ☺░ ",
|
||
" ☺ ",
|
||
" ☺ &",
|
||
" ☺ ☼&",
|
||
" ☺ ☼ &",
|
||
" ☺☼ &",
|
||
" ☺☼ & ",
|
||
" ‼ & ",
|
||
" ☺ & ",
|
||
" ‼ & ",
|
||
" ☺ & ",
|
||
" ‼ & ",
|
||
" ☺ & ",
|
||
"‼ & ",
|
||
" & ",
|
||
" & ",
|
||
" & ░ ",
|
||
" & ▒ ",
|
||
" & ▓ ",
|
||
" & £ ",
|
||
" & ░£ ",
|
||
" & ▒£ ",
|
||
" & ▓£ ",
|
||
" & ££ ",
|
||
" & ░££ ",
|
||
" & ▒££ ",
|
||
"& ▓££ ",
|
||
"& £££ ",
|
||
" ░£££ ",
|
||
" ▒£££ ",
|
||
" ▓£££ ",
|
||
" █£££ ",
|
||
" ░█£££ ",
|
||
" ▒█£££ ",
|
||
" ▓█£££ ",
|
||
" ██£££ ",
|
||
" ░██£££ ",
|
||
" ▒██£££ ",
|
||
" ▓██£££ ",
|
||
" ███£££ ",
|
||
" ░███£££ ",
|
||
" ▒███£££ ",
|
||
" ▓███£££ ",
|
||
" ████£££ ",
|
||
" ░████£££ ",
|
||
" ▒████£££ ",
|
||
" ▓████£££ ",
|
||
" █████£££ ",
|
||
" ░█████£££ ",
|
||
" ▒█████£££ ",
|
||
" ▓█████£££ ",
|
||
" ██████£££ ",
|
||
" ██████£££ "
|
||
]
|
||
};
|
||
var require$$0$1 = {
|
||
dots: dots,
|
||
dots2: dots2,
|
||
dots3: dots3,
|
||
dots4: dots4,
|
||
dots5: dots5,
|
||
dots6: dots6,
|
||
dots7: dots7,
|
||
dots8: dots8,
|
||
dots9: dots9,
|
||
dots10: dots10,
|
||
dots11: dots11,
|
||
dots12: dots12,
|
||
dots13: dots13,
|
||
dots8Bit: dots8Bit,
|
||
sand: sand,
|
||
line: line,
|
||
line2: line2,
|
||
pipe: pipe,
|
||
simpleDots: simpleDots,
|
||
simpleDotsScrolling: simpleDotsScrolling,
|
||
star: star,
|
||
star2: star2,
|
||
flip: flip,
|
||
hamburger: hamburger,
|
||
growVertical: growVertical,
|
||
growHorizontal: growHorizontal,
|
||
balloon: balloon,
|
||
balloon2: balloon2,
|
||
noise: noise,
|
||
bounce: bounce,
|
||
boxBounce: boxBounce,
|
||
boxBounce2: boxBounce2,
|
||
triangle: triangle,
|
||
binary: binary,
|
||
arc: arc,
|
||
circle: circle,
|
||
squareCorners: squareCorners,
|
||
circleQuarters: circleQuarters,
|
||
circleHalves: circleHalves,
|
||
squish: squish,
|
||
toggle: toggle,
|
||
toggle2: toggle2,
|
||
toggle3: toggle3,
|
||
toggle4: toggle4,
|
||
toggle5: toggle5,
|
||
toggle6: toggle6,
|
||
toggle7: toggle7,
|
||
toggle8: toggle8,
|
||
toggle9: toggle9,
|
||
toggle10: toggle10,
|
||
toggle11: toggle11,
|
||
toggle12: toggle12,
|
||
toggle13: toggle13,
|
||
arrow: arrow,
|
||
arrow2: arrow2,
|
||
arrow3: arrow3,
|
||
bouncingBar: bouncingBar,
|
||
bouncingBall: bouncingBall,
|
||
smiley: smiley,
|
||
monkey: monkey,
|
||
hearts: hearts,
|
||
clock: clock,
|
||
earth: earth,
|
||
material: material,
|
||
moon: moon,
|
||
runner: runner,
|
||
pong: pong,
|
||
shark: shark,
|
||
dqpb: dqpb,
|
||
weather: weather,
|
||
christmas: christmas,
|
||
grenade: grenade,
|
||
point: point,
|
||
layer: layer,
|
||
betaWave: betaWave,
|
||
fingerDance: fingerDance,
|
||
fistBump: fistBump,
|
||
soccerHeader: soccerHeader,
|
||
mindblown: mindblown,
|
||
speaker: speaker,
|
||
orangePulse: orangePulse,
|
||
bluePulse: bluePulse,
|
||
orangeBluePulse: orangeBluePulse,
|
||
timeTravel: timeTravel,
|
||
aesthetic: aesthetic,
|
||
dwarfFortress: dwarfFortress
|
||
};
|
||
|
||
const spinners = Object.assign({}, require$$0$1); // eslint-disable-line import/extensions
|
||
|
||
const spinnersList = Object.keys(spinners);
|
||
|
||
Object.defineProperty(spinners, 'random', {
|
||
get() {
|
||
const randomIndex = Math.floor(Math.random() * spinnersList.length);
|
||
const spinnerName = spinnersList[randomIndex];
|
||
return spinners[spinnerName];
|
||
}
|
||
});
|
||
|
||
var cliSpinners = spinners;
|
||
|
||
var cliSpinners$1 = /*@__PURE__*/getDefaultExportFromCjs(cliSpinners);
|
||
|
||
const logSymbols = {
|
||
info: 'ℹ️',
|
||
success: '✅',
|
||
warning: '⚠️',
|
||
error: '❌️',
|
||
};
|
||
|
||
function ansiRegex({onlyFirst = false} = {}) {
|
||
const pattern = [
|
||
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
|
||
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'
|
||
].join('|');
|
||
|
||
return new RegExp(pattern, onlyFirst ? undefined : 'g');
|
||
}
|
||
|
||
const regex = ansiRegex();
|
||
|
||
function stripAnsi(string) {
|
||
if (typeof string !== 'string') {
|
||
throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
|
||
}
|
||
|
||
// Even though the regex is global, we don't need to reset the `.lastIndex`
|
||
// because unlike `.exec()` and `.test()`, `.replace()` does it automatically
|
||
// and doing it manually has a performance penalty.
|
||
return string.replace(regex, '');
|
||
}
|
||
|
||
var eastasianwidth = {exports: {}};
|
||
|
||
(function (module) {
|
||
var eaw = {};
|
||
|
||
{
|
||
module.exports = eaw;
|
||
}
|
||
|
||
eaw.eastAsianWidth = function(character) {
|
||
var x = character.charCodeAt(0);
|
||
var y = (character.length == 2) ? character.charCodeAt(1) : 0;
|
||
var codePoint = x;
|
||
if ((0xD800 <= x && x <= 0xDBFF) && (0xDC00 <= y && y <= 0xDFFF)) {
|
||
x &= 0x3FF;
|
||
y &= 0x3FF;
|
||
codePoint = (x << 10) | y;
|
||
codePoint += 0x10000;
|
||
}
|
||
|
||
if ((0x3000 == codePoint) ||
|
||
(0xFF01 <= codePoint && codePoint <= 0xFF60) ||
|
||
(0xFFE0 <= codePoint && codePoint <= 0xFFE6)) {
|
||
return 'F';
|
||
}
|
||
if ((0x20A9 == codePoint) ||
|
||
(0xFF61 <= codePoint && codePoint <= 0xFFBE) ||
|
||
(0xFFC2 <= codePoint && codePoint <= 0xFFC7) ||
|
||
(0xFFCA <= codePoint && codePoint <= 0xFFCF) ||
|
||
(0xFFD2 <= codePoint && codePoint <= 0xFFD7) ||
|
||
(0xFFDA <= codePoint && codePoint <= 0xFFDC) ||
|
||
(0xFFE8 <= codePoint && codePoint <= 0xFFEE)) {
|
||
return 'H';
|
||
}
|
||
if ((0x1100 <= codePoint && codePoint <= 0x115F) ||
|
||
(0x11A3 <= codePoint && codePoint <= 0x11A7) ||
|
||
(0x11FA <= codePoint && codePoint <= 0x11FF) ||
|
||
(0x2329 <= codePoint && codePoint <= 0x232A) ||
|
||
(0x2E80 <= codePoint && codePoint <= 0x2E99) ||
|
||
(0x2E9B <= codePoint && codePoint <= 0x2EF3) ||
|
||
(0x2F00 <= codePoint && codePoint <= 0x2FD5) ||
|
||
(0x2FF0 <= codePoint && codePoint <= 0x2FFB) ||
|
||
(0x3001 <= codePoint && codePoint <= 0x303E) ||
|
||
(0x3041 <= codePoint && codePoint <= 0x3096) ||
|
||
(0x3099 <= codePoint && codePoint <= 0x30FF) ||
|
||
(0x3105 <= codePoint && codePoint <= 0x312D) ||
|
||
(0x3131 <= codePoint && codePoint <= 0x318E) ||
|
||
(0x3190 <= codePoint && codePoint <= 0x31BA) ||
|
||
(0x31C0 <= codePoint && codePoint <= 0x31E3) ||
|
||
(0x31F0 <= codePoint && codePoint <= 0x321E) ||
|
||
(0x3220 <= codePoint && codePoint <= 0x3247) ||
|
||
(0x3250 <= codePoint && codePoint <= 0x32FE) ||
|
||
(0x3300 <= codePoint && codePoint <= 0x4DBF) ||
|
||
(0x4E00 <= codePoint && codePoint <= 0xA48C) ||
|
||
(0xA490 <= codePoint && codePoint <= 0xA4C6) ||
|
||
(0xA960 <= codePoint && codePoint <= 0xA97C) ||
|
||
(0xAC00 <= codePoint && codePoint <= 0xD7A3) ||
|
||
(0xD7B0 <= codePoint && codePoint <= 0xD7C6) ||
|
||
(0xD7CB <= codePoint && codePoint <= 0xD7FB) ||
|
||
(0xF900 <= codePoint && codePoint <= 0xFAFF) ||
|
||
(0xFE10 <= codePoint && codePoint <= 0xFE19) ||
|
||
(0xFE30 <= codePoint && codePoint <= 0xFE52) ||
|
||
(0xFE54 <= codePoint && codePoint <= 0xFE66) ||
|
||
(0xFE68 <= codePoint && codePoint <= 0xFE6B) ||
|
||
(0x1B000 <= codePoint && codePoint <= 0x1B001) ||
|
||
(0x1F200 <= codePoint && codePoint <= 0x1F202) ||
|
||
(0x1F210 <= codePoint && codePoint <= 0x1F23A) ||
|
||
(0x1F240 <= codePoint && codePoint <= 0x1F248) ||
|
||
(0x1F250 <= codePoint && codePoint <= 0x1F251) ||
|
||
(0x20000 <= codePoint && codePoint <= 0x2F73F) ||
|
||
(0x2B740 <= codePoint && codePoint <= 0x2FFFD) ||
|
||
(0x30000 <= codePoint && codePoint <= 0x3FFFD)) {
|
||
return 'W';
|
||
}
|
||
if ((0x0020 <= codePoint && codePoint <= 0x007E) ||
|
||
(0x00A2 <= codePoint && codePoint <= 0x00A3) ||
|
||
(0x00A5 <= codePoint && codePoint <= 0x00A6) ||
|
||
(0x00AC == codePoint) ||
|
||
(0x00AF == codePoint) ||
|
||
(0x27E6 <= codePoint && codePoint <= 0x27ED) ||
|
||
(0x2985 <= codePoint && codePoint <= 0x2986)) {
|
||
return 'Na';
|
||
}
|
||
if ((0x00A1 == codePoint) ||
|
||
(0x00A4 == codePoint) ||
|
||
(0x00A7 <= codePoint && codePoint <= 0x00A8) ||
|
||
(0x00AA == codePoint) ||
|
||
(0x00AD <= codePoint && codePoint <= 0x00AE) ||
|
||
(0x00B0 <= codePoint && codePoint <= 0x00B4) ||
|
||
(0x00B6 <= codePoint && codePoint <= 0x00BA) ||
|
||
(0x00BC <= codePoint && codePoint <= 0x00BF) ||
|
||
(0x00C6 == codePoint) ||
|
||
(0x00D0 == codePoint) ||
|
||
(0x00D7 <= codePoint && codePoint <= 0x00D8) ||
|
||
(0x00DE <= codePoint && codePoint <= 0x00E1) ||
|
||
(0x00E6 == codePoint) ||
|
||
(0x00E8 <= codePoint && codePoint <= 0x00EA) ||
|
||
(0x00EC <= codePoint && codePoint <= 0x00ED) ||
|
||
(0x00F0 == codePoint) ||
|
||
(0x00F2 <= codePoint && codePoint <= 0x00F3) ||
|
||
(0x00F7 <= codePoint && codePoint <= 0x00FA) ||
|
||
(0x00FC == codePoint) ||
|
||
(0x00FE == codePoint) ||
|
||
(0x0101 == codePoint) ||
|
||
(0x0111 == codePoint) ||
|
||
(0x0113 == codePoint) ||
|
||
(0x011B == codePoint) ||
|
||
(0x0126 <= codePoint && codePoint <= 0x0127) ||
|
||
(0x012B == codePoint) ||
|
||
(0x0131 <= codePoint && codePoint <= 0x0133) ||
|
||
(0x0138 == codePoint) ||
|
||
(0x013F <= codePoint && codePoint <= 0x0142) ||
|
||
(0x0144 == codePoint) ||
|
||
(0x0148 <= codePoint && codePoint <= 0x014B) ||
|
||
(0x014D == codePoint) ||
|
||
(0x0152 <= codePoint && codePoint <= 0x0153) ||
|
||
(0x0166 <= codePoint && codePoint <= 0x0167) ||
|
||
(0x016B == codePoint) ||
|
||
(0x01CE == codePoint) ||
|
||
(0x01D0 == codePoint) ||
|
||
(0x01D2 == codePoint) ||
|
||
(0x01D4 == codePoint) ||
|
||
(0x01D6 == codePoint) ||
|
||
(0x01D8 == codePoint) ||
|
||
(0x01DA == codePoint) ||
|
||
(0x01DC == codePoint) ||
|
||
(0x0251 == codePoint) ||
|
||
(0x0261 == codePoint) ||
|
||
(0x02C4 == codePoint) ||
|
||
(0x02C7 == codePoint) ||
|
||
(0x02C9 <= codePoint && codePoint <= 0x02CB) ||
|
||
(0x02CD == codePoint) ||
|
||
(0x02D0 == codePoint) ||
|
||
(0x02D8 <= codePoint && codePoint <= 0x02DB) ||
|
||
(0x02DD == codePoint) ||
|
||
(0x02DF == codePoint) ||
|
||
(0x0300 <= codePoint && codePoint <= 0x036F) ||
|
||
(0x0391 <= codePoint && codePoint <= 0x03A1) ||
|
||
(0x03A3 <= codePoint && codePoint <= 0x03A9) ||
|
||
(0x03B1 <= codePoint && codePoint <= 0x03C1) ||
|
||
(0x03C3 <= codePoint && codePoint <= 0x03C9) ||
|
||
(0x0401 == codePoint) ||
|
||
(0x0410 <= codePoint && codePoint <= 0x044F) ||
|
||
(0x0451 == codePoint) ||
|
||
(0x2010 == codePoint) ||
|
||
(0x2013 <= codePoint && codePoint <= 0x2016) ||
|
||
(0x2018 <= codePoint && codePoint <= 0x2019) ||
|
||
(0x201C <= codePoint && codePoint <= 0x201D) ||
|
||
(0x2020 <= codePoint && codePoint <= 0x2022) ||
|
||
(0x2024 <= codePoint && codePoint <= 0x2027) ||
|
||
(0x2030 == codePoint) ||
|
||
(0x2032 <= codePoint && codePoint <= 0x2033) ||
|
||
(0x2035 == codePoint) ||
|
||
(0x203B == codePoint) ||
|
||
(0x203E == codePoint) ||
|
||
(0x2074 == codePoint) ||
|
||
(0x207F == codePoint) ||
|
||
(0x2081 <= codePoint && codePoint <= 0x2084) ||
|
||
(0x20AC == codePoint) ||
|
||
(0x2103 == codePoint) ||
|
||
(0x2105 == codePoint) ||
|
||
(0x2109 == codePoint) ||
|
||
(0x2113 == codePoint) ||
|
||
(0x2116 == codePoint) ||
|
||
(0x2121 <= codePoint && codePoint <= 0x2122) ||
|
||
(0x2126 == codePoint) ||
|
||
(0x212B == codePoint) ||
|
||
(0x2153 <= codePoint && codePoint <= 0x2154) ||
|
||
(0x215B <= codePoint && codePoint <= 0x215E) ||
|
||
(0x2160 <= codePoint && codePoint <= 0x216B) ||
|
||
(0x2170 <= codePoint && codePoint <= 0x2179) ||
|
||
(0x2189 == codePoint) ||
|
||
(0x2190 <= codePoint && codePoint <= 0x2199) ||
|
||
(0x21B8 <= codePoint && codePoint <= 0x21B9) ||
|
||
(0x21D2 == codePoint) ||
|
||
(0x21D4 == codePoint) ||
|
||
(0x21E7 == codePoint) ||
|
||
(0x2200 == codePoint) ||
|
||
(0x2202 <= codePoint && codePoint <= 0x2203) ||
|
||
(0x2207 <= codePoint && codePoint <= 0x2208) ||
|
||
(0x220B == codePoint) ||
|
||
(0x220F == codePoint) ||
|
||
(0x2211 == codePoint) ||
|
||
(0x2215 == codePoint) ||
|
||
(0x221A == codePoint) ||
|
||
(0x221D <= codePoint && codePoint <= 0x2220) ||
|
||
(0x2223 == codePoint) ||
|
||
(0x2225 == codePoint) ||
|
||
(0x2227 <= codePoint && codePoint <= 0x222C) ||
|
||
(0x222E == codePoint) ||
|
||
(0x2234 <= codePoint && codePoint <= 0x2237) ||
|
||
(0x223C <= codePoint && codePoint <= 0x223D) ||
|
||
(0x2248 == codePoint) ||
|
||
(0x224C == codePoint) ||
|
||
(0x2252 == codePoint) ||
|
||
(0x2260 <= codePoint && codePoint <= 0x2261) ||
|
||
(0x2264 <= codePoint && codePoint <= 0x2267) ||
|
||
(0x226A <= codePoint && codePoint <= 0x226B) ||
|
||
(0x226E <= codePoint && codePoint <= 0x226F) ||
|
||
(0x2282 <= codePoint && codePoint <= 0x2283) ||
|
||
(0x2286 <= codePoint && codePoint <= 0x2287) ||
|
||
(0x2295 == codePoint) ||
|
||
(0x2299 == codePoint) ||
|
||
(0x22A5 == codePoint) ||
|
||
(0x22BF == codePoint) ||
|
||
(0x2312 == codePoint) ||
|
||
(0x2460 <= codePoint && codePoint <= 0x24E9) ||
|
||
(0x24EB <= codePoint && codePoint <= 0x254B) ||
|
||
(0x2550 <= codePoint && codePoint <= 0x2573) ||
|
||
(0x2580 <= codePoint && codePoint <= 0x258F) ||
|
||
(0x2592 <= codePoint && codePoint <= 0x2595) ||
|
||
(0x25A0 <= codePoint && codePoint <= 0x25A1) ||
|
||
(0x25A3 <= codePoint && codePoint <= 0x25A9) ||
|
||
(0x25B2 <= codePoint && codePoint <= 0x25B3) ||
|
||
(0x25B6 <= codePoint && codePoint <= 0x25B7) ||
|
||
(0x25BC <= codePoint && codePoint <= 0x25BD) ||
|
||
(0x25C0 <= codePoint && codePoint <= 0x25C1) ||
|
||
(0x25C6 <= codePoint && codePoint <= 0x25C8) ||
|
||
(0x25CB == codePoint) ||
|
||
(0x25CE <= codePoint && codePoint <= 0x25D1) ||
|
||
(0x25E2 <= codePoint && codePoint <= 0x25E5) ||
|
||
(0x25EF == codePoint) ||
|
||
(0x2605 <= codePoint && codePoint <= 0x2606) ||
|
||
(0x2609 == codePoint) ||
|
||
(0x260E <= codePoint && codePoint <= 0x260F) ||
|
||
(0x2614 <= codePoint && codePoint <= 0x2615) ||
|
||
(0x261C == codePoint) ||
|
||
(0x261E == codePoint) ||
|
||
(0x2640 == codePoint) ||
|
||
(0x2642 == codePoint) ||
|
||
(0x2660 <= codePoint && codePoint <= 0x2661) ||
|
||
(0x2663 <= codePoint && codePoint <= 0x2665) ||
|
||
(0x2667 <= codePoint && codePoint <= 0x266A) ||
|
||
(0x266C <= codePoint && codePoint <= 0x266D) ||
|
||
(0x266F == codePoint) ||
|
||
(0x269E <= codePoint && codePoint <= 0x269F) ||
|
||
(0x26BE <= codePoint && codePoint <= 0x26BF) ||
|
||
(0x26C4 <= codePoint && codePoint <= 0x26CD) ||
|
||
(0x26CF <= codePoint && codePoint <= 0x26E1) ||
|
||
(0x26E3 == codePoint) ||
|
||
(0x26E8 <= codePoint && codePoint <= 0x26FF) ||
|
||
(0x273D == codePoint) ||
|
||
(0x2757 == codePoint) ||
|
||
(0x2776 <= codePoint && codePoint <= 0x277F) ||
|
||
(0x2B55 <= codePoint && codePoint <= 0x2B59) ||
|
||
(0x3248 <= codePoint && codePoint <= 0x324F) ||
|
||
(0xE000 <= codePoint && codePoint <= 0xF8FF) ||
|
||
(0xFE00 <= codePoint && codePoint <= 0xFE0F) ||
|
||
(0xFFFD == codePoint) ||
|
||
(0x1F100 <= codePoint && codePoint <= 0x1F10A) ||
|
||
(0x1F110 <= codePoint && codePoint <= 0x1F12D) ||
|
||
(0x1F130 <= codePoint && codePoint <= 0x1F169) ||
|
||
(0x1F170 <= codePoint && codePoint <= 0x1F19A) ||
|
||
(0xE0100 <= codePoint && codePoint <= 0xE01EF) ||
|
||
(0xF0000 <= codePoint && codePoint <= 0xFFFFD) ||
|
||
(0x100000 <= codePoint && codePoint <= 0x10FFFD)) {
|
||
return 'A';
|
||
}
|
||
|
||
return 'N';
|
||
};
|
||
|
||
eaw.characterLength = function(character) {
|
||
var code = this.eastAsianWidth(character);
|
||
if (code == 'F' || code == 'W' || code == 'A') {
|
||
return 2;
|
||
} else {
|
||
return 1;
|
||
}
|
||
};
|
||
|
||
// Split a string considering surrogate-pairs.
|
||
function stringToArray(string) {
|
||
return string.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g) || [];
|
||
}
|
||
|
||
eaw.length = function(string) {
|
||
var characters = stringToArray(string);
|
||
var len = 0;
|
||
for (var i = 0; i < characters.length; i++) {
|
||
len = len + this.characterLength(characters[i]);
|
||
}
|
||
return len;
|
||
};
|
||
|
||
eaw.slice = function(text, start, end) {
|
||
textLen = eaw.length(text);
|
||
start = start ? start : 0;
|
||
end = end ? end : 1;
|
||
if (start < 0) {
|
||
start = textLen + start;
|
||
}
|
||
if (end < 0) {
|
||
end = textLen + end;
|
||
}
|
||
var result = '';
|
||
var eawLen = 0;
|
||
var chars = stringToArray(text);
|
||
for (var i = 0; i < chars.length; i++) {
|
||
var char = chars[i];
|
||
var charLen = eaw.length(char);
|
||
if (eawLen >= start - (charLen == 2 ? 1 : 0)) {
|
||
if (eawLen + charLen <= end) {
|
||
result += char;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
eawLen += charLen;
|
||
}
|
||
return result;
|
||
};
|
||
} (eastasianwidth));
|
||
|
||
var eastasianwidthExports = eastasianwidth.exports;
|
||
var eastAsianWidth = /*@__PURE__*/getDefaultExportFromCjs(eastasianwidthExports);
|
||
|
||
var emojiRegex = function () {
|
||
// https://mths.be/emoji
|
||
return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC)?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299]|\uD83C[\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\uD83D\uDC41\uFE0F|\uD83C\uDFF3\uFE0F|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD1D\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78\uDD7A-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCB\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6]|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26A7\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5-\uDED7\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDD77\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g;
|
||
};
|
||
|
||
var emojiRegex$1 = /*@__PURE__*/getDefaultExportFromCjs(emojiRegex);
|
||
|
||
function stringWidth(string, options = {}) {
|
||
if (typeof string !== 'string' || string.length === 0) {
|
||
return 0;
|
||
}
|
||
|
||
options = {
|
||
ambiguousIsNarrow: true,
|
||
...options
|
||
};
|
||
|
||
string = stripAnsi(string);
|
||
|
||
if (string.length === 0) {
|
||
return 0;
|
||
}
|
||
|
||
string = string.replace(emojiRegex$1(), ' ');
|
||
|
||
const ambiguousCharacterWidth = options.ambiguousIsNarrow ? 1 : 2;
|
||
let width = 0;
|
||
|
||
for (const character of string) {
|
||
const codePoint = character.codePointAt(0);
|
||
|
||
// Ignore control characters
|
||
if (codePoint <= 0x1F || (codePoint >= 0x7F && codePoint <= 0x9F)) {
|
||
continue;
|
||
}
|
||
|
||
// Ignore combining characters
|
||
if (codePoint >= 0x300 && codePoint <= 0x36F) {
|
||
continue;
|
||
}
|
||
|
||
const code = eastAsianWidth.eastAsianWidth(character);
|
||
switch (code) {
|
||
case 'F':
|
||
case 'W':
|
||
width += 2;
|
||
break;
|
||
case 'A':
|
||
width += ambiguousCharacterWidth;
|
||
break;
|
||
default:
|
||
width += 1;
|
||
}
|
||
}
|
||
|
||
return width;
|
||
}
|
||
|
||
function isInteractive({stream = process.stdout} = {}) {
|
||
return Boolean(
|
||
stream && stream.isTTY &&
|
||
process.env.TERM !== 'dumb' &&
|
||
!('CI' in process.env)
|
||
);
|
||
}
|
||
|
||
function isUnicodeSupported() {
|
||
if (process$2.platform !== 'win32') {
|
||
return process$2.env.TERM !== 'linux'; // Linux console (kernel)
|
||
}
|
||
|
||
return Boolean(process$2.env.WT_SESSION) // Windows Terminal
|
||
|| Boolean(process$2.env.TERMINUS_SUBLIME) // Terminus (<0.2.27)
|
||
|| process$2.env.ConEmuTask === '{cmd::Cmder}' // ConEmu and cmder
|
||
|| process$2.env.TERM_PROGRAM === 'Terminus-Sublime'
|
||
|| process$2.env.TERM_PROGRAM === 'vscode'
|
||
|| process$2.env.TERM === 'xterm-256color'
|
||
|| process$2.env.TERM === 'alacritty'
|
||
|| process$2.env.TERMINAL_EMULATOR === 'JetBrains-JediTerm';
|
||
}
|
||
|
||
const ASCII_ETX_CODE = 0x03; // Ctrl+C emits this code
|
||
|
||
class StdinDiscarder {
|
||
#activeCount = 0;
|
||
|
||
start() {
|
||
this.#activeCount++;
|
||
|
||
if (this.#activeCount === 1) {
|
||
this.#realStart();
|
||
}
|
||
}
|
||
|
||
stop() {
|
||
if (this.#activeCount <= 0) {
|
||
throw new Error('`stop` called more times than `start`');
|
||
}
|
||
|
||
this.#activeCount--;
|
||
|
||
if (this.#activeCount === 0) {
|
||
this.#realStop();
|
||
}
|
||
}
|
||
|
||
#realStart() {
|
||
// No known way to make it work reliably on Windows.
|
||
if (process$2.platform === 'win32' || !process$2.stdin.isTTY) {
|
||
return;
|
||
}
|
||
|
||
process$2.stdin.setRawMode(true);
|
||
process$2.stdin.on('data', this.#handleInput);
|
||
process$2.stdin.unref();
|
||
}
|
||
|
||
#realStop() {
|
||
if (!process$2.stdin.isTTY) {
|
||
return;
|
||
}
|
||
|
||
process$2.stdin.setRawMode(false);
|
||
process$2.stdin.off('data', this.#handleInput);
|
||
}
|
||
|
||
#handleInput(chunk) {
|
||
// Allow Ctrl+C to gracefully exit.
|
||
if (chunk[0] === ASCII_ETX_CODE) {
|
||
process$2.emit('SIGINT');
|
||
}
|
||
}
|
||
}
|
||
|
||
const stdinDiscarder = new StdinDiscarder();
|
||
|
||
class Ora {
|
||
#linesToClear = 0;
|
||
#isDiscardingStdin = false;
|
||
#lineCount = 0;
|
||
#frameIndex = 0;
|
||
#options;
|
||
#spinner;
|
||
#stream;
|
||
#id;
|
||
#initialInterval;
|
||
#isEnabled;
|
||
#isSilent;
|
||
#indent;
|
||
#text;
|
||
#prefixText;
|
||
#suffixText;
|
||
|
||
color;
|
||
|
||
constructor(options) {
|
||
if (typeof options === 'string') {
|
||
options = {
|
||
text: options,
|
||
};
|
||
}
|
||
|
||
this.#options = {
|
||
color: 'cyan',
|
||
stream: process$2.stderr,
|
||
discardStdin: true,
|
||
hideCursor: true,
|
||
...options,
|
||
};
|
||
|
||
// Public
|
||
this.color = this.#options.color;
|
||
|
||
// It's important that these use the public setters.
|
||
this.spinner = this.#options.spinner;
|
||
|
||
this.#initialInterval = this.#options.interval;
|
||
this.#stream = this.#options.stream;
|
||
this.#isEnabled = typeof this.#options.isEnabled === 'boolean' ? this.#options.isEnabled : isInteractive({stream: this.#stream});
|
||
this.#isSilent = typeof this.#options.isSilent === 'boolean' ? this.#options.isSilent : false;
|
||
|
||
// Set *after* `this.#stream`.
|
||
// It's important that these use the public setters.
|
||
this.text = this.#options.text;
|
||
this.prefixText = this.#options.prefixText;
|
||
this.suffixText = this.#options.suffixText;
|
||
this.indent = this.#options.indent;
|
||
|
||
if (process$2.env.NODE_ENV === 'test') {
|
||
this._stream = this.#stream;
|
||
this._isEnabled = this.#isEnabled;
|
||
|
||
Object.defineProperty(this, '_linesToClear', {
|
||
get() {
|
||
return this.#linesToClear;
|
||
},
|
||
set(newValue) {
|
||
this.#linesToClear = newValue;
|
||
},
|
||
});
|
||
|
||
Object.defineProperty(this, '_frameIndex', {
|
||
get() {
|
||
return this.#frameIndex;
|
||
},
|
||
});
|
||
|
||
Object.defineProperty(this, '_lineCount', {
|
||
get() {
|
||
return this.#lineCount;
|
||
},
|
||
});
|
||
}
|
||
}
|
||
|
||
get indent() {
|
||
return this.#indent;
|
||
}
|
||
|
||
set indent(indent = 0) {
|
||
if (!(indent >= 0 && Number.isInteger(indent))) {
|
||
throw new Error('The `indent` option must be an integer from 0 and up');
|
||
}
|
||
|
||
this.#indent = indent;
|
||
this.#updateLineCount();
|
||
}
|
||
|
||
get interval() {
|
||
return this.#initialInterval ?? this.#spinner.interval ?? 100;
|
||
}
|
||
|
||
get spinner() {
|
||
return this.#spinner;
|
||
}
|
||
|
||
set spinner(spinner) {
|
||
this.#frameIndex = 0;
|
||
this.#initialInterval = undefined;
|
||
|
||
if (typeof spinner === 'object') {
|
||
if (spinner.frames === undefined) {
|
||
throw new Error('The given spinner must have a `frames` property');
|
||
}
|
||
|
||
this.#spinner = spinner;
|
||
} else if (!isUnicodeSupported()) {
|
||
this.#spinner = cliSpinners$1.line;
|
||
} else if (spinner === undefined) {
|
||
// Set default spinner
|
||
this.#spinner = cliSpinners$1.dots;
|
||
} else if (spinner !== 'default' && cliSpinners$1[spinner]) {
|
||
this.#spinner = cliSpinners$1[spinner];
|
||
} else {
|
||
throw new Error(`There is no built-in spinner named '${spinner}'. See https://github.com/sindresorhus/cli-spinners/blob/main/spinners.json for a full list.`);
|
||
}
|
||
}
|
||
|
||
get text() {
|
||
return this.#text;
|
||
}
|
||
|
||
set text(value = '') {
|
||
this.#text = value;
|
||
this.#updateLineCount();
|
||
}
|
||
|
||
get prefixText() {
|
||
return this.#prefixText;
|
||
}
|
||
|
||
set prefixText(value = '') {
|
||
this.#prefixText = value;
|
||
this.#updateLineCount();
|
||
}
|
||
|
||
get suffixText() {
|
||
return this.#suffixText;
|
||
}
|
||
|
||
set suffixText(value = '') {
|
||
this.#suffixText = value;
|
||
this.#updateLineCount();
|
||
}
|
||
|
||
get isSpinning() {
|
||
return this.#id !== undefined;
|
||
}
|
||
|
||
#getFullPrefixText(prefixText = this.#prefixText, postfix = ' ') {
|
||
if (typeof prefixText === 'string' && prefixText !== '') {
|
||
return prefixText + postfix;
|
||
}
|
||
|
||
if (typeof prefixText === 'function') {
|
||
return prefixText() + postfix;
|
||
}
|
||
|
||
return '';
|
||
}
|
||
|
||
#getFullSuffixText(suffixText = this.#suffixText, prefix = ' ') {
|
||
if (typeof suffixText === 'string' && suffixText !== '') {
|
||
return prefix + suffixText;
|
||
}
|
||
|
||
if (typeof suffixText === 'function') {
|
||
return prefix + suffixText();
|
||
}
|
||
|
||
return '';
|
||
}
|
||
|
||
#updateLineCount() {
|
||
const columns = this.#stream.columns ?? 80;
|
||
const fullPrefixText = this.#getFullPrefixText(this.#prefixText, '-');
|
||
const fullSuffixText = this.#getFullSuffixText(this.#suffixText, '-');
|
||
const fullText = ' '.repeat(this.#indent) + fullPrefixText + '--' + this.#text + '--' + fullSuffixText;
|
||
|
||
this.#lineCount = 0;
|
||
for (const line of stripAnsi(fullText).split('\n')) {
|
||
this.#lineCount += Math.max(1, Math.ceil(stringWidth(line, {countAnsiEscapeCodes: true}) / columns));
|
||
}
|
||
}
|
||
|
||
get isEnabled() {
|
||
return this.#isEnabled && !this.#isSilent;
|
||
}
|
||
|
||
set isEnabled(value) {
|
||
if (typeof value !== 'boolean') {
|
||
throw new TypeError('The `isEnabled` option must be a boolean');
|
||
}
|
||
|
||
this.#isEnabled = value;
|
||
}
|
||
|
||
get isSilent() {
|
||
return this.#isSilent;
|
||
}
|
||
|
||
set isSilent(value) {
|
||
if (typeof value !== 'boolean') {
|
||
throw new TypeError('The `isSilent` option must be a boolean');
|
||
}
|
||
|
||
this.#isSilent = value;
|
||
}
|
||
|
||
frame() {
|
||
const {frames} = this.#spinner;
|
||
let frame = frames[this.#frameIndex];
|
||
|
||
if (this.color) {
|
||
frame = chalk[this.color](frame);
|
||
}
|
||
|
||
this.#frameIndex = ++this.#frameIndex % frames.length;
|
||
const fullPrefixText = (typeof this.#prefixText === 'string' && this.#prefixText !== '') ? this.#prefixText + ' ' : '';
|
||
const fullText = typeof this.text === 'string' ? ' ' + this.text : '';
|
||
const fullSuffixText = (typeof this.#suffixText === 'string' && this.#suffixText !== '') ? ' ' + this.#suffixText : '';
|
||
|
||
return fullPrefixText + frame + fullText + fullSuffixText;
|
||
}
|
||
|
||
clear() {
|
||
if (!this.#isEnabled || !this.#stream.isTTY) {
|
||
return this;
|
||
}
|
||
|
||
this.#stream.cursorTo(0);
|
||
|
||
for (let index = 0; index < this.#linesToClear; index++) {
|
||
if (index > 0) {
|
||
this.#stream.moveCursor(0, -1);
|
||
}
|
||
|
||
this.#stream.clearLine(1);
|
||
}
|
||
|
||
if (this.#indent || this.lastIndent !== this.#indent) {
|
||
this.#stream.cursorTo(this.#indent);
|
||
}
|
||
|
||
this.lastIndent = this.#indent;
|
||
this.#linesToClear = 0;
|
||
|
||
return this;
|
||
}
|
||
|
||
render() {
|
||
if (this.#isSilent) {
|
||
return this;
|
||
}
|
||
|
||
this.clear();
|
||
this.#stream.write(this.frame());
|
||
this.#linesToClear = this.#lineCount;
|
||
|
||
return this;
|
||
}
|
||
|
||
start(text) {
|
||
if (text) {
|
||
this.text = text;
|
||
}
|
||
|
||
if (this.#isSilent) {
|
||
return this;
|
||
}
|
||
|
||
if (!this.#isEnabled) {
|
||
if (this.text) {
|
||
this.#stream.write(`- ${this.text}\n`);
|
||
}
|
||
|
||
return this;
|
||
}
|
||
|
||
if (this.isSpinning) {
|
||
return this;
|
||
}
|
||
|
||
if (this.#options.hideCursor) {
|
||
cliCursor.hide(this.#stream);
|
||
}
|
||
|
||
if (this.#options.discardStdin && process$2.stdin.isTTY) {
|
||
this.#isDiscardingStdin = true;
|
||
stdinDiscarder.start();
|
||
}
|
||
|
||
this.render();
|
||
this.#id = setInterval(this.render.bind(this), this.interval);
|
||
|
||
return this;
|
||
}
|
||
|
||
stop() {
|
||
if (!this.#isEnabled) {
|
||
return this;
|
||
}
|
||
|
||
clearInterval(this.#id);
|
||
this.#id = undefined;
|
||
this.#frameIndex = 0;
|
||
this.clear();
|
||
if (this.#options.hideCursor) {
|
||
cliCursor.show(this.#stream);
|
||
}
|
||
|
||
if (this.#options.discardStdin && process$2.stdin.isTTY && this.#isDiscardingStdin) {
|
||
stdinDiscarder.stop();
|
||
this.#isDiscardingStdin = false;
|
||
}
|
||
|
||
return this;
|
||
}
|
||
|
||
succeed(text) {
|
||
return this.stopAndPersist({symbol: logSymbols.success, text});
|
||
}
|
||
|
||
fail(text) {
|
||
return this.stopAndPersist({symbol: logSymbols.error, text});
|
||
}
|
||
|
||
warn(text) {
|
||
return this.stopAndPersist({symbol: logSymbols.warning, text});
|
||
}
|
||
|
||
info(text) {
|
||
return this.stopAndPersist({symbol: logSymbols.info, text});
|
||
}
|
||
|
||
stopAndPersist(options = {}) {
|
||
if (this.#isSilent) {
|
||
return this;
|
||
}
|
||
|
||
const prefixText = options.prefixText ?? this.#prefixText;
|
||
const fullPrefixText = this.#getFullPrefixText(prefixText, ' ');
|
||
|
||
const symbolText = options.symbol ?? ' ';
|
||
|
||
const text = options.text ?? this.text;
|
||
const fullText = (typeof text === 'string') ? ' ' + text : '';
|
||
|
||
const suffixText = options.suffixText ?? this.#suffixText;
|
||
const fullSuffixText = this.#getFullSuffixText(suffixText, ' ');
|
||
|
||
const textToWrite = fullPrefixText + symbolText + fullText + fullSuffixText + '\n';
|
||
|
||
this.stop();
|
||
this.#stream.write(textToWrite);
|
||
|
||
return this;
|
||
}
|
||
}
|
||
|
||
function ora(options) {
|
||
return new Ora(options);
|
||
}
|
||
|
||
const okMark = "\x1B[32m\u2713\x1B[0m";
|
||
const failMark = "\x1B[31m\u2716\x1B[0m";
|
||
async function task(taskName, task2) {
|
||
const spinner = ora({ discardStdin: false });
|
||
spinner.start(taskName + "...");
|
||
try {
|
||
await task2();
|
||
} catch (e) {
|
||
spinner.stopAndPersist({ symbol: failMark });
|
||
throw e;
|
||
}
|
||
spinner.stopAndPersist({ symbol: okMark });
|
||
}
|
||
|
||
const debug$2 = _debug("vitepress:local-search");
|
||
const LOCAL_SEARCH_INDEX_ID = "@localSearchIndex";
|
||
const LOCAL_SEARCH_INDEX_REQUEST_PATH = "/" + LOCAL_SEARCH_INDEX_ID;
|
||
async function localSearchPlugin(siteConfig) {
|
||
if (siteConfig.site.themeConfig?.search?.provider !== "local") {
|
||
return {
|
||
name: "vitepress:local-search",
|
||
resolveId(id) {
|
||
if (id.startsWith(LOCAL_SEARCH_INDEX_ID)) {
|
||
return `/${id}`;
|
||
}
|
||
},
|
||
load(id) {
|
||
if (id.startsWith(LOCAL_SEARCH_INDEX_REQUEST_PATH)) {
|
||
return `export default '{}'`;
|
||
}
|
||
}
|
||
};
|
||
}
|
||
const md = await createMarkdownRenderer(
|
||
siteConfig.srcDir,
|
||
siteConfig.markdown,
|
||
siteConfig.site.base,
|
||
siteConfig.logger
|
||
);
|
||
const options = siteConfig.site.themeConfig.search.options || {};
|
||
async function render(file) {
|
||
if (!fs$a.existsSync(file))
|
||
return "";
|
||
const { srcDir, cleanUrls = false } = siteConfig;
|
||
const relativePath = slash(path$q.relative(srcDir, file));
|
||
const env = { path: file, relativePath, cleanUrls };
|
||
const md_raw = await fs$a.promises.readFile(file, "utf-8");
|
||
const md_src = processIncludes(srcDir, md_raw, file, []);
|
||
if (options._render)
|
||
return await options._render(md_src, env, md);
|
||
else {
|
||
const html = md.render(md_src, env);
|
||
return env.frontmatter?.search === false ? "" : html;
|
||
}
|
||
}
|
||
const indexByLocales = /* @__PURE__ */ new Map();
|
||
function getIndexByLocale(locale) {
|
||
let index = indexByLocales.get(locale);
|
||
if (!index) {
|
||
index = new MiniSearch({
|
||
fields: ["title", "titles", "text"],
|
||
storeFields: ["title", "titles"],
|
||
...options.miniSearch?.options
|
||
});
|
||
indexByLocales.set(locale, index);
|
||
}
|
||
return index;
|
||
}
|
||
function getLocaleForPath(file) {
|
||
const relativePath = slash(path$q.relative(siteConfig.srcDir, file));
|
||
const siteData = resolveSiteDataByRoute(siteConfig.site, relativePath);
|
||
return siteData?.localeIndex ?? "root";
|
||
}
|
||
let server;
|
||
function onIndexUpdated() {
|
||
if (server) {
|
||
server.moduleGraph.onFileChange(LOCAL_SEARCH_INDEX_REQUEST_PATH);
|
||
const mod = server.moduleGraph.getModuleById(
|
||
LOCAL_SEARCH_INDEX_REQUEST_PATH
|
||
);
|
||
if (!mod)
|
||
return;
|
||
server.ws.send({
|
||
type: "update",
|
||
updates: [
|
||
{
|
||
acceptedPath: mod.url,
|
||
path: mod.url,
|
||
timestamp: Date.now(),
|
||
type: "js-update"
|
||
}
|
||
]
|
||
});
|
||
}
|
||
}
|
||
function getDocId(file) {
|
||
let relFile = slash(path$q.relative(siteConfig.srcDir, file));
|
||
relFile = siteConfig.rewrites.map[relFile] || relFile;
|
||
let id = slash(path$q.join(siteConfig.site.base, relFile));
|
||
id = id.replace(/(^|\/)index\.md$/, "$1");
|
||
id = id.replace(/\.md$/, siteConfig.cleanUrls ? "" : ".html");
|
||
return id;
|
||
}
|
||
async function indexFile(page) {
|
||
const file = path$q.join(siteConfig.srcDir, page);
|
||
const fileId = getDocId(file);
|
||
const locale = getLocaleForPath(file);
|
||
const index = getIndexByLocale(locale);
|
||
const html = await render(file);
|
||
const sections = (
|
||
// user provided generator
|
||
await options.miniSearch?._splitIntoSections?.(file, html) ?? // default implementation
|
||
splitPageIntoSections(html)
|
||
);
|
||
for await (const section of sections) {
|
||
if (!section || !(section.text || section.titles))
|
||
break;
|
||
const { anchor, text, titles } = section;
|
||
const id = anchor ? [fileId, anchor].join("#") : fileId;
|
||
index.add({
|
||
id,
|
||
text,
|
||
title: titles.at(-1),
|
||
titles: titles.slice(0, -1)
|
||
});
|
||
}
|
||
}
|
||
async function scanForBuild() {
|
||
debug$2("\u{1F50D}\uFE0F Indexing files for search...");
|
||
await pMap(siteConfig.pages, indexFile, {
|
||
concurrency: siteConfig.buildConcurrency
|
||
});
|
||
debug$2("\u2705 Indexing finished...");
|
||
}
|
||
return {
|
||
name: "vitepress:local-search",
|
||
config: () => ({
|
||
optimizeDeps: {
|
||
include: [
|
||
"vitepress > @vueuse/integrations/useFocusTrap",
|
||
"vitepress > mark.js/src/vanilla.js",
|
||
"vitepress > minisearch"
|
||
]
|
||
}
|
||
}),
|
||
async configureServer(_server) {
|
||
server = _server;
|
||
await scanForBuild();
|
||
onIndexUpdated();
|
||
},
|
||
resolveId(id) {
|
||
if (id.startsWith(LOCAL_SEARCH_INDEX_ID)) {
|
||
return `/${id}`;
|
||
}
|
||
},
|
||
async load(id) {
|
||
if (id === LOCAL_SEARCH_INDEX_REQUEST_PATH) {
|
||
if (process.env.NODE_ENV === "production") {
|
||
await scanForBuild();
|
||
}
|
||
let records = [];
|
||
for (const [locale] of indexByLocales) {
|
||
records.push(
|
||
`${JSON.stringify(
|
||
locale
|
||
)}: () => import('@localSearchIndex${locale}')`
|
||
);
|
||
}
|
||
return `export default {${records.join(",")}}`;
|
||
} else if (id.startsWith(LOCAL_SEARCH_INDEX_REQUEST_PATH)) {
|
||
return `export default ${JSON.stringify(
|
||
JSON.stringify(
|
||
indexByLocales.get(
|
||
id.replace(LOCAL_SEARCH_INDEX_REQUEST_PATH, "")
|
||
) ?? {}
|
||
)
|
||
)}`;
|
||
}
|
||
},
|
||
async handleHotUpdate({ file }) {
|
||
if (file.endsWith(".md")) {
|
||
await indexFile(file);
|
||
debug$2("\u{1F50D}\uFE0F Updated", file);
|
||
onIndexUpdated();
|
||
}
|
||
}
|
||
};
|
||
}
|
||
const headingRegex = /<h(\d*).*?>(.*?<a.*? href="#.*?".*?>.*?<\/a>)<\/h\1>/gi;
|
||
const headingContentRegex = /(.*?)<a.*? href="#(.*?)".*?>.*?<\/a>/i;
|
||
function* splitPageIntoSections(html) {
|
||
const result = html.split(headingRegex);
|
||
result.shift();
|
||
let parentTitles = [];
|
||
for (let i = 0; i < result.length; i += 3) {
|
||
const level = parseInt(result[i]) - 1;
|
||
const heading = result[i + 1];
|
||
const headingResult = headingContentRegex.exec(heading);
|
||
const title = clearHtmlTags(headingResult?.[1] ?? "").trim();
|
||
const anchor = headingResult?.[2] ?? "";
|
||
const content = result[i + 2];
|
||
if (!title || !content)
|
||
continue;
|
||
const titles = parentTitles.slice(0, level);
|
||
titles[level] = title;
|
||
yield { anchor, titles, text: getSearchableText(content) };
|
||
if (level === 0) {
|
||
parentTitles = [title];
|
||
} else {
|
||
parentTitles[level] = title;
|
||
}
|
||
}
|
||
}
|
||
function getSearchableText(content) {
|
||
content = clearHtmlTags(content);
|
||
return content;
|
||
}
|
||
function clearHtmlTags(str) {
|
||
return str.replace(/<[^>]*>/g, "");
|
||
}
|
||
|
||
const loaderMatch = /\.data\.m?(j|t)s($|\?)/;
|
||
let server;
|
||
function defineLoader(loader) {
|
||
return loader;
|
||
}
|
||
const idToLoaderModulesMap = /* @__PURE__ */ Object.create(null);
|
||
const depToLoaderModuleIdMap = /* @__PURE__ */ Object.create(null);
|
||
let idToPendingPromiseMap = /* @__PURE__ */ Object.create(null);
|
||
let isBuild = false;
|
||
const staticDataPlugin = {
|
||
name: "vitepress:data",
|
||
configResolved(config) {
|
||
isBuild = config.command === "build";
|
||
},
|
||
configureServer(_server) {
|
||
server = _server;
|
||
},
|
||
async load(id) {
|
||
if (loaderMatch.test(id)) {
|
||
let _resolve;
|
||
if (isBuild) {
|
||
if (idToPendingPromiseMap[id]) {
|
||
return idToPendingPromiseMap[id];
|
||
}
|
||
idToPendingPromiseMap[id] = new Promise((r) => {
|
||
_resolve = r;
|
||
});
|
||
}
|
||
const base = dirname(id);
|
||
let watch;
|
||
let load;
|
||
const existing = idToLoaderModulesMap[id];
|
||
if (existing) {
|
||
({ watch, load } = existing);
|
||
} else {
|
||
const res = await loadConfigFromFile({}, id.replace(/\?.*$/, ""));
|
||
if (server && res) {
|
||
for (const dep of res.dependencies) {
|
||
depToLoaderModuleIdMap[normalizePath(path$q.resolve(dep))] = id;
|
||
}
|
||
}
|
||
const loaderModule = res?.config;
|
||
watch = typeof loaderModule.watch === "string" ? [loaderModule.watch] : loaderModule.watch;
|
||
if (watch) {
|
||
watch = watch.map((p) => {
|
||
return p.startsWith(".") ? normalizePath(resolve$1(base, p)) : normalizePath(p);
|
||
});
|
||
}
|
||
load = loaderModule.load;
|
||
}
|
||
let watchedFiles;
|
||
if (watch) {
|
||
watchedFiles = (await glob(watch, {
|
||
ignore: ["**/node_modules/**", "**/dist/**"]
|
||
})).sort();
|
||
}
|
||
const data = await load(watchedFiles || []);
|
||
if (server) {
|
||
idToLoaderModulesMap[id] = { watch, load };
|
||
}
|
||
const result = `export const data = JSON.parse(${JSON.stringify(
|
||
JSON.stringify(data)
|
||
)})`;
|
||
if (_resolve)
|
||
_resolve(result);
|
||
return result;
|
||
}
|
||
},
|
||
transform(_code, id) {
|
||
if (server && loaderMatch.test(id)) {
|
||
const { watch } = idToLoaderModulesMap[id];
|
||
if (watch) {
|
||
server._importGlobMap.set(
|
||
id,
|
||
[Array.isArray(watch) ? watch : [watch]].map((globs) => {
|
||
const affirmed = [];
|
||
const negated = [];
|
||
for (const glob2 of globs) {
|
||
(glob2[0] === "!" ? negated : affirmed).push(glob2);
|
||
}
|
||
return { affirmed, negated };
|
||
})
|
||
);
|
||
}
|
||
}
|
||
return null;
|
||
},
|
||
handleHotUpdate(ctx) {
|
||
const file = ctx.file;
|
||
if (file in depToLoaderModuleIdMap) {
|
||
const id = depToLoaderModuleIdMap[file];
|
||
delete idToLoaderModulesMap[id];
|
||
ctx.modules.push(server.moduleGraph.getModuleById(id));
|
||
}
|
||
for (const id in idToLoaderModulesMap) {
|
||
const { watch } = idToLoaderModulesMap[id];
|
||
if (watch && micromatch_1.isMatch(file, watch)) {
|
||
ctx.modules.push(server.moduleGraph.getModuleById(id));
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
const webfontMarkerRE = /\/(?:\*|\/) *webfont-marker-begin *(?:\*\/|\n|\r|\n\r|\r\n)([^]*?)\/(?:\*|\/) *webfont-marker-end *(?:\*\/|\n|\r|\n\r|\r\n|$)/;
|
||
const webFontsPlugin = (enabled = false) => ({
|
||
name: "vitepress:webfonts",
|
||
enforce: "pre",
|
||
transform(code, id) {
|
||
if (/[\\/]fonts\.s?css/.test(id)) {
|
||
if (enabled) {
|
||
return code.match(webfontMarkerRE)?.[1];
|
||
} else {
|
||
return code.replace(webfontMarkerRE, "");
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
const themeRE = /\/\.vitepress\/theme\/index\.(m|c)?(j|t)s$/;
|
||
const hashRE = /\.([-\w]+)\.js$/;
|
||
const staticInjectMarkerRE = /\b(const _hoisted_\d+ = \/\*(?:#|@)__PURE__\*\/\s*createStaticVNode)\("(.*)", (\d+)\)/g;
|
||
const staticStripRE = /['"`]__VP_STATIC_START__[^]*?__VP_STATIC_END__['"`]/g;
|
||
const staticRestoreRE = /__VP_STATIC_(START|END)__/g;
|
||
const scriptClientRE = /<script\b[^>]*client\b[^>]*>([^]*?)<\/script>/;
|
||
const isPageChunk = (chunk) => !!(chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId && chunk.facadeModuleId.endsWith(".md"));
|
||
const cleanUrl = (url) => url.replace(/#.*$/s, "").replace(/\?.*$/s, "");
|
||
async function createVitePressPlugin(siteConfig, ssr = false, pageToHashMap, clientJSMap, recreateServer) {
|
||
const {
|
||
srcDir,
|
||
configPath,
|
||
configDeps,
|
||
markdown,
|
||
site,
|
||
vue: userVuePluginOptions,
|
||
vite: userViteConfig,
|
||
pages,
|
||
lastUpdated,
|
||
cleanUrls
|
||
} = siteConfig;
|
||
let markdownToVue;
|
||
const userCustomElementChecker = userVuePluginOptions?.template?.compilerOptions?.isCustomElement;
|
||
let isCustomElement = userCustomElementChecker;
|
||
if (markdown?.math) {
|
||
isCustomElement = (tag) => {
|
||
if (["mjx-container", "mjx-assistive-mml"].includes(tag)) {
|
||
return true;
|
||
}
|
||
return userCustomElementChecker?.(tag) ?? false;
|
||
};
|
||
}
|
||
const vuePlugin = await import('@vitejs/plugin-vue').then(
|
||
(r) => r.default({
|
||
include: [/\.vue$/, /\.md$/],
|
||
...userVuePluginOptions,
|
||
template: {
|
||
...userVuePluginOptions?.template,
|
||
compilerOptions: {
|
||
...userVuePluginOptions?.template?.compilerOptions,
|
||
isCustomElement
|
||
}
|
||
}
|
||
})
|
||
);
|
||
const processClientJS = (code, id) => {
|
||
return scriptClientRE.test(code) ? code.replace(scriptClientRE, (_, content) => {
|
||
if (ssr && clientJSMap)
|
||
clientJSMap[id] = content;
|
||
return `
|
||
`.repeat(_.split("\n").length - 1);
|
||
}) : code;
|
||
};
|
||
let siteData = site;
|
||
let allDeadLinks = [];
|
||
let config;
|
||
let importerMap = {};
|
||
const vitePressPlugin = {
|
||
name: "vitepress",
|
||
async configResolved(resolvedConfig) {
|
||
config = resolvedConfig;
|
||
markdownToVue = await createMarkdownToVueRenderFn(
|
||
srcDir,
|
||
markdown,
|
||
pages,
|
||
config.command === "build",
|
||
config.base,
|
||
lastUpdated,
|
||
cleanUrls,
|
||
siteConfig
|
||
);
|
||
},
|
||
config() {
|
||
const baseConfig = {
|
||
resolve: {
|
||
alias: resolveAliases(siteConfig, ssr)
|
||
},
|
||
define: {
|
||
__VP_LOCAL_SEARCH__: site.themeConfig?.search?.provider === "local",
|
||
__ALGOLIA__: site.themeConfig?.search?.provider === "algolia" || !!site.themeConfig?.algolia,
|
||
// legacy
|
||
__CARBON__: !!site.themeConfig?.carbonAds,
|
||
__ASSETS_DIR__: JSON.stringify(siteConfig.assetsDir),
|
||
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: !!process.env.DEBUG
|
||
},
|
||
optimizeDeps: {
|
||
// force include vue to avoid duplicated copies when linked + optimized
|
||
include: [
|
||
"vue",
|
||
"vitepress > @vue/devtools-api",
|
||
"vitepress > @vueuse/core"
|
||
],
|
||
exclude: ["@docsearch/js", "vitepress"]
|
||
},
|
||
server: {
|
||
fs: {
|
||
allow: [
|
||
DIST_CLIENT_PATH,
|
||
srcDir,
|
||
searchForWorkspaceRoot(process.cwd())
|
||
]
|
||
}
|
||
},
|
||
vitepress: siteConfig
|
||
};
|
||
return userViteConfig ? mergeConfig$1(baseConfig, userViteConfig) : baseConfig;
|
||
},
|
||
resolveId(id) {
|
||
if (id === SITE_DATA_REQUEST_PATH) {
|
||
return SITE_DATA_REQUEST_PATH;
|
||
}
|
||
},
|
||
load(id) {
|
||
if (id === SITE_DATA_REQUEST_PATH) {
|
||
let data = siteData;
|
||
if (config.command === "build") {
|
||
data = { ...siteData, head: [] };
|
||
if (!ssr) {
|
||
return `export default window.__VP_SITE_DATA__`;
|
||
}
|
||
}
|
||
data = serializeFunctions(data);
|
||
return `${deserializeFunctions};export default deserializeFunctions(JSON.parse(${JSON.stringify(
|
||
JSON.stringify(data)
|
||
)}))`;
|
||
}
|
||
},
|
||
async transform(code, id) {
|
||
if (id.endsWith(".vue")) {
|
||
return processClientJS(code, id);
|
||
} else if (id.endsWith(".md")) {
|
||
const { vueSrc, deadLinks, includes } = await markdownToVue(
|
||
code,
|
||
id,
|
||
config.publicDir
|
||
);
|
||
allDeadLinks.push(...deadLinks);
|
||
if (includes.length) {
|
||
includes.forEach((i) => {
|
||
(importerMap[slash(i)] ??= /* @__PURE__ */ new Set()).add(id);
|
||
this.addWatchFile(i);
|
||
});
|
||
}
|
||
return processClientJS(vueSrc, id);
|
||
}
|
||
},
|
||
renderStart() {
|
||
if (allDeadLinks.length > 0) {
|
||
allDeadLinks.forEach(({ url, file }, i) => {
|
||
siteConfig.logger.warn(
|
||
c$2.yellow(
|
||
`${i === 0 ? "\n\n" : ""}(!) Found dead link ${c$2.cyan(
|
||
url
|
||
)} in file ${c$2.white(c$2.dim(file))}`
|
||
)
|
||
);
|
||
});
|
||
siteConfig.logger.info(
|
||
c$2.cyan(
|
||
"\nIf this is expected, you can disable this check via config. Refer: https://vitepress.dev/reference/site-config#ignoredeadlinks\n"
|
||
)
|
||
);
|
||
throw new Error(`${allDeadLinks.length} dead link(s) found.`);
|
||
}
|
||
},
|
||
configureServer(server) {
|
||
if (configPath) {
|
||
server.watcher.add(configPath);
|
||
configDeps.forEach((file) => server.watcher.add(file));
|
||
}
|
||
const onFileAddDelete = async (added, _file) => {
|
||
const file = slash(_file);
|
||
if (themeRE.test(file)) {
|
||
siteConfig.logger.info(
|
||
c$2.green(
|
||
`${path$q.relative(process.cwd(), _file)} ${added ? "created" : "deleted"}, restarting server...
|
||
`
|
||
),
|
||
{ clear: true, timestamp: true }
|
||
);
|
||
await recreateServer?.();
|
||
}
|
||
if (file.endsWith(".md")) {
|
||
Object.assign(
|
||
siteConfig,
|
||
await resolvePages(
|
||
siteConfig.srcDir,
|
||
siteConfig.userConfig,
|
||
siteConfig.logger
|
||
)
|
||
);
|
||
}
|
||
if (!added && importerMap[file]) {
|
||
delete importerMap[file];
|
||
}
|
||
};
|
||
server.watcher.on("add", onFileAddDelete.bind(null, true)).on("unlink", onFileAddDelete.bind(null, false));
|
||
return () => {
|
||
server.middlewares.use(async (req, res, next) => {
|
||
const url = req.url && cleanUrl(req.url);
|
||
if (url?.endsWith(".html")) {
|
||
res.statusCode = 200;
|
||
res.setHeader("Content-Type", "text/html");
|
||
let html = `<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title></title>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<meta name="description" content="">
|
||
</head>
|
||
<body>
|
||
<div id="app"></div>
|
||
<script type="module" src="/@fs/${APP_PATH}/index.js"><\/script>
|
||
</body>
|
||
</html>`;
|
||
html = await server.transformIndexHtml(url, html, req.originalUrl);
|
||
res.end(html);
|
||
return;
|
||
}
|
||
next();
|
||
});
|
||
};
|
||
},
|
||
renderChunk(code, chunk) {
|
||
if (!ssr && isPageChunk(chunk)) {
|
||
code = code.replace(
|
||
staticInjectMarkerRE,
|
||
'$1("__VP_STATIC_START__$2__VP_STATIC_END__", $3)'
|
||
);
|
||
return code;
|
||
}
|
||
return null;
|
||
},
|
||
generateBundle(_options, bundle) {
|
||
if (ssr) {
|
||
this.emitFile({
|
||
type: "asset",
|
||
fileName: "package.json",
|
||
source: '{ "private": true, "type": "module" }'
|
||
});
|
||
} else {
|
||
for (const name in bundle) {
|
||
const chunk = bundle[name];
|
||
if (isPageChunk(chunk)) {
|
||
const hash = chunk.fileName.match(hashRE)[1];
|
||
pageToHashMap[chunk.name.toLowerCase()] = hash;
|
||
bundle[name + "-lean"] = {
|
||
...chunk,
|
||
fileName: chunk.fileName.replace(/\.js$/, ".lean.js"),
|
||
preliminaryFileName: chunk.preliminaryFileName.replace(
|
||
/\.js$/,
|
||
".lean.js"
|
||
),
|
||
code: chunk.code.replace(staticStripRE, `""`)
|
||
};
|
||
chunk.code = chunk.code.replace(staticRestoreRE, "");
|
||
}
|
||
}
|
||
}
|
||
},
|
||
async handleHotUpdate(ctx) {
|
||
const { file, read, server } = ctx;
|
||
if (file === configPath || configDeps.includes(file)) {
|
||
siteConfig.logger.info(
|
||
c$2.green(
|
||
`${path$q.relative(
|
||
process.cwd(),
|
||
file
|
||
)} changed, restarting server...
|
||
`
|
||
),
|
||
{ clear: true, timestamp: true }
|
||
);
|
||
try {
|
||
await resolveUserConfig(siteConfig.root, "serve", "development");
|
||
} catch (err) {
|
||
return;
|
||
}
|
||
clearCache();
|
||
await recreateServer?.();
|
||
return;
|
||
}
|
||
if (file.endsWith(".md")) {
|
||
const content = await read();
|
||
const { pageData, vueSrc } = await markdownToVue(
|
||
content,
|
||
file,
|
||
config.publicDir
|
||
);
|
||
const payload = {
|
||
path: `/${slash(path$q.relative(srcDir, file))}`,
|
||
pageData
|
||
};
|
||
server.ws.send({
|
||
type: "custom",
|
||
event: "vitepress:pageData",
|
||
data: payload
|
||
});
|
||
ctx.read = () => vueSrc;
|
||
}
|
||
}
|
||
};
|
||
const hmrFix = {
|
||
name: "vitepress:hmr-fix",
|
||
async handleHotUpdate({ file, server, modules }) {
|
||
const importers = [...importerMap[slash(file)] || []];
|
||
if (importers.length > 0) {
|
||
return [
|
||
...modules,
|
||
...importers.map((id) => {
|
||
clearCache(id);
|
||
return server.moduleGraph.getModuleById(id);
|
||
})
|
||
].filter(Boolean);
|
||
}
|
||
}
|
||
};
|
||
return [
|
||
vitePressPlugin,
|
||
rewritesPlugin(siteConfig),
|
||
vuePlugin,
|
||
hmrFix,
|
||
webFontsPlugin(siteConfig.useWebFonts),
|
||
...userViteConfig?.plugins || [],
|
||
await localSearchPlugin(siteConfig),
|
||
staticDataPlugin,
|
||
await dynamicRoutesPlugin(siteConfig)
|
||
];
|
||
}
|
||
|
||
const virtualEntry = "client.js";
|
||
async function buildMPAClient(js, config) {
|
||
const files = Object.keys(js);
|
||
const themeFiles = files.filter((f) => !f.endsWith(".md"));
|
||
const pages = files.filter((f) => f.endsWith(".md"));
|
||
return build$1({
|
||
root: config.srcDir,
|
||
cacheDir: config.cacheDir,
|
||
base: config.site.base,
|
||
logLevel: config.vite?.logLevel ?? "warn",
|
||
build: {
|
||
emptyOutDir: false,
|
||
outDir: config.outDir,
|
||
rollupOptions: {
|
||
input: [virtualEntry, ...pages]
|
||
}
|
||
},
|
||
plugins: [
|
||
{
|
||
name: "vitepress-mpa-client",
|
||
resolveId(id) {
|
||
if (id === virtualEntry) {
|
||
return id;
|
||
}
|
||
},
|
||
load(id) {
|
||
if (id === virtualEntry) {
|
||
return themeFiles.map((file) => `import ${JSON.stringify(file)}`).join("\n");
|
||
} else if (id in js) {
|
||
return js[id];
|
||
}
|
||
}
|
||
}
|
||
]
|
||
});
|
||
}
|
||
|
||
const CSS_LANGS_RE = /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/;
|
||
const clientDir = normalizePath(
|
||
path$q.resolve(path$q.dirname(fileURLToPath$1(import.meta.url)), "../client")
|
||
);
|
||
const excludedModules = [
|
||
"/@siteData",
|
||
"node_modules/@vueuse/core/",
|
||
"node_modules/@vueuse/shared/",
|
||
"node_modules/vue/",
|
||
"node_modules/vue-demi/",
|
||
clientDir
|
||
];
|
||
async function bundle(config, options) {
|
||
const pageToHashMap = /* @__PURE__ */ Object.create(null);
|
||
const clientJSMap = /* @__PURE__ */ Object.create(null);
|
||
const input = {};
|
||
config.pages.forEach((file) => {
|
||
const alias = config.rewrites.map[file] || file;
|
||
input[slash(alias).replace(/\//g, "_")] = path$q.resolve(config.srcDir, file);
|
||
});
|
||
const themeEntryRE = new RegExp(
|
||
`^${escapeRegExp$1(
|
||
path$q.resolve(config.themeDir, "index.js").replace(/\\/g, "/")
|
||
).slice(0, -2)}m?(j|t)s`
|
||
);
|
||
const { rollupOptions } = options;
|
||
const resolveViteConfig = async (ssr) => ({
|
||
root: config.srcDir,
|
||
cacheDir: config.cacheDir,
|
||
base: config.site.base,
|
||
logLevel: config.vite?.logLevel ?? "warn",
|
||
plugins: await createVitePressPlugin(
|
||
config,
|
||
ssr,
|
||
pageToHashMap,
|
||
clientJSMap
|
||
),
|
||
ssr: {
|
||
noExternal: ["vitepress", "@docsearch/css"]
|
||
},
|
||
build: {
|
||
...options,
|
||
emptyOutDir: true,
|
||
ssr,
|
||
ssrEmitAssets: config.mpa,
|
||
// minify with esbuild in MPA mode (for CSS)
|
||
minify: ssr ? config.mpa ? "esbuild" : false : typeof options.minify === "boolean" ? options.minify : !process.env.DEBUG,
|
||
outDir: ssr ? config.tempDir : config.outDir,
|
||
cssCodeSplit: false,
|
||
rollupOptions: {
|
||
...rollupOptions,
|
||
input: {
|
||
...input,
|
||
// use different entry based on ssr or not
|
||
app: path$q.resolve(APP_PATH, ssr ? "ssr.js" : "index.js")
|
||
},
|
||
// important so that each page chunk and the index export things for each
|
||
// other
|
||
preserveEntrySignatures: "allow-extension",
|
||
output: {
|
||
sanitizeFileName,
|
||
...rollupOptions?.output,
|
||
assetFileNames: `${config.assetsDir}/[name].[hash].[ext]`,
|
||
...ssr ? {
|
||
entryFileNames: "[name].js",
|
||
chunkFileNames: "[name].[hash].js"
|
||
} : {
|
||
entryFileNames: `${config.assetsDir}/[name].[hash].js`,
|
||
chunkFileNames(chunk) {
|
||
return /(?:Carbon|BuySell)Ads/.test(chunk.name) ? `${config.assetsDir}/chunks/ui-custom.[hash].js` : `${config.assetsDir}/chunks/[name].[hash].js`;
|
||
},
|
||
manualChunks(id, ctx) {
|
||
if (id.startsWith("\0vite")) {
|
||
return "framework";
|
||
}
|
||
if (id.includes("plugin-vue:export-helper")) {
|
||
return "framework";
|
||
}
|
||
if (id.includes(`${clientDir}/app`) && id !== `${clientDir}/app/index.js`) {
|
||
return "framework";
|
||
}
|
||
if (isEagerChunk(id, ctx.getModuleInfo) && /@vue\/(runtime|shared|reactivity)/.test(id)) {
|
||
return "framework";
|
||
}
|
||
if ((id.startsWith(`${clientDir}/theme-default`) || !excludedModules.some((i) => id.includes(i))) && staticImportedByEntry(
|
||
id,
|
||
ctx.getModuleInfo,
|
||
cacheTheme,
|
||
themeEntryRE
|
||
)) {
|
||
return "theme";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
configFile: config.vite?.configFile
|
||
});
|
||
let clientResult;
|
||
let serverResult;
|
||
await task("building client + server bundles", async () => {
|
||
clientResult = config.mpa ? null : await build$1(await resolveViteConfig(false));
|
||
serverResult = await build$1(
|
||
await resolveViteConfig(true)
|
||
);
|
||
});
|
||
if (config.mpa) {
|
||
await Promise.all(
|
||
serverResult.output.map(async (chunk) => {
|
||
if (!chunk.fileName.endsWith(".js")) {
|
||
const tempPath = path$q.resolve(config.tempDir, chunk.fileName);
|
||
const outPath = path$q.resolve(config.outDir, chunk.fileName);
|
||
await fs$a.copy(tempPath, outPath);
|
||
}
|
||
})
|
||
);
|
||
const publicDir = path$q.resolve(config.srcDir, "public");
|
||
if (fs$a.existsSync(publicDir)) {
|
||
await fs$a.copy(publicDir, config.outDir);
|
||
}
|
||
if (Object.keys(clientJSMap).length) {
|
||
clientResult = await buildMPAClient(clientJSMap, config);
|
||
}
|
||
}
|
||
return { clientResult, serverResult, pageToHashMap };
|
||
}
|
||
const cache = /* @__PURE__ */ new Map();
|
||
const cacheTheme = /* @__PURE__ */ new Map();
|
||
function isEagerChunk(id, getModuleInfo) {
|
||
if (id.includes("node_modules") && !CSS_LANGS_RE.test(id) && staticImportedByEntry(id, getModuleInfo, cache)) {
|
||
return true;
|
||
}
|
||
}
|
||
function staticImportedByEntry(id, getModuleInfo, cache2, entryRE = null, importStack = []) {
|
||
if (cache2.has(id)) {
|
||
return !!cache2.get(id);
|
||
}
|
||
if (importStack.includes(id)) {
|
||
cache2.set(id, false);
|
||
return false;
|
||
}
|
||
const mod = getModuleInfo(id);
|
||
if (!mod) {
|
||
cache2.set(id, false);
|
||
return false;
|
||
}
|
||
if (entryRE ? entryRE.test(id) : mod.isEntry) {
|
||
cache2.set(id, true);
|
||
return true;
|
||
}
|
||
const someImporterIs = mod.importers.some(
|
||
(importer) => staticImportedByEntry(
|
||
importer,
|
||
getModuleInfo,
|
||
cache2,
|
||
entryRE,
|
||
importStack.concat(id)
|
||
)
|
||
);
|
||
cache2.set(id, someImporterIs);
|
||
return someImporterIs;
|
||
}
|
||
|
||
var dist = {};
|
||
|
||
var sitemapItemStream = {};
|
||
|
||
var errors = {};
|
||
|
||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||
/*!
|
||
* Sitemap
|
||
* Copyright(c) 2011 Eugene Kalinin
|
||
* MIT Licensed
|
||
*/
|
||
Object.defineProperty(errors, "__esModule", { value: true });
|
||
errors.EmptySitemap = errors.EmptyStream = errors.InvalidVideoPriceCurrency = errors.InvalidVideoResolution = errors.InvalidVideoPriceType = errors.InvalidVideoRestrictionRelationship = errors.InvalidVideoRestriction = errors.InvalidVideoFamilyFriendly = errors.InvalidVideoCategory = errors.InvalidVideoTagCount = errors.InvalidVideoViewCount = errors.InvalidVideoTitle = errors.XMLLintUnavailable = errors.InvalidNewsAccessValue = errors.InvalidNewsFormat = errors.InvalidAttr = errors.InvalidAttrValue = errors.InvalidVideoRating = errors.InvalidVideoDescription = errors.InvalidVideoDuration = errors.InvalidVideoFormat = errors.UndefinedTargetFolder = errors.PriorityInvalidError = errors.ChangeFreqInvalidError = errors.NoConfigError = errors.NoURLError = void 0;
|
||
/**
|
||
* URL in SitemapItem does not exist
|
||
*/
|
||
class NoURLError extends Error {
|
||
constructor(message) {
|
||
super(message || 'URL is required');
|
||
this.name = 'NoURLError';
|
||
Error.captureStackTrace(this, NoURLError);
|
||
}
|
||
}
|
||
errors.NoURLError = NoURLError;
|
||
/**
|
||
* Config was not passed to SitemapItem constructor
|
||
*/
|
||
class NoConfigError extends Error {
|
||
constructor(message) {
|
||
super(message || 'SitemapItem requires a configuration');
|
||
this.name = 'NoConfigError';
|
||
Error.captureStackTrace(this, NoConfigError);
|
||
}
|
||
}
|
||
errors.NoConfigError = NoConfigError;
|
||
/**
|
||
* changefreq property in sitemap is invalid
|
||
*/
|
||
class ChangeFreqInvalidError extends Error {
|
||
constructor(url, changefreq) {
|
||
super(`${url}: changefreq "${changefreq}" is invalid`);
|
||
this.name = 'ChangeFreqInvalidError';
|
||
Error.captureStackTrace(this, ChangeFreqInvalidError);
|
||
}
|
||
}
|
||
errors.ChangeFreqInvalidError = ChangeFreqInvalidError;
|
||
/**
|
||
* priority property in sitemap is invalid
|
||
*/
|
||
class PriorityInvalidError extends Error {
|
||
constructor(url, priority) {
|
||
super(`${url}: priority "${priority}" must be a number between 0 and 1 inclusive`);
|
||
this.name = 'PriorityInvalidError';
|
||
Error.captureStackTrace(this, PriorityInvalidError);
|
||
}
|
||
}
|
||
errors.PriorityInvalidError = PriorityInvalidError;
|
||
/**
|
||
* SitemapIndex target Folder does not exists
|
||
*/
|
||
class UndefinedTargetFolder extends Error {
|
||
constructor(message) {
|
||
super(message || 'Target folder must exist');
|
||
this.name = 'UndefinedTargetFolder';
|
||
Error.captureStackTrace(this, UndefinedTargetFolder);
|
||
}
|
||
}
|
||
errors.UndefinedTargetFolder = UndefinedTargetFolder;
|
||
class InvalidVideoFormat extends Error {
|
||
constructor(url) {
|
||
super(`${url} video must include thumbnail_loc, title and description fields for videos`);
|
||
this.name = 'InvalidVideoFormat';
|
||
Error.captureStackTrace(this, InvalidVideoFormat);
|
||
}
|
||
}
|
||
errors.InvalidVideoFormat = InvalidVideoFormat;
|
||
class InvalidVideoDuration extends Error {
|
||
constructor(url, duration) {
|
||
super(`${url} duration "${duration}" must be an integer of seconds between 0 and 28800`);
|
||
this.name = 'InvalidVideoDuration';
|
||
Error.captureStackTrace(this, InvalidVideoDuration);
|
||
}
|
||
}
|
||
errors.InvalidVideoDuration = InvalidVideoDuration;
|
||
class InvalidVideoDescription extends Error {
|
||
constructor(url, length) {
|
||
const message = `${url}: video description is too long ${length} vs limit of 2048 characters.`;
|
||
super(message);
|
||
this.name = 'InvalidVideoDescription';
|
||
Error.captureStackTrace(this, InvalidVideoDescription);
|
||
}
|
||
}
|
||
errors.InvalidVideoDescription = InvalidVideoDescription;
|
||
class InvalidVideoRating extends Error {
|
||
constructor(url, title, rating) {
|
||
super(`${url}: video "${title}" rating "${rating}" must be between 0 and 5 inclusive`);
|
||
this.name = 'InvalidVideoRating';
|
||
Error.captureStackTrace(this, InvalidVideoRating);
|
||
}
|
||
}
|
||
errors.InvalidVideoRating = InvalidVideoRating;
|
||
class InvalidAttrValue extends Error {
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
constructor(key, val, validator) {
|
||
super('"' +
|
||
val +
|
||
'" tested against: ' +
|
||
validator +
|
||
' is not a valid value for attr: "' +
|
||
key +
|
||
'"');
|
||
this.name = 'InvalidAttrValue';
|
||
Error.captureStackTrace(this, InvalidAttrValue);
|
||
}
|
||
}
|
||
errors.InvalidAttrValue = InvalidAttrValue;
|
||
// InvalidAttr is only thrown when attrbuilder is called incorrectly internally
|
||
/* istanbul ignore next */
|
||
class InvalidAttr extends Error {
|
||
constructor(key) {
|
||
super('"' + key + '" is malformed');
|
||
this.name = 'InvalidAttr';
|
||
Error.captureStackTrace(this, InvalidAttr);
|
||
}
|
||
}
|
||
errors.InvalidAttr = InvalidAttr;
|
||
class InvalidNewsFormat extends Error {
|
||
constructor(url) {
|
||
super(`${url} News must include publication, publication name, publication language, title, and publication_date for news`);
|
||
this.name = 'InvalidNewsFormat';
|
||
Error.captureStackTrace(this, InvalidNewsFormat);
|
||
}
|
||
}
|
||
errors.InvalidNewsFormat = InvalidNewsFormat;
|
||
class InvalidNewsAccessValue extends Error {
|
||
constructor(url, access) {
|
||
super(`${url} News access "${access}" must be either Registration, Subscription or not be present`);
|
||
this.name = 'InvalidNewsAccessValue';
|
||
Error.captureStackTrace(this, InvalidNewsAccessValue);
|
||
}
|
||
}
|
||
errors.InvalidNewsAccessValue = InvalidNewsAccessValue;
|
||
class XMLLintUnavailable extends Error {
|
||
constructor(message) {
|
||
super(message || 'xmlLint is not installed. XMLLint is required to validate');
|
||
this.name = 'XMLLintUnavailable';
|
||
Error.captureStackTrace(this, XMLLintUnavailable);
|
||
}
|
||
}
|
||
errors.XMLLintUnavailable = XMLLintUnavailable;
|
||
class InvalidVideoTitle extends Error {
|
||
constructor(url, length) {
|
||
super(`${url}: video title is too long ${length} vs 100 character limit`);
|
||
this.name = 'InvalidVideoTitle';
|
||
Error.captureStackTrace(this, InvalidVideoTitle);
|
||
}
|
||
}
|
||
errors.InvalidVideoTitle = InvalidVideoTitle;
|
||
class InvalidVideoViewCount extends Error {
|
||
constructor(url, count) {
|
||
super(`${url}: video view count must be positive, view count was ${count}`);
|
||
this.name = 'InvalidVideoViewCount';
|
||
Error.captureStackTrace(this, InvalidVideoViewCount);
|
||
}
|
||
}
|
||
errors.InvalidVideoViewCount = InvalidVideoViewCount;
|
||
class InvalidVideoTagCount extends Error {
|
||
constructor(url, count) {
|
||
super(`${url}: video can have no more than 32 tags, this has ${count}`);
|
||
this.name = 'InvalidVideoTagCount';
|
||
Error.captureStackTrace(this, InvalidVideoTagCount);
|
||
}
|
||
}
|
||
errors.InvalidVideoTagCount = InvalidVideoTagCount;
|
||
class InvalidVideoCategory extends Error {
|
||
constructor(url, count) {
|
||
super(`${url}: video category can only be 256 characters but was passed ${count}`);
|
||
this.name = 'InvalidVideoCategory';
|
||
Error.captureStackTrace(this, InvalidVideoCategory);
|
||
}
|
||
}
|
||
errors.InvalidVideoCategory = InvalidVideoCategory;
|
||
class InvalidVideoFamilyFriendly extends Error {
|
||
constructor(url, fam) {
|
||
super(`${url}: video family friendly must be yes or no, was passed "${fam}"`);
|
||
this.name = 'InvalidVideoFamilyFriendly';
|
||
Error.captureStackTrace(this, InvalidVideoFamilyFriendly);
|
||
}
|
||
}
|
||
errors.InvalidVideoFamilyFriendly = InvalidVideoFamilyFriendly;
|
||
class InvalidVideoRestriction extends Error {
|
||
constructor(url, code) {
|
||
super(`${url}: video restriction must be one or more two letter country codes. Was passed "${code}"`);
|
||
this.name = 'InvalidVideoRestriction';
|
||
Error.captureStackTrace(this, InvalidVideoRestriction);
|
||
}
|
||
}
|
||
errors.InvalidVideoRestriction = InvalidVideoRestriction;
|
||
class InvalidVideoRestrictionRelationship extends Error {
|
||
constructor(url, val) {
|
||
super(`${url}: video restriction relationship must be either allow or deny. Was passed "${val}"`);
|
||
this.name = 'InvalidVideoRestrictionRelationship';
|
||
Error.captureStackTrace(this, InvalidVideoRestrictionRelationship);
|
||
}
|
||
}
|
||
errors.InvalidVideoRestrictionRelationship = InvalidVideoRestrictionRelationship;
|
||
class InvalidVideoPriceType extends Error {
|
||
constructor(url, priceType, price) {
|
||
super(priceType === undefined && price === ''
|
||
? `${url}: video priceType is required when price is not provided`
|
||
: `${url}: video price type "${priceType}" is not "rent" or "purchase"`);
|
||
this.name = 'InvalidVideoPriceType';
|
||
Error.captureStackTrace(this, InvalidVideoPriceType);
|
||
}
|
||
}
|
||
errors.InvalidVideoPriceType = InvalidVideoPriceType;
|
||
class InvalidVideoResolution extends Error {
|
||
constructor(url, resolution) {
|
||
super(`${url}: video price resolution "${resolution}" is not hd or sd`);
|
||
this.name = 'InvalidVideoResolution';
|
||
Error.captureStackTrace(this, InvalidVideoResolution);
|
||
}
|
||
}
|
||
errors.InvalidVideoResolution = InvalidVideoResolution;
|
||
class InvalidVideoPriceCurrency extends Error {
|
||
constructor(url, currency) {
|
||
super(`${url}: video price currency "${currency}" must be a three capital letter abbrieviation for the country currency`);
|
||
this.name = 'InvalidVideoPriceCurrency';
|
||
Error.captureStackTrace(this, InvalidVideoPriceCurrency);
|
||
}
|
||
}
|
||
errors.InvalidVideoPriceCurrency = InvalidVideoPriceCurrency;
|
||
class EmptyStream extends Error {
|
||
constructor() {
|
||
super('You have ended the stream before anything was written. streamToPromise MUST be called before ending the stream.');
|
||
this.name = 'EmptyStream';
|
||
Error.captureStackTrace(this, EmptyStream);
|
||
}
|
||
}
|
||
errors.EmptyStream = EmptyStream;
|
||
class EmptySitemap extends Error {
|
||
constructor() {
|
||
super('You ended the stream without writing anything.');
|
||
this.name = 'EmptySitemap';
|
||
Error.captureStackTrace(this, EmptyStream);
|
||
}
|
||
}
|
||
errors.EmptySitemap = EmptySitemap;
|
||
|
||
var types = {};
|
||
|
||
(function (exports) {
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.IndexTagNames = exports.TagNames = exports.ErrorLevel = exports.isAllowDeny = exports.EnumAllowDeny = exports.isValidYesNo = exports.EnumYesNo = exports.isValidChangeFreq = exports.CHANGEFREQ = exports.isResolution = exports.isPriceType = exports.validators = exports.EnumChangefreq = void 0;
|
||
/**
|
||
* How frequently the page is likely to change. This value provides general
|
||
* information to search engines and may not correlate exactly to how often they crawl the page. Please note that the
|
||
* value of this tag is considered a hint and not a command. See
|
||
* <https://www.sitemaps.org/protocol.html#xmlTagDefinitions> for the acceptable
|
||
* values
|
||
*/
|
||
var EnumChangefreq;
|
||
(function (EnumChangefreq) {
|
||
EnumChangefreq["DAILY"] = "daily";
|
||
EnumChangefreq["MONTHLY"] = "monthly";
|
||
EnumChangefreq["ALWAYS"] = "always";
|
||
EnumChangefreq["HOURLY"] = "hourly";
|
||
EnumChangefreq["WEEKLY"] = "weekly";
|
||
EnumChangefreq["YEARLY"] = "yearly";
|
||
EnumChangefreq["NEVER"] = "never";
|
||
})(EnumChangefreq = exports.EnumChangefreq || (exports.EnumChangefreq = {}));
|
||
const allowDeny = /^(?:allow|deny)$/;
|
||
exports.validators = {
|
||
'price:currency': /^[A-Z]{3}$/,
|
||
'price:type': /^(?:rent|purchase|RENT|PURCHASE)$/,
|
||
'price:resolution': /^(?:HD|hd|sd|SD)$/,
|
||
'platform:relationship': allowDeny,
|
||
'restriction:relationship': allowDeny,
|
||
restriction: /^([A-Z]{2}( +[A-Z]{2})*)?$/,
|
||
platform: /^((web|mobile|tv)( (web|mobile|tv))*)?$/,
|
||
language: /^zh-cn|zh-tw|([a-z]{2,3})$/,
|
||
genres: /^(PressRelease|Satire|Blog|OpEd|Opinion|UserGenerated)(, *(PressRelease|Satire|Blog|OpEd|Opinion|UserGenerated))*$/,
|
||
stock_tickers: /^(\w+:\w+(, *\w+:\w+){0,4})?$/,
|
||
};
|
||
function isPriceType(pt) {
|
||
return exports.validators['price:type'].test(pt);
|
||
}
|
||
exports.isPriceType = isPriceType;
|
||
function isResolution(res) {
|
||
return exports.validators['price:resolution'].test(res);
|
||
}
|
||
exports.isResolution = isResolution;
|
||
exports.CHANGEFREQ = Object.values(EnumChangefreq);
|
||
function isValidChangeFreq(freq) {
|
||
return exports.CHANGEFREQ.includes(freq);
|
||
}
|
||
exports.isValidChangeFreq = isValidChangeFreq;
|
||
(function (EnumYesNo) {
|
||
EnumYesNo["YES"] = "YES";
|
||
EnumYesNo["NO"] = "NO";
|
||
EnumYesNo["Yes"] = "Yes";
|
||
EnumYesNo["No"] = "No";
|
||
EnumYesNo["yes"] = "yes";
|
||
EnumYesNo["no"] = "no";
|
||
})(exports.EnumYesNo || (exports.EnumYesNo = {}));
|
||
function isValidYesNo(yn) {
|
||
return /^YES|NO|[Yy]es|[Nn]o$/.test(yn);
|
||
}
|
||
exports.isValidYesNo = isValidYesNo;
|
||
(function (EnumAllowDeny) {
|
||
EnumAllowDeny["ALLOW"] = "allow";
|
||
EnumAllowDeny["DENY"] = "deny";
|
||
})(exports.EnumAllowDeny || (exports.EnumAllowDeny = {}));
|
||
function isAllowDeny(ad) {
|
||
return allowDeny.test(ad);
|
||
}
|
||
exports.isAllowDeny = isAllowDeny;
|
||
(function (ErrorLevel) {
|
||
/**
|
||
* Validation will be skipped and nothing logged or thrown.
|
||
*/
|
||
ErrorLevel["SILENT"] = "silent";
|
||
/**
|
||
* If an invalid value is encountered, a console.warn will be called with details
|
||
*/
|
||
ErrorLevel["WARN"] = "warn";
|
||
/**
|
||
* An Error will be thrown on encountering invalid data.
|
||
*/
|
||
ErrorLevel["THROW"] = "throw";
|
||
})(exports.ErrorLevel || (exports.ErrorLevel = {}));
|
||
(function (TagNames) {
|
||
TagNames["url"] = "url";
|
||
TagNames["loc"] = "loc";
|
||
TagNames["urlset"] = "urlset";
|
||
TagNames["lastmod"] = "lastmod";
|
||
TagNames["changefreq"] = "changefreq";
|
||
TagNames["priority"] = "priority";
|
||
TagNames["video:thumbnail_loc"] = "video:thumbnail_loc";
|
||
TagNames["video:video"] = "video:video";
|
||
TagNames["video:title"] = "video:title";
|
||
TagNames["video:description"] = "video:description";
|
||
TagNames["video:tag"] = "video:tag";
|
||
TagNames["video:duration"] = "video:duration";
|
||
TagNames["video:player_loc"] = "video:player_loc";
|
||
TagNames["video:content_loc"] = "video:content_loc";
|
||
TagNames["image:image"] = "image:image";
|
||
TagNames["image:loc"] = "image:loc";
|
||
TagNames["image:geo_location"] = "image:geo_location";
|
||
TagNames["image:license"] = "image:license";
|
||
TagNames["image:title"] = "image:title";
|
||
TagNames["image:caption"] = "image:caption";
|
||
TagNames["video:requires_subscription"] = "video:requires_subscription";
|
||
TagNames["video:publication_date"] = "video:publication_date";
|
||
TagNames["video:id"] = "video:id";
|
||
TagNames["video:restriction"] = "video:restriction";
|
||
TagNames["video:family_friendly"] = "video:family_friendly";
|
||
TagNames["video:view_count"] = "video:view_count";
|
||
TagNames["video:uploader"] = "video:uploader";
|
||
TagNames["video:expiration_date"] = "video:expiration_date";
|
||
TagNames["video:platform"] = "video:platform";
|
||
TagNames["video:price"] = "video:price";
|
||
TagNames["video:rating"] = "video:rating";
|
||
TagNames["video:category"] = "video:category";
|
||
TagNames["video:live"] = "video:live";
|
||
TagNames["video:gallery_loc"] = "video:gallery_loc";
|
||
TagNames["news:news"] = "news:news";
|
||
TagNames["news:publication"] = "news:publication";
|
||
TagNames["news:name"] = "news:name";
|
||
TagNames["news:access"] = "news:access";
|
||
TagNames["news:genres"] = "news:genres";
|
||
TagNames["news:publication_date"] = "news:publication_date";
|
||
TagNames["news:title"] = "news:title";
|
||
TagNames["news:keywords"] = "news:keywords";
|
||
TagNames["news:stock_tickers"] = "news:stock_tickers";
|
||
TagNames["news:language"] = "news:language";
|
||
TagNames["mobile:mobile"] = "mobile:mobile";
|
||
TagNames["xhtml:link"] = "xhtml:link";
|
||
TagNames["expires"] = "expires";
|
||
})(exports.TagNames || (exports.TagNames = {}));
|
||
(function (IndexTagNames) {
|
||
IndexTagNames["sitemap"] = "sitemap";
|
||
IndexTagNames["sitemapindex"] = "sitemapindex";
|
||
IndexTagNames["loc"] = "loc";
|
||
IndexTagNames["lastmod"] = "lastmod";
|
||
})(exports.IndexTagNames || (exports.IndexTagNames = {}));
|
||
} (types));
|
||
|
||
var sitemapXml = {};
|
||
|
||
Object.defineProperty(sitemapXml, "__esModule", { value: true });
|
||
sitemapXml.element = sitemapXml.ctag = sitemapXml.otag = sitemapXml.text = void 0;
|
||
const invalidXMLUnicodeRegex =
|
||
// eslint-disable-next-line no-control-regex
|
||
/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u0084\u0086-\u009F\uD800-\uDFFF\uFDD0-\uFDDF\u{1FFFE}-\u{1FFFF}\u{2FFFE}-\u{2FFFF}\u{3FFFE}-\u{3FFFF}\u{4FFFE}-\u{4FFFF}\u{5FFFE}-\u{5FFFF}\u{6FFFE}-\u{6FFFF}\u{7FFFE}-\u{7FFFF}\u{8FFFE}-\u{8FFFF}\u{9FFFE}-\u{9FFFF}\u{AFFFE}-\u{AFFFF}\u{BFFFE}-\u{BFFFF}\u{CFFFE}-\u{CFFFF}\u{DFFFE}-\u{DFFFF}\u{EFFFE}-\u{EFFFF}\u{FFFFE}-\u{FFFFF}\u{10FFFE}-\u{10FFFF}]/gu;
|
||
const amp = /&/g;
|
||
const lt = /</g;
|
||
const apos = /'/g;
|
||
const quot = /"/g;
|
||
function text(txt) {
|
||
return txt
|
||
.replace(amp, '&')
|
||
.replace(lt, '<')
|
||
.replace(invalidXMLUnicodeRegex, '');
|
||
}
|
||
sitemapXml.text = text;
|
||
function otag(nodeName, attrs, selfClose = false) {
|
||
let attrstr = '';
|
||
for (const k in attrs) {
|
||
const val = attrs[k]
|
||
.replace(amp, '&')
|
||
.replace(lt, '<')
|
||
.replace(apos, ''')
|
||
.replace(quot, '"')
|
||
.replace(invalidXMLUnicodeRegex, '');
|
||
attrstr += ` ${k}="${val}"`;
|
||
}
|
||
return `<${nodeName}${attrstr}${selfClose ? '/' : ''}>`;
|
||
}
|
||
sitemapXml.otag = otag;
|
||
function ctag(nodeName) {
|
||
return `</${nodeName}>`;
|
||
}
|
||
sitemapXml.ctag = ctag;
|
||
function element(nodeName, attrs, innerText) {
|
||
if (typeof attrs === 'string') {
|
||
return otag(nodeName) + text(attrs) + ctag(nodeName);
|
||
}
|
||
else if (innerText) {
|
||
return otag(nodeName, attrs) + text(innerText) + ctag(nodeName);
|
||
}
|
||
else {
|
||
return otag(nodeName, attrs, true);
|
||
}
|
||
}
|
||
sitemapXml.element = element;
|
||
|
||
Object.defineProperty(sitemapItemStream, "__esModule", { value: true });
|
||
sitemapItemStream.SitemapItemStream = void 0;
|
||
const stream_1$3 = require$$0$3;
|
||
const errors_1$2 = errors;
|
||
const types_1$3 = types;
|
||
const sitemap_xml_1 = sitemapXml;
|
||
function attrBuilder(conf, keys) {
|
||
if (typeof keys === 'string') {
|
||
keys = [keys];
|
||
}
|
||
const iv = {};
|
||
return keys.reduce((attrs, key) => {
|
||
// eslint-disable-next-line
|
||
if (conf[key] !== undefined) {
|
||
const keyAr = key.split(':');
|
||
if (keyAr.length !== 2) {
|
||
throw new errors_1$2.InvalidAttr(key);
|
||
}
|
||
attrs[keyAr[1]] = conf[key];
|
||
}
|
||
return attrs;
|
||
}, iv);
|
||
}
|
||
/**
|
||
* Takes a stream of SitemapItemOptions and spits out xml for each
|
||
* @example
|
||
* // writes <url><loc>https://example.com</loc><url><url><loc>https://example.com/2</loc><url>
|
||
* const smis = new SitemapItemStream({level: 'warn'})
|
||
* smis.pipe(writestream)
|
||
* smis.write({url: 'https://example.com', img: [], video: [], links: []})
|
||
* smis.write({url: 'https://example.com/2', img: [], video: [], links: []})
|
||
* smis.end()
|
||
* @param level - Error level
|
||
*/
|
||
class SitemapItemStream extends stream_1$3.Transform {
|
||
constructor(opts = { level: types_1$3.ErrorLevel.WARN }) {
|
||
opts.objectMode = true;
|
||
super(opts);
|
||
this.level = opts.level || types_1$3.ErrorLevel.WARN;
|
||
}
|
||
_transform(item, encoding, callback) {
|
||
this.push((0, sitemap_xml_1.otag)(types_1$3.TagNames.url));
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames.loc, item.url));
|
||
if (item.lastmod) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames.lastmod, item.lastmod));
|
||
}
|
||
if (item.changefreq) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames.changefreq, item.changefreq));
|
||
}
|
||
if (item.priority !== undefined && item.priority !== null) {
|
||
if (item.fullPrecisionPriority) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames.priority, item.priority.toString()));
|
||
}
|
||
else {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames.priority, item.priority.toFixed(1)));
|
||
}
|
||
}
|
||
item.video.forEach((video) => {
|
||
this.push((0, sitemap_xml_1.otag)(types_1$3.TagNames['video:video']));
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:thumbnail_loc'], video.thumbnail_loc));
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:title'], video.title));
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:description'], video.description));
|
||
if (video.content_loc) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:content_loc'], video.content_loc));
|
||
}
|
||
if (video.player_loc) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:player_loc'], attrBuilder(video, [
|
||
'player_loc:autoplay',
|
||
'player_loc:allow_embed',
|
||
]), video.player_loc));
|
||
}
|
||
if (video.duration) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:duration'], video.duration.toString()));
|
||
}
|
||
if (video.expiration_date) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:expiration_date'], video.expiration_date));
|
||
}
|
||
if (video.rating !== undefined) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:rating'], video.rating.toString()));
|
||
}
|
||
if (video.view_count !== undefined) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:view_count'], video.view_count.toString()));
|
||
}
|
||
if (video.publication_date) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:publication_date'], video.publication_date));
|
||
}
|
||
for (const tag of video.tag) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:tag'], tag));
|
||
}
|
||
if (video.category) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:category'], video.category));
|
||
}
|
||
if (video.family_friendly) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:family_friendly'], video.family_friendly));
|
||
}
|
||
if (video.restriction) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:restriction'], attrBuilder(video, 'restriction:relationship'), video.restriction));
|
||
}
|
||
if (video.gallery_loc) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:gallery_loc'], { title: video['gallery_loc:title'] }, video.gallery_loc));
|
||
}
|
||
if (video.price) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:price'], attrBuilder(video, [
|
||
'price:resolution',
|
||
'price:currency',
|
||
'price:type',
|
||
]), video.price));
|
||
}
|
||
if (video.requires_subscription) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:requires_subscription'], video.requires_subscription));
|
||
}
|
||
if (video.uploader) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:uploader'], attrBuilder(video, 'uploader:info'), video.uploader));
|
||
}
|
||
if (video.platform) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:platform'], attrBuilder(video, 'platform:relationship'), video.platform));
|
||
}
|
||
if (video.live) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:live'], video.live));
|
||
}
|
||
if (video.id) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['video:id'], { type: 'url' }, video.id));
|
||
}
|
||
this.push((0, sitemap_xml_1.ctag)(types_1$3.TagNames['video:video']));
|
||
});
|
||
item.links.forEach((link) => {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['xhtml:link'], {
|
||
rel: 'alternate',
|
||
hreflang: link.lang || link.hreflang,
|
||
href: link.url,
|
||
}));
|
||
});
|
||
if (item.expires) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames.expires, new Date(item.expires).toISOString()));
|
||
}
|
||
if (item.androidLink) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['xhtml:link'], {
|
||
rel: 'alternate',
|
||
href: item.androidLink,
|
||
}));
|
||
}
|
||
if (item.ampLink) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['xhtml:link'], {
|
||
rel: 'amphtml',
|
||
href: item.ampLink,
|
||
}));
|
||
}
|
||
if (item.news) {
|
||
this.push((0, sitemap_xml_1.otag)(types_1$3.TagNames['news:news']));
|
||
this.push((0, sitemap_xml_1.otag)(types_1$3.TagNames['news:publication']));
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['news:name'], item.news.publication.name));
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['news:language'], item.news.publication.language));
|
||
this.push((0, sitemap_xml_1.ctag)(types_1$3.TagNames['news:publication']));
|
||
if (item.news.access) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['news:access'], item.news.access));
|
||
}
|
||
if (item.news.genres) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['news:genres'], item.news.genres));
|
||
}
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['news:publication_date'], item.news.publication_date));
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['news:title'], item.news.title));
|
||
if (item.news.keywords) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['news:keywords'], item.news.keywords));
|
||
}
|
||
if (item.news.stock_tickers) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['news:stock_tickers'], item.news.stock_tickers));
|
||
}
|
||
this.push((0, sitemap_xml_1.ctag)(types_1$3.TagNames['news:news']));
|
||
}
|
||
// Image handling
|
||
item.img.forEach((image) => {
|
||
this.push((0, sitemap_xml_1.otag)(types_1$3.TagNames['image:image']));
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['image:loc'], image.url));
|
||
if (image.caption) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['image:caption'], image.caption));
|
||
}
|
||
if (image.geoLocation) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['image:geo_location'], image.geoLocation));
|
||
}
|
||
if (image.title) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['image:title'], image.title));
|
||
}
|
||
if (image.license) {
|
||
this.push((0, sitemap_xml_1.element)(types_1$3.TagNames['image:license'], image.license));
|
||
}
|
||
this.push((0, sitemap_xml_1.ctag)(types_1$3.TagNames['image:image']));
|
||
});
|
||
this.push((0, sitemap_xml_1.ctag)(types_1$3.TagNames.url));
|
||
callback();
|
||
}
|
||
}
|
||
sitemapItemStream.SitemapItemStream = SitemapItemStream;
|
||
|
||
var sitemapIndexStream = {};
|
||
|
||
var sitemapStream = {};
|
||
|
||
var utils = {};
|
||
|
||
Object.defineProperty(utils, "__esModule", { value: true });
|
||
utils.normalizeURL = utils.chunk = utils.lineSeparatedURLsToSitemapOptions = utils.ReadlineStream = utils.mergeStreams = utils.validateSMIOptions = void 0;
|
||
/*!
|
||
* Sitemap
|
||
* Copyright(c) 2011 Eugene Kalinin
|
||
* MIT Licensed
|
||
*/
|
||
const fs_1 = fs__default;
|
||
const stream_1$2 = require$$0$3;
|
||
const readline_1 = require$$2$1;
|
||
const url_1 = require$$3;
|
||
const types_1$2 = types;
|
||
const errors_1$1 = errors;
|
||
const types_2 = types;
|
||
function validate(subject, name, url, level) {
|
||
Object.keys(subject).forEach((key) => {
|
||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||
// @ts-ignore
|
||
const val = subject[key];
|
||
if (types_2.validators[key] && !types_2.validators[key].test(val)) {
|
||
if (level === types_1$2.ErrorLevel.THROW) {
|
||
throw new errors_1$1.InvalidAttrValue(key, val, types_2.validators[key]);
|
||
}
|
||
else {
|
||
console.warn(`${url}: ${name} key ${key} has invalid value: ${val}`);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
function handleError(error, level) {
|
||
if (level === types_1$2.ErrorLevel.THROW) {
|
||
throw error;
|
||
}
|
||
else if (level === types_1$2.ErrorLevel.WARN) {
|
||
console.warn(error.name, error.message);
|
||
}
|
||
}
|
||
/**
|
||
* Verifies all data passed in will comply with sitemap spec.
|
||
* @param conf Options to validate
|
||
* @param level logging level
|
||
* @param errorHandler error handling func
|
||
*/
|
||
function validateSMIOptions(conf, level = types_1$2.ErrorLevel.WARN, errorHandler = handleError) {
|
||
if (!conf) {
|
||
throw new errors_1$1.NoConfigError();
|
||
}
|
||
if (level === types_1$2.ErrorLevel.SILENT) {
|
||
return conf;
|
||
}
|
||
const { url, changefreq, priority, news, video } = conf;
|
||
if (!url) {
|
||
errorHandler(new errors_1$1.NoURLError(), level);
|
||
}
|
||
if (changefreq) {
|
||
if (!(0, types_1$2.isValidChangeFreq)(changefreq)) {
|
||
errorHandler(new errors_1$1.ChangeFreqInvalidError(url, changefreq), level);
|
||
}
|
||
}
|
||
if (priority) {
|
||
if (!(priority >= 0.0 && priority <= 1.0)) {
|
||
errorHandler(new errors_1$1.PriorityInvalidError(url, priority), level);
|
||
}
|
||
}
|
||
if (news) {
|
||
if (news.access &&
|
||
news.access !== 'Registration' &&
|
||
news.access !== 'Subscription') {
|
||
errorHandler(new errors_1$1.InvalidNewsAccessValue(url, news.access), level);
|
||
}
|
||
if (!news.publication ||
|
||
!news.publication.name ||
|
||
!news.publication.language ||
|
||
!news.publication_date ||
|
||
!news.title) {
|
||
errorHandler(new errors_1$1.InvalidNewsFormat(url), level);
|
||
}
|
||
validate(news, 'news', url, level);
|
||
validate(news.publication, 'publication', url, level);
|
||
}
|
||
if (video) {
|
||
video.forEach((vid) => {
|
||
var _a;
|
||
if (vid.duration !== undefined) {
|
||
if (vid.duration < 0 || vid.duration > 28800) {
|
||
errorHandler(new errors_1$1.InvalidVideoDuration(url, vid.duration), level);
|
||
}
|
||
}
|
||
if (vid.rating !== undefined && (vid.rating < 0 || vid.rating > 5)) {
|
||
errorHandler(new errors_1$1.InvalidVideoRating(url, vid.title, vid.rating), level);
|
||
}
|
||
if (typeof vid !== 'object' ||
|
||
!vid.thumbnail_loc ||
|
||
!vid.title ||
|
||
!vid.description) {
|
||
// has to be an object and include required categories https://support.google.com/webmasters/answer/80471?hl=en&ref_topic=4581190
|
||
errorHandler(new errors_1$1.InvalidVideoFormat(url), level);
|
||
}
|
||
if (vid.title.length > 100) {
|
||
errorHandler(new errors_1$1.InvalidVideoTitle(url, vid.title.length), level);
|
||
}
|
||
if (vid.description.length > 2048) {
|
||
errorHandler(new errors_1$1.InvalidVideoDescription(url, vid.description.length), level);
|
||
}
|
||
if (vid.view_count !== undefined && vid.view_count < 0) {
|
||
errorHandler(new errors_1$1.InvalidVideoViewCount(url, vid.view_count), level);
|
||
}
|
||
if (vid.tag.length > 32) {
|
||
errorHandler(new errors_1$1.InvalidVideoTagCount(url, vid.tag.length), level);
|
||
}
|
||
if (vid.category !== undefined && ((_a = vid.category) === null || _a === void 0 ? void 0 : _a.length) > 256) {
|
||
errorHandler(new errors_1$1.InvalidVideoCategory(url, vid.category.length), level);
|
||
}
|
||
if (vid.family_friendly !== undefined &&
|
||
!(0, types_1$2.isValidYesNo)(vid.family_friendly)) {
|
||
errorHandler(new errors_1$1.InvalidVideoFamilyFriendly(url, vid.family_friendly), level);
|
||
}
|
||
if (vid.restriction) {
|
||
if (!types_2.validators.restriction.test(vid.restriction)) {
|
||
errorHandler(new errors_1$1.InvalidVideoRestriction(url, vid.restriction), level);
|
||
}
|
||
if (!vid['restriction:relationship'] ||
|
||
!(0, types_1$2.isAllowDeny)(vid['restriction:relationship'])) {
|
||
errorHandler(new errors_1$1.InvalidVideoRestrictionRelationship(url, vid['restriction:relationship']), level);
|
||
}
|
||
}
|
||
// TODO price element should be unbounded
|
||
if ((vid.price === '' && vid['price:type'] === undefined) ||
|
||
(vid['price:type'] !== undefined && !(0, types_1$2.isPriceType)(vid['price:type']))) {
|
||
errorHandler(new errors_1$1.InvalidVideoPriceType(url, vid['price:type'], vid.price), level);
|
||
}
|
||
if (vid['price:resolution'] !== undefined &&
|
||
!(0, types_1$2.isResolution)(vid['price:resolution'])) {
|
||
errorHandler(new errors_1$1.InvalidVideoResolution(url, vid['price:resolution']), level);
|
||
}
|
||
if (vid['price:currency'] !== undefined &&
|
||
!types_2.validators['price:currency'].test(vid['price:currency'])) {
|
||
errorHandler(new errors_1$1.InvalidVideoPriceCurrency(url, vid['price:currency']), level);
|
||
}
|
||
validate(vid, 'video', url, level);
|
||
});
|
||
}
|
||
return conf;
|
||
}
|
||
utils.validateSMIOptions = validateSMIOptions;
|
||
/**
|
||
* Combines multiple streams into one
|
||
* @param streams the streams to combine
|
||
*/
|
||
function mergeStreams(streams, options) {
|
||
let pass = new stream_1$2.PassThrough(options);
|
||
let waiting = streams.length;
|
||
for (const stream of streams) {
|
||
pass = stream.pipe(pass, { end: false });
|
||
stream.once('end', () => --waiting === 0 && pass.emit('end'));
|
||
}
|
||
return pass;
|
||
}
|
||
utils.mergeStreams = mergeStreams;
|
||
/**
|
||
* Wraps node's ReadLine in a stream
|
||
*/
|
||
class ReadlineStream extends stream_1$2.Readable {
|
||
constructor(options) {
|
||
if (options.autoDestroy === undefined) {
|
||
options.autoDestroy = true;
|
||
}
|
||
options.objectMode = true;
|
||
super(options);
|
||
this._source = (0, readline_1.createInterface)({
|
||
input: options.input,
|
||
terminal: false,
|
||
crlfDelay: Infinity,
|
||
});
|
||
// Every time there's data, push it into the internal buffer.
|
||
this._source.on('line', (chunk) => {
|
||
// If push() returns false, then stop reading from source.
|
||
if (!this.push(chunk))
|
||
this._source.pause();
|
||
});
|
||
// When the source ends, push the EOF-signaling `null` chunk.
|
||
this._source.on('close', () => {
|
||
this.push(null);
|
||
});
|
||
}
|
||
// _read() will be called when the stream wants to pull more data in.
|
||
// The advisory size argument is ignored in this case.
|
||
_read(size) {
|
||
this._source.resume();
|
||
}
|
||
}
|
||
utils.ReadlineStream = ReadlineStream;
|
||
/**
|
||
* Takes a stream likely from fs.createReadStream('./path') and returns a stream
|
||
* of sitemap items
|
||
* @param stream a stream of line separated urls.
|
||
* @param opts.isJSON is the stream line separated JSON. leave undefined to guess
|
||
*/
|
||
function lineSeparatedURLsToSitemapOptions(stream, { isJSON } = {}) {
|
||
return new ReadlineStream({ input: stream }).pipe(new stream_1$2.Transform({
|
||
objectMode: true,
|
||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||
transform: (line, encoding, cb) => {
|
||
if (isJSON || (isJSON === undefined && line[0] === '{')) {
|
||
cb(null, JSON.parse(line));
|
||
}
|
||
else {
|
||
cb(null, line);
|
||
}
|
||
},
|
||
}));
|
||
}
|
||
utils.lineSeparatedURLsToSitemapOptions = lineSeparatedURLsToSitemapOptions;
|
||
/**
|
||
* Based on lodash's implementation of chunk.
|
||
*
|
||
* Copyright JS Foundation and other contributors <https://js.foundation/>
|
||
*
|
||
* Based on Underscore.js, copyright Jeremy Ashkenas,
|
||
* DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
|
||
*
|
||
* This software consists of voluntary contributions made by many
|
||
* individuals. For exact contribution history, see the revision history
|
||
* available at https://github.com/lodash/lodash
|
||
*/
|
||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||
function chunk(array, size = 1) {
|
||
size = Math.max(Math.trunc(size), 0);
|
||
const length = array ? array.length : 0;
|
||
if (!length || size < 1) {
|
||
return [];
|
||
}
|
||
const result = Array(Math.ceil(length / size));
|
||
let index = 0, resIndex = 0;
|
||
while (index < length) {
|
||
result[resIndex++] = array.slice(index, (index += size));
|
||
}
|
||
return result;
|
||
}
|
||
utils.chunk = chunk;
|
||
function boolToYESNO(bool) {
|
||
if (bool === undefined) {
|
||
return bool;
|
||
}
|
||
if (typeof bool === 'boolean') {
|
||
return bool ? types_1$2.EnumYesNo.yes : types_1$2.EnumYesNo.no;
|
||
}
|
||
return bool;
|
||
}
|
||
/**
|
||
* Converts the passed in sitemap entry into one capable of being consumed by SitemapItem
|
||
* @param {string | SitemapItemLoose} elem the string or object to be converted
|
||
* @param {string} hostname
|
||
* @returns SitemapItemOptions a strict sitemap item option
|
||
*/
|
||
function normalizeURL(elem, hostname, lastmodDateOnly = false) {
|
||
// SitemapItem
|
||
// create object with url property
|
||
let smi = {
|
||
img: [],
|
||
video: [],
|
||
links: [],
|
||
url: '',
|
||
};
|
||
let smiLoose;
|
||
if (typeof elem === 'string') {
|
||
smi.url = elem;
|
||
smiLoose = { url: elem };
|
||
}
|
||
else {
|
||
smiLoose = elem;
|
||
}
|
||
smi.url = new url_1.URL(smiLoose.url, hostname).toString();
|
||
let img = [];
|
||
if (smiLoose.img) {
|
||
if (typeof smiLoose.img === 'string') {
|
||
// string -> array of objects
|
||
smiLoose.img = [{ url: smiLoose.img }];
|
||
}
|
||
else if (!Array.isArray(smiLoose.img)) {
|
||
// object -> array of objects
|
||
smiLoose.img = [smiLoose.img];
|
||
}
|
||
img = smiLoose.img.map((el) => (typeof el === 'string' ? { url: el } : el));
|
||
}
|
||
// prepend hostname to all image urls
|
||
smi.img = img.map((el) => ({
|
||
...el,
|
||
url: new url_1.URL(el.url, hostname).toString(),
|
||
}));
|
||
let links = [];
|
||
if (smiLoose.links) {
|
||
links = smiLoose.links;
|
||
}
|
||
smi.links = links.map((link) => {
|
||
return { ...link, url: new url_1.URL(link.url, hostname).toString() };
|
||
});
|
||
if (smiLoose.video) {
|
||
if (!Array.isArray(smiLoose.video)) {
|
||
// make it an array
|
||
smiLoose.video = [smiLoose.video];
|
||
}
|
||
smi.video = smiLoose.video.map((video) => {
|
||
const nv = {
|
||
...video,
|
||
family_friendly: boolToYESNO(video.family_friendly),
|
||
live: boolToYESNO(video.live),
|
||
requires_subscription: boolToYESNO(video.requires_subscription),
|
||
tag: [],
|
||
rating: undefined,
|
||
};
|
||
if (video.tag !== undefined) {
|
||
nv.tag = !Array.isArray(video.tag) ? [video.tag] : video.tag;
|
||
}
|
||
if (video.rating !== undefined) {
|
||
if (typeof video.rating === 'string') {
|
||
nv.rating = parseFloat(video.rating);
|
||
}
|
||
else {
|
||
nv.rating = video.rating;
|
||
}
|
||
}
|
||
if (typeof video.view_count === 'string') {
|
||
nv.view_count = parseInt(video.view_count, 10);
|
||
}
|
||
else if (typeof video.view_count === 'number') {
|
||
nv.view_count = video.view_count;
|
||
}
|
||
return nv;
|
||
});
|
||
}
|
||
// If given a file to use for last modified date
|
||
if (smiLoose.lastmodfile) {
|
||
const { mtime } = (0, fs_1.statSync)(smiLoose.lastmodfile);
|
||
smi.lastmod = new Date(mtime).toISOString();
|
||
// The date of last modification (YYYY-MM-DD)
|
||
}
|
||
else if (smiLoose.lastmodISO) {
|
||
smi.lastmod = new Date(smiLoose.lastmodISO).toISOString();
|
||
}
|
||
else if (smiLoose.lastmod) {
|
||
smi.lastmod = new Date(smiLoose.lastmod).toISOString();
|
||
}
|
||
if (lastmodDateOnly && smi.lastmod) {
|
||
smi.lastmod = smi.lastmod.slice(0, 10);
|
||
}
|
||
delete smiLoose.lastmodfile;
|
||
delete smiLoose.lastmodISO;
|
||
smi = { ...smiLoose, ...smi };
|
||
return smi;
|
||
}
|
||
utils.normalizeURL = normalizeURL;
|
||
|
||
(function (exports) {
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.streamToPromise = exports.SitemapStream = exports.closetag = exports.stylesheetInclude = void 0;
|
||
const stream_1 = require$$0$3;
|
||
const types_1 = types;
|
||
const utils_1 = utils;
|
||
const sitemap_item_stream_1 = sitemapItemStream;
|
||
const errors_1 = errors;
|
||
const xmlDec = '<?xml version="1.0" encoding="UTF-8"?>';
|
||
const stylesheetInclude = (url) => {
|
||
return `<?xml-stylesheet type="text/xsl" href="${url}"?>`;
|
||
};
|
||
exports.stylesheetInclude = stylesheetInclude;
|
||
const urlsetTagStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"';
|
||
const getURLSetNs = ({ news, video, image, xhtml, custom }, xslURL) => {
|
||
let ns = xmlDec;
|
||
if (xslURL) {
|
||
ns += (0, exports.stylesheetInclude)(xslURL);
|
||
}
|
||
ns += urlsetTagStart;
|
||
if (news) {
|
||
ns += ' xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"';
|
||
}
|
||
if (xhtml) {
|
||
ns += ' xmlns:xhtml="http://www.w3.org/1999/xhtml"';
|
||
}
|
||
if (image) {
|
||
ns += ' xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"';
|
||
}
|
||
if (video) {
|
||
ns += ' xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"';
|
||
}
|
||
if (custom) {
|
||
ns += ' ' + custom.join(' ');
|
||
}
|
||
return ns + '>';
|
||
};
|
||
exports.closetag = '</urlset>';
|
||
const defaultXMLNS = {
|
||
news: true,
|
||
xhtml: true,
|
||
image: true,
|
||
video: true,
|
||
};
|
||
const defaultStreamOpts = {
|
||
xmlns: defaultXMLNS,
|
||
};
|
||
/**
|
||
* A [Transform](https://nodejs.org/api/stream.html#stream_implementing_a_transform_stream)
|
||
* for turning a
|
||
* [Readable stream](https://nodejs.org/api/stream.html#stream_readable_streams)
|
||
* of either [SitemapItemOptions](#sitemap-item-options) or url strings into a
|
||
* Sitemap. The readable stream it transforms **must** be in object mode.
|
||
*/
|
||
class SitemapStream extends stream_1.Transform {
|
||
constructor(opts = defaultStreamOpts) {
|
||
opts.objectMode = true;
|
||
super(opts);
|
||
this.hasHeadOutput = false;
|
||
this.hostname = opts.hostname;
|
||
this.level = opts.level || types_1.ErrorLevel.WARN;
|
||
this.errorHandler = opts.errorHandler;
|
||
this.smiStream = new sitemap_item_stream_1.SitemapItemStream({ level: opts.level });
|
||
this.smiStream.on('data', (data) => this.push(data));
|
||
this.lastmodDateOnly = opts.lastmodDateOnly || false;
|
||
this.xmlNS = opts.xmlns || defaultXMLNS;
|
||
this.xslUrl = opts.xslUrl;
|
||
}
|
||
_transform(item, encoding, callback) {
|
||
if (!this.hasHeadOutput) {
|
||
this.hasHeadOutput = true;
|
||
this.push(getURLSetNs(this.xmlNS, this.xslUrl));
|
||
}
|
||
this.smiStream.write((0, utils_1.validateSMIOptions)((0, utils_1.normalizeURL)(item, this.hostname, this.lastmodDateOnly), this.level, this.errorHandler));
|
||
callback();
|
||
}
|
||
_flush(cb) {
|
||
if (!this.hasHeadOutput) {
|
||
cb(new errors_1.EmptySitemap());
|
||
}
|
||
else {
|
||
this.push(exports.closetag);
|
||
cb();
|
||
}
|
||
}
|
||
}
|
||
exports.SitemapStream = SitemapStream;
|
||
/**
|
||
* Takes a stream returns a promise that resolves when stream emits finish
|
||
* @param stream what you want wrapped in a promise
|
||
*/
|
||
function streamToPromise(stream) {
|
||
return new Promise((resolve, reject) => {
|
||
const drain = [];
|
||
stream
|
||
.pipe(new stream_1.Writable({
|
||
write(chunk, enc, next) {
|
||
drain.push(chunk);
|
||
next();
|
||
},
|
||
}))
|
||
.on('error', reject)
|
||
.on('finish', () => {
|
||
if (!drain.length) {
|
||
reject(new errors_1.EmptyStream());
|
||
}
|
||
else {
|
||
resolve(Buffer.concat(drain));
|
||
}
|
||
});
|
||
});
|
||
}
|
||
exports.streamToPromise = streamToPromise;
|
||
} (sitemapStream));
|
||
|
||
(function (exports) {
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.SitemapAndIndexStream = exports.SitemapIndexStream = exports.IndexTagNames = void 0;
|
||
const stream_1 = require$$0$3;
|
||
const types_1 = types;
|
||
const sitemap_stream_1 = sitemapStream;
|
||
const sitemap_xml_1 = sitemapXml;
|
||
var IndexTagNames;
|
||
(function (IndexTagNames) {
|
||
IndexTagNames["sitemap"] = "sitemap";
|
||
IndexTagNames["loc"] = "loc";
|
||
IndexTagNames["lastmod"] = "lastmod";
|
||
})(IndexTagNames = exports.IndexTagNames || (exports.IndexTagNames = {}));
|
||
const xmlDec = '<?xml version="1.0" encoding="UTF-8"?>';
|
||
const sitemapIndexTagStart = '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
|
||
const closetag = '</sitemapindex>';
|
||
const defaultStreamOpts = {};
|
||
class SitemapIndexStream extends stream_1.Transform {
|
||
constructor(opts = defaultStreamOpts) {
|
||
var _a;
|
||
opts.objectMode = true;
|
||
super(opts);
|
||
this.hasHeadOutput = false;
|
||
this.lastmodDateOnly = opts.lastmodDateOnly || false;
|
||
this.level = (_a = opts.level) !== null && _a !== void 0 ? _a : types_1.ErrorLevel.WARN;
|
||
this.xslUrl = opts.xslUrl;
|
||
}
|
||
_transform(item, encoding, callback) {
|
||
if (!this.hasHeadOutput) {
|
||
this.hasHeadOutput = true;
|
||
let stylesheet = '';
|
||
if (this.xslUrl) {
|
||
stylesheet = (0, sitemap_stream_1.stylesheetInclude)(this.xslUrl);
|
||
}
|
||
this.push(xmlDec + stylesheet + sitemapIndexTagStart);
|
||
}
|
||
this.push((0, sitemap_xml_1.otag)(IndexTagNames.sitemap));
|
||
if (typeof item === 'string') {
|
||
this.push((0, sitemap_xml_1.element)(IndexTagNames.loc, item));
|
||
}
|
||
else {
|
||
this.push((0, sitemap_xml_1.element)(IndexTagNames.loc, item.url));
|
||
if (item.lastmod) {
|
||
const lastmod = new Date(item.lastmod).toISOString();
|
||
this.push((0, sitemap_xml_1.element)(IndexTagNames.lastmod, this.lastmodDateOnly ? lastmod.slice(0, 10) : lastmod));
|
||
}
|
||
}
|
||
this.push((0, sitemap_xml_1.ctag)(IndexTagNames.sitemap));
|
||
callback();
|
||
}
|
||
_flush(cb) {
|
||
this.push(closetag);
|
||
cb();
|
||
}
|
||
}
|
||
exports.SitemapIndexStream = SitemapIndexStream;
|
||
// const defaultSIStreamOpts: SitemapAndIndexStreamOptions = {};
|
||
class SitemapAndIndexStream extends SitemapIndexStream {
|
||
constructor(opts) {
|
||
var _a;
|
||
opts.objectMode = true;
|
||
super(opts);
|
||
this.i = 0;
|
||
this.getSitemapStream = opts.getSitemapStream;
|
||
[this.idxItem, this.currentSitemap, this.currentSitemapPipeline] =
|
||
this.getSitemapStream(0);
|
||
this.limit = (_a = opts.limit) !== null && _a !== void 0 ? _a : 45000;
|
||
}
|
||
_writeSMI(item) {
|
||
this.currentSitemap.write(item);
|
||
this.i++;
|
||
}
|
||
_transform(item, encoding, callback) {
|
||
var _a;
|
||
if (this.i === 0) {
|
||
this._writeSMI(item);
|
||
super._transform(this.idxItem, encoding, callback);
|
||
}
|
||
else if (this.i % this.limit === 0) {
|
||
const onFinish = () => {
|
||
const [idxItem, currentSitemap, currentSitemapPipeline] = this.getSitemapStream(this.i / this.limit);
|
||
this.currentSitemap = currentSitemap;
|
||
this.currentSitemapPipeline = currentSitemapPipeline;
|
||
this._writeSMI(item);
|
||
// push to index stream
|
||
super._transform(idxItem, encoding, callback);
|
||
};
|
||
(_a = this.currentSitemapPipeline) === null || _a === void 0 ? void 0 : _a.on('finish', onFinish);
|
||
this.currentSitemap.end(!this.currentSitemapPipeline ? onFinish : undefined);
|
||
}
|
||
else {
|
||
this._writeSMI(item);
|
||
callback();
|
||
}
|
||
}
|
||
_flush(cb) {
|
||
var _a;
|
||
const onFinish = () => super._flush(cb);
|
||
(_a = this.currentSitemapPipeline) === null || _a === void 0 ? void 0 : _a.on('finish', onFinish);
|
||
this.currentSitemap.end(!this.currentSitemapPipeline ? onFinish : undefined);
|
||
}
|
||
}
|
||
exports.SitemapAndIndexStream = SitemapAndIndexStream;
|
||
} (sitemapIndexStream));
|
||
|
||
var xmllint = {};
|
||
|
||
Object.defineProperty(xmllint, "__esModule", { value: true });
|
||
xmllint.xmlLint = void 0;
|
||
const path_1 = path$q;
|
||
const child_process_1 = require$$0$8;
|
||
const errors_1 = errors;
|
||
/**
|
||
* Verify the passed in xml is valid. Requires xmllib be installed
|
||
* @param xml what you want validated
|
||
* @return {Promise<void>} resolves on valid rejects [error stderr]
|
||
*/
|
||
function xmlLint(xml) {
|
||
const args = [
|
||
'--schema',
|
||
(0, path_1.resolve)(__dirname, '..', '..', 'schema', 'all.xsd'),
|
||
'--noout',
|
||
'-',
|
||
];
|
||
if (typeof xml === 'string') {
|
||
args[args.length - 1] = xml;
|
||
}
|
||
return new Promise((resolve, reject) => {
|
||
(0, child_process_1.execFile)('which', ['xmllint'], (error, stdout, stderr) => {
|
||
if (error) {
|
||
reject([new errors_1.XMLLintUnavailable()]);
|
||
return;
|
||
}
|
||
const xmllint = (0, child_process_1.execFile)('xmllint', args, (error, stdout, stderr) => {
|
||
if (error) {
|
||
reject([error, stderr]);
|
||
}
|
||
resolve();
|
||
});
|
||
if (xmllint.stdout) {
|
||
xmllint.stdout.unpipe();
|
||
if (typeof xml !== 'string' && xml && xmllint.stdin) {
|
||
xml.pipe(xmllint.stdin);
|
||
}
|
||
}
|
||
});
|
||
});
|
||
}
|
||
xmllint.xmlLint = xmlLint;
|
||
|
||
var sitemapParser = {};
|
||
|
||
var sax = {};
|
||
|
||
(function (exports) {
|
||
(function (sax) { // wrapper for non-node envs
|
||
sax.parser = function (strict, opt) { return new SAXParser(strict, opt) };
|
||
sax.SAXParser = SAXParser;
|
||
sax.SAXStream = SAXStream;
|
||
sax.createStream = createStream;
|
||
|
||
// When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns.
|
||
// When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)),
|
||
// since that's the earliest that a buffer overrun could occur. This way, checks are
|
||
// as rare as required, but as often as necessary to ensure never crossing this bound.
|
||
// Furthermore, buffers are only tested at most once per write(), so passing a very
|
||
// large string into write() might have undesirable effects, but this is manageable by
|
||
// the caller, so it is assumed to be safe. Thus, a call to write() may, in the extreme
|
||
// edge case, result in creating at most one complete copy of the string passed in.
|
||
// Set to Infinity to have unlimited buffers.
|
||
sax.MAX_BUFFER_LENGTH = 64 * 1024;
|
||
|
||
var buffers = [
|
||
'comment', 'sgmlDecl', 'textNode', 'tagName', 'doctype',
|
||
'procInstName', 'procInstBody', 'entity', 'attribName',
|
||
'attribValue', 'cdata', 'script'
|
||
];
|
||
|
||
sax.EVENTS = [
|
||
'text',
|
||
'processinginstruction',
|
||
'sgmldeclaration',
|
||
'doctype',
|
||
'comment',
|
||
'opentagstart',
|
||
'attribute',
|
||
'opentag',
|
||
'closetag',
|
||
'opencdata',
|
||
'cdata',
|
||
'closecdata',
|
||
'error',
|
||
'end',
|
||
'ready',
|
||
'script',
|
||
'opennamespace',
|
||
'closenamespace'
|
||
];
|
||
|
||
function SAXParser (strict, opt) {
|
||
if (!(this instanceof SAXParser)) {
|
||
return new SAXParser(strict, opt)
|
||
}
|
||
|
||
var parser = this;
|
||
clearBuffers(parser);
|
||
parser.q = parser.c = '';
|
||
parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH;
|
||
parser.opt = opt || {};
|
||
parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags;
|
||
parser.looseCase = parser.opt.lowercase ? 'toLowerCase' : 'toUpperCase';
|
||
parser.tags = [];
|
||
parser.closed = parser.closedRoot = parser.sawRoot = false;
|
||
parser.tag = parser.error = null;
|
||
parser.strict = !!strict;
|
||
parser.noscript = !!(strict || parser.opt.noscript);
|
||
parser.state = S.BEGIN;
|
||
parser.strictEntities = parser.opt.strictEntities;
|
||
parser.ENTITIES = parser.strictEntities ? Object.create(sax.XML_ENTITIES) : Object.create(sax.ENTITIES);
|
||
parser.attribList = [];
|
||
|
||
// namespaces form a prototype chain.
|
||
// it always points at the current tag,
|
||
// which protos to its parent tag.
|
||
if (parser.opt.xmlns) {
|
||
parser.ns = Object.create(rootNS);
|
||
}
|
||
|
||
// mostly just for error reporting
|
||
parser.trackPosition = parser.opt.position !== false;
|
||
if (parser.trackPosition) {
|
||
parser.position = parser.line = parser.column = 0;
|
||
}
|
||
emit(parser, 'onready');
|
||
}
|
||
|
||
if (!Object.create) {
|
||
Object.create = function (o) {
|
||
function F () {}
|
||
F.prototype = o;
|
||
var newf = new F();
|
||
return newf
|
||
};
|
||
}
|
||
|
||
if (!Object.keys) {
|
||
Object.keys = function (o) {
|
||
var a = [];
|
||
for (var i in o) if (o.hasOwnProperty(i)) a.push(i);
|
||
return a
|
||
};
|
||
}
|
||
|
||
function checkBufferLength (parser) {
|
||
var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10);
|
||
var maxActual = 0;
|
||
for (var i = 0, l = buffers.length; i < l; i++) {
|
||
var len = parser[buffers[i]].length;
|
||
if (len > maxAllowed) {
|
||
// Text/cdata nodes can get big, and since they're buffered,
|
||
// we can get here under normal conditions.
|
||
// Avoid issues by emitting the text node now,
|
||
// so at least it won't get any bigger.
|
||
switch (buffers[i]) {
|
||
case 'textNode':
|
||
closeText(parser);
|
||
break
|
||
|
||
case 'cdata':
|
||
emitNode(parser, 'oncdata', parser.cdata);
|
||
parser.cdata = '';
|
||
break
|
||
|
||
case 'script':
|
||
emitNode(parser, 'onscript', parser.script);
|
||
parser.script = '';
|
||
break
|
||
|
||
default:
|
||
error(parser, 'Max buffer length exceeded: ' + buffers[i]);
|
||
}
|
||
}
|
||
maxActual = Math.max(maxActual, len);
|
||
}
|
||
// schedule the next check for the earliest possible buffer overrun.
|
||
var m = sax.MAX_BUFFER_LENGTH - maxActual;
|
||
parser.bufferCheckPosition = m + parser.position;
|
||
}
|
||
|
||
function clearBuffers (parser) {
|
||
for (var i = 0, l = buffers.length; i < l; i++) {
|
||
parser[buffers[i]] = '';
|
||
}
|
||
}
|
||
|
||
function flushBuffers (parser) {
|
||
closeText(parser);
|
||
if (parser.cdata !== '') {
|
||
emitNode(parser, 'oncdata', parser.cdata);
|
||
parser.cdata = '';
|
||
}
|
||
if (parser.script !== '') {
|
||
emitNode(parser, 'onscript', parser.script);
|
||
parser.script = '';
|
||
}
|
||
}
|
||
|
||
SAXParser.prototype = {
|
||
end: function () { end(this); },
|
||
write: write,
|
||
resume: function () { this.error = null; return this },
|
||
close: function () { return this.write(null) },
|
||
flush: function () { flushBuffers(this); }
|
||
};
|
||
|
||
var Stream;
|
||
try {
|
||
Stream = require('stream').Stream;
|
||
} catch (ex) {
|
||
Stream = function () {};
|
||
}
|
||
if (!Stream) Stream = function () {};
|
||
|
||
var streamWraps = sax.EVENTS.filter(function (ev) {
|
||
return ev !== 'error' && ev !== 'end'
|
||
});
|
||
|
||
function createStream (strict, opt) {
|
||
return new SAXStream(strict, opt)
|
||
}
|
||
|
||
function SAXStream (strict, opt) {
|
||
if (!(this instanceof SAXStream)) {
|
||
return new SAXStream(strict, opt)
|
||
}
|
||
|
||
Stream.apply(this);
|
||
|
||
this._parser = new SAXParser(strict, opt);
|
||
this.writable = true;
|
||
this.readable = true;
|
||
|
||
var me = this;
|
||
|
||
this._parser.onend = function () {
|
||
me.emit('end');
|
||
};
|
||
|
||
this._parser.onerror = function (er) {
|
||
me.emit('error', er);
|
||
|
||
// if didn't throw, then means error was handled.
|
||
// go ahead and clear error, so we can write again.
|
||
me._parser.error = null;
|
||
};
|
||
|
||
this._decoder = null;
|
||
|
||
streamWraps.forEach(function (ev) {
|
||
Object.defineProperty(me, 'on' + ev, {
|
||
get: function () {
|
||
return me._parser['on' + ev]
|
||
},
|
||
set: function (h) {
|
||
if (!h) {
|
||
me.removeAllListeners(ev);
|
||
me._parser['on' + ev] = h;
|
||
return h
|
||
}
|
||
me.on(ev, h);
|
||
},
|
||
enumerable: true,
|
||
configurable: false
|
||
});
|
||
});
|
||
}
|
||
|
||
SAXStream.prototype = Object.create(Stream.prototype, {
|
||
constructor: {
|
||
value: SAXStream
|
||
}
|
||
});
|
||
|
||
SAXStream.prototype.write = function (data) {
|
||
if (typeof Buffer === 'function' &&
|
||
typeof Buffer.isBuffer === 'function' &&
|
||
Buffer.isBuffer(data)) {
|
||
if (!this._decoder) {
|
||
var SD = require$$1.StringDecoder;
|
||
this._decoder = new SD('utf8');
|
||
}
|
||
data = this._decoder.write(data);
|
||
}
|
||
|
||
this._parser.write(data.toString());
|
||
this.emit('data', data);
|
||
return true
|
||
};
|
||
|
||
SAXStream.prototype.end = function (chunk) {
|
||
if (chunk && chunk.length) {
|
||
this.write(chunk);
|
||
}
|
||
this._parser.end();
|
||
return true
|
||
};
|
||
|
||
SAXStream.prototype.on = function (ev, handler) {
|
||
var me = this;
|
||
if (!me._parser['on' + ev] && streamWraps.indexOf(ev) !== -1) {
|
||
me._parser['on' + ev] = function () {
|
||
var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments);
|
||
args.splice(0, 0, ev);
|
||
me.emit.apply(me, args);
|
||
};
|
||
}
|
||
|
||
return Stream.prototype.on.call(me, ev, handler)
|
||
};
|
||
|
||
// this really needs to be replaced with character classes.
|
||
// XML allows all manner of ridiculous numbers and digits.
|
||
var CDATA = '[CDATA[';
|
||
var DOCTYPE = 'DOCTYPE';
|
||
var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
|
||
var XMLNS_NAMESPACE = 'http://www.w3.org/2000/xmlns/';
|
||
var rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE };
|
||
|
||
// http://www.w3.org/TR/REC-xml/#NT-NameStartChar
|
||
// This implementation works on strings, a single character at a time
|
||
// as such, it cannot ever support astral-plane characters (10000-EFFFF)
|
||
// without a significant breaking change to either this parser, or the
|
||
// JavaScript language. Implementation of an emoji-capable xml parser
|
||
// is left as an exercise for the reader.
|
||
var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/;
|
||
|
||
var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/;
|
||
|
||
var entityStart = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/;
|
||
var entityBody = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/;
|
||
|
||
function isWhitespace (c) {
|
||
return c === ' ' || c === '\n' || c === '\r' || c === '\t'
|
||
}
|
||
|
||
function isQuote (c) {
|
||
return c === '"' || c === '\''
|
||
}
|
||
|
||
function isAttribEnd (c) {
|
||
return c === '>' || isWhitespace(c)
|
||
}
|
||
|
||
function isMatch (regex, c) {
|
||
return regex.test(c)
|
||
}
|
||
|
||
function notMatch (regex, c) {
|
||
return !isMatch(regex, c)
|
||
}
|
||
|
||
var S = 0;
|
||
sax.STATE = {
|
||
BEGIN: S++, // leading byte order mark or whitespace
|
||
BEGIN_WHITESPACE: S++, // leading whitespace
|
||
TEXT: S++, // general stuff
|
||
TEXT_ENTITY: S++, // & and such.
|
||
OPEN_WAKA: S++, // <
|
||
SGML_DECL: S++, // <!BLARG
|
||
SGML_DECL_QUOTED: S++, // <!BLARG foo "bar
|
||
DOCTYPE: S++, // <!DOCTYPE
|
||
DOCTYPE_QUOTED: S++, // <!DOCTYPE "//blah
|
||
DOCTYPE_DTD: S++, // <!DOCTYPE "//blah" [ ...
|
||
DOCTYPE_DTD_QUOTED: S++, // <!DOCTYPE "//blah" [ "foo
|
||
COMMENT_STARTING: S++, // <!-
|
||
COMMENT: S++, // <!--
|
||
COMMENT_ENDING: S++, // <!-- blah -
|
||
COMMENT_ENDED: S++, // <!-- blah --
|
||
CDATA: S++, // <![CDATA[ something
|
||
CDATA_ENDING: S++, // ]
|
||
CDATA_ENDING_2: S++, // ]]
|
||
PROC_INST: S++, // <?hi
|
||
PROC_INST_BODY: S++, // <?hi there
|
||
PROC_INST_ENDING: S++, // <?hi "there" ?
|
||
OPEN_TAG: S++, // <strong
|
||
OPEN_TAG_SLASH: S++, // <strong /
|
||
ATTRIB: S++, // <a
|
||
ATTRIB_NAME: S++, // <a foo
|
||
ATTRIB_NAME_SAW_WHITE: S++, // <a foo _
|
||
ATTRIB_VALUE: S++, // <a foo=
|
||
ATTRIB_VALUE_QUOTED: S++, // <a foo="bar
|
||
ATTRIB_VALUE_CLOSED: S++, // <a foo="bar"
|
||
ATTRIB_VALUE_UNQUOTED: S++, // <a foo=bar
|
||
ATTRIB_VALUE_ENTITY_Q: S++, // <foo bar="""
|
||
ATTRIB_VALUE_ENTITY_U: S++, // <foo bar="
|
||
CLOSE_TAG: S++, // </a
|
||
CLOSE_TAG_SAW_WHITE: S++, // </a >
|
||
SCRIPT: S++, // <script> ...
|
||
SCRIPT_ENDING: S++ // <script> ... <
|
||
};
|
||
|
||
sax.XML_ENTITIES = {
|
||
'amp': '&',
|
||
'gt': '>',
|
||
'lt': '<',
|
||
'quot': '"',
|
||
'apos': "'"
|
||
};
|
||
|
||
sax.ENTITIES = {
|
||
'amp': '&',
|
||
'gt': '>',
|
||
'lt': '<',
|
||
'quot': '"',
|
||
'apos': "'",
|
||
'AElig': 198,
|
||
'Aacute': 193,
|
||
'Acirc': 194,
|
||
'Agrave': 192,
|
||
'Aring': 197,
|
||
'Atilde': 195,
|
||
'Auml': 196,
|
||
'Ccedil': 199,
|
||
'ETH': 208,
|
||
'Eacute': 201,
|
||
'Ecirc': 202,
|
||
'Egrave': 200,
|
||
'Euml': 203,
|
||
'Iacute': 205,
|
||
'Icirc': 206,
|
||
'Igrave': 204,
|
||
'Iuml': 207,
|
||
'Ntilde': 209,
|
||
'Oacute': 211,
|
||
'Ocirc': 212,
|
||
'Ograve': 210,
|
||
'Oslash': 216,
|
||
'Otilde': 213,
|
||
'Ouml': 214,
|
||
'THORN': 222,
|
||
'Uacute': 218,
|
||
'Ucirc': 219,
|
||
'Ugrave': 217,
|
||
'Uuml': 220,
|
||
'Yacute': 221,
|
||
'aacute': 225,
|
||
'acirc': 226,
|
||
'aelig': 230,
|
||
'agrave': 224,
|
||
'aring': 229,
|
||
'atilde': 227,
|
||
'auml': 228,
|
||
'ccedil': 231,
|
||
'eacute': 233,
|
||
'ecirc': 234,
|
||
'egrave': 232,
|
||
'eth': 240,
|
||
'euml': 235,
|
||
'iacute': 237,
|
||
'icirc': 238,
|
||
'igrave': 236,
|
||
'iuml': 239,
|
||
'ntilde': 241,
|
||
'oacute': 243,
|
||
'ocirc': 244,
|
||
'ograve': 242,
|
||
'oslash': 248,
|
||
'otilde': 245,
|
||
'ouml': 246,
|
||
'szlig': 223,
|
||
'thorn': 254,
|
||
'uacute': 250,
|
||
'ucirc': 251,
|
||
'ugrave': 249,
|
||
'uuml': 252,
|
||
'yacute': 253,
|
||
'yuml': 255,
|
||
'copy': 169,
|
||
'reg': 174,
|
||
'nbsp': 160,
|
||
'iexcl': 161,
|
||
'cent': 162,
|
||
'pound': 163,
|
||
'curren': 164,
|
||
'yen': 165,
|
||
'brvbar': 166,
|
||
'sect': 167,
|
||
'uml': 168,
|
||
'ordf': 170,
|
||
'laquo': 171,
|
||
'not': 172,
|
||
'shy': 173,
|
||
'macr': 175,
|
||
'deg': 176,
|
||
'plusmn': 177,
|
||
'sup1': 185,
|
||
'sup2': 178,
|
||
'sup3': 179,
|
||
'acute': 180,
|
||
'micro': 181,
|
||
'para': 182,
|
||
'middot': 183,
|
||
'cedil': 184,
|
||
'ordm': 186,
|
||
'raquo': 187,
|
||
'frac14': 188,
|
||
'frac12': 189,
|
||
'frac34': 190,
|
||
'iquest': 191,
|
||
'times': 215,
|
||
'divide': 247,
|
||
'OElig': 338,
|
||
'oelig': 339,
|
||
'Scaron': 352,
|
||
'scaron': 353,
|
||
'Yuml': 376,
|
||
'fnof': 402,
|
||
'circ': 710,
|
||
'tilde': 732,
|
||
'Alpha': 913,
|
||
'Beta': 914,
|
||
'Gamma': 915,
|
||
'Delta': 916,
|
||
'Epsilon': 917,
|
||
'Zeta': 918,
|
||
'Eta': 919,
|
||
'Theta': 920,
|
||
'Iota': 921,
|
||
'Kappa': 922,
|
||
'Lambda': 923,
|
||
'Mu': 924,
|
||
'Nu': 925,
|
||
'Xi': 926,
|
||
'Omicron': 927,
|
||
'Pi': 928,
|
||
'Rho': 929,
|
||
'Sigma': 931,
|
||
'Tau': 932,
|
||
'Upsilon': 933,
|
||
'Phi': 934,
|
||
'Chi': 935,
|
||
'Psi': 936,
|
||
'Omega': 937,
|
||
'alpha': 945,
|
||
'beta': 946,
|
||
'gamma': 947,
|
||
'delta': 948,
|
||
'epsilon': 949,
|
||
'zeta': 950,
|
||
'eta': 951,
|
||
'theta': 952,
|
||
'iota': 953,
|
||
'kappa': 954,
|
||
'lambda': 955,
|
||
'mu': 956,
|
||
'nu': 957,
|
||
'xi': 958,
|
||
'omicron': 959,
|
||
'pi': 960,
|
||
'rho': 961,
|
||
'sigmaf': 962,
|
||
'sigma': 963,
|
||
'tau': 964,
|
||
'upsilon': 965,
|
||
'phi': 966,
|
||
'chi': 967,
|
||
'psi': 968,
|
||
'omega': 969,
|
||
'thetasym': 977,
|
||
'upsih': 978,
|
||
'piv': 982,
|
||
'ensp': 8194,
|
||
'emsp': 8195,
|
||
'thinsp': 8201,
|
||
'zwnj': 8204,
|
||
'zwj': 8205,
|
||
'lrm': 8206,
|
||
'rlm': 8207,
|
||
'ndash': 8211,
|
||
'mdash': 8212,
|
||
'lsquo': 8216,
|
||
'rsquo': 8217,
|
||
'sbquo': 8218,
|
||
'ldquo': 8220,
|
||
'rdquo': 8221,
|
||
'bdquo': 8222,
|
||
'dagger': 8224,
|
||
'Dagger': 8225,
|
||
'bull': 8226,
|
||
'hellip': 8230,
|
||
'permil': 8240,
|
||
'prime': 8242,
|
||
'Prime': 8243,
|
||
'lsaquo': 8249,
|
||
'rsaquo': 8250,
|
||
'oline': 8254,
|
||
'frasl': 8260,
|
||
'euro': 8364,
|
||
'image': 8465,
|
||
'weierp': 8472,
|
||
'real': 8476,
|
||
'trade': 8482,
|
||
'alefsym': 8501,
|
||
'larr': 8592,
|
||
'uarr': 8593,
|
||
'rarr': 8594,
|
||
'darr': 8595,
|
||
'harr': 8596,
|
||
'crarr': 8629,
|
||
'lArr': 8656,
|
||
'uArr': 8657,
|
||
'rArr': 8658,
|
||
'dArr': 8659,
|
||
'hArr': 8660,
|
||
'forall': 8704,
|
||
'part': 8706,
|
||
'exist': 8707,
|
||
'empty': 8709,
|
||
'nabla': 8711,
|
||
'isin': 8712,
|
||
'notin': 8713,
|
||
'ni': 8715,
|
||
'prod': 8719,
|
||
'sum': 8721,
|
||
'minus': 8722,
|
||
'lowast': 8727,
|
||
'radic': 8730,
|
||
'prop': 8733,
|
||
'infin': 8734,
|
||
'ang': 8736,
|
||
'and': 8743,
|
||
'or': 8744,
|
||
'cap': 8745,
|
||
'cup': 8746,
|
||
'int': 8747,
|
||
'there4': 8756,
|
||
'sim': 8764,
|
||
'cong': 8773,
|
||
'asymp': 8776,
|
||
'ne': 8800,
|
||
'equiv': 8801,
|
||
'le': 8804,
|
||
'ge': 8805,
|
||
'sub': 8834,
|
||
'sup': 8835,
|
||
'nsub': 8836,
|
||
'sube': 8838,
|
||
'supe': 8839,
|
||
'oplus': 8853,
|
||
'otimes': 8855,
|
||
'perp': 8869,
|
||
'sdot': 8901,
|
||
'lceil': 8968,
|
||
'rceil': 8969,
|
||
'lfloor': 8970,
|
||
'rfloor': 8971,
|
||
'lang': 9001,
|
||
'rang': 9002,
|
||
'loz': 9674,
|
||
'spades': 9824,
|
||
'clubs': 9827,
|
||
'hearts': 9829,
|
||
'diams': 9830
|
||
};
|
||
|
||
Object.keys(sax.ENTITIES).forEach(function (key) {
|
||
var e = sax.ENTITIES[key];
|
||
var s = typeof e === 'number' ? String.fromCharCode(e) : e;
|
||
sax.ENTITIES[key] = s;
|
||
});
|
||
|
||
for (var s in sax.STATE) {
|
||
sax.STATE[sax.STATE[s]] = s;
|
||
}
|
||
|
||
// shorthand
|
||
S = sax.STATE;
|
||
|
||
function emit (parser, event, data) {
|
||
parser[event] && parser[event](data);
|
||
}
|
||
|
||
function emitNode (parser, nodeType, data) {
|
||
if (parser.textNode) closeText(parser);
|
||
emit(parser, nodeType, data);
|
||
}
|
||
|
||
function closeText (parser) {
|
||
parser.textNode = textopts(parser.opt, parser.textNode);
|
||
if (parser.textNode) emit(parser, 'ontext', parser.textNode);
|
||
parser.textNode = '';
|
||
}
|
||
|
||
function textopts (opt, text) {
|
||
if (opt.trim) text = text.trim();
|
||
if (opt.normalize) text = text.replace(/\s+/g, ' ');
|
||
return text
|
||
}
|
||
|
||
function error (parser, er) {
|
||
closeText(parser);
|
||
if (parser.trackPosition) {
|
||
er += '\nLine: ' + parser.line +
|
||
'\nColumn: ' + parser.column +
|
||
'\nChar: ' + parser.c;
|
||
}
|
||
er = new Error(er);
|
||
parser.error = er;
|
||
emit(parser, 'onerror', er);
|
||
return parser
|
||
}
|
||
|
||
function end (parser) {
|
||
if (parser.sawRoot && !parser.closedRoot) strictFail(parser, 'Unclosed root tag');
|
||
if ((parser.state !== S.BEGIN) &&
|
||
(parser.state !== S.BEGIN_WHITESPACE) &&
|
||
(parser.state !== S.TEXT)) {
|
||
error(parser, 'Unexpected end');
|
||
}
|
||
closeText(parser);
|
||
parser.c = '';
|
||
parser.closed = true;
|
||
emit(parser, 'onend');
|
||
SAXParser.call(parser, parser.strict, parser.opt);
|
||
return parser
|
||
}
|
||
|
||
function strictFail (parser, message) {
|
||
if (typeof parser !== 'object' || !(parser instanceof SAXParser)) {
|
||
throw new Error('bad call to strictFail')
|
||
}
|
||
if (parser.strict) {
|
||
error(parser, message);
|
||
}
|
||
}
|
||
|
||
function newTag (parser) {
|
||
if (!parser.strict) parser.tagName = parser.tagName[parser.looseCase]();
|
||
var parent = parser.tags[parser.tags.length - 1] || parser;
|
||
var tag = parser.tag = { name: parser.tagName, attributes: {} };
|
||
|
||
// will be overridden if tag contails an xmlns="foo" or xmlns:foo="bar"
|
||
if (parser.opt.xmlns) {
|
||
tag.ns = parent.ns;
|
||
}
|
||
parser.attribList.length = 0;
|
||
emitNode(parser, 'onopentagstart', tag);
|
||
}
|
||
|
||
function qname (name, attribute) {
|
||
var i = name.indexOf(':');
|
||
var qualName = i < 0 ? [ '', name ] : name.split(':');
|
||
var prefix = qualName[0];
|
||
var local = qualName[1];
|
||
|
||
// <x "xmlns"="http://foo">
|
||
if (attribute && name === 'xmlns') {
|
||
prefix = 'xmlns';
|
||
local = '';
|
||
}
|
||
|
||
return { prefix: prefix, local: local }
|
||
}
|
||
|
||
function attrib (parser) {
|
||
if (!parser.strict) {
|
||
parser.attribName = parser.attribName[parser.looseCase]();
|
||
}
|
||
|
||
if (parser.attribList.indexOf(parser.attribName) !== -1 ||
|
||
parser.tag.attributes.hasOwnProperty(parser.attribName)) {
|
||
parser.attribName = parser.attribValue = '';
|
||
return
|
||
}
|
||
|
||
if (parser.opt.xmlns) {
|
||
var qn = qname(parser.attribName, true);
|
||
var prefix = qn.prefix;
|
||
var local = qn.local;
|
||
|
||
if (prefix === 'xmlns') {
|
||
// namespace binding attribute. push the binding into scope
|
||
if (local === 'xml' && parser.attribValue !== XML_NAMESPACE) {
|
||
strictFail(parser,
|
||
'xml: prefix must be bound to ' + XML_NAMESPACE + '\n' +
|
||
'Actual: ' + parser.attribValue);
|
||
} else if (local === 'xmlns' && parser.attribValue !== XMLNS_NAMESPACE) {
|
||
strictFail(parser,
|
||
'xmlns: prefix must be bound to ' + XMLNS_NAMESPACE + '\n' +
|
||
'Actual: ' + parser.attribValue);
|
||
} else {
|
||
var tag = parser.tag;
|
||
var parent = parser.tags[parser.tags.length - 1] || parser;
|
||
if (tag.ns === parent.ns) {
|
||
tag.ns = Object.create(parent.ns);
|
||
}
|
||
tag.ns[local] = parser.attribValue;
|
||
}
|
||
}
|
||
|
||
// defer onattribute events until all attributes have been seen
|
||
// so any new bindings can take effect. preserve attribute order
|
||
// so deferred events can be emitted in document order
|
||
parser.attribList.push([parser.attribName, parser.attribValue]);
|
||
} else {
|
||
// in non-xmlns mode, we can emit the event right away
|
||
parser.tag.attributes[parser.attribName] = parser.attribValue;
|
||
emitNode(parser, 'onattribute', {
|
||
name: parser.attribName,
|
||
value: parser.attribValue
|
||
});
|
||
}
|
||
|
||
parser.attribName = parser.attribValue = '';
|
||
}
|
||
|
||
function openTag (parser, selfClosing) {
|
||
if (parser.opt.xmlns) {
|
||
// emit namespace binding events
|
||
var tag = parser.tag;
|
||
|
||
// add namespace info to tag
|
||
var qn = qname(parser.tagName);
|
||
tag.prefix = qn.prefix;
|
||
tag.local = qn.local;
|
||
tag.uri = tag.ns[qn.prefix] || '';
|
||
|
||
if (tag.prefix && !tag.uri) {
|
||
strictFail(parser, 'Unbound namespace prefix: ' +
|
||
JSON.stringify(parser.tagName));
|
||
tag.uri = qn.prefix;
|
||
}
|
||
|
||
var parent = parser.tags[parser.tags.length - 1] || parser;
|
||
if (tag.ns && parent.ns !== tag.ns) {
|
||
Object.keys(tag.ns).forEach(function (p) {
|
||
emitNode(parser, 'onopennamespace', {
|
||
prefix: p,
|
||
uri: tag.ns[p]
|
||
});
|
||
});
|
||
}
|
||
|
||
// handle deferred onattribute events
|
||
// Note: do not apply default ns to attributes:
|
||
// http://www.w3.org/TR/REC-xml-names/#defaulting
|
||
for (var i = 0, l = parser.attribList.length; i < l; i++) {
|
||
var nv = parser.attribList[i];
|
||
var name = nv[0];
|
||
var value = nv[1];
|
||
var qualName = qname(name, true);
|
||
var prefix = qualName.prefix;
|
||
var local = qualName.local;
|
||
var uri = prefix === '' ? '' : (tag.ns[prefix] || '');
|
||
var a = {
|
||
name: name,
|
||
value: value,
|
||
prefix: prefix,
|
||
local: local,
|
||
uri: uri
|
||
};
|
||
|
||
// if there's any attributes with an undefined namespace,
|
||
// then fail on them now.
|
||
if (prefix && prefix !== 'xmlns' && !uri) {
|
||
strictFail(parser, 'Unbound namespace prefix: ' +
|
||
JSON.stringify(prefix));
|
||
a.uri = prefix;
|
||
}
|
||
parser.tag.attributes[name] = a;
|
||
emitNode(parser, 'onattribute', a);
|
||
}
|
||
parser.attribList.length = 0;
|
||
}
|
||
|
||
parser.tag.isSelfClosing = !!selfClosing;
|
||
|
||
// process the tag
|
||
parser.sawRoot = true;
|
||
parser.tags.push(parser.tag);
|
||
emitNode(parser, 'onopentag', parser.tag);
|
||
if (!selfClosing) {
|
||
// special case for <script> in non-strict mode.
|
||
if (!parser.noscript && parser.tagName.toLowerCase() === 'script') {
|
||
parser.state = S.SCRIPT;
|
||
} else {
|
||
parser.state = S.TEXT;
|
||
}
|
||
parser.tag = null;
|
||
parser.tagName = '';
|
||
}
|
||
parser.attribName = parser.attribValue = '';
|
||
parser.attribList.length = 0;
|
||
}
|
||
|
||
function closeTag (parser) {
|
||
if (!parser.tagName) {
|
||
strictFail(parser, 'Weird empty close tag.');
|
||
parser.textNode += '</>';
|
||
parser.state = S.TEXT;
|
||
return
|
||
}
|
||
|
||
if (parser.script) {
|
||
if (parser.tagName !== 'script') {
|
||
parser.script += '</' + parser.tagName + '>';
|
||
parser.tagName = '';
|
||
parser.state = S.SCRIPT;
|
||
return
|
||
}
|
||
emitNode(parser, 'onscript', parser.script);
|
||
parser.script = '';
|
||
}
|
||
|
||
// first make sure that the closing tag actually exists.
|
||
// <a><b></c></b></a> will close everything, otherwise.
|
||
var t = parser.tags.length;
|
||
var tagName = parser.tagName;
|
||
if (!parser.strict) {
|
||
tagName = tagName[parser.looseCase]();
|
||
}
|
||
var closeTo = tagName;
|
||
while (t--) {
|
||
var close = parser.tags[t];
|
||
if (close.name !== closeTo) {
|
||
// fail the first time in strict mode
|
||
strictFail(parser, 'Unexpected close tag');
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
|
||
// didn't find it. we already failed for strict, so just abort.
|
||
if (t < 0) {
|
||
strictFail(parser, 'Unmatched closing tag: ' + parser.tagName);
|
||
parser.textNode += '</' + parser.tagName + '>';
|
||
parser.state = S.TEXT;
|
||
return
|
||
}
|
||
parser.tagName = tagName;
|
||
var s = parser.tags.length;
|
||
while (s-- > t) {
|
||
var tag = parser.tag = parser.tags.pop();
|
||
parser.tagName = parser.tag.name;
|
||
emitNode(parser, 'onclosetag', parser.tagName);
|
||
|
||
var x = {};
|
||
for (var i in tag.ns) {
|
||
x[i] = tag.ns[i];
|
||
}
|
||
|
||
var parent = parser.tags[parser.tags.length - 1] || parser;
|
||
if (parser.opt.xmlns && tag.ns !== parent.ns) {
|
||
// remove namespace bindings introduced by tag
|
||
Object.keys(tag.ns).forEach(function (p) {
|
||
var n = tag.ns[p];
|
||
emitNode(parser, 'onclosenamespace', { prefix: p, uri: n });
|
||
});
|
||
}
|
||
}
|
||
if (t === 0) parser.closedRoot = true;
|
||
parser.tagName = parser.attribValue = parser.attribName = '';
|
||
parser.attribList.length = 0;
|
||
parser.state = S.TEXT;
|
||
}
|
||
|
||
function parseEntity (parser) {
|
||
var entity = parser.entity;
|
||
var entityLC = entity.toLowerCase();
|
||
var num;
|
||
var numStr = '';
|
||
|
||
if (parser.ENTITIES[entity]) {
|
||
return parser.ENTITIES[entity]
|
||
}
|
||
if (parser.ENTITIES[entityLC]) {
|
||
return parser.ENTITIES[entityLC]
|
||
}
|
||
entity = entityLC;
|
||
if (entity.charAt(0) === '#') {
|
||
if (entity.charAt(1) === 'x') {
|
||
entity = entity.slice(2);
|
||
num = parseInt(entity, 16);
|
||
numStr = num.toString(16);
|
||
} else {
|
||
entity = entity.slice(1);
|
||
num = parseInt(entity, 10);
|
||
numStr = num.toString(10);
|
||
}
|
||
}
|
||
entity = entity.replace(/^0+/, '');
|
||
if (isNaN(num) || numStr.toLowerCase() !== entity) {
|
||
strictFail(parser, 'Invalid character entity');
|
||
return '&' + parser.entity + ';'
|
||
}
|
||
|
||
return String.fromCodePoint(num)
|
||
}
|
||
|
||
function beginWhiteSpace (parser, c) {
|
||
if (c === '<') {
|
||
parser.state = S.OPEN_WAKA;
|
||
parser.startTagPosition = parser.position;
|
||
} else if (!isWhitespace(c)) {
|
||
// have to process this as a text node.
|
||
// weird, but happens.
|
||
strictFail(parser, 'Non-whitespace before first tag.');
|
||
parser.textNode = c;
|
||
parser.state = S.TEXT;
|
||
}
|
||
}
|
||
|
||
function charAt (chunk, i) {
|
||
var result = '';
|
||
if (i < chunk.length) {
|
||
result = chunk.charAt(i);
|
||
}
|
||
return result
|
||
}
|
||
|
||
function write (chunk) {
|
||
var parser = this;
|
||
if (this.error) {
|
||
throw this.error
|
||
}
|
||
if (parser.closed) {
|
||
return error(parser,
|
||
'Cannot write after close. Assign an onready handler.')
|
||
}
|
||
if (chunk === null) {
|
||
return end(parser)
|
||
}
|
||
if (typeof chunk === 'object') {
|
||
chunk = chunk.toString();
|
||
}
|
||
var i = 0;
|
||
var c = '';
|
||
while (true) {
|
||
c = charAt(chunk, i++);
|
||
parser.c = c;
|
||
|
||
if (!c) {
|
||
break
|
||
}
|
||
|
||
if (parser.trackPosition) {
|
||
parser.position++;
|
||
if (c === '\n') {
|
||
parser.line++;
|
||
parser.column = 0;
|
||
} else {
|
||
parser.column++;
|
||
}
|
||
}
|
||
|
||
switch (parser.state) {
|
||
case S.BEGIN:
|
||
parser.state = S.BEGIN_WHITESPACE;
|
||
if (c === '\uFEFF') {
|
||
continue
|
||
}
|
||
beginWhiteSpace(parser, c);
|
||
continue
|
||
|
||
case S.BEGIN_WHITESPACE:
|
||
beginWhiteSpace(parser, c);
|
||
continue
|
||
|
||
case S.TEXT:
|
||
if (parser.sawRoot && !parser.closedRoot) {
|
||
var starti = i - 1;
|
||
while (c && c !== '<' && c !== '&') {
|
||
c = charAt(chunk, i++);
|
||
if (c && parser.trackPosition) {
|
||
parser.position++;
|
||
if (c === '\n') {
|
||
parser.line++;
|
||
parser.column = 0;
|
||
} else {
|
||
parser.column++;
|
||
}
|
||
}
|
||
}
|
||
parser.textNode += chunk.substring(starti, i - 1);
|
||
}
|
||
if (c === '<' && !(parser.sawRoot && parser.closedRoot && !parser.strict)) {
|
||
parser.state = S.OPEN_WAKA;
|
||
parser.startTagPosition = parser.position;
|
||
} else {
|
||
if (!isWhitespace(c) && (!parser.sawRoot || parser.closedRoot)) {
|
||
strictFail(parser, 'Text data outside of root node.');
|
||
}
|
||
if (c === '&') {
|
||
parser.state = S.TEXT_ENTITY;
|
||
} else {
|
||
parser.textNode += c;
|
||
}
|
||
}
|
||
continue
|
||
|
||
case S.SCRIPT:
|
||
// only non-strict
|
||
if (c === '<') {
|
||
parser.state = S.SCRIPT_ENDING;
|
||
} else {
|
||
parser.script += c;
|
||
}
|
||
continue
|
||
|
||
case S.SCRIPT_ENDING:
|
||
if (c === '/') {
|
||
parser.state = S.CLOSE_TAG;
|
||
} else {
|
||
parser.script += '<' + c;
|
||
parser.state = S.SCRIPT;
|
||
}
|
||
continue
|
||
|
||
case S.OPEN_WAKA:
|
||
// either a /, ?, !, or text is coming next.
|
||
if (c === '!') {
|
||
parser.state = S.SGML_DECL;
|
||
parser.sgmlDecl = '';
|
||
} else if (isWhitespace(c)) ; else if (isMatch(nameStart, c)) {
|
||
parser.state = S.OPEN_TAG;
|
||
parser.tagName = c;
|
||
} else if (c === '/') {
|
||
parser.state = S.CLOSE_TAG;
|
||
parser.tagName = '';
|
||
} else if (c === '?') {
|
||
parser.state = S.PROC_INST;
|
||
parser.procInstName = parser.procInstBody = '';
|
||
} else {
|
||
strictFail(parser, 'Unencoded <');
|
||
// if there was some whitespace, then add that in.
|
||
if (parser.startTagPosition + 1 < parser.position) {
|
||
var pad = parser.position - parser.startTagPosition;
|
||
c = new Array(pad).join(' ') + c;
|
||
}
|
||
parser.textNode += '<' + c;
|
||
parser.state = S.TEXT;
|
||
}
|
||
continue
|
||
|
||
case S.SGML_DECL:
|
||
if ((parser.sgmlDecl + c).toUpperCase() === CDATA) {
|
||
emitNode(parser, 'onopencdata');
|
||
parser.state = S.CDATA;
|
||
parser.sgmlDecl = '';
|
||
parser.cdata = '';
|
||
} else if (parser.sgmlDecl + c === '--') {
|
||
parser.state = S.COMMENT;
|
||
parser.comment = '';
|
||
parser.sgmlDecl = '';
|
||
} else if ((parser.sgmlDecl + c).toUpperCase() === DOCTYPE) {
|
||
parser.state = S.DOCTYPE;
|
||
if (parser.doctype || parser.sawRoot) {
|
||
strictFail(parser,
|
||
'Inappropriately located doctype declaration');
|
||
}
|
||
parser.doctype = '';
|
||
parser.sgmlDecl = '';
|
||
} else if (c === '>') {
|
||
emitNode(parser, 'onsgmldeclaration', parser.sgmlDecl);
|
||
parser.sgmlDecl = '';
|
||
parser.state = S.TEXT;
|
||
} else if (isQuote(c)) {
|
||
parser.state = S.SGML_DECL_QUOTED;
|
||
parser.sgmlDecl += c;
|
||
} else {
|
||
parser.sgmlDecl += c;
|
||
}
|
||
continue
|
||
|
||
case S.SGML_DECL_QUOTED:
|
||
if (c === parser.q) {
|
||
parser.state = S.SGML_DECL;
|
||
parser.q = '';
|
||
}
|
||
parser.sgmlDecl += c;
|
||
continue
|
||
|
||
case S.DOCTYPE:
|
||
if (c === '>') {
|
||
parser.state = S.TEXT;
|
||
emitNode(parser, 'ondoctype', parser.doctype);
|
||
parser.doctype = true; // just remember that we saw it.
|
||
} else {
|
||
parser.doctype += c;
|
||
if (c === '[') {
|
||
parser.state = S.DOCTYPE_DTD;
|
||
} else if (isQuote(c)) {
|
||
parser.state = S.DOCTYPE_QUOTED;
|
||
parser.q = c;
|
||
}
|
||
}
|
||
continue
|
||
|
||
case S.DOCTYPE_QUOTED:
|
||
parser.doctype += c;
|
||
if (c === parser.q) {
|
||
parser.q = '';
|
||
parser.state = S.DOCTYPE;
|
||
}
|
||
continue
|
||
|
||
case S.DOCTYPE_DTD:
|
||
parser.doctype += c;
|
||
if (c === ']') {
|
||
parser.state = S.DOCTYPE;
|
||
} else if (isQuote(c)) {
|
||
parser.state = S.DOCTYPE_DTD_QUOTED;
|
||
parser.q = c;
|
||
}
|
||
continue
|
||
|
||
case S.DOCTYPE_DTD_QUOTED:
|
||
parser.doctype += c;
|
||
if (c === parser.q) {
|
||
parser.state = S.DOCTYPE_DTD;
|
||
parser.q = '';
|
||
}
|
||
continue
|
||
|
||
case S.COMMENT:
|
||
if (c === '-') {
|
||
parser.state = S.COMMENT_ENDING;
|
||
} else {
|
||
parser.comment += c;
|
||
}
|
||
continue
|
||
|
||
case S.COMMENT_ENDING:
|
||
if (c === '-') {
|
||
parser.state = S.COMMENT_ENDED;
|
||
parser.comment = textopts(parser.opt, parser.comment);
|
||
if (parser.comment) {
|
||
emitNode(parser, 'oncomment', parser.comment);
|
||
}
|
||
parser.comment = '';
|
||
} else {
|
||
parser.comment += '-' + c;
|
||
parser.state = S.COMMENT;
|
||
}
|
||
continue
|
||
|
||
case S.COMMENT_ENDED:
|
||
if (c !== '>') {
|
||
strictFail(parser, 'Malformed comment');
|
||
// allow <!-- blah -- bloo --> in non-strict mode,
|
||
// which is a comment of " blah -- bloo "
|
||
parser.comment += '--' + c;
|
||
parser.state = S.COMMENT;
|
||
} else {
|
||
parser.state = S.TEXT;
|
||
}
|
||
continue
|
||
|
||
case S.CDATA:
|
||
if (c === ']') {
|
||
parser.state = S.CDATA_ENDING;
|
||
} else {
|
||
parser.cdata += c;
|
||
}
|
||
continue
|
||
|
||
case S.CDATA_ENDING:
|
||
if (c === ']') {
|
||
parser.state = S.CDATA_ENDING_2;
|
||
} else {
|
||
parser.cdata += ']' + c;
|
||
parser.state = S.CDATA;
|
||
}
|
||
continue
|
||
|
||
case S.CDATA_ENDING_2:
|
||
if (c === '>') {
|
||
if (parser.cdata) {
|
||
emitNode(parser, 'oncdata', parser.cdata);
|
||
}
|
||
emitNode(parser, 'onclosecdata');
|
||
parser.cdata = '';
|
||
parser.state = S.TEXT;
|
||
} else if (c === ']') {
|
||
parser.cdata += ']';
|
||
} else {
|
||
parser.cdata += ']]' + c;
|
||
parser.state = S.CDATA;
|
||
}
|
||
continue
|
||
|
||
case S.PROC_INST:
|
||
if (c === '?') {
|
||
parser.state = S.PROC_INST_ENDING;
|
||
} else if (isWhitespace(c)) {
|
||
parser.state = S.PROC_INST_BODY;
|
||
} else {
|
||
parser.procInstName += c;
|
||
}
|
||
continue
|
||
|
||
case S.PROC_INST_BODY:
|
||
if (!parser.procInstBody && isWhitespace(c)) {
|
||
continue
|
||
} else if (c === '?') {
|
||
parser.state = S.PROC_INST_ENDING;
|
||
} else {
|
||
parser.procInstBody += c;
|
||
}
|
||
continue
|
||
|
||
case S.PROC_INST_ENDING:
|
||
if (c === '>') {
|
||
emitNode(parser, 'onprocessinginstruction', {
|
||
name: parser.procInstName,
|
||
body: parser.procInstBody
|
||
});
|
||
parser.procInstName = parser.procInstBody = '';
|
||
parser.state = S.TEXT;
|
||
} else {
|
||
parser.procInstBody += '?' + c;
|
||
parser.state = S.PROC_INST_BODY;
|
||
}
|
||
continue
|
||
|
||
case S.OPEN_TAG:
|
||
if (isMatch(nameBody, c)) {
|
||
parser.tagName += c;
|
||
} else {
|
||
newTag(parser);
|
||
if (c === '>') {
|
||
openTag(parser);
|
||
} else if (c === '/') {
|
||
parser.state = S.OPEN_TAG_SLASH;
|
||
} else {
|
||
if (!isWhitespace(c)) {
|
||
strictFail(parser, 'Invalid character in tag name');
|
||
}
|
||
parser.state = S.ATTRIB;
|
||
}
|
||
}
|
||
continue
|
||
|
||
case S.OPEN_TAG_SLASH:
|
||
if (c === '>') {
|
||
openTag(parser, true);
|
||
closeTag(parser);
|
||
} else {
|
||
strictFail(parser, 'Forward-slash in opening tag not followed by >');
|
||
parser.state = S.ATTRIB;
|
||
}
|
||
continue
|
||
|
||
case S.ATTRIB:
|
||
// haven't read the attribute name yet.
|
||
if (isWhitespace(c)) {
|
||
continue
|
||
} else if (c === '>') {
|
||
openTag(parser);
|
||
} else if (c === '/') {
|
||
parser.state = S.OPEN_TAG_SLASH;
|
||
} else if (isMatch(nameStart, c)) {
|
||
parser.attribName = c;
|
||
parser.attribValue = '';
|
||
parser.state = S.ATTRIB_NAME;
|
||
} else {
|
||
strictFail(parser, 'Invalid attribute name');
|
||
}
|
||
continue
|
||
|
||
case S.ATTRIB_NAME:
|
||
if (c === '=') {
|
||
parser.state = S.ATTRIB_VALUE;
|
||
} else if (c === '>') {
|
||
strictFail(parser, 'Attribute without value');
|
||
parser.attribValue = parser.attribName;
|
||
attrib(parser);
|
||
openTag(parser);
|
||
} else if (isWhitespace(c)) {
|
||
parser.state = S.ATTRIB_NAME_SAW_WHITE;
|
||
} else if (isMatch(nameBody, c)) {
|
||
parser.attribName += c;
|
||
} else {
|
||
strictFail(parser, 'Invalid attribute name');
|
||
}
|
||
continue
|
||
|
||
case S.ATTRIB_NAME_SAW_WHITE:
|
||
if (c === '=') {
|
||
parser.state = S.ATTRIB_VALUE;
|
||
} else if (isWhitespace(c)) {
|
||
continue
|
||
} else {
|
||
strictFail(parser, 'Attribute without value');
|
||
parser.tag.attributes[parser.attribName] = '';
|
||
parser.attribValue = '';
|
||
emitNode(parser, 'onattribute', {
|
||
name: parser.attribName,
|
||
value: ''
|
||
});
|
||
parser.attribName = '';
|
||
if (c === '>') {
|
||
openTag(parser);
|
||
} else if (isMatch(nameStart, c)) {
|
||
parser.attribName = c;
|
||
parser.state = S.ATTRIB_NAME;
|
||
} else {
|
||
strictFail(parser, 'Invalid attribute name');
|
||
parser.state = S.ATTRIB;
|
||
}
|
||
}
|
||
continue
|
||
|
||
case S.ATTRIB_VALUE:
|
||
if (isWhitespace(c)) {
|
||
continue
|
||
} else if (isQuote(c)) {
|
||
parser.q = c;
|
||
parser.state = S.ATTRIB_VALUE_QUOTED;
|
||
} else {
|
||
strictFail(parser, 'Unquoted attribute value');
|
||
parser.state = S.ATTRIB_VALUE_UNQUOTED;
|
||
parser.attribValue = c;
|
||
}
|
||
continue
|
||
|
||
case S.ATTRIB_VALUE_QUOTED:
|
||
if (c !== parser.q) {
|
||
if (c === '&') {
|
||
parser.state = S.ATTRIB_VALUE_ENTITY_Q;
|
||
} else {
|
||
parser.attribValue += c;
|
||
}
|
||
continue
|
||
}
|
||
attrib(parser);
|
||
parser.q = '';
|
||
parser.state = S.ATTRIB_VALUE_CLOSED;
|
||
continue
|
||
|
||
case S.ATTRIB_VALUE_CLOSED:
|
||
if (isWhitespace(c)) {
|
||
parser.state = S.ATTRIB;
|
||
} else if (c === '>') {
|
||
openTag(parser);
|
||
} else if (c === '/') {
|
||
parser.state = S.OPEN_TAG_SLASH;
|
||
} else if (isMatch(nameStart, c)) {
|
||
strictFail(parser, 'No whitespace between attributes');
|
||
parser.attribName = c;
|
||
parser.attribValue = '';
|
||
parser.state = S.ATTRIB_NAME;
|
||
} else {
|
||
strictFail(parser, 'Invalid attribute name');
|
||
}
|
||
continue
|
||
|
||
case S.ATTRIB_VALUE_UNQUOTED:
|
||
if (!isAttribEnd(c)) {
|
||
if (c === '&') {
|
||
parser.state = S.ATTRIB_VALUE_ENTITY_U;
|
||
} else {
|
||
parser.attribValue += c;
|
||
}
|
||
continue
|
||
}
|
||
attrib(parser);
|
||
if (c === '>') {
|
||
openTag(parser);
|
||
} else {
|
||
parser.state = S.ATTRIB;
|
||
}
|
||
continue
|
||
|
||
case S.CLOSE_TAG:
|
||
if (!parser.tagName) {
|
||
if (isWhitespace(c)) {
|
||
continue
|
||
} else if (notMatch(nameStart, c)) {
|
||
if (parser.script) {
|
||
parser.script += '</' + c;
|
||
parser.state = S.SCRIPT;
|
||
} else {
|
||
strictFail(parser, 'Invalid tagname in closing tag.');
|
||
}
|
||
} else {
|
||
parser.tagName = c;
|
||
}
|
||
} else if (c === '>') {
|
||
closeTag(parser);
|
||
} else if (isMatch(nameBody, c)) {
|
||
parser.tagName += c;
|
||
} else if (parser.script) {
|
||
parser.script += '</' + parser.tagName;
|
||
parser.tagName = '';
|
||
parser.state = S.SCRIPT;
|
||
} else {
|
||
if (!isWhitespace(c)) {
|
||
strictFail(parser, 'Invalid tagname in closing tag');
|
||
}
|
||
parser.state = S.CLOSE_TAG_SAW_WHITE;
|
||
}
|
||
continue
|
||
|
||
case S.CLOSE_TAG_SAW_WHITE:
|
||
if (isWhitespace(c)) {
|
||
continue
|
||
}
|
||
if (c === '>') {
|
||
closeTag(parser);
|
||
} else {
|
||
strictFail(parser, 'Invalid characters in closing tag');
|
||
}
|
||
continue
|
||
|
||
case S.TEXT_ENTITY:
|
||
case S.ATTRIB_VALUE_ENTITY_Q:
|
||
case S.ATTRIB_VALUE_ENTITY_U:
|
||
var returnState;
|
||
var buffer;
|
||
switch (parser.state) {
|
||
case S.TEXT_ENTITY:
|
||
returnState = S.TEXT;
|
||
buffer = 'textNode';
|
||
break
|
||
|
||
case S.ATTRIB_VALUE_ENTITY_Q:
|
||
returnState = S.ATTRIB_VALUE_QUOTED;
|
||
buffer = 'attribValue';
|
||
break
|
||
|
||
case S.ATTRIB_VALUE_ENTITY_U:
|
||
returnState = S.ATTRIB_VALUE_UNQUOTED;
|
||
buffer = 'attribValue';
|
||
break
|
||
}
|
||
|
||
if (c === ';') {
|
||
if (parser.opt.unparsedEntities) {
|
||
var parsedEntity = parseEntity(parser);
|
||
parser.entity = '';
|
||
parser.state = returnState;
|
||
parser.write(parsedEntity);
|
||
} else {
|
||
parser[buffer] += parseEntity(parser);
|
||
parser.entity = '';
|
||
parser.state = returnState;
|
||
}
|
||
} else if (isMatch(parser.entity.length ? entityBody : entityStart, c)) {
|
||
parser.entity += c;
|
||
} else {
|
||
strictFail(parser, 'Invalid character in entity name');
|
||
parser[buffer] += '&' + parser.entity + c;
|
||
parser.entity = '';
|
||
parser.state = returnState;
|
||
}
|
||
|
||
continue
|
||
|
||
default: /* istanbul ignore next */ {
|
||
throw new Error(parser, 'Unknown state: ' + parser.state)
|
||
}
|
||
}
|
||
} // while
|
||
|
||
if (parser.position >= parser.bufferCheckPosition) {
|
||
checkBufferLength(parser);
|
||
}
|
||
return parser
|
||
}
|
||
|
||
/*! http://mths.be/fromcodepoint v0.1.0 by @mathias */
|
||
/* istanbul ignore next */
|
||
if (!String.fromCodePoint) {
|
||
(function () {
|
||
var stringFromCharCode = String.fromCharCode;
|
||
var floor = Math.floor;
|
||
var fromCodePoint = function () {
|
||
var MAX_SIZE = 0x4000;
|
||
var codeUnits = [];
|
||
var highSurrogate;
|
||
var lowSurrogate;
|
||
var index = -1;
|
||
var length = arguments.length;
|
||
if (!length) {
|
||
return ''
|
||
}
|
||
var result = '';
|
||
while (++index < length) {
|
||
var codePoint = Number(arguments[index]);
|
||
if (
|
||
!isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
|
||
codePoint < 0 || // not a valid Unicode code point
|
||
codePoint > 0x10FFFF || // not a valid Unicode code point
|
||
floor(codePoint) !== codePoint // not an integer
|
||
) {
|
||
throw RangeError('Invalid code point: ' + codePoint)
|
||
}
|
||
if (codePoint <= 0xFFFF) { // BMP code point
|
||
codeUnits.push(codePoint);
|
||
} else { // Astral code point; split in surrogate halves
|
||
// http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
|
||
codePoint -= 0x10000;
|
||
highSurrogate = (codePoint >> 10) + 0xD800;
|
||
lowSurrogate = (codePoint % 0x400) + 0xDC00;
|
||
codeUnits.push(highSurrogate, lowSurrogate);
|
||
}
|
||
if (index + 1 === length || codeUnits.length > MAX_SIZE) {
|
||
result += stringFromCharCode.apply(null, codeUnits);
|
||
codeUnits.length = 0;
|
||
}
|
||
}
|
||
return result
|
||
};
|
||
/* istanbul ignore next */
|
||
if (Object.defineProperty) {
|
||
Object.defineProperty(String, 'fromCodePoint', {
|
||
value: fromCodePoint,
|
||
configurable: true,
|
||
writable: true
|
||
});
|
||
} else {
|
||
String.fromCodePoint = fromCodePoint;
|
||
}
|
||
}());
|
||
}
|
||
})(exports);
|
||
} (sax));
|
||
|
||
var __importDefault$1 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
|
||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||
};
|
||
Object.defineProperty(sitemapParser, "__esModule", { value: true });
|
||
sitemapParser.ObjectStreamToJSON = sitemapParser.parseSitemap = sitemapParser.XMLToSitemapItemStream = void 0;
|
||
const sax_1$1 = __importDefault$1(sax);
|
||
const stream_1$1 = require$$0$3;
|
||
const types_1$1 = types;
|
||
function isValidTagName$1(tagName) {
|
||
// This only works because the enum name and value are the same
|
||
return tagName in types_1$1.TagNames;
|
||
}
|
||
function tagTemplate$1() {
|
||
return {
|
||
img: [],
|
||
video: [],
|
||
links: [],
|
||
url: '',
|
||
};
|
||
}
|
||
function videoTemplate() {
|
||
return {
|
||
tag: [],
|
||
thumbnail_loc: '',
|
||
title: '',
|
||
description: '',
|
||
};
|
||
}
|
||
const imageTemplate = {
|
||
url: '',
|
||
};
|
||
const linkTemplate = {
|
||
lang: '',
|
||
url: '',
|
||
};
|
||
function newsTemplate() {
|
||
return {
|
||
publication: { name: '', language: '' },
|
||
publication_date: '',
|
||
title: '',
|
||
};
|
||
}
|
||
const defaultLogger$1 = (level, ...message) => console[level](...message);
|
||
const defaultStreamOpts$1 = {
|
||
logger: defaultLogger$1,
|
||
};
|
||
// TODO does this need to end with `options`
|
||
/**
|
||
* Takes a stream of xml and transforms it into a stream of SitemapItems
|
||
* Use this to parse existing sitemaps into config options compatible with this library
|
||
*/
|
||
class XMLToSitemapItemStream extends stream_1$1.Transform {
|
||
constructor(opts = defaultStreamOpts$1) {
|
||
var _a;
|
||
opts.objectMode = true;
|
||
super(opts);
|
||
this.error = null;
|
||
this.saxStream = sax_1$1.default.createStream(true, {
|
||
xmlns: true,
|
||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||
// @ts-ignore
|
||
strictEntities: true,
|
||
trim: true,
|
||
});
|
||
this.level = opts.level || types_1$1.ErrorLevel.WARN;
|
||
if (this.level !== types_1$1.ErrorLevel.SILENT && opts.logger !== false) {
|
||
this.logger = (_a = opts.logger) !== null && _a !== void 0 ? _a : defaultLogger$1;
|
||
}
|
||
else {
|
||
this.logger = () => undefined;
|
||
}
|
||
let currentItem = tagTemplate$1();
|
||
let currentTag;
|
||
let currentVideo = videoTemplate();
|
||
let currentImage = { ...imageTemplate };
|
||
let currentLink = { ...linkTemplate };
|
||
let dontpushCurrentLink = false;
|
||
this.saxStream.on('opentagstart', (tag) => {
|
||
currentTag = tag.name;
|
||
if (currentTag.startsWith('news:') && !currentItem.news) {
|
||
currentItem.news = newsTemplate();
|
||
}
|
||
});
|
||
this.saxStream.on('opentag', (tag) => {
|
||
if (isValidTagName$1(tag.name)) {
|
||
if (tag.name === 'xhtml:link') {
|
||
if (typeof tag.attributes.rel === 'string' ||
|
||
typeof tag.attributes.href === 'string') {
|
||
return;
|
||
}
|
||
if (tag.attributes.rel.value === 'alternate' &&
|
||
tag.attributes.hreflang) {
|
||
currentLink.url = tag.attributes.href.value;
|
||
if (typeof tag.attributes.hreflang === 'string')
|
||
return;
|
||
currentLink.lang = tag.attributes.hreflang.value;
|
||
}
|
||
else if (tag.attributes.rel.value === 'alternate') {
|
||
dontpushCurrentLink = true;
|
||
currentItem.androidLink = tag.attributes.href.value;
|
||
}
|
||
else if (tag.attributes.rel.value === 'amphtml') {
|
||
dontpushCurrentLink = true;
|
||
currentItem.ampLink = tag.attributes.href.value;
|
||
}
|
||
else {
|
||
this.logger('log', 'unhandled attr for xhtml:link', tag.attributes);
|
||
this.err(`unhandled attr for xhtml:link ${tag.attributes}`);
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
this.logger('warn', 'unhandled tag', tag.name);
|
||
this.err(`unhandled tag: ${tag.name}`);
|
||
}
|
||
});
|
||
this.saxStream.on('text', (text) => {
|
||
switch (currentTag) {
|
||
case 'mobile:mobile':
|
||
break;
|
||
case types_1$1.TagNames.loc:
|
||
currentItem.url = text;
|
||
break;
|
||
case types_1$1.TagNames.changefreq:
|
||
if ((0, types_1$1.isValidChangeFreq)(text)) {
|
||
currentItem.changefreq = text;
|
||
}
|
||
break;
|
||
case types_1$1.TagNames.priority:
|
||
currentItem.priority = parseFloat(text);
|
||
break;
|
||
case types_1$1.TagNames.lastmod:
|
||
currentItem.lastmod = text;
|
||
break;
|
||
case types_1$1.TagNames['video:thumbnail_loc']:
|
||
currentVideo.thumbnail_loc = text;
|
||
break;
|
||
case types_1$1.TagNames['video:tag']:
|
||
currentVideo.tag.push(text);
|
||
break;
|
||
case types_1$1.TagNames['video:duration']:
|
||
currentVideo.duration = parseInt(text, 10);
|
||
break;
|
||
case types_1$1.TagNames['video:player_loc']:
|
||
currentVideo.player_loc = text;
|
||
break;
|
||
case types_1$1.TagNames['video:content_loc']:
|
||
currentVideo.content_loc = text;
|
||
break;
|
||
case types_1$1.TagNames['video:requires_subscription']:
|
||
if ((0, types_1$1.isValidYesNo)(text)) {
|
||
currentVideo.requires_subscription = text;
|
||
}
|
||
break;
|
||
case types_1$1.TagNames['video:publication_date']:
|
||
currentVideo.publication_date = text;
|
||
break;
|
||
case types_1$1.TagNames['video:id']:
|
||
currentVideo.id = text;
|
||
break;
|
||
case types_1$1.TagNames['video:restriction']:
|
||
currentVideo.restriction = text;
|
||
break;
|
||
case types_1$1.TagNames['video:view_count']:
|
||
currentVideo.view_count = parseInt(text, 10);
|
||
break;
|
||
case types_1$1.TagNames['video:uploader']:
|
||
currentVideo.uploader = text;
|
||
break;
|
||
case types_1$1.TagNames['video:family_friendly']:
|
||
if ((0, types_1$1.isValidYesNo)(text)) {
|
||
currentVideo.family_friendly = text;
|
||
}
|
||
break;
|
||
case types_1$1.TagNames['video:expiration_date']:
|
||
currentVideo.expiration_date = text;
|
||
break;
|
||
case types_1$1.TagNames['video:platform']:
|
||
currentVideo.platform = text;
|
||
break;
|
||
case types_1$1.TagNames['video:price']:
|
||
currentVideo.price = text;
|
||
break;
|
||
case types_1$1.TagNames['video:rating']:
|
||
currentVideo.rating = parseFloat(text);
|
||
break;
|
||
case types_1$1.TagNames['video:category']:
|
||
currentVideo.category = text;
|
||
break;
|
||
case types_1$1.TagNames['video:live']:
|
||
if ((0, types_1$1.isValidYesNo)(text)) {
|
||
currentVideo.live = text;
|
||
}
|
||
break;
|
||
case types_1$1.TagNames['video:gallery_loc']:
|
||
currentVideo.gallery_loc = text;
|
||
break;
|
||
case types_1$1.TagNames['image:loc']:
|
||
currentImage.url = text;
|
||
break;
|
||
case types_1$1.TagNames['image:geo_location']:
|
||
currentImage.geoLocation = text;
|
||
break;
|
||
case types_1$1.TagNames['image:license']:
|
||
currentImage.license = text;
|
||
break;
|
||
case types_1$1.TagNames['news:access']:
|
||
if (!currentItem.news) {
|
||
currentItem.news = newsTemplate();
|
||
}
|
||
currentItem.news.access = text;
|
||
break;
|
||
case types_1$1.TagNames['news:genres']:
|
||
if (!currentItem.news) {
|
||
currentItem.news = newsTemplate();
|
||
}
|
||
currentItem.news.genres = text;
|
||
break;
|
||
case types_1$1.TagNames['news:publication_date']:
|
||
if (!currentItem.news) {
|
||
currentItem.news = newsTemplate();
|
||
}
|
||
currentItem.news.publication_date = text;
|
||
break;
|
||
case types_1$1.TagNames['news:keywords']:
|
||
if (!currentItem.news) {
|
||
currentItem.news = newsTemplate();
|
||
}
|
||
currentItem.news.keywords = text;
|
||
break;
|
||
case types_1$1.TagNames['news:stock_tickers']:
|
||
if (!currentItem.news) {
|
||
currentItem.news = newsTemplate();
|
||
}
|
||
currentItem.news.stock_tickers = text;
|
||
break;
|
||
case types_1$1.TagNames['news:language']:
|
||
if (!currentItem.news) {
|
||
currentItem.news = newsTemplate();
|
||
}
|
||
currentItem.news.publication.language = text;
|
||
break;
|
||
case types_1$1.TagNames['video:title']:
|
||
currentVideo.title += text;
|
||
break;
|
||
case types_1$1.TagNames['video:description']:
|
||
currentVideo.description += text;
|
||
break;
|
||
case types_1$1.TagNames['news:name']:
|
||
if (!currentItem.news) {
|
||
currentItem.news = newsTemplate();
|
||
}
|
||
currentItem.news.publication.name += text;
|
||
break;
|
||
case types_1$1.TagNames['news:title']:
|
||
if (!currentItem.news) {
|
||
currentItem.news = newsTemplate();
|
||
}
|
||
currentItem.news.title += text;
|
||
break;
|
||
case types_1$1.TagNames['image:caption']:
|
||
if (!currentImage.caption) {
|
||
currentImage.caption = text;
|
||
}
|
||
else {
|
||
currentImage.caption += text;
|
||
}
|
||
break;
|
||
case types_1$1.TagNames['image:title']:
|
||
if (!currentImage.title) {
|
||
currentImage.title = text;
|
||
}
|
||
else {
|
||
currentImage.title += text;
|
||
}
|
||
break;
|
||
default:
|
||
this.logger('log', 'unhandled text for tag:', currentTag, `'${text}'`);
|
||
this.err(`unhandled text for tag: ${currentTag} '${text}'`);
|
||
break;
|
||
}
|
||
});
|
||
this.saxStream.on('cdata', (text) => {
|
||
switch (currentTag) {
|
||
case types_1$1.TagNames['video:title']:
|
||
currentVideo.title += text;
|
||
break;
|
||
case types_1$1.TagNames['video:description']:
|
||
currentVideo.description += text;
|
||
break;
|
||
case types_1$1.TagNames['news:name']:
|
||
if (!currentItem.news) {
|
||
currentItem.news = newsTemplate();
|
||
}
|
||
currentItem.news.publication.name += text;
|
||
break;
|
||
case types_1$1.TagNames['news:title']:
|
||
if (!currentItem.news) {
|
||
currentItem.news = newsTemplate();
|
||
}
|
||
currentItem.news.title += text;
|
||
break;
|
||
case types_1$1.TagNames['image:caption']:
|
||
if (!currentImage.caption) {
|
||
currentImage.caption = text;
|
||
}
|
||
else {
|
||
currentImage.caption += text;
|
||
}
|
||
break;
|
||
case types_1$1.TagNames['image:title']:
|
||
if (!currentImage.title) {
|
||
currentImage.title = text;
|
||
}
|
||
else {
|
||
currentImage.title += text;
|
||
}
|
||
break;
|
||
default:
|
||
this.logger('log', 'unhandled cdata for tag:', currentTag);
|
||
this.err(`unhandled cdata for tag: ${currentTag}`);
|
||
break;
|
||
}
|
||
});
|
||
this.saxStream.on('attribute', (attr) => {
|
||
switch (currentTag) {
|
||
case types_1$1.TagNames['urlset']:
|
||
case types_1$1.TagNames['xhtml:link']:
|
||
case types_1$1.TagNames['video:id']:
|
||
break;
|
||
case types_1$1.TagNames['video:restriction']:
|
||
if (attr.name === 'relationship' && (0, types_1$1.isAllowDeny)(attr.value)) {
|
||
currentVideo['restriction:relationship'] = attr.value;
|
||
}
|
||
else {
|
||
this.logger('log', 'unhandled attr', currentTag, attr.name);
|
||
this.err(`unhandled attr: ${currentTag} ${attr.name}`);
|
||
}
|
||
break;
|
||
case types_1$1.TagNames['video:price']:
|
||
if (attr.name === 'type' && (0, types_1$1.isPriceType)(attr.value)) {
|
||
currentVideo['price:type'] = attr.value;
|
||
}
|
||
else if (attr.name === 'currency') {
|
||
currentVideo['price:currency'] = attr.value;
|
||
}
|
||
else if (attr.name === 'resolution' && (0, types_1$1.isResolution)(attr.value)) {
|
||
currentVideo['price:resolution'] = attr.value;
|
||
}
|
||
else {
|
||
this.logger('log', 'unhandled attr for video:price', attr.name);
|
||
this.err(`unhandled attr: ${currentTag} ${attr.name}`);
|
||
}
|
||
break;
|
||
case types_1$1.TagNames['video:player_loc']:
|
||
if (attr.name === 'autoplay') {
|
||
currentVideo['player_loc:autoplay'] = attr.value;
|
||
}
|
||
else if (attr.name === 'allow_embed' && (0, types_1$1.isValidYesNo)(attr.value)) {
|
||
currentVideo['player_loc:allow_embed'] = attr.value;
|
||
}
|
||
else {
|
||
this.logger('log', 'unhandled attr for video:player_loc', attr.name);
|
||
this.err(`unhandled attr: ${currentTag} ${attr.name}`);
|
||
}
|
||
break;
|
||
case types_1$1.TagNames['video:platform']:
|
||
if (attr.name === 'relationship' && (0, types_1$1.isAllowDeny)(attr.value)) {
|
||
currentVideo['platform:relationship'] = attr.value;
|
||
}
|
||
else {
|
||
this.logger('log', 'unhandled attr for video:platform', attr.name, attr.value);
|
||
this.err(`unhandled attr: ${currentTag} ${attr.name} ${attr.value}`);
|
||
}
|
||
break;
|
||
case types_1$1.TagNames['video:gallery_loc']:
|
||
if (attr.name === 'title') {
|
||
currentVideo['gallery_loc:title'] = attr.value;
|
||
}
|
||
else {
|
||
this.logger('log', 'unhandled attr for video:galler_loc', attr.name);
|
||
this.err(`unhandled attr: ${currentTag} ${attr.name}`);
|
||
}
|
||
break;
|
||
case types_1$1.TagNames['video:uploader']:
|
||
if (attr.name === 'info') {
|
||
currentVideo['uploader:info'] = attr.value;
|
||
}
|
||
else {
|
||
this.logger('log', 'unhandled attr for video:uploader', attr.name);
|
||
this.err(`unhandled attr: ${currentTag} ${attr.name}`);
|
||
}
|
||
break;
|
||
default:
|
||
this.logger('log', 'unhandled attr', currentTag, attr.name);
|
||
this.err(`unhandled attr: ${currentTag} ${attr.name}`);
|
||
}
|
||
});
|
||
this.saxStream.on('closetag', (tag) => {
|
||
switch (tag) {
|
||
case types_1$1.TagNames.url:
|
||
this.push(currentItem);
|
||
currentItem = tagTemplate$1();
|
||
break;
|
||
case types_1$1.TagNames['video:video']:
|
||
currentItem.video.push(currentVideo);
|
||
currentVideo = videoTemplate();
|
||
break;
|
||
case types_1$1.TagNames['image:image']:
|
||
currentItem.img.push(currentImage);
|
||
currentImage = { ...imageTemplate };
|
||
break;
|
||
case types_1$1.TagNames['xhtml:link']:
|
||
if (!dontpushCurrentLink) {
|
||
currentItem.links.push(currentLink);
|
||
}
|
||
currentLink = { ...linkTemplate };
|
||
break;
|
||
}
|
||
});
|
||
}
|
||
_transform(data, encoding, callback) {
|
||
try {
|
||
// correcting the type here can be done without making it a breaking change
|
||
// TODO fix this
|
||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||
// @ts-ignore
|
||
this.saxStream.write(data, encoding);
|
||
callback(this.level === types_1$1.ErrorLevel.THROW ? this.error : null);
|
||
}
|
||
catch (error) {
|
||
callback(error);
|
||
}
|
||
}
|
||
err(msg) {
|
||
if (!this.error)
|
||
this.error = new Error(msg);
|
||
}
|
||
}
|
||
sitemapParser.XMLToSitemapItemStream = XMLToSitemapItemStream;
|
||
/**
|
||
Read xml and resolve with the configuration that would produce it or reject with
|
||
an error
|
||
```
|
||
const { createReadStream } = require('fs')
|
||
const { parseSitemap, createSitemap } = require('sitemap')
|
||
parseSitemap(createReadStream('./example.xml')).then(
|
||
// produces the same xml
|
||
// you can, of course, more practically modify it or store it
|
||
(xmlConfig) => console.log(createSitemap(xmlConfig).toString()),
|
||
(err) => console.log(err)
|
||
)
|
||
```
|
||
@param {Readable} xml what to parse
|
||
@return {Promise<SitemapItem[]>} resolves with list of sitemap items that can be fed into a SitemapStream. Rejects with an Error object.
|
||
*/
|
||
async function parseSitemap(xml) {
|
||
const urls = [];
|
||
return new Promise((resolve, reject) => {
|
||
xml
|
||
.pipe(new XMLToSitemapItemStream())
|
||
.on('data', (smi) => urls.push(smi))
|
||
.on('end', () => {
|
||
resolve(urls);
|
||
})
|
||
.on('error', (error) => {
|
||
reject(error);
|
||
});
|
||
});
|
||
}
|
||
sitemapParser.parseSitemap = parseSitemap;
|
||
const defaultObjectStreamOpts$1 = {
|
||
lineSeparated: false,
|
||
};
|
||
/**
|
||
* A Transform that converts a stream of objects into a JSON Array or a line
|
||
* separated stringified JSON
|
||
* @param [lineSeparated=false] whether to separate entries by a new line or comma
|
||
*/
|
||
class ObjectStreamToJSON extends stream_1$1.Transform {
|
||
constructor(opts = defaultObjectStreamOpts$1) {
|
||
opts.writableObjectMode = true;
|
||
super(opts);
|
||
this.lineSeparated = opts.lineSeparated;
|
||
this.firstWritten = false;
|
||
}
|
||
_transform(chunk, encoding, cb) {
|
||
if (!this.firstWritten) {
|
||
this.firstWritten = true;
|
||
if (!this.lineSeparated) {
|
||
this.push('[');
|
||
}
|
||
}
|
||
else if (this.lineSeparated) {
|
||
this.push('\n');
|
||
}
|
||
else {
|
||
this.push(',');
|
||
}
|
||
if (chunk) {
|
||
this.push(JSON.stringify(chunk));
|
||
}
|
||
cb();
|
||
}
|
||
_flush(cb) {
|
||
if (!this.lineSeparated) {
|
||
this.push(']');
|
||
}
|
||
cb();
|
||
}
|
||
}
|
||
sitemapParser.ObjectStreamToJSON = ObjectStreamToJSON;
|
||
|
||
var sitemapIndexParser = {};
|
||
|
||
var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
|
||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||
};
|
||
Object.defineProperty(sitemapIndexParser, "__esModule", { value: true });
|
||
sitemapIndexParser.IndexObjectStreamToJSON = sitemapIndexParser.parseSitemapIndex = sitemapIndexParser.XMLToSitemapIndexStream = void 0;
|
||
const sax_1 = __importDefault(sax);
|
||
const stream_1 = require$$0$3;
|
||
const types_1 = types;
|
||
function isValidTagName(tagName) {
|
||
// This only works because the enum name and value are the same
|
||
return tagName in types_1.IndexTagNames;
|
||
}
|
||
function tagTemplate() {
|
||
return {
|
||
url: '',
|
||
};
|
||
}
|
||
const defaultLogger = (level, ...message) => console[level](...message);
|
||
const defaultStreamOpts = {
|
||
logger: defaultLogger,
|
||
};
|
||
// TODO does this need to end with `options`
|
||
/**
|
||
* Takes a stream of xml and transforms it into a stream of IndexItems
|
||
* Use this to parse existing sitemap indices into config options compatible with this library
|
||
*/
|
||
class XMLToSitemapIndexStream extends stream_1.Transform {
|
||
constructor(opts = defaultStreamOpts) {
|
||
var _a;
|
||
opts.objectMode = true;
|
||
super(opts);
|
||
this.saxStream = sax_1.default.createStream(true, {
|
||
xmlns: true,
|
||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||
// @ts-ignore
|
||
strictEntities: true,
|
||
trim: true,
|
||
});
|
||
this.level = opts.level || types_1.ErrorLevel.WARN;
|
||
if (this.level !== types_1.ErrorLevel.SILENT && opts.logger !== false) {
|
||
this.logger = (_a = opts.logger) !== null && _a !== void 0 ? _a : defaultLogger;
|
||
}
|
||
else {
|
||
this.logger = () => undefined;
|
||
}
|
||
let currentItem = tagTemplate();
|
||
let currentTag;
|
||
this.saxStream.on('opentagstart', (tag) => {
|
||
currentTag = tag.name;
|
||
});
|
||
this.saxStream.on('opentag', (tag) => {
|
||
if (!isValidTagName(tag.name)) {
|
||
this.logger('warn', 'unhandled tag', tag.name);
|
||
}
|
||
});
|
||
this.saxStream.on('text', (text) => {
|
||
switch (currentTag) {
|
||
case types_1.IndexTagNames.loc:
|
||
currentItem.url = text;
|
||
break;
|
||
case types_1.IndexTagNames.lastmod:
|
||
currentItem.lastmod = text;
|
||
break;
|
||
default:
|
||
this.logger('log', 'unhandled text for tag:', currentTag, `'${text}'`);
|
||
break;
|
||
}
|
||
});
|
||
this.saxStream.on('cdata', (_text) => {
|
||
switch (currentTag) {
|
||
default:
|
||
this.logger('log', 'unhandled cdata for tag:', currentTag);
|
||
break;
|
||
}
|
||
});
|
||
this.saxStream.on('attribute', (attr) => {
|
||
switch (currentTag) {
|
||
case types_1.IndexTagNames.sitemapindex:
|
||
break;
|
||
default:
|
||
this.logger('log', 'unhandled attr', currentTag, attr.name);
|
||
}
|
||
});
|
||
this.saxStream.on('closetag', (tag) => {
|
||
switch (tag) {
|
||
case types_1.IndexTagNames.sitemap:
|
||
this.push(currentItem);
|
||
currentItem = tagTemplate();
|
||
break;
|
||
}
|
||
});
|
||
}
|
||
_transform(data, encoding, callback) {
|
||
try {
|
||
// correcting the type here can be done without making it a breaking change
|
||
// TODO fix this
|
||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||
// @ts-ignore
|
||
this.saxStream.write(data, encoding);
|
||
callback();
|
||
}
|
||
catch (error) {
|
||
callback(error);
|
||
}
|
||
}
|
||
}
|
||
sitemapIndexParser.XMLToSitemapIndexStream = XMLToSitemapIndexStream;
|
||
/**
|
||
Read xml and resolve with the configuration that would produce it or reject with
|
||
an error
|
||
```
|
||
const { createReadStream } = require('fs')
|
||
const { parseSitemapIndex, createSitemap } = require('sitemap')
|
||
parseSitemapIndex(createReadStream('./example-index.xml')).then(
|
||
// produces the same xml
|
||
// you can, of course, more practically modify it or store it
|
||
(xmlConfig) => console.log(createSitemap(xmlConfig).toString()),
|
||
(err) => console.log(err)
|
||
)
|
||
```
|
||
@param {Readable} xml what to parse
|
||
@return {Promise<IndexItem[]>} resolves with list of index items that can be fed into a SitemapIndexStream. Rejects with an Error object.
|
||
*/
|
||
async function parseSitemapIndex(xml) {
|
||
const urls = [];
|
||
return new Promise((resolve, reject) => {
|
||
xml
|
||
.pipe(new XMLToSitemapIndexStream())
|
||
.on('data', (smi) => urls.push(smi))
|
||
.on('end', () => {
|
||
resolve(urls);
|
||
})
|
||
.on('error', (error) => {
|
||
reject(error);
|
||
});
|
||
});
|
||
}
|
||
sitemapIndexParser.parseSitemapIndex = parseSitemapIndex;
|
||
const defaultObjectStreamOpts = {
|
||
lineSeparated: false,
|
||
};
|
||
/**
|
||
* A Transform that converts a stream of objects into a JSON Array or a line
|
||
* separated stringified JSON
|
||
* @param [lineSeparated=false] whether to separate entries by a new line or comma
|
||
*/
|
||
class IndexObjectStreamToJSON extends stream_1.Transform {
|
||
constructor(opts = defaultObjectStreamOpts) {
|
||
opts.writableObjectMode = true;
|
||
super(opts);
|
||
this.lineSeparated = opts.lineSeparated;
|
||
this.firstWritten = false;
|
||
}
|
||
_transform(chunk, encoding, cb) {
|
||
if (!this.firstWritten) {
|
||
this.firstWritten = true;
|
||
if (!this.lineSeparated) {
|
||
this.push('[');
|
||
}
|
||
}
|
||
else if (this.lineSeparated) {
|
||
this.push('\n');
|
||
}
|
||
else {
|
||
this.push(',');
|
||
}
|
||
if (chunk) {
|
||
this.push(JSON.stringify(chunk));
|
||
}
|
||
cb();
|
||
}
|
||
_flush(cb) {
|
||
if (!this.lineSeparated) {
|
||
this.push(']');
|
||
}
|
||
cb();
|
||
}
|
||
}
|
||
sitemapIndexParser.IndexObjectStreamToJSON = IndexObjectStreamToJSON;
|
||
|
||
var sitemapSimple = {};
|
||
|
||
var hasRequiredSitemapSimple;
|
||
|
||
function requireSitemapSimple () {
|
||
if (hasRequiredSitemapSimple) return sitemapSimple;
|
||
hasRequiredSitemapSimple = 1;
|
||
(function (exports) {
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.simpleSitemapAndIndex = void 0;
|
||
const index_1 = requireDist();
|
||
const zlib_1 = require$$1$1;
|
||
const fs_1 = fs__default;
|
||
const path_1 = path$q;
|
||
const stream_1 = require$$0$3;
|
||
const util_1 = require$$0$4;
|
||
const url_1 = require$$3;
|
||
const pipeline = (0, util_1.promisify)(stream_1.pipeline);
|
||
/**
|
||
*
|
||
* @param {object} options -
|
||
* @param {string} options.hostname - The hostname for all URLs
|
||
* @param {string} [options.sitemapHostname] - The hostname for the sitemaps if different than hostname
|
||
* @param {SitemapItemLoose[] | string | Readable | string[]} options.sourceData - The urls you want to make a sitemap out of.
|
||
* @param {string} options.destinationDir - where to write the sitemaps and index
|
||
* @param {string} [options.publicBasePath] - where the sitemaps are relative to the hostname. Defaults to root.
|
||
* @param {number} [options.limit] - how many URLs to write before switching to a new file. Defaults to 50k
|
||
* @param {boolean} [options.gzip] - whether to compress the written files. Defaults to true
|
||
* @returns {Promise<void>} an empty promise that resolves when everything is done
|
||
*/
|
||
const simpleSitemapAndIndex = async ({ hostname, sitemapHostname = hostname, // if different
|
||
/**
|
||
* Pass a line separated list of sitemap items or a stream or an array
|
||
*/
|
||
sourceData, destinationDir, limit = 50000, gzip = true, publicBasePath = './', }) => {
|
||
await fs_1.promises.mkdir(destinationDir, { recursive: true });
|
||
const sitemapAndIndexStream = new index_1.SitemapAndIndexStream({
|
||
limit,
|
||
getSitemapStream: (i) => {
|
||
const sitemapStream = new index_1.SitemapStream({
|
||
hostname,
|
||
});
|
||
const path = `./sitemap-${i}.xml`;
|
||
const writePath = (0, path_1.resolve)(destinationDir, path + (gzip ? '.gz' : ''));
|
||
if (!publicBasePath.endsWith('/')) {
|
||
publicBasePath += '/';
|
||
}
|
||
const publicPath = (0, path_1.normalize)(publicBasePath + path);
|
||
let pipeline;
|
||
if (gzip) {
|
||
pipeline = sitemapStream
|
||
.pipe((0, zlib_1.createGzip)()) // compress the output of the sitemap
|
||
.pipe((0, fs_1.createWriteStream)(writePath)); // write it to sitemap-NUMBER.xml
|
||
}
|
||
else {
|
||
pipeline = sitemapStream.pipe((0, fs_1.createWriteStream)(writePath)); // write it to sitemap-NUMBER.xml
|
||
}
|
||
return [
|
||
new url_1.URL(`${publicPath}${gzip ? '.gz' : ''}`, sitemapHostname).toString(),
|
||
sitemapStream,
|
||
pipeline,
|
||
];
|
||
},
|
||
});
|
||
let src;
|
||
if (typeof sourceData === 'string') {
|
||
src = (0, index_1.lineSeparatedURLsToSitemapOptions)((0, fs_1.createReadStream)(sourceData));
|
||
}
|
||
else if (sourceData instanceof stream_1.Readable) {
|
||
src = sourceData;
|
||
}
|
||
else if (Array.isArray(sourceData)) {
|
||
src = stream_1.Readable.from(sourceData);
|
||
}
|
||
else {
|
||
throw new Error("unhandled source type. You've passed in data that is not supported");
|
||
}
|
||
const writePath = (0, path_1.resolve)(destinationDir, `./sitemap-index.xml${gzip ? '.gz' : ''}`);
|
||
if (gzip) {
|
||
return pipeline(src, sitemapAndIndexStream, (0, zlib_1.createGzip)(), (0, fs_1.createWriteStream)(writePath));
|
||
}
|
||
else {
|
||
return pipeline(src, sitemapAndIndexStream, (0, fs_1.createWriteStream)(writePath));
|
||
}
|
||
};
|
||
exports.simpleSitemapAndIndex = simpleSitemapAndIndex;
|
||
exports.default = exports.simpleSitemapAndIndex;
|
||
} (sitemapSimple));
|
||
return sitemapSimple;
|
||
}
|
||
|
||
var hasRequiredDist;
|
||
|
||
function requireDist () {
|
||
if (hasRequiredDist) return dist;
|
||
hasRequiredDist = 1;
|
||
(function (exports) {
|
||
var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||
if (k2 === undefined) k2 = k;
|
||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||
}) : (function(o, m, k, k2) {
|
||
if (k2 === undefined) k2 = k;
|
||
o[k2] = m[k];
|
||
}));
|
||
var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) {
|
||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||
};
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.simpleSitemapAndIndex = exports.IndexObjectStreamToJSON = exports.XMLToSitemapIndexStream = exports.parseSitemapIndex = exports.ObjectStreamToJSON = exports.XMLToSitemapItemStream = exports.parseSitemap = exports.xmlLint = exports.ReadlineStream = exports.normalizeURL = exports.validateSMIOptions = exports.mergeStreams = exports.lineSeparatedURLsToSitemapOptions = exports.SitemapStream = exports.streamToPromise = exports.SitemapAndIndexStream = exports.SitemapIndexStream = exports.IndexTagNames = exports.SitemapItemStream = void 0;
|
||
/*!
|
||
* Sitemap
|
||
* Copyright(c) 2011 Eugene Kalinin
|
||
* MIT Licensed
|
||
*/
|
||
var sitemap_item_stream_1 = sitemapItemStream;
|
||
Object.defineProperty(exports, "SitemapItemStream", { enumerable: true, get: function () { return sitemap_item_stream_1.SitemapItemStream; } });
|
||
var sitemap_index_stream_1 = sitemapIndexStream;
|
||
Object.defineProperty(exports, "IndexTagNames", { enumerable: true, get: function () { return sitemap_index_stream_1.IndexTagNames; } });
|
||
Object.defineProperty(exports, "SitemapIndexStream", { enumerable: true, get: function () { return sitemap_index_stream_1.SitemapIndexStream; } });
|
||
Object.defineProperty(exports, "SitemapAndIndexStream", { enumerable: true, get: function () { return sitemap_index_stream_1.SitemapAndIndexStream; } });
|
||
var sitemap_stream_1 = sitemapStream;
|
||
Object.defineProperty(exports, "streamToPromise", { enumerable: true, get: function () { return sitemap_stream_1.streamToPromise; } });
|
||
Object.defineProperty(exports, "SitemapStream", { enumerable: true, get: function () { return sitemap_stream_1.SitemapStream; } });
|
||
__exportStar(errors, exports);
|
||
__exportStar(types, exports);
|
||
var utils_1 = utils;
|
||
Object.defineProperty(exports, "lineSeparatedURLsToSitemapOptions", { enumerable: true, get: function () { return utils_1.lineSeparatedURLsToSitemapOptions; } });
|
||
Object.defineProperty(exports, "mergeStreams", { enumerable: true, get: function () { return utils_1.mergeStreams; } });
|
||
Object.defineProperty(exports, "validateSMIOptions", { enumerable: true, get: function () { return utils_1.validateSMIOptions; } });
|
||
Object.defineProperty(exports, "normalizeURL", { enumerable: true, get: function () { return utils_1.normalizeURL; } });
|
||
Object.defineProperty(exports, "ReadlineStream", { enumerable: true, get: function () { return utils_1.ReadlineStream; } });
|
||
var xmllint_1 = xmllint;
|
||
Object.defineProperty(exports, "xmlLint", { enumerable: true, get: function () { return xmllint_1.xmlLint; } });
|
||
var sitemap_parser_1 = sitemapParser;
|
||
Object.defineProperty(exports, "parseSitemap", { enumerable: true, get: function () { return sitemap_parser_1.parseSitemap; } });
|
||
Object.defineProperty(exports, "XMLToSitemapItemStream", { enumerable: true, get: function () { return sitemap_parser_1.XMLToSitemapItemStream; } });
|
||
Object.defineProperty(exports, "ObjectStreamToJSON", { enumerable: true, get: function () { return sitemap_parser_1.ObjectStreamToJSON; } });
|
||
var sitemap_index_parser_1 = sitemapIndexParser;
|
||
Object.defineProperty(exports, "parseSitemapIndex", { enumerable: true, get: function () { return sitemap_index_parser_1.parseSitemapIndex; } });
|
||
Object.defineProperty(exports, "XMLToSitemapIndexStream", { enumerable: true, get: function () { return sitemap_index_parser_1.XMLToSitemapIndexStream; } });
|
||
Object.defineProperty(exports, "IndexObjectStreamToJSON", { enumerable: true, get: function () { return sitemap_index_parser_1.IndexObjectStreamToJSON; } });
|
||
var sitemap_simple_1 = requireSitemapSimple();
|
||
Object.defineProperty(exports, "simpleSitemapAndIndex", { enumerable: true, get: function () { return sitemap_simple_1.simpleSitemapAndIndex; } });
|
||
} (dist));
|
||
return dist;
|
||
}
|
||
|
||
var distExports = requireDist();
|
||
|
||
async function generateSitemap(siteConfig) {
|
||
if (!siteConfig.sitemap?.hostname)
|
||
return;
|
||
const getLastmod = async (url) => {
|
||
if (!siteConfig.lastUpdated)
|
||
return void 0;
|
||
let file = url.replace(/(^|\/)$/, "$1index");
|
||
file = file.replace(/(\.html)?$/, ".md");
|
||
file = siteConfig.rewrites.inv[file] || file;
|
||
file = path$q.join(siteConfig.srcDir, file);
|
||
return await getGitTimestamp(file) || void 0;
|
||
};
|
||
await task("generating sitemap", async () => {
|
||
const locales = siteConfig.userConfig.locales || {};
|
||
const filteredLocales = Object.keys(locales).filter(
|
||
(locale) => locales[locale].lang && locale !== "root"
|
||
);
|
||
const defaultLang = locales?.root?.lang || siteConfig.userConfig.lang || "en-US";
|
||
const pages = siteConfig.pages.map(
|
||
(page) => siteConfig.rewrites.map[page] || page
|
||
);
|
||
const groupedPages = {};
|
||
pages.forEach((page) => {
|
||
const locale = page.split("/")[0];
|
||
const lang = locales[locale]?.lang || defaultLang;
|
||
let url = page.replace(/(^|\/)index\.md$/, "$1");
|
||
url = url.replace(/\.md$/, siteConfig.cleanUrls ? "" : ".html");
|
||
if (filteredLocales.includes(locale))
|
||
page = page.slice(locale.length + 1);
|
||
if (!groupedPages[page])
|
||
groupedPages[page] = [];
|
||
groupedPages[page].push({ url, lang });
|
||
});
|
||
const _items = await Promise.all(
|
||
Object.values(groupedPages).map(async (pages2) => {
|
||
if (pages2.length < 2)
|
||
return { url: pages2[0].url, lastmod: await getLastmod(pages2[0].url) };
|
||
return await Promise.all(
|
||
pages2.map(async ({ url }) => {
|
||
return { url, lastmod: await getLastmod(url), links: pages2 };
|
||
})
|
||
);
|
||
})
|
||
);
|
||
let items = _items.flat();
|
||
items = await siteConfig.sitemap?.transformItems?.(items) || items;
|
||
const sitemapStream = new distExports.SitemapStream(siteConfig.sitemap);
|
||
const sitemapPath = path$q.join(siteConfig.outDir, "sitemap.xml");
|
||
const writeStream = fs$a.createWriteStream(sitemapPath);
|
||
sitemapStream.pipe(writeStream);
|
||
items.forEach((item) => sitemapStream.write(item));
|
||
sitemapStream.end();
|
||
});
|
||
}
|
||
|
||
function makeMap(str, expectsLowerCase) {
|
||
const set = new Set(str.split(","));
|
||
return expectsLowerCase ? (val) => set.has(val.toLowerCase()) : (val) => set.has(val);
|
||
}
|
||
|
||
!!(process.env.NODE_ENV !== "production") ? Object.freeze({}) : {};
|
||
!!(process.env.NODE_ENV !== "production") ? Object.freeze([]) : [];
|
||
|
||
const specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;
|
||
const isBooleanAttr = /* @__PURE__ */ makeMap(
|
||
specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,inert,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected`
|
||
);
|
||
|
||
/*!
|
||
* escape-html
|
||
* Copyright(c) 2012-2013 TJ Holowaychuk
|
||
* Copyright(c) 2015 Andreas Lubbe
|
||
* Copyright(c) 2015 Tiancheng "Timothy" Gu
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* Module variables.
|
||
* @private
|
||
*/
|
||
|
||
var matchHtmlRegExp = /["'&<>]/;
|
||
|
||
/**
|
||
* Module exports.
|
||
* @public
|
||
*/
|
||
|
||
var escapeHtml_1 = escapeHtml;
|
||
|
||
/**
|
||
* Escape special characters in the given string of html.
|
||
*
|
||
* @param {string} string The string to escape for inserting into HTML
|
||
* @return {string}
|
||
* @public
|
||
*/
|
||
|
||
function escapeHtml(string) {
|
||
var str = '' + string;
|
||
var match = matchHtmlRegExp.exec(str);
|
||
|
||
if (!match) {
|
||
return str;
|
||
}
|
||
|
||
var escape;
|
||
var html = '';
|
||
var index = 0;
|
||
var lastIndex = 0;
|
||
|
||
for (index = match.index; index < str.length; index++) {
|
||
switch (str.charCodeAt(index)) {
|
||
case 34: // "
|
||
escape = '"';
|
||
break;
|
||
case 38: // &
|
||
escape = '&';
|
||
break;
|
||
case 39: // '
|
||
escape = ''';
|
||
break;
|
||
case 60: // <
|
||
escape = '<';
|
||
break;
|
||
case 62: // >
|
||
escape = '>';
|
||
break;
|
||
default:
|
||
continue;
|
||
}
|
||
|
||
if (lastIndex !== index) {
|
||
html += str.substring(lastIndex, index);
|
||
}
|
||
|
||
lastIndex = index + 1;
|
||
html += escape;
|
||
}
|
||
|
||
return lastIndex !== index
|
||
? html + str.substring(lastIndex, index)
|
||
: html;
|
||
}
|
||
|
||
var escape$1 = /*@__PURE__*/getDefaultExportFromCjs(escapeHtml_1);
|
||
|
||
var version = "1.0.0-rc.35";
|
||
|
||
async function renderPage(render, config, page, result, appChunk, cssChunk, assets, pageToHashMap, metadataScript, additionalHeadTags) {
|
||
const routePath = `/${page.replace(/\.md$/, "")}`;
|
||
const siteData = resolveSiteDataByRoute(config.site, routePath);
|
||
const context = await render(routePath);
|
||
const { content, teleports } = await config.postRender?.(context) ?? context;
|
||
const pageName = sanitizeFileName(page.replace(/\//g, "_"));
|
||
const pageServerJsFileName = pageName + ".js";
|
||
const pageHash = pageToHashMap[pageName.toLowerCase()];
|
||
const pageClientJsFileName = `${config.assetsDir}/${pageName}.${pageHash}.lean.js`;
|
||
let pageData;
|
||
let hasCustom404 = true;
|
||
try {
|
||
const { __pageData } = await import(pathToFileURL(
|
||
path$q.join(config.tempDir, pageServerJsFileName)
|
||
).toString() + "?t=" + Date.now());
|
||
pageData = __pageData;
|
||
} catch (e) {
|
||
if (page === "404.md") {
|
||
hasCustom404 = false;
|
||
pageData = notFoundPageData;
|
||
} else {
|
||
throw e;
|
||
}
|
||
}
|
||
const title = createTitle(siteData, pageData);
|
||
const description = pageData.description || siteData.description;
|
||
const stylesheetLink = cssChunk ? `<link rel="preload stylesheet" href="${siteData.base}${cssChunk.fileName}" as="style">` : "";
|
||
let preloadLinks = config.mpa || !hasCustom404 && page === "404.md" ? [] : result && appChunk ? [
|
||
.../* @__PURE__ */ new Set([
|
||
// resolve imports for index.js + page.md.js and inject script tags
|
||
// for them as well so we fetch everything as early as possible
|
||
// without having to wait for entry chunks to parse
|
||
...resolvePageImports(config, page, result, appChunk),
|
||
pageClientJsFileName
|
||
])
|
||
] : [];
|
||
let prefetchLinks = [];
|
||
const { shouldPreload } = config;
|
||
if (shouldPreload) {
|
||
prefetchLinks = preloadLinks.filter((link) => !shouldPreload(link, page));
|
||
preloadLinks = preloadLinks.filter((link) => shouldPreload(link, page));
|
||
}
|
||
const toHeadTags = (files, rel) => files.map((file) => [
|
||
"link",
|
||
{
|
||
rel,
|
||
// don't add base to external urls
|
||
href: (EXTERNAL_URL_RE.test(file) ? "" : siteData.base) + file
|
||
}
|
||
]);
|
||
const preloadHeadTags = toHeadTags(preloadLinks, "modulepreload");
|
||
const prefetchHeadTags = toHeadTags(prefetchLinks, "prefetch");
|
||
const headBeforeTransform = [
|
||
...additionalHeadTags,
|
||
...preloadHeadTags,
|
||
...prefetchHeadTags,
|
||
...mergeHead(
|
||
siteData.head,
|
||
filterOutHeadDescription(pageData.frontmatter.head)
|
||
)
|
||
];
|
||
const head = mergeHead(
|
||
headBeforeTransform,
|
||
await config.transformHead?.({
|
||
page,
|
||
siteConfig: config,
|
||
siteData,
|
||
pageData,
|
||
title,
|
||
description,
|
||
head: headBeforeTransform,
|
||
content,
|
||
assets
|
||
}) || []
|
||
);
|
||
let inlinedScript = "";
|
||
if (config.mpa && result) {
|
||
const matchingChunk = result.output.find(
|
||
(chunk) => chunk.type === "chunk" && chunk.facadeModuleId === slash(path$q.join(config.srcDir, page))
|
||
);
|
||
if (matchingChunk) {
|
||
if (!matchingChunk.code.includes("import")) {
|
||
inlinedScript = `<script type="module">${matchingChunk.code}<\/script>`;
|
||
fs$a.removeSync(path$q.resolve(config.outDir, matchingChunk.fileName));
|
||
} else {
|
||
inlinedScript = `<script type="module" src="${siteData.base}${matchingChunk.fileName}"><\/script>`;
|
||
}
|
||
}
|
||
}
|
||
const dir = pageData.frontmatter.dir || siteData.dir || "ltr";
|
||
const html = `<!DOCTYPE html>
|
||
<html lang="${siteData.lang}" dir="${dir}">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
${isMetaViewportOverridden(head) ? "" : '<meta name="viewport" content="width=device-width,initial-scale=1">'}
|
||
<title>${title}</title>
|
||
${isDescriptionOverridden(head) ? "" : `<meta name="description" content="${description}">`}
|
||
<meta name="generator" content="VitePress v${version}">
|
||
${stylesheetLink}
|
||
${metadataScript.inHead ? metadataScript.html : ""}
|
||
${appChunk ? `<script type="module" src="${siteData.base}${appChunk.fileName}"><\/script>` : ""}
|
||
${await renderHead(head)}
|
||
</head>
|
||
<body>${teleports?.body || ""}
|
||
<div id="app">${content}</div>
|
||
${metadataScript.inHead ? "" : metadataScript.html}
|
||
${inlinedScript}
|
||
</body>
|
||
</html>`;
|
||
const htmlFileName = path$q.join(config.outDir, page.replace(/\.md$/, ".html"));
|
||
await fs$a.ensureDir(path$q.dirname(htmlFileName));
|
||
const transformedHtml = await config.transformHtml?.(html, htmlFileName, {
|
||
page,
|
||
siteConfig: config,
|
||
siteData,
|
||
pageData,
|
||
title,
|
||
description,
|
||
head,
|
||
content,
|
||
assets
|
||
});
|
||
await fs$a.writeFile(htmlFileName, transformedHtml || html);
|
||
}
|
||
function resolvePageImports(config, page, result, appChunk) {
|
||
page = config.rewrites.inv[page] || page;
|
||
let srcPath = path$q.resolve(config.srcDir, page);
|
||
try {
|
||
if (!config.vite?.resolve?.preserveSymlinks) {
|
||
srcPath = fs$a.realpathSync(srcPath);
|
||
}
|
||
} catch (e) {
|
||
}
|
||
srcPath = normalizePath(srcPath);
|
||
const pageChunk = result.output.find(
|
||
(chunk) => chunk.type === "chunk" && chunk.facadeModuleId === srcPath
|
||
);
|
||
return [
|
||
...appChunk.imports,
|
||
...appChunk.dynamicImports,
|
||
...pageChunk.imports,
|
||
...pageChunk.dynamicImports
|
||
];
|
||
}
|
||
async function renderHead(head) {
|
||
const tags = await Promise.all(
|
||
head.map(async ([tag, attrs = {}, innerHTML = ""]) => {
|
||
const openTag = `<${tag}${renderAttrs(attrs)}>`;
|
||
if (tag !== "link" && tag !== "meta") {
|
||
if (tag === "script" && (attrs.type === void 0 || attrs.type.includes("javascript"))) {
|
||
innerHTML = (await transformWithEsbuild(innerHTML, "inline-script.js", {
|
||
minify: true
|
||
})).code.trim();
|
||
}
|
||
return `${openTag}${innerHTML}</${tag}>`;
|
||
} else {
|
||
return openTag;
|
||
}
|
||
})
|
||
);
|
||
return tags.join("\n ");
|
||
}
|
||
function renderAttrs(attrs) {
|
||
return Object.keys(attrs).map((key) => {
|
||
if (isBooleanAttr(key))
|
||
return ` ${key}`;
|
||
return ` ${key}="${escape$1(attrs[key])}"`;
|
||
}).join("");
|
||
}
|
||
function filterOutHeadDescription(head = []) {
|
||
return head.filter(([type, attrs]) => {
|
||
return !(type === "meta" && attrs?.name === "description");
|
||
});
|
||
}
|
||
function isDescriptionOverridden(head = []) {
|
||
return head.some(([type, attrs]) => {
|
||
return type === "meta" && attrs?.name === "description";
|
||
});
|
||
}
|
||
function isMetaViewportOverridden(head = []) {
|
||
return head.some(([type, attrs]) => {
|
||
return type === "meta" && attrs?.name === "viewport";
|
||
});
|
||
}
|
||
|
||
async function build(root, buildOptions = {}) {
|
||
const start = Date.now();
|
||
process.env.NODE_ENV = "production";
|
||
const siteConfig = await resolveConfig(root, "build", "production");
|
||
const unlinkVue = linkVue();
|
||
if (buildOptions.base) {
|
||
siteConfig.site.base = buildOptions.base;
|
||
delete buildOptions.base;
|
||
}
|
||
if (buildOptions.mpa) {
|
||
siteConfig.mpa = true;
|
||
delete buildOptions.mpa;
|
||
}
|
||
if (buildOptions.outDir) {
|
||
siteConfig.outDir = path$q.resolve(process.cwd(), buildOptions.outDir);
|
||
delete buildOptions.outDir;
|
||
}
|
||
try {
|
||
const { clientResult, serverResult, pageToHashMap } = await bundle(
|
||
siteConfig,
|
||
buildOptions
|
||
);
|
||
if (process.env.BUNDLE_ONLY) {
|
||
return;
|
||
}
|
||
const entryPath = path$q.join(siteConfig.tempDir, "app.js");
|
||
const { render } = await import(pathToFileURL(entryPath).toString() + "?t=" + Date.now());
|
||
await task("rendering pages", async () => {
|
||
const appChunk = clientResult && clientResult.output.find(
|
||
(chunk) => chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId?.endsWith(".js")
|
||
);
|
||
const cssChunk = (siteConfig.mpa ? serverResult : clientResult).output.find(
|
||
(chunk) => chunk.type === "asset" && chunk.fileName.endsWith(".css")
|
||
);
|
||
const assets = (siteConfig.mpa ? serverResult : clientResult).output.filter(
|
||
(chunk) => chunk.type === "asset" && !chunk.fileName.endsWith(".css")
|
||
).map((asset) => siteConfig.site.base + asset.fileName);
|
||
const additionalHeadTags = [];
|
||
const isDefaultTheme = clientResult && clientResult.output.some(
|
||
(chunk) => chunk.type === "chunk" && chunk.name === "theme" && chunk.moduleIds.some((id) => id.includes("client/theme-default"))
|
||
);
|
||
const metadataScript = generateMetadataScript(pageToHashMap, siteConfig);
|
||
if (isDefaultTheme) {
|
||
const fontURL = assets.find(
|
||
(file) => /inter-roman-latin\.\w+\.woff2/.test(file)
|
||
);
|
||
if (fontURL) {
|
||
additionalHeadTags.push([
|
||
"link",
|
||
{
|
||
rel: "preload",
|
||
href: fontURL,
|
||
as: "font",
|
||
type: "font/woff2",
|
||
crossorigin: ""
|
||
}
|
||
]);
|
||
}
|
||
}
|
||
await pMap(
|
||
["404.md", ...siteConfig.pages],
|
||
async (page) => {
|
||
await renderPage(
|
||
render,
|
||
siteConfig,
|
||
siteConfig.rewrites.map[page] || page,
|
||
clientResult,
|
||
appChunk,
|
||
cssChunk,
|
||
assets,
|
||
pageToHashMap,
|
||
metadataScript,
|
||
additionalHeadTags
|
||
);
|
||
},
|
||
{ concurrency: siteConfig.buildConcurrency }
|
||
);
|
||
});
|
||
fs$a.writeJSONSync(
|
||
path$q.join(siteConfig.outDir, "hashmap.json"),
|
||
pageToHashMap
|
||
);
|
||
} finally {
|
||
unlinkVue();
|
||
if (!process.env.DEBUG)
|
||
await rimraf(siteConfig.tempDir);
|
||
}
|
||
await generateSitemap(siteConfig);
|
||
await siteConfig.buildEnd?.(siteConfig);
|
||
clearCache();
|
||
siteConfig.logger.info(
|
||
`build complete in ${((Date.now() - start) / 1e3).toFixed(2)}s.`
|
||
);
|
||
}
|
||
function linkVue() {
|
||
const root = packageDirectorySync();
|
||
if (root) {
|
||
const dest = path$q.resolve(root, "node_modules/vue");
|
||
if (!fs$a.existsSync(dest)) {
|
||
const src = path$q.dirname(createRequire(import.meta.url).resolve("vue"));
|
||
fs$a.ensureSymlinkSync(src, dest, "junction");
|
||
return () => {
|
||
fs$a.unlinkSync(dest);
|
||
};
|
||
}
|
||
}
|
||
return () => {
|
||
};
|
||
}
|
||
function generateMetadataScript(pageToHashMap, config) {
|
||
if (config.mpa) {
|
||
return { html: "", inHead: false };
|
||
}
|
||
const hashMapString = JSON.stringify(JSON.stringify(pageToHashMap));
|
||
const siteDataString = JSON.stringify(
|
||
JSON.stringify(serializeFunctions({ ...config.site, head: [] }))
|
||
);
|
||
const metadataContent = `window.__VP_HASH_MAP__=JSON.parse(${hashMapString});${siteDataString.includes("_vp-fn_") ? `${deserializeFunctions};window.__VP_SITE_DATA__=deserializeFunctions(JSON.parse(${siteDataString}));` : `window.__VP_SITE_DATA__=JSON.parse(${siteDataString});`}`;
|
||
if (!config.metaChunk) {
|
||
return { html: `<script>${metadataContent}<\/script>`, inHead: false };
|
||
}
|
||
const metadataFile = path$q.join(
|
||
config.assetsDir,
|
||
"chunks",
|
||
`metadata.${createHash("sha256").update(metadataContent).digest("hex").slice(0, 8)}.js`
|
||
);
|
||
const resolvedMetadataFile = path$q.join(config.outDir, metadataFile);
|
||
const metadataFileURL = slash(`${config.site.base}${metadataFile}`);
|
||
fs$a.ensureDirSync(path$q.dirname(resolvedMetadataFile));
|
||
fs$a.writeFileSync(resolvedMetadataFile, metadataContent);
|
||
return {
|
||
html: `<script type="module" src="${metadataFileURL}"><\/script>`,
|
||
inHead: true
|
||
};
|
||
}
|
||
|
||
const ESC = '\x1B';
|
||
const CSI = `${ESC}[`;
|
||
const beep = '\u0007';
|
||
|
||
const cursor = {
|
||
to(x, y) {
|
||
if (!y) return `${CSI}${x + 1}G`;
|
||
return `${CSI}${y + 1};${x + 1}H`;
|
||
},
|
||
move(x, y) {
|
||
let ret = '';
|
||
|
||
if (x < 0) ret += `${CSI}${-x}D`;
|
||
else if (x > 0) ret += `${CSI}${x}C`;
|
||
|
||
if (y < 0) ret += `${CSI}${-y}A`;
|
||
else if (y > 0) ret += `${CSI}${y}B`;
|
||
|
||
return ret;
|
||
},
|
||
up: (count = 1) => `${CSI}${count}A`,
|
||
down: (count = 1) => `${CSI}${count}B`,
|
||
forward: (count = 1) => `${CSI}${count}C`,
|
||
backward: (count = 1) => `${CSI}${count}D`,
|
||
nextLine: (count = 1) => `${CSI}E`.repeat(count),
|
||
prevLine: (count = 1) => `${CSI}F`.repeat(count),
|
||
left: `${CSI}G`,
|
||
hide: `${CSI}?25l`,
|
||
show: `${CSI}?25h`,
|
||
save: `${ESC}7`,
|
||
restore: `${ESC}8`
|
||
};
|
||
|
||
const scroll = {
|
||
up: (count = 1) => `${CSI}S`.repeat(count),
|
||
down: (count = 1) => `${CSI}T`.repeat(count)
|
||
};
|
||
|
||
const erase = {
|
||
screen: `${CSI}2J`,
|
||
up: (count = 1) => `${CSI}1J`.repeat(count),
|
||
down: (count = 1) => `${CSI}J`.repeat(count),
|
||
line: `${CSI}2K`,
|
||
lineEnd: `${CSI}K`,
|
||
lineStart: `${CSI}1K`,
|
||
lines(count) {
|
||
let clear = '';
|
||
for (let i = 0; i < count; i++)
|
||
clear += this.line + (i < count - 1 ? cursor.up() : '');
|
||
if (count)
|
||
clear += cursor.left;
|
||
return clear;
|
||
}
|
||
};
|
||
|
||
var src$1 = { cursor, scroll, erase, beep };
|
||
|
||
function z({onlyFirst:t=!1}={}){const u=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(u,t?void 0:"g")}function $(t){if(typeof t!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof t}\``);return t.replace(z(),"")}var m={},G={get exports(){return m},set exports(t){m=t;}};(function(t){var u={};t.exports=u,u.eastAsianWidth=function(e){var s=e.charCodeAt(0),C=e.length==2?e.charCodeAt(1):0,D=s;return 55296<=s&&s<=56319&&56320<=C&&C<=57343&&(s&=1023,C&=1023,D=s<<10|C,D+=65536),D==12288||65281<=D&&D<=65376||65504<=D&&D<=65510?"F":D==8361||65377<=D&&D<=65470||65474<=D&&D<=65479||65482<=D&&D<=65487||65490<=D&&D<=65495||65498<=D&&D<=65500||65512<=D&&D<=65518?"H":4352<=D&&D<=4447||4515<=D&&D<=4519||4602<=D&&D<=4607||9001<=D&&D<=9002||11904<=D&&D<=11929||11931<=D&&D<=12019||12032<=D&&D<=12245||12272<=D&&D<=12283||12289<=D&&D<=12350||12353<=D&&D<=12438||12441<=D&&D<=12543||12549<=D&&D<=12589||12593<=D&&D<=12686||12688<=D&&D<=12730||12736<=D&&D<=12771||12784<=D&&D<=12830||12832<=D&&D<=12871||12880<=D&&D<=13054||13056<=D&&D<=19903||19968<=D&&D<=42124||42128<=D&&D<=42182||43360<=D&&D<=43388||44032<=D&&D<=55203||55216<=D&&D<=55238||55243<=D&&D<=55291||63744<=D&&D<=64255||65040<=D&&D<=65049||65072<=D&&D<=65106||65108<=D&&D<=65126||65128<=D&&D<=65131||110592<=D&&D<=110593||127488<=D&&D<=127490||127504<=D&&D<=127546||127552<=D&&D<=127560||127568<=D&&D<=127569||131072<=D&&D<=194367||177984<=D&&D<=196605||196608<=D&&D<=262141?"W":32<=D&&D<=126||162<=D&&D<=163||165<=D&&D<=166||D==172||D==175||10214<=D&&D<=10221||10629<=D&&D<=10630?"Na":D==161||D==164||167<=D&&D<=168||D==170||173<=D&&D<=174||176<=D&&D<=180||182<=D&&D<=186||188<=D&&D<=191||D==198||D==208||215<=D&&D<=216||222<=D&&D<=225||D==230||232<=D&&D<=234||236<=D&&D<=237||D==240||242<=D&&D<=243||247<=D&&D<=250||D==252||D==254||D==257||D==273||D==275||D==283||294<=D&&D<=295||D==299||305<=D&&D<=307||D==312||319<=D&&D<=322||D==324||328<=D&&D<=331||D==333||338<=D&&D<=339||358<=D&&D<=359||D==363||D==462||D==464||D==466||D==468||D==470||D==472||D==474||D==476||D==593||D==609||D==708||D==711||713<=D&&D<=715||D==717||D==720||728<=D&&D<=731||D==733||D==735||768<=D&&D<=879||913<=D&&D<=929||931<=D&&D<=937||945<=D&&D<=961||963<=D&&D<=969||D==1025||1040<=D&&D<=1103||D==1105||D==8208||8211<=D&&D<=8214||8216<=D&&D<=8217||8220<=D&&D<=8221||8224<=D&&D<=8226||8228<=D&&D<=8231||D==8240||8242<=D&&D<=8243||D==8245||D==8251||D==8254||D==8308||D==8319||8321<=D&&D<=8324||D==8364||D==8451||D==8453||D==8457||D==8467||D==8470||8481<=D&&D<=8482||D==8486||D==8491||8531<=D&&D<=8532||8539<=D&&D<=8542||8544<=D&&D<=8555||8560<=D&&D<=8569||D==8585||8592<=D&&D<=8601||8632<=D&&D<=8633||D==8658||D==8660||D==8679||D==8704||8706<=D&&D<=8707||8711<=D&&D<=8712||D==8715||D==8719||D==8721||D==8725||D==8730||8733<=D&&D<=8736||D==8739||D==8741||8743<=D&&D<=8748||D==8750||8756<=D&&D<=8759||8764<=D&&D<=8765||D==8776||D==8780||D==8786||8800<=D&&D<=8801||8804<=D&&D<=8807||8810<=D&&D<=8811||8814<=D&&D<=8815||8834<=D&&D<=8835||8838<=D&&D<=8839||D==8853||D==8857||D==8869||D==8895||D==8978||9312<=D&&D<=9449||9451<=D&&D<=9547||9552<=D&&D<=9587||9600<=D&&D<=9615||9618<=D&&D<=9621||9632<=D&&D<=9633||9635<=D&&D<=9641||9650<=D&&D<=9651||9654<=D&&D<=9655||9660<=D&&D<=9661||9664<=D&&D<=9665||9670<=D&&D<=9672||D==9675||9678<=D&&D<=9681||9698<=D&&D<=9701||D==9711||9733<=D&&D<=9734||D==9737||9742<=D&&D<=9743||9748<=D&&D<=9749||D==9756||D==9758||D==9792||D==9794||9824<=D&&D<=9825||9827<=D&&D<=9829||9831<=D&&D<=9834||9836<=D&&D<=9837||D==9839||9886<=D&&D<=9887||9918<=D&&D<=9919||9924<=D&&D<=9933||9935<=D&&D<=9953||D==9955||9960<=D&&D<=9983||D==10045||D==10071||10102<=D&&D<=10111||11093<=D&&D<=11097||12872<=D&&D<=12879||57344<=D&&D<=63743||65024<=D&&D<=65039||D==65533||127232<=D&&D<=127242||127248<=D&&D<=127277||127280<=D&&D<=127337||127344<=D&&D<=127386||917760<=D&&D<=917999||983040<=D&&D<=1048573||1048576<=D&&D<=1114109?"A":"N"},u.characterLength=function(e){var s=this.eastAsianWidth(e);return s=="F"||s=="W"||s=="A"?2:1};function F(e){return e.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g)||[]}u.length=function(e){for(var s=F(e),C=0,D=0;D<s.length;D++)C=C+this.characterLength(s[D]);return C},u.slice=function(e,s,C){textLen=u.length(e),s=s||0,C=C||1,s<0&&(s=textLen+s),C<0&&(C=textLen+C);for(var D="",i=0,o=F(e),E=0;E<o.length;E++){var a=o[E],n=u.length(a);if(i>=s-(n==2?1:0))if(i+n<=C)D+=a;else break;i+=n;}return D};})(G);const K$1=m;var Y=function(){return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC)?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299]|\uD83C[\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\uD83D\uDC41\uFE0F|\uD83C\uDFF3\uFE0F|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD1D\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78\uDD7A-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCB\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6]|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26A7\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5-\uDED7\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDD77\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g};function c(t,u={}){if(typeof t!="string"||t.length===0||(u={ambiguousIsNarrow:!0,...u},t=$(t),t.length===0))return 0;t=t.replace(Y()," ");const F=u.ambiguousIsNarrow?1:2;let e=0;for(const s of t){const C=s.codePointAt(0);if(C<=31||C>=127&&C<=159||C>=768&&C<=879)continue;switch(K$1.eastAsianWidth(s)){case"F":case"W":e+=2;break;case"A":e+=F;break;default:e+=1;}}return e}const v=10,M=(t=0)=>u=>`\x1B[${u+t}m`,L=(t=0)=>u=>`\x1B[${38+t};5;${u}m`,T=(t=0)=>(u,F,e)=>`\x1B[${38+t};2;${u};${F};${e}m`,r={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};Object.keys(r.modifier);const Z=Object.keys(r.color),H$1=Object.keys(r.bgColor);[...Z,...H$1];function U(){const t=new Map;for(const[u,F]of Object.entries(r)){for(const[e,s]of Object.entries(F))r[e]={open:`\x1B[${s[0]}m`,close:`\x1B[${s[1]}m`},F[e]=r[e],t.set(s[0],s[1]);Object.defineProperty(r,u,{value:F,enumerable:!1});}return Object.defineProperty(r,"codes",{value:t,enumerable:!1}),r.color.close="\x1B[39m",r.bgColor.close="\x1B[49m",r.color.ansi=M(),r.color.ansi256=L(),r.color.ansi16m=T(),r.bgColor.ansi=M(v),r.bgColor.ansi256=L(v),r.bgColor.ansi16m=T(v),Object.defineProperties(r,{rgbToAnsi256:{value:(u,F,e)=>u===F&&F===e?u<8?16:u>248?231:Math.round((u-8)/247*24)+232:16+36*Math.round(u/255*5)+6*Math.round(F/255*5)+Math.round(e/255*5),enumerable:!1},hexToRgb:{value:u=>{const F=/[a-f\d]{6}|[a-f\d]{3}/i.exec(u.toString(16));if(!F)return [0,0,0];let[e]=F;e.length===3&&(e=[...e].map(C=>C+C).join(""));const s=Number.parseInt(e,16);return [s>>16&255,s>>8&255,s&255]},enumerable:!1},hexToAnsi256:{value:u=>r.rgbToAnsi256(...r.hexToRgb(u)),enumerable:!1},ansi256ToAnsi:{value:u=>{if(u<8)return 30+u;if(u<16)return 90+(u-8);let F,e,s;if(u>=232)F=((u-232)*10+8)/255,e=F,s=F;else {u-=16;const i=u%36;F=Math.floor(u/36)/5,e=Math.floor(i/6)/5,s=i%6/5;}const C=Math.max(F,e,s)*2;if(C===0)return 30;let D=30+(Math.round(s)<<2|Math.round(e)<<1|Math.round(F));return C===2&&(D+=60),D},enumerable:!1},rgbToAnsi:{value:(u,F,e)=>r.ansi256ToAnsi(r.rgbToAnsi256(u,F,e)),enumerable:!1},hexToAnsi:{value:u=>r.ansi256ToAnsi(r.hexToAnsi256(u)),enumerable:!1}}),r}const q$1=U(),p=new Set(["\x1B","\x9B"]),J=39,b$1="\x07",W="[",Q="]",I$1="m",w=`${Q}8;;`,N=t=>`${p.values().next().value}${W}${t}${I$1}`,j=t=>`${p.values().next().value}${w}${t}${b$1}`,X=t=>t.split(" ").map(u=>c(u)),_$1=(t,u,F)=>{const e=[...u];let s=!1,C=!1,D=c($(t[t.length-1]));for(const[i,o]of e.entries()){const E=c(o);if(D+E<=F?t[t.length-1]+=o:(t.push(o),D=0),p.has(o)&&(s=!0,C=e.slice(i+1).join("").startsWith(w)),s){C?o===b$1&&(s=!1,C=!1):o===I$1&&(s=!1);continue}D+=E,D===F&&i<e.length-1&&(t.push(""),D=0);}!D&&t[t.length-1].length>0&&t.length>1&&(t[t.length-2]+=t.pop());},DD=t=>{const u=t.split(" ");let F=u.length;for(;F>0&&!(c(u[F-1])>0);)F--;return F===u.length?t:u.slice(0,F).join(" ")+u.slice(F).join("")},uD=(t,u,F={})=>{if(F.trim!==!1&&t.trim()==="")return "";let e="",s,C;const D=X(t);let i=[""];for(const[E,a]of t.split(" ").entries()){F.trim!==!1&&(i[i.length-1]=i[i.length-1].trimStart());let n=c(i[i.length-1]);if(E!==0&&(n>=u&&(F.wordWrap===!1||F.trim===!1)&&(i.push(""),n=0),(n>0||F.trim===!1)&&(i[i.length-1]+=" ",n++)),F.hard&&D[E]>u){const B=u-n,A=1+Math.floor((D[E]-B-1)/u);Math.floor((D[E]-1)/u)<A&&i.push(""),_$1(i,a,u);continue}if(n+D[E]>u&&n>0&&D[E]>0){if(F.wordWrap===!1&&n<u){_$1(i,a,u);continue}i.push("");}if(n+D[E]>u&&F.wordWrap===!1){_$1(i,a,u);continue}i[i.length-1]+=a;}F.trim!==!1&&(i=i.map(E=>DD(E)));const o=[...i.join(`
|
||
`)];for(const[E,a]of o.entries()){if(e+=a,p.has(a)){const{groups:B}=new RegExp(`(?:\\${W}(?<code>\\d+)m|\\${w}(?<uri>.*)${b$1})`).exec(o.slice(E).join(""))||{groups:{}};if(B.code!==void 0){const A=Number.parseFloat(B.code);s=A===J?void 0:A;}else B.uri!==void 0&&(C=B.uri.length===0?void 0:B.uri);}const n=q$1.codes.get(Number(s));o[E+1]===`
|
||
`?(C&&(e+=j("")),s&&n&&(e+=N(n))):a===`
|
||
`&&(s&&n&&(e+=N(s)),C&&(e+=j(C)));}return e};function P(t,u,F){return String(t).normalize().replace(/\r\n/g,`
|
||
`).split(`
|
||
`).map(e=>uD(e,u,F)).join(`
|
||
`)}function FD(t,u){if(t===u)return;const F=t.split(`
|
||
`),e=u.split(`
|
||
`),s=[];for(let C=0;C<Math.max(F.length,e.length);C++)F[C]!==e[C]&&s.push(C);return s}const R=Symbol("clack:cancel");function eD(t){return t===R}function g(t,u){t.isTTY&&t.setRawMode(u);}const V=new Map([["k","up"],["j","down"],["h","left"],["l","right"]]),tD=new Set(["up","down","left","right","space","enter"]);class h{constructor({render:u,input:F=stdin,output:e=stdout,...s},C=!0){this._track=!1,this._cursor=0,this.state="initial",this.error="",this.subscribers=new Map,this._prevFrame="",this.opts=s,this.onKeypress=this.onKeypress.bind(this),this.close=this.close.bind(this),this.render=this.render.bind(this),this._render=u.bind(this),this._track=C,this.input=F,this.output=e;}prompt(){const u=new WriteStream(0);return u._write=(F,e,s)=>{this._track&&(this.value=this.rl.line.replace(/\t/g,""),this._cursor=this.rl.cursor,this.emit("value",this.value)),s();},this.input.pipe(u),this.rl=f$1.createInterface({input:this.input,output:u,tabSize:2,prompt:"",escapeCodeTimeout:50}),f$1.emitKeypressEvents(this.input,this.rl),this.rl.prompt(),this.opts.initialValue!==void 0&&this._track&&this.rl.write(this.opts.initialValue),this.input.on("keypress",this.onKeypress),g(this.input,!0),this.output.on("resize",this.render),this.render(),new Promise((F,e)=>{this.once("submit",()=>{this.output.write(src$1.cursor.show),this.output.off("resize",this.render),g(this.input,!1),F(this.value);}),this.once("cancel",()=>{this.output.write(src$1.cursor.show),this.output.off("resize",this.render),g(this.input,!1),F(R);});})}on(u,F){const e=this.subscribers.get(u)??[];e.push({cb:F}),this.subscribers.set(u,e);}once(u,F){const e=this.subscribers.get(u)??[];e.push({cb:F,once:!0}),this.subscribers.set(u,e);}emit(u,...F){const e=this.subscribers.get(u)??[],s=[];for(const C of e)C.cb(...F),C.once&&s.push(()=>e.splice(e.indexOf(C),1));for(const C of s)C();}unsubscribe(){this.subscribers.clear();}onKeypress(u,F){if(this.state==="error"&&(this.state="active"),F?.name&&!this._track&&V.has(F.name)&&this.emit("cursor",V.get(F.name)),F?.name&&tD.has(F.name)&&this.emit("cursor",F.name),u&&(u.toLowerCase()==="y"||u.toLowerCase()==="n")&&this.emit("confirm",u.toLowerCase()==="y"),u&&this.emit("key",u.toLowerCase()),F?.name==="return"){if(this.opts.validate){const e=this.opts.validate(this.value);e&&(this.error=e,this.state="error",this.rl.write(this.value));}this.state!=="error"&&(this.state="submit");}u===""&&(this.state="cancel"),(this.state==="submit"||this.state==="cancel")&&this.emit("finalize"),this.render(),(this.state==="submit"||this.state==="cancel")&&this.close();}close(){this.input.unpipe(),this.input.removeListener("keypress",this.onKeypress),this.output.write(`
|
||
`),g(this.input,!1),this.rl.close(),this.emit(`${this.state}`,this.value),this.unsubscribe();}restoreCursor(){const u=P(this._prevFrame,process.stdout.columns,{hard:!0}).split(`
|
||
`).length-1;this.output.write(src$1.cursor.move(-999,u*-1));}render(){const u=P(this._render(this)??"",process.stdout.columns,{hard:!0});if(u!==this._prevFrame){if(this.state==="initial")this.output.write(src$1.cursor.hide);else {const F=FD(this._prevFrame,u);if(this.restoreCursor(),F&&F?.length===1){const e=F[0];this.output.write(src$1.cursor.move(0,e)),this.output.write(src$1.erase.lines(1));const s=u.split(`
|
||
`);this.output.write(s[e]),this._prevFrame=u,this.output.write(src$1.cursor.move(0,s.length-e-1));return}else if(F&&F?.length>1){const e=F[0];this.output.write(src$1.cursor.move(0,e)),this.output.write(src$1.erase.down());const C=u.split(`
|
||
`).slice(e);this.output.write(C.join(`
|
||
`)),this._prevFrame=u;return}this.output.write(src$1.erase.down());}this.output.write(u),this.state==="initial"&&(this.state="active"),this._prevFrame=u;}}}class sD extends h{get cursor(){return this.value?0:1}get _value(){return this.cursor===0}constructor(u){super(u,!1),this.value=!!u.initialValue,this.on("value",()=>{this.value=this._value;}),this.on("confirm",F=>{this.output.write(src$1.cursor.move(0,-1)),this.value=F,this.state="submit",this.close();}),this.on("cursor",()=>{this.value=!this.value;});}}class ED extends h{constructor(u){super(u,!1),this.cursor=0,this.options=u.options,this.cursor=this.options.findIndex(({value:F})=>F===u.initialValue),this.cursor===-1&&(this.cursor=0),this.changeValue(),this.on("cursor",F=>{switch(F){case"left":case"up":this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break;case"down":case"right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break}this.changeValue();});}get _value(){return this.options[this.cursor]}changeValue(){this.value=this._value.value;}}class oD extends h{constructor(u){super(u),this.valueWithCursor="",this.on("finalize",()=>{this.value||(this.value=u.defaultValue),this.valueWithCursor=this.value;}),this.on("value",()=>{if(this.cursor>=this.value.length)this.valueWithCursor=`${this.value}${c$2.inverse(c$2.hidden("_"))}`;else {const F=this.value.slice(0,this.cursor),e=this.value.slice(this.cursor);this.valueWithCursor=`${F}${c$2.inverse(e[0])}${e.slice(1)}`;}});}get cursor(){return this._cursor}}
|
||
|
||
function q(){return process$2.platform!=="win32"?process$2.env.TERM!=="linux":Boolean(process$2.env.CI)||Boolean(process$2.env.WT_SESSION)||Boolean(process$2.env.TERMINUS_SUBLIME)||process$2.env.ConEmuTask==="{cmd::Cmder}"||process$2.env.TERM_PROGRAM==="Terminus-Sublime"||process$2.env.TERM_PROGRAM==="vscode"||process$2.env.TERM==="xterm-256color"||process$2.env.TERM==="alacritty"||process$2.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}const _=q(),o=(r,n)=>_?r:n,H=o("\u25C6","*"),I=o("\u25A0","x"),x=o("\u25B2","x"),S=o("\u25C7","o"),K=o("\u250C","T"),a=o("\u2502","|"),d=o("\u2514","\u2014"),b=o("\u25CF",">"),E=o("\u25CB"," "),y=r=>{switch(r){case"initial":case"active":return c$2.cyan(H);case"cancel":return c$2.red(I);case"error":return c$2.yellow(x);case"submit":return c$2.green(S)}},te=r=>new oD({validate:r.validate,placeholder:r.placeholder,defaultValue:r.defaultValue,initialValue:r.initialValue,render(){const n=`${c$2.gray(a)}
|
||
${y(this.state)} ${r.message}
|
||
`,i=r.placeholder?c$2.inverse(r.placeholder[0])+c$2.dim(r.placeholder.slice(1)):c$2.inverse(c$2.hidden("_")),t=this.value?this.valueWithCursor:i;switch(this.state){case"error":return `${n.trim()}
|
||
${c$2.yellow(a)} ${t}
|
||
${c$2.yellow(d)} ${c$2.yellow(this.error)}
|
||
`;case"submit":return `${n}${c$2.gray(a)} ${c$2.dim(this.value||r.placeholder)}`;case"cancel":return `${n}${c$2.gray(a)} ${c$2.strikethrough(c$2.dim(this.value??""))}${this.value?.trim()?`
|
||
`+c$2.gray(a):""}`;default:return `${n}${c$2.cyan(a)} ${t}
|
||
${c$2.cyan(d)}
|
||
`}}}).prompt(),se=r=>{const n=r.active??"Yes",i=r.inactive??"No";return new sD({active:n,inactive:i,initialValue:r.initialValue??!0,render(){const t=`${c$2.gray(a)}
|
||
${y(this.state)} ${r.message}
|
||
`,s=this.value?n:i;switch(this.state){case"submit":return `${t}${c$2.gray(a)} ${c$2.dim(s)}`;case"cancel":return `${t}${c$2.gray(a)} ${c$2.strikethrough(c$2.dim(s))}
|
||
${c$2.gray(a)}`;default:return `${t}${c$2.cyan(a)} ${this.value?`${c$2.green(b)} ${n}`:`${c$2.dim(E)} ${c$2.dim(n)}`} ${c$2.dim("/")} ${this.value?`${c$2.dim(E)} ${c$2.dim(i)}`:`${c$2.green(b)} ${i}`}
|
||
${c$2.cyan(d)}
|
||
`}}}).prompt()},ie=r=>{const n=(t,s)=>{const c=t.label??String(t.value);return s==="active"?`${c$2.green(b)} ${c} ${t.hint?c$2.dim(`(${t.hint})`):""}`:s==="selected"?`${c$2.dim(c)}`:s==="cancelled"?`${c$2.strikethrough(c$2.dim(c))}`:`${c$2.dim(E)} ${c$2.dim(c)}`};let i=0;return new ED({options:r.options,initialValue:r.initialValue,render(){const t=`${c$2.gray(a)}
|
||
${y(this.state)} ${r.message}
|
||
`;switch(this.state){case"submit":return `${t}${c$2.gray(a)} ${n(this.options[this.cursor],"selected")}`;case"cancel":return `${t}${c$2.gray(a)} ${n(this.options[this.cursor],"cancelled")}
|
||
${c$2.gray(a)}`;default:{const s=r.maxItems===void 0?1/0:Math.max(r.maxItems,5);this.cursor>=i+s-3?i=Math.max(Math.min(this.cursor-s+3,this.options.length-s),0):this.cursor<i+2&&(i=Math.max(this.cursor-2,0));const c=s<this.options.length&&i>0,l=s<this.options.length&&i+s<this.options.length;return `${t}${c$2.cyan(a)} ${this.options.slice(i,i+s).map((u,m,$)=>m===0&&c?c$2.dim("..."):m===$.length-1&&l?c$2.dim("..."):n(u,m+i===this.cursor?"active":"inactive")).join(`
|
||
${c$2.cyan(a)} `)}
|
||
${c$2.cyan(d)}
|
||
`}}}}).prompt()},ue=(r="")=>{process.stdout.write(`${c$2.gray(d)} ${c$2.red(r)}
|
||
|
||
`);},oe=(r="")=>{process.stdout.write(`${c$2.gray(K)} ${r}
|
||
`);},$e=(r="")=>{process.stdout.write(`${c$2.gray(a)}
|
||
${c$2.gray(d)} ${r}
|
||
|
||
`);};const he=async(r,n)=>{const i={},t=Object.keys(r);for(const s of t){const c=r[s],l=await c({results:i})?.catch(u=>{throw u});if(typeof n?.onCancel=="function"&&eD(l)){i[s]="canceled",n.onCancel({results:i});continue}i[s]=l;}return i};
|
||
|
||
var lodash_template = {exports: {}};
|
||
|
||
/**
|
||
* lodash 3.0.0 (Custom Build) <https://lodash.com/>
|
||
* Build: `lodash modern modularize exports="npm" -o ./`
|
||
* Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
|
||
* Based on Underscore.js 1.7.0 <http://underscorejs.org/LICENSE>
|
||
* Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||
* Available under MIT license <https://lodash.com/license>
|
||
*/
|
||
|
||
/** Used to match template delimiters. */
|
||
var reInterpolate$1 = /<%=([\s\S]+?)%>/g;
|
||
|
||
var lodash__reinterpolate = reInterpolate$1;
|
||
|
||
/**
|
||
* Lodash (Custom Build) <https://lodash.com/>
|
||
* Build: `lodash modularize exports="npm" -o ./`
|
||
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
||
* Released under MIT license <https://lodash.com/license>
|
||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
||
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||
*/
|
||
|
||
var reInterpolate = lodash__reinterpolate;
|
||
|
||
/** Used as references for various `Number` constants. */
|
||
var INFINITY = 1 / 0;
|
||
|
||
/** `Object#toString` result references. */
|
||
var nullTag = '[object Null]',
|
||
symbolTag = '[object Symbol]',
|
||
undefinedTag = '[object Undefined]';
|
||
|
||
/** Used to match HTML entities and HTML characters. */
|
||
var reUnescapedHtml = /[&<>"']/g,
|
||
reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
|
||
|
||
/** Used to match template delimiters. */
|
||
var reEscape = /<%-([\s\S]+?)%>/g,
|
||
reEvaluate = /<%([\s\S]+?)%>/g;
|
||
|
||
/** Used to map characters to HTML entities. */
|
||
var htmlEscapes = {
|
||
'&': '&',
|
||
'<': '<',
|
||
'>': '>',
|
||
'"': '"',
|
||
"'": '''
|
||
};
|
||
|
||
/** Detect free variable `global` from Node.js. */
|
||
var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
|
||
|
||
/** Detect free variable `self`. */
|
||
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
|
||
|
||
/** Used as a reference to the global object. */
|
||
var root = freeGlobal || freeSelf || Function('return this')();
|
||
|
||
/**
|
||
* A specialized version of `_.map` for arrays without support for iteratee
|
||
* shorthands.
|
||
*
|
||
* @private
|
||
* @param {Array} [array] The array to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {Array} Returns the new mapped array.
|
||
*/
|
||
function arrayMap(array, iteratee) {
|
||
var index = -1,
|
||
length = array == null ? 0 : array.length,
|
||
result = Array(length);
|
||
|
||
while (++index < length) {
|
||
result[index] = iteratee(array[index], index, array);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.propertyOf` without support for deep paths.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @returns {Function} Returns the new accessor function.
|
||
*/
|
||
function basePropertyOf(object) {
|
||
return function(key) {
|
||
return object == null ? undefined : object[key];
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Used by `_.escape` to convert characters to HTML entities.
|
||
*
|
||
* @private
|
||
* @param {string} chr The matched character to escape.
|
||
* @returns {string} Returns the escaped character.
|
||
*/
|
||
var escapeHtmlChar = basePropertyOf(htmlEscapes);
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto = Object.prototype;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty = objectProto.hasOwnProperty;
|
||
|
||
/**
|
||
* Used to resolve the
|
||
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
||
* of values.
|
||
*/
|
||
var nativeObjectToString = objectProto.toString;
|
||
|
||
/** Built-in value references. */
|
||
var Symbol$1 = root.Symbol,
|
||
symToStringTag = Symbol$1 ? Symbol$1.toStringTag : undefined;
|
||
|
||
/** Used to convert symbols to primitives and strings. */
|
||
var symbolProto = Symbol$1 ? Symbol$1.prototype : undefined,
|
||
symbolToString = symbolProto ? symbolProto.toString : undefined;
|
||
|
||
/**
|
||
* By default, the template delimiters used by lodash are like those in
|
||
* embedded Ruby (ERB) as well as ES2015 template strings. Change the
|
||
* following template settings to use alternative delimiters.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @type {Object}
|
||
*/
|
||
var templateSettings = {
|
||
|
||
/**
|
||
* Used to detect `data` property values to be HTML-escaped.
|
||
*
|
||
* @memberOf _.templateSettings
|
||
* @type {RegExp}
|
||
*/
|
||
'escape': reEscape,
|
||
|
||
/**
|
||
* Used to detect code to be evaluated.
|
||
*
|
||
* @memberOf _.templateSettings
|
||
* @type {RegExp}
|
||
*/
|
||
'evaluate': reEvaluate,
|
||
|
||
/**
|
||
* Used to detect `data` property values to inject.
|
||
*
|
||
* @memberOf _.templateSettings
|
||
* @type {RegExp}
|
||
*/
|
||
'interpolate': reInterpolate,
|
||
|
||
/**
|
||
* Used to reference the data object in the template text.
|
||
*
|
||
* @memberOf _.templateSettings
|
||
* @type {string}
|
||
*/
|
||
'variable': '',
|
||
|
||
/**
|
||
* Used to import variables into the compiled template.
|
||
*
|
||
* @memberOf _.templateSettings
|
||
* @type {Object}
|
||
*/
|
||
'imports': {
|
||
|
||
/**
|
||
* A reference to the `lodash` function.
|
||
*
|
||
* @memberOf _.templateSettings.imports
|
||
* @type {Function}
|
||
*/
|
||
'_': { 'escape': escape }
|
||
}
|
||
};
|
||
|
||
/**
|
||
* The base implementation of `getTag` without fallbacks for buggy environments.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to query.
|
||
* @returns {string} Returns the `toStringTag`.
|
||
*/
|
||
function baseGetTag(value) {
|
||
if (value == null) {
|
||
return value === undefined ? undefinedTag : nullTag;
|
||
}
|
||
return (symToStringTag && symToStringTag in Object(value))
|
||
? getRawTag(value)
|
||
: objectToString(value);
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.toString` which doesn't convert nullish
|
||
* values to empty strings.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to process.
|
||
* @returns {string} Returns the string.
|
||
*/
|
||
function baseToString(value) {
|
||
// Exit early for strings to avoid a performance hit in some environments.
|
||
if (typeof value == 'string') {
|
||
return value;
|
||
}
|
||
if (isArray(value)) {
|
||
// Recursively convert values (susceptible to call stack limits).
|
||
return arrayMap(value, baseToString) + '';
|
||
}
|
||
if (isSymbol(value)) {
|
||
return symbolToString ? symbolToString.call(value) : '';
|
||
}
|
||
var result = (value + '');
|
||
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to query.
|
||
* @returns {string} Returns the raw `toStringTag`.
|
||
*/
|
||
function getRawTag(value) {
|
||
var isOwn = hasOwnProperty.call(value, symToStringTag),
|
||
tag = value[symToStringTag];
|
||
|
||
try {
|
||
value[symToStringTag] = undefined;
|
||
var unmasked = true;
|
||
} catch (e) {}
|
||
|
||
var result = nativeObjectToString.call(value);
|
||
if (unmasked) {
|
||
if (isOwn) {
|
||
value[symToStringTag] = tag;
|
||
} else {
|
||
delete value[symToStringTag];
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Converts `value` to a string using `Object.prototype.toString`.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to convert.
|
||
* @returns {string} Returns the converted string.
|
||
*/
|
||
function objectToString(value) {
|
||
return nativeObjectToString.call(value);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is classified as an `Array` object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 0.1.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is an array, else `false`.
|
||
* @example
|
||
*
|
||
* _.isArray([1, 2, 3]);
|
||
* // => true
|
||
*
|
||
* _.isArray(document.body.children);
|
||
* // => false
|
||
*
|
||
* _.isArray('abc');
|
||
* // => false
|
||
*
|
||
* _.isArray(_.noop);
|
||
* // => false
|
||
*/
|
||
var isArray = Array.isArray;
|
||
|
||
/**
|
||
* Checks if `value` is object-like. A value is object-like if it's not `null`
|
||
* and has a `typeof` result of "object".
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
|
||
* @example
|
||
*
|
||
* _.isObjectLike({});
|
||
* // => true
|
||
*
|
||
* _.isObjectLike([1, 2, 3]);
|
||
* // => true
|
||
*
|
||
* _.isObjectLike(_.noop);
|
||
* // => false
|
||
*
|
||
* _.isObjectLike(null);
|
||
* // => false
|
||
*/
|
||
function isObjectLike(value) {
|
||
return value != null && typeof value == 'object';
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is classified as a `Symbol` primitive or object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
|
||
* @example
|
||
*
|
||
* _.isSymbol(Symbol.iterator);
|
||
* // => true
|
||
*
|
||
* _.isSymbol('abc');
|
||
* // => false
|
||
*/
|
||
function isSymbol(value) {
|
||
return typeof value == 'symbol' ||
|
||
(isObjectLike(value) && baseGetTag(value) == symbolTag);
|
||
}
|
||
|
||
/**
|
||
* Converts `value` to a string. An empty string is returned for `null`
|
||
* and `undefined` values. The sign of `-0` is preserved.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Lang
|
||
* @param {*} value The value to convert.
|
||
* @returns {string} Returns the converted string.
|
||
* @example
|
||
*
|
||
* _.toString(null);
|
||
* // => ''
|
||
*
|
||
* _.toString(-0);
|
||
* // => '-0'
|
||
*
|
||
* _.toString([1, 2, 3]);
|
||
* // => '1,2,3'
|
||
*/
|
||
function toString(value) {
|
||
return value == null ? '' : baseToString(value);
|
||
}
|
||
|
||
/**
|
||
* Converts the characters "&", "<", ">", '"', and "'" in `string` to their
|
||
* corresponding HTML entities.
|
||
*
|
||
* **Note:** No other characters are escaped. To escape additional
|
||
* characters use a third-party library like [_he_](https://mths.be/he).
|
||
*
|
||
* Though the ">" character is escaped for symmetry, characters like
|
||
* ">" and "/" don't need escaping in HTML and have no special meaning
|
||
* unless they're part of a tag or unquoted attribute value. See
|
||
* [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
|
||
* (under "semi-related fun fact") for more details.
|
||
*
|
||
* When working with HTML you should always
|
||
* [quote attribute values](http://wonko.com/post/html-escaping) to reduce
|
||
* XSS vectors.
|
||
*
|
||
* @static
|
||
* @since 0.1.0
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to escape.
|
||
* @returns {string} Returns the escaped string.
|
||
* @example
|
||
*
|
||
* _.escape('fred, barney, & pebbles');
|
||
* // => 'fred, barney, & pebbles'
|
||
*/
|
||
function escape(string) {
|
||
string = toString(string);
|
||
return (string && reHasUnescapedHtml.test(string))
|
||
? string.replace(reUnescapedHtml, escapeHtmlChar)
|
||
: string;
|
||
}
|
||
|
||
var lodash_templatesettings = templateSettings;
|
||
|
||
/**
|
||
* Lodash (Custom Build) <https://lodash.com/>
|
||
* Build: `lodash modularize exports="npm" -o ./`
|
||
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
||
* Released under MIT license <https://lodash.com/license>
|
||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
||
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||
*/
|
||
lodash_template.exports;
|
||
|
||
(function (module, exports) {
|
||
var reInterpolate = lodash__reinterpolate,
|
||
templateSettings = lodash_templatesettings;
|
||
|
||
/** Used to detect hot functions by number of calls within a span of milliseconds. */
|
||
var HOT_COUNT = 800,
|
||
HOT_SPAN = 16;
|
||
|
||
/** Used as references for various `Number` constants. */
|
||
var INFINITY = 1 / 0,
|
||
MAX_SAFE_INTEGER = 9007199254740991;
|
||
|
||
/** `Object#toString` result references. */
|
||
var argsTag = '[object Arguments]',
|
||
arrayTag = '[object Array]',
|
||
asyncTag = '[object AsyncFunction]',
|
||
boolTag = '[object Boolean]',
|
||
dateTag = '[object Date]',
|
||
domExcTag = '[object DOMException]',
|
||
errorTag = '[object Error]',
|
||
funcTag = '[object Function]',
|
||
genTag = '[object GeneratorFunction]',
|
||
mapTag = '[object Map]',
|
||
numberTag = '[object Number]',
|
||
nullTag = '[object Null]',
|
||
objectTag = '[object Object]',
|
||
proxyTag = '[object Proxy]',
|
||
regexpTag = '[object RegExp]',
|
||
setTag = '[object Set]',
|
||
stringTag = '[object String]',
|
||
symbolTag = '[object Symbol]',
|
||
undefinedTag = '[object Undefined]',
|
||
weakMapTag = '[object WeakMap]';
|
||
|
||
var arrayBufferTag = '[object ArrayBuffer]',
|
||
dataViewTag = '[object DataView]',
|
||
float32Tag = '[object Float32Array]',
|
||
float64Tag = '[object Float64Array]',
|
||
int8Tag = '[object Int8Array]',
|
||
int16Tag = '[object Int16Array]',
|
||
int32Tag = '[object Int32Array]',
|
||
uint8Tag = '[object Uint8Array]',
|
||
uint8ClampedTag = '[object Uint8ClampedArray]',
|
||
uint16Tag = '[object Uint16Array]',
|
||
uint32Tag = '[object Uint32Array]';
|
||
|
||
/** Used to match empty string literals in compiled template source. */
|
||
var reEmptyStringLeading = /\b__p \+= '';/g,
|
||
reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
|
||
reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
|
||
|
||
/**
|
||
* Used to match `RegExp`
|
||
* [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
|
||
*/
|
||
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
|
||
|
||
/**
|
||
* Used to match
|
||
* [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
|
||
*/
|
||
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
|
||
|
||
/** Used to detect host constructors (Safari). */
|
||
var reIsHostCtor = /^\[object .+?Constructor\]$/;
|
||
|
||
/** Used to detect unsigned integer values. */
|
||
var reIsUint = /^(?:0|[1-9]\d*)$/;
|
||
|
||
/** Used to ensure capturing order of template delimiters. */
|
||
var reNoMatch = /($^)/;
|
||
|
||
/** Used to match unescaped characters in compiled string literals. */
|
||
var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
|
||
|
||
/** Used to identify `toStringTag` values of typed arrays. */
|
||
var typedArrayTags = {};
|
||
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
|
||
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
|
||
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
|
||
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
|
||
typedArrayTags[uint32Tag] = true;
|
||
typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
|
||
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
|
||
typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
|
||
typedArrayTags[errorTag] = typedArrayTags[funcTag] =
|
||
typedArrayTags[mapTag] = typedArrayTags[numberTag] =
|
||
typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
|
||
typedArrayTags[setTag] = typedArrayTags[stringTag] =
|
||
typedArrayTags[weakMapTag] = false;
|
||
|
||
/** Used to escape characters for inclusion in compiled string literals. */
|
||
var stringEscapes = {
|
||
'\\': '\\',
|
||
"'": "'",
|
||
'\n': 'n',
|
||
'\r': 'r',
|
||
'\u2028': 'u2028',
|
||
'\u2029': 'u2029'
|
||
};
|
||
|
||
/** Detect free variable `global` from Node.js. */
|
||
var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
|
||
|
||
/** Detect free variable `self`. */
|
||
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
|
||
|
||
/** Used as a reference to the global object. */
|
||
var root = freeGlobal || freeSelf || Function('return this')();
|
||
|
||
/** Detect free variable `exports`. */
|
||
var freeExports = exports && !exports.nodeType && exports;
|
||
|
||
/** Detect free variable `module`. */
|
||
var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
|
||
|
||
/** Detect the popular CommonJS extension `module.exports`. */
|
||
var moduleExports = freeModule && freeModule.exports === freeExports;
|
||
|
||
/** Detect free variable `process` from Node.js. */
|
||
var freeProcess = moduleExports && freeGlobal.process;
|
||
|
||
/** Used to access faster Node.js helpers. */
|
||
var nodeUtil = (function() {
|
||
try {
|
||
// Use `util.types` for Node.js 10+.
|
||
var types = freeModule && freeModule.require && freeModule.require('util').types;
|
||
|
||
if (types) {
|
||
return types;
|
||
}
|
||
|
||
// Legacy `process.binding('util')` for Node.js < 10.
|
||
return freeProcess && freeProcess.binding && freeProcess.binding('util');
|
||
} catch (e) {}
|
||
}());
|
||
|
||
/* Node.js helper references. */
|
||
var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
|
||
|
||
/**
|
||
* A faster alternative to `Function#apply`, this function invokes `func`
|
||
* with the `this` binding of `thisArg` and the arguments of `args`.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to invoke.
|
||
* @param {*} thisArg The `this` binding of `func`.
|
||
* @param {Array} args The arguments to invoke `func` with.
|
||
* @returns {*} Returns the result of `func`.
|
||
*/
|
||
function apply(func, thisArg, args) {
|
||
switch (args.length) {
|
||
case 0: return func.call(thisArg);
|
||
case 1: return func.call(thisArg, args[0]);
|
||
case 2: return func.call(thisArg, args[0], args[1]);
|
||
case 3: return func.call(thisArg, args[0], args[1], args[2]);
|
||
}
|
||
return func.apply(thisArg, args);
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `_.map` for arrays without support for iteratee
|
||
* shorthands.
|
||
*
|
||
* @private
|
||
* @param {Array} [array] The array to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {Array} Returns the new mapped array.
|
||
*/
|
||
function arrayMap(array, iteratee) {
|
||
var index = -1,
|
||
length = array == null ? 0 : array.length,
|
||
result = Array(length);
|
||
|
||
while (++index < length) {
|
||
result[index] = iteratee(array[index], index, array);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.times` without support for iteratee shorthands
|
||
* or max array length checks.
|
||
*
|
||
* @private
|
||
* @param {number} n The number of times to invoke `iteratee`.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {Array} Returns the array of results.
|
||
*/
|
||
function baseTimes(n, iteratee) {
|
||
var index = -1,
|
||
result = Array(n);
|
||
|
||
while (++index < n) {
|
||
result[index] = iteratee(index);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.unary` without support for storing metadata.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to cap arguments for.
|
||
* @returns {Function} Returns the new capped function.
|
||
*/
|
||
function baseUnary(func) {
|
||
return function(value) {
|
||
return func(value);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.values` and `_.valuesIn` which creates an
|
||
* array of `object` property values corresponding to the property names
|
||
* of `props`.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @param {Array} props The property names to get values for.
|
||
* @returns {Object} Returns the array of property values.
|
||
*/
|
||
function baseValues(object, props) {
|
||
return arrayMap(props, function(key) {
|
||
return object[key];
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Used by `_.template` to escape characters for inclusion in compiled string literals.
|
||
*
|
||
* @private
|
||
* @param {string} chr The matched character to escape.
|
||
* @returns {string} Returns the escaped character.
|
||
*/
|
||
function escapeStringChar(chr) {
|
||
return '\\' + stringEscapes[chr];
|
||
}
|
||
|
||
/**
|
||
* Gets the value at `key` of `object`.
|
||
*
|
||
* @private
|
||
* @param {Object} [object] The object to query.
|
||
* @param {string} key The key of the property to get.
|
||
* @returns {*} Returns the property value.
|
||
*/
|
||
function getValue(object, key) {
|
||
return object == null ? undefined : object[key];
|
||
}
|
||
|
||
/**
|
||
* Creates a unary function that invokes `func` with its argument transformed.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to wrap.
|
||
* @param {Function} transform The argument transform.
|
||
* @returns {Function} Returns the new function.
|
||
*/
|
||
function overArg(func, transform) {
|
||
return function(arg) {
|
||
return func(transform(arg));
|
||
};
|
||
}
|
||
|
||
/** Used for built-in method references. */
|
||
var funcProto = Function.prototype,
|
||
objectProto = Object.prototype;
|
||
|
||
/** Used to detect overreaching core-js shims. */
|
||
var coreJsData = root['__core-js_shared__'];
|
||
|
||
/** Used to resolve the decompiled source of functions. */
|
||
var funcToString = funcProto.toString;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty = objectProto.hasOwnProperty;
|
||
|
||
/** Used to detect methods masquerading as native. */
|
||
var maskSrcKey = (function() {
|
||
var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
|
||
return uid ? ('Symbol(src)_1.' + uid) : '';
|
||
}());
|
||
|
||
/**
|
||
* Used to resolve the
|
||
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
||
* of values.
|
||
*/
|
||
var nativeObjectToString = objectProto.toString;
|
||
|
||
/** Used to infer the `Object` constructor. */
|
||
var objectCtorString = funcToString.call(Object);
|
||
|
||
/** Used to detect if a method is native. */
|
||
var reIsNative = RegExp('^' +
|
||
funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
|
||
.replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
|
||
);
|
||
|
||
/** Built-in value references. */
|
||
var Buffer = moduleExports ? root.Buffer : undefined,
|
||
Symbol = root.Symbol,
|
||
getPrototype = overArg(Object.getPrototypeOf, Object),
|
||
propertyIsEnumerable = objectProto.propertyIsEnumerable,
|
||
symToStringTag = Symbol ? Symbol.toStringTag : undefined;
|
||
|
||
var defineProperty = (function() {
|
||
try {
|
||
var func = getNative(Object, 'defineProperty');
|
||
func({}, '', {});
|
||
return func;
|
||
} catch (e) {}
|
||
}());
|
||
|
||
/* Built-in method references for those with the same name as other `lodash` methods. */
|
||
var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
|
||
nativeKeys = overArg(Object.keys, Object),
|
||
nativeMax = Math.max,
|
||
nativeNow = Date.now;
|
||
|
||
/** Used to convert symbols to primitives and strings. */
|
||
var symbolProto = Symbol ? Symbol.prototype : undefined,
|
||
symbolToString = symbolProto ? symbolProto.toString : undefined;
|
||
|
||
/**
|
||
* Creates an array of the enumerable property names of the array-like `value`.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to query.
|
||
* @param {boolean} inherited Specify returning inherited property names.
|
||
* @returns {Array} Returns the array of property names.
|
||
*/
|
||
function arrayLikeKeys(value, inherited) {
|
||
var isArr = isArray(value),
|
||
isArg = !isArr && isArguments(value),
|
||
isBuff = !isArr && !isArg && isBuffer(value),
|
||
isType = !isArr && !isArg && !isBuff && isTypedArray(value),
|
||
skipIndexes = isArr || isArg || isBuff || isType,
|
||
result = skipIndexes ? baseTimes(value.length, String) : [],
|
||
length = result.length;
|
||
|
||
for (var key in value) {
|
||
if ((inherited || hasOwnProperty.call(value, key)) &&
|
||
!(skipIndexes && (
|
||
// Safari 9 has enumerable `arguments.length` in strict mode.
|
||
key == 'length' ||
|
||
// Node.js 0.10 has enumerable non-index properties on buffers.
|
||
(isBuff && (key == 'offset' || key == 'parent')) ||
|
||
// PhantomJS 2 has enumerable non-index properties on typed arrays.
|
||
(isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
|
||
// Skip index properties.
|
||
isIndex(key, length)
|
||
))) {
|
||
result.push(key);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Assigns `value` to `key` of `object` if the existing value is not equivalent
|
||
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
||
* for equality comparisons.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to modify.
|
||
* @param {string} key The key of the property to assign.
|
||
* @param {*} value The value to assign.
|
||
*/
|
||
function assignValue(object, key, value) {
|
||
var objValue = object[key];
|
||
if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
|
||
(value === undefined && !(key in object))) {
|
||
baseAssignValue(object, key, value);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `assignValue` and `assignMergeValue` without
|
||
* value checks.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to modify.
|
||
* @param {string} key The key of the property to assign.
|
||
* @param {*} value The value to assign.
|
||
*/
|
||
function baseAssignValue(object, key, value) {
|
||
if (key == '__proto__' && defineProperty) {
|
||
defineProperty(object, key, {
|
||
'configurable': true,
|
||
'enumerable': true,
|
||
'value': value,
|
||
'writable': true
|
||
});
|
||
} else {
|
||
object[key] = value;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `getTag` without fallbacks for buggy environments.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to query.
|
||
* @returns {string} Returns the `toStringTag`.
|
||
*/
|
||
function baseGetTag(value) {
|
||
if (value == null) {
|
||
return value === undefined ? undefinedTag : nullTag;
|
||
}
|
||
return (symToStringTag && symToStringTag in Object(value))
|
||
? getRawTag(value)
|
||
: objectToString(value);
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.isArguments`.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is an `arguments` object,
|
||
*/
|
||
function baseIsArguments(value) {
|
||
return isObjectLike(value) && baseGetTag(value) == argsTag;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.isNative` without bad shim checks.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a native function,
|
||
* else `false`.
|
||
*/
|
||
function baseIsNative(value) {
|
||
if (!isObject(value) || isMasked(value)) {
|
||
return false;
|
||
}
|
||
var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
|
||
return pattern.test(toSource(value));
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.isTypedArray` without Node.js optimizations.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
|
||
*/
|
||
function baseIsTypedArray(value) {
|
||
return isObjectLike(value) &&
|
||
isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @returns {Array} Returns the array of property names.
|
||
*/
|
||
function baseKeys(object) {
|
||
if (!isPrototype(object)) {
|
||
return nativeKeys(object);
|
||
}
|
||
var result = [];
|
||
for (var key in Object(object)) {
|
||
if (hasOwnProperty.call(object, key) && key != 'constructor') {
|
||
result.push(key);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @returns {Array} Returns the array of property names.
|
||
*/
|
||
function baseKeysIn(object) {
|
||
if (!isObject(object)) {
|
||
return nativeKeysIn(object);
|
||
}
|
||
var isProto = isPrototype(object),
|
||
result = [];
|
||
|
||
for (var key in object) {
|
||
if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
|
||
result.push(key);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.rest` which doesn't validate or coerce arguments.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to apply a rest parameter to.
|
||
* @param {number} [start=func.length-1] The start position of the rest parameter.
|
||
* @returns {Function} Returns the new function.
|
||
*/
|
||
function baseRest(func, start) {
|
||
return setToString(overRest(func, start, identity), func + '');
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `setToString` without support for hot loop shorting.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to modify.
|
||
* @param {Function} string The `toString` result.
|
||
* @returns {Function} Returns `func`.
|
||
*/
|
||
var baseSetToString = !defineProperty ? identity : function(func, string) {
|
||
return defineProperty(func, 'toString', {
|
||
'configurable': true,
|
||
'enumerable': false,
|
||
'value': constant(string),
|
||
'writable': true
|
||
});
|
||
};
|
||
|
||
/**
|
||
* The base implementation of `_.toString` which doesn't convert nullish
|
||
* values to empty strings.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to process.
|
||
* @returns {string} Returns the string.
|
||
*/
|
||
function baseToString(value) {
|
||
// Exit early for strings to avoid a performance hit in some environments.
|
||
if (typeof value == 'string') {
|
||
return value;
|
||
}
|
||
if (isArray(value)) {
|
||
// Recursively convert values (susceptible to call stack limits).
|
||
return arrayMap(value, baseToString) + '';
|
||
}
|
||
if (isSymbol(value)) {
|
||
return symbolToString ? symbolToString.call(value) : '';
|
||
}
|
||
var result = (value + '');
|
||
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
|
||
}
|
||
|
||
/**
|
||
* Copies properties of `source` to `object`.
|
||
*
|
||
* @private
|
||
* @param {Object} source The object to copy properties from.
|
||
* @param {Array} props The property identifiers to copy.
|
||
* @param {Object} [object={}] The object to copy properties to.
|
||
* @param {Function} [customizer] The function to customize copied values.
|
||
* @returns {Object} Returns `object`.
|
||
*/
|
||
function copyObject(source, props, object, customizer) {
|
||
var isNew = !object;
|
||
object || (object = {});
|
||
|
||
var index = -1,
|
||
length = props.length;
|
||
|
||
while (++index < length) {
|
||
var key = props[index];
|
||
|
||
var newValue = customizer
|
||
? customizer(object[key], source[key], key, object, source)
|
||
: undefined;
|
||
|
||
if (newValue === undefined) {
|
||
newValue = source[key];
|
||
}
|
||
if (isNew) {
|
||
baseAssignValue(object, key, newValue);
|
||
} else {
|
||
assignValue(object, key, newValue);
|
||
}
|
||
}
|
||
return object;
|
||
}
|
||
|
||
/**
|
||
* Creates a function like `_.assign`.
|
||
*
|
||
* @private
|
||
* @param {Function} assigner The function to assign values.
|
||
* @returns {Function} Returns the new assigner function.
|
||
*/
|
||
function createAssigner(assigner) {
|
||
return baseRest(function(object, sources) {
|
||
var index = -1,
|
||
length = sources.length,
|
||
customizer = length > 1 ? sources[length - 1] : undefined,
|
||
guard = length > 2 ? sources[2] : undefined;
|
||
|
||
customizer = (assigner.length > 3 && typeof customizer == 'function')
|
||
? (length--, customizer)
|
||
: undefined;
|
||
|
||
if (guard && isIterateeCall(sources[0], sources[1], guard)) {
|
||
customizer = length < 3 ? undefined : customizer;
|
||
length = 1;
|
||
}
|
||
object = Object(object);
|
||
while (++index < length) {
|
||
var source = sources[index];
|
||
if (source) {
|
||
assigner(object, source, index, customizer);
|
||
}
|
||
}
|
||
return object;
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Used by `_.defaults` to customize its `_.assignIn` use to assign properties
|
||
* of source objects to the destination object for all destination properties
|
||
* that resolve to `undefined`.
|
||
*
|
||
* @private
|
||
* @param {*} objValue The destination value.
|
||
* @param {*} srcValue The source value.
|
||
* @param {string} key The key of the property to assign.
|
||
* @param {Object} object The parent object of `objValue`.
|
||
* @returns {*} Returns the value to assign.
|
||
*/
|
||
function customDefaultsAssignIn(objValue, srcValue, key, object) {
|
||
if (objValue === undefined ||
|
||
(eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
|
||
return srcValue;
|
||
}
|
||
return objValue;
|
||
}
|
||
|
||
/**
|
||
* Gets the native function at `key` of `object`.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @param {string} key The key of the method to get.
|
||
* @returns {*} Returns the function if it's native, else `undefined`.
|
||
*/
|
||
function getNative(object, key) {
|
||
var value = getValue(object, key);
|
||
return baseIsNative(value) ? value : undefined;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to query.
|
||
* @returns {string} Returns the raw `toStringTag`.
|
||
*/
|
||
function getRawTag(value) {
|
||
var isOwn = hasOwnProperty.call(value, symToStringTag),
|
||
tag = value[symToStringTag];
|
||
|
||
try {
|
||
value[symToStringTag] = undefined;
|
||
var unmasked = true;
|
||
} catch (e) {}
|
||
|
||
var result = nativeObjectToString.call(value);
|
||
if (unmasked) {
|
||
if (isOwn) {
|
||
value[symToStringTag] = tag;
|
||
} else {
|
||
delete value[symToStringTag];
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is a valid array-like index.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
|
||
* @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
|
||
*/
|
||
function isIndex(value, length) {
|
||
var type = typeof value;
|
||
length = length == null ? MAX_SAFE_INTEGER : length;
|
||
|
||
return !!length &&
|
||
(type == 'number' ||
|
||
(type != 'symbol' && reIsUint.test(value))) &&
|
||
(value > -1 && value % 1 == 0 && value < length);
|
||
}
|
||
|
||
/**
|
||
* Checks if the given arguments are from an iteratee call.
|
||
*
|
||
* @private
|
||
* @param {*} value The potential iteratee value argument.
|
||
* @param {*} index The potential iteratee index or key argument.
|
||
* @param {*} object The potential iteratee object argument.
|
||
* @returns {boolean} Returns `true` if the arguments are from an iteratee call,
|
||
* else `false`.
|
||
*/
|
||
function isIterateeCall(value, index, object) {
|
||
if (!isObject(object)) {
|
||
return false;
|
||
}
|
||
var type = typeof index;
|
||
if (type == 'number'
|
||
? (isArrayLike(object) && isIndex(index, object.length))
|
||
: (type == 'string' && index in object)
|
||
) {
|
||
return eq(object[index], value);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Checks if `func` has its source masked.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to check.
|
||
* @returns {boolean} Returns `true` if `func` is masked, else `false`.
|
||
*/
|
||
function isMasked(func) {
|
||
return !!maskSrcKey && (maskSrcKey in func);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is likely a prototype object.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
|
||
*/
|
||
function isPrototype(value) {
|
||
var Ctor = value && value.constructor,
|
||
proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
|
||
|
||
return value === proto;
|
||
}
|
||
|
||
/**
|
||
* This function is like
|
||
* [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
|
||
* except that it includes inherited enumerable properties.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @returns {Array} Returns the array of property names.
|
||
*/
|
||
function nativeKeysIn(object) {
|
||
var result = [];
|
||
if (object != null) {
|
||
for (var key in Object(object)) {
|
||
result.push(key);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Converts `value` to a string using `Object.prototype.toString`.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to convert.
|
||
* @returns {string} Returns the converted string.
|
||
*/
|
||
function objectToString(value) {
|
||
return nativeObjectToString.call(value);
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `baseRest` which transforms the rest array.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to apply a rest parameter to.
|
||
* @param {number} [start=func.length-1] The start position of the rest parameter.
|
||
* @param {Function} transform The rest array transform.
|
||
* @returns {Function} Returns the new function.
|
||
*/
|
||
function overRest(func, start, transform) {
|
||
start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
|
||
return function() {
|
||
var args = arguments,
|
||
index = -1,
|
||
length = nativeMax(args.length - start, 0),
|
||
array = Array(length);
|
||
|
||
while (++index < length) {
|
||
array[index] = args[start + index];
|
||
}
|
||
index = -1;
|
||
var otherArgs = Array(start + 1);
|
||
while (++index < start) {
|
||
otherArgs[index] = args[index];
|
||
}
|
||
otherArgs[start] = transform(array);
|
||
return apply(func, this, otherArgs);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Sets the `toString` method of `func` to return `string`.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to modify.
|
||
* @param {Function} string The `toString` result.
|
||
* @returns {Function} Returns `func`.
|
||
*/
|
||
var setToString = shortOut(baseSetToString);
|
||
|
||
/**
|
||
* Creates a function that'll short out and invoke `identity` instead
|
||
* of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
|
||
* milliseconds.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to restrict.
|
||
* @returns {Function} Returns the new shortable function.
|
||
*/
|
||
function shortOut(func) {
|
||
var count = 0,
|
||
lastCalled = 0;
|
||
|
||
return function() {
|
||
var stamp = nativeNow(),
|
||
remaining = HOT_SPAN - (stamp - lastCalled);
|
||
|
||
lastCalled = stamp;
|
||
if (remaining > 0) {
|
||
if (++count >= HOT_COUNT) {
|
||
return arguments[0];
|
||
}
|
||
} else {
|
||
count = 0;
|
||
}
|
||
return func.apply(undefined, arguments);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Converts `func` to its source code.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to convert.
|
||
* @returns {string} Returns the source code.
|
||
*/
|
||
function toSource(func) {
|
||
if (func != null) {
|
||
try {
|
||
return funcToString.call(func);
|
||
} catch (e) {}
|
||
try {
|
||
return (func + '');
|
||
} catch (e) {}
|
||
}
|
||
return '';
|
||
}
|
||
|
||
/**
|
||
* Performs a
|
||
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
||
* comparison between two values to determine if they are equivalent.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Lang
|
||
* @param {*} value The value to compare.
|
||
* @param {*} other The other value to compare.
|
||
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
|
||
* @example
|
||
*
|
||
* var object = { 'a': 1 };
|
||
* var other = { 'a': 1 };
|
||
*
|
||
* _.eq(object, object);
|
||
* // => true
|
||
*
|
||
* _.eq(object, other);
|
||
* // => false
|
||
*
|
||
* _.eq('a', 'a');
|
||
* // => true
|
||
*
|
||
* _.eq('a', Object('a'));
|
||
* // => false
|
||
*
|
||
* _.eq(NaN, NaN);
|
||
* // => true
|
||
*/
|
||
function eq(value, other) {
|
||
return value === other || (value !== value && other !== other);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is likely an `arguments` object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 0.1.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is an `arguments` object,
|
||
* else `false`.
|
||
* @example
|
||
*
|
||
* _.isArguments(function() { return arguments; }());
|
||
* // => true
|
||
*
|
||
* _.isArguments([1, 2, 3]);
|
||
* // => false
|
||
*/
|
||
var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
|
||
return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
|
||
!propertyIsEnumerable.call(value, 'callee');
|
||
};
|
||
|
||
/**
|
||
* Checks if `value` is classified as an `Array` object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 0.1.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is an array, else `false`.
|
||
* @example
|
||
*
|
||
* _.isArray([1, 2, 3]);
|
||
* // => true
|
||
*
|
||
* _.isArray(document.body.children);
|
||
* // => false
|
||
*
|
||
* _.isArray('abc');
|
||
* // => false
|
||
*
|
||
* _.isArray(_.noop);
|
||
* // => false
|
||
*/
|
||
var isArray = Array.isArray;
|
||
|
||
/**
|
||
* Checks if `value` is array-like. A value is considered array-like if it's
|
||
* not a function and has a `value.length` that's an integer greater than or
|
||
* equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is array-like, else `false`.
|
||
* @example
|
||
*
|
||
* _.isArrayLike([1, 2, 3]);
|
||
* // => true
|
||
*
|
||
* _.isArrayLike(document.body.children);
|
||
* // => true
|
||
*
|
||
* _.isArrayLike('abc');
|
||
* // => true
|
||
*
|
||
* _.isArrayLike(_.noop);
|
||
* // => false
|
||
*/
|
||
function isArrayLike(value) {
|
||
return value != null && isLength(value.length) && !isFunction(value);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is a buffer.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.3.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
|
||
* @example
|
||
*
|
||
* _.isBuffer(new Buffer(2));
|
||
* // => true
|
||
*
|
||
* _.isBuffer(new Uint8Array(2));
|
||
* // => false
|
||
*/
|
||
var isBuffer = nativeIsBuffer || stubFalse;
|
||
|
||
/**
|
||
* Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
|
||
* `SyntaxError`, `TypeError`, or `URIError` object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.0.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is an error object, else `false`.
|
||
* @example
|
||
*
|
||
* _.isError(new Error);
|
||
* // => true
|
||
*
|
||
* _.isError(Error);
|
||
* // => false
|
||
*/
|
||
function isError(value) {
|
||
if (!isObjectLike(value)) {
|
||
return false;
|
||
}
|
||
var tag = baseGetTag(value);
|
||
return tag == errorTag || tag == domExcTag ||
|
||
(typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is classified as a `Function` object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 0.1.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a function, else `false`.
|
||
* @example
|
||
*
|
||
* _.isFunction(_);
|
||
* // => true
|
||
*
|
||
* _.isFunction(/abc/);
|
||
* // => false
|
||
*/
|
||
function isFunction(value) {
|
||
if (!isObject(value)) {
|
||
return false;
|
||
}
|
||
// The use of `Object#toString` avoids issues with the `typeof` operator
|
||
// in Safari 9 which returns 'object' for typed arrays and other constructors.
|
||
var tag = baseGetTag(value);
|
||
return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is a valid array-like length.
|
||
*
|
||
* **Note:** This method is loosely based on
|
||
* [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
|
||
* @example
|
||
*
|
||
* _.isLength(3);
|
||
* // => true
|
||
*
|
||
* _.isLength(Number.MIN_VALUE);
|
||
* // => false
|
||
*
|
||
* _.isLength(Infinity);
|
||
* // => false
|
||
*
|
||
* _.isLength('3');
|
||
* // => false
|
||
*/
|
||
function isLength(value) {
|
||
return typeof value == 'number' &&
|
||
value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is the
|
||
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
|
||
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 0.1.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
|
||
* @example
|
||
*
|
||
* _.isObject({});
|
||
* // => true
|
||
*
|
||
* _.isObject([1, 2, 3]);
|
||
* // => true
|
||
*
|
||
* _.isObject(_.noop);
|
||
* // => true
|
||
*
|
||
* _.isObject(null);
|
||
* // => false
|
||
*/
|
||
function isObject(value) {
|
||
var type = typeof value;
|
||
return value != null && (type == 'object' || type == 'function');
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is object-like. A value is object-like if it's not `null`
|
||
* and has a `typeof` result of "object".
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
|
||
* @example
|
||
*
|
||
* _.isObjectLike({});
|
||
* // => true
|
||
*
|
||
* _.isObjectLike([1, 2, 3]);
|
||
* // => true
|
||
*
|
||
* _.isObjectLike(_.noop);
|
||
* // => false
|
||
*
|
||
* _.isObjectLike(null);
|
||
* // => false
|
||
*/
|
||
function isObjectLike(value) {
|
||
return value != null && typeof value == 'object';
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is a plain object, that is, an object created by the
|
||
* `Object` constructor or one with a `[[Prototype]]` of `null`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 0.8.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
|
||
* @example
|
||
*
|
||
* function Foo() {
|
||
* this.a = 1;
|
||
* }
|
||
*
|
||
* _.isPlainObject(new Foo);
|
||
* // => false
|
||
*
|
||
* _.isPlainObject([1, 2, 3]);
|
||
* // => false
|
||
*
|
||
* _.isPlainObject({ 'x': 0, 'y': 0 });
|
||
* // => true
|
||
*
|
||
* _.isPlainObject(Object.create(null));
|
||
* // => true
|
||
*/
|
||
function isPlainObject(value) {
|
||
if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
|
||
return false;
|
||
}
|
||
var proto = getPrototype(value);
|
||
if (proto === null) {
|
||
return true;
|
||
}
|
||
var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
|
||
return typeof Ctor == 'function' && Ctor instanceof Ctor &&
|
||
funcToString.call(Ctor) == objectCtorString;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is classified as a `Symbol` primitive or object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
|
||
* @example
|
||
*
|
||
* _.isSymbol(Symbol.iterator);
|
||
* // => true
|
||
*
|
||
* _.isSymbol('abc');
|
||
* // => false
|
||
*/
|
||
function isSymbol(value) {
|
||
return typeof value == 'symbol' ||
|
||
(isObjectLike(value) && baseGetTag(value) == symbolTag);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is classified as a typed array.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.0.0
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
|
||
* @example
|
||
*
|
||
* _.isTypedArray(new Uint8Array);
|
||
* // => true
|
||
*
|
||
* _.isTypedArray([]);
|
||
* // => false
|
||
*/
|
||
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
|
||
|
||
/**
|
||
* Converts `value` to a string. An empty string is returned for `null`
|
||
* and `undefined` values. The sign of `-0` is preserved.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Lang
|
||
* @param {*} value The value to convert.
|
||
* @returns {string} Returns the converted string.
|
||
* @example
|
||
*
|
||
* _.toString(null);
|
||
* // => ''
|
||
*
|
||
* _.toString(-0);
|
||
* // => '-0'
|
||
*
|
||
* _.toString([1, 2, 3]);
|
||
* // => '1,2,3'
|
||
*/
|
||
function toString(value) {
|
||
return value == null ? '' : baseToString(value);
|
||
}
|
||
|
||
/**
|
||
* This method is like `_.assignIn` except that it accepts `customizer`
|
||
* which is invoked to produce the assigned values. If `customizer` returns
|
||
* `undefined`, assignment is handled by the method instead. The `customizer`
|
||
* is invoked with five arguments: (objValue, srcValue, key, object, source).
|
||
*
|
||
* **Note:** This method mutates `object`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @alias extendWith
|
||
* @category Object
|
||
* @param {Object} object The destination object.
|
||
* @param {...Object} sources The source objects.
|
||
* @param {Function} [customizer] The function to customize assigned values.
|
||
* @returns {Object} Returns `object`.
|
||
* @see _.assignWith
|
||
* @example
|
||
*
|
||
* function customizer(objValue, srcValue) {
|
||
* return _.isUndefined(objValue) ? srcValue : objValue;
|
||
* }
|
||
*
|
||
* var defaults = _.partialRight(_.assignInWith, customizer);
|
||
*
|
||
* defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
|
||
* // => { 'a': 1, 'b': 2 }
|
||
*/
|
||
var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
|
||
copyObject(source, keysIn(source), object, customizer);
|
||
});
|
||
|
||
/**
|
||
* Creates an array of the own enumerable property names of `object`.
|
||
*
|
||
* **Note:** Non-object values are coerced to objects. See the
|
||
* [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
|
||
* for more details.
|
||
*
|
||
* @static
|
||
* @since 0.1.0
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to query.
|
||
* @returns {Array} Returns the array of property names.
|
||
* @example
|
||
*
|
||
* function Foo() {
|
||
* this.a = 1;
|
||
* this.b = 2;
|
||
* }
|
||
*
|
||
* Foo.prototype.c = 3;
|
||
*
|
||
* _.keys(new Foo);
|
||
* // => ['a', 'b'] (iteration order is not guaranteed)
|
||
*
|
||
* _.keys('hi');
|
||
* // => ['0', '1']
|
||
*/
|
||
function keys(object) {
|
||
return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
|
||
}
|
||
|
||
/**
|
||
* Creates an array of the own and inherited enumerable property names of `object`.
|
||
*
|
||
* **Note:** Non-object values are coerced to objects.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.0.0
|
||
* @category Object
|
||
* @param {Object} object The object to query.
|
||
* @returns {Array} Returns the array of property names.
|
||
* @example
|
||
*
|
||
* function Foo() {
|
||
* this.a = 1;
|
||
* this.b = 2;
|
||
* }
|
||
*
|
||
* Foo.prototype.c = 3;
|
||
*
|
||
* _.keysIn(new Foo);
|
||
* // => ['a', 'b', 'c'] (iteration order is not guaranteed)
|
||
*/
|
||
function keysIn(object) {
|
||
return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
|
||
}
|
||
|
||
/**
|
||
* Creates a compiled template function that can interpolate data properties
|
||
* in "interpolate" delimiters, HTML-escape interpolated data properties in
|
||
* "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
|
||
* properties may be accessed as free variables in the template. If a setting
|
||
* object is given, it takes precedence over `_.templateSettings` values.
|
||
*
|
||
* **Note:** In the development build `_.template` utilizes
|
||
* [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
|
||
* for easier debugging.
|
||
*
|
||
* For more information on precompiling templates see
|
||
* [lodash's custom builds documentation](https://lodash.com/custom-builds).
|
||
*
|
||
* For more information on Chrome extension sandboxes see
|
||
* [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
|
||
*
|
||
* @static
|
||
* @since 0.1.0
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The template string.
|
||
* @param {Object} [options={}] The options object.
|
||
* @param {RegExp} [options.escape=_.templateSettings.escape]
|
||
* The HTML "escape" delimiter.
|
||
* @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
|
||
* The "evaluate" delimiter.
|
||
* @param {Object} [options.imports=_.templateSettings.imports]
|
||
* An object to import into the template as free variables.
|
||
* @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
|
||
* The "interpolate" delimiter.
|
||
* @param {string} [options.sourceURL='templateSources[n]']
|
||
* The sourceURL of the compiled template.
|
||
* @param {string} [options.variable='obj']
|
||
* The data object variable name.
|
||
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
||
* @returns {Function} Returns the compiled template function.
|
||
* @example
|
||
*
|
||
* // Use the "interpolate" delimiter to create a compiled template.
|
||
* var compiled = _.template('hello <%= user %>!');
|
||
* compiled({ 'user': 'fred' });
|
||
* // => 'hello fred!'
|
||
*
|
||
* // Use the HTML "escape" delimiter to escape data property values.
|
||
* var compiled = _.template('<b><%- value %></b>');
|
||
* compiled({ 'value': '<script>' });
|
||
* // => '<b><script></b>'
|
||
*
|
||
* // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
|
||
* var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
|
||
* compiled({ 'users': ['fred', 'barney'] });
|
||
* // => '<li>fred</li><li>barney</li>'
|
||
*
|
||
* // Use the internal `print` function in "evaluate" delimiters.
|
||
* var compiled = _.template('<% print("hello " + user); %>!');
|
||
* compiled({ 'user': 'barney' });
|
||
* // => 'hello barney!'
|
||
*
|
||
* // Use the ES template literal delimiter as an "interpolate" delimiter.
|
||
* // Disable support by replacing the "interpolate" delimiter.
|
||
* var compiled = _.template('hello ${ user }!');
|
||
* compiled({ 'user': 'pebbles' });
|
||
* // => 'hello pebbles!'
|
||
*
|
||
* // Use backslashes to treat delimiters as plain text.
|
||
* var compiled = _.template('<%= "\\<%- value %\\>" %>');
|
||
* compiled({ 'value': 'ignored' });
|
||
* // => '<%- value %>'
|
||
*
|
||
* // Use the `imports` option to import `jQuery` as `jq`.
|
||
* var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
|
||
* var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
|
||
* compiled({ 'users': ['fred', 'barney'] });
|
||
* // => '<li>fred</li><li>barney</li>'
|
||
*
|
||
* // Use the `sourceURL` option to specify a custom sourceURL for the template.
|
||
* var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
|
||
* compiled(data);
|
||
* // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
|
||
*
|
||
* // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
|
||
* var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
|
||
* compiled.source;
|
||
* // => function(data) {
|
||
* // var __t, __p = '';
|
||
* // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
|
||
* // return __p;
|
||
* // }
|
||
*
|
||
* // Use custom template delimiters.
|
||
* _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
|
||
* var compiled = _.template('hello {{ user }}!');
|
||
* compiled({ 'user': 'mustache' });
|
||
* // => 'hello mustache!'
|
||
*
|
||
* // Use the `source` property to inline compiled templates for meaningful
|
||
* // line numbers in error messages and stack traces.
|
||
* fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
|
||
* var JST = {\
|
||
* "main": ' + _.template(mainText).source + '\
|
||
* };\
|
||
* ');
|
||
*/
|
||
function template(string, options, guard) {
|
||
// Based on John Resig's `tmpl` implementation
|
||
// (http://ejohn.org/blog/javascript-micro-templating/)
|
||
// and Laura Doktorova's doT.js (https://github.com/olado/doT).
|
||
var settings = templateSettings.imports._.templateSettings || templateSettings;
|
||
|
||
if (guard && isIterateeCall(string, options, guard)) {
|
||
options = undefined;
|
||
}
|
||
string = toString(string);
|
||
options = assignInWith({}, options, settings, customDefaultsAssignIn);
|
||
|
||
var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
|
||
importsKeys = keys(imports),
|
||
importsValues = baseValues(imports, importsKeys);
|
||
|
||
var isEscaping,
|
||
isEvaluating,
|
||
index = 0,
|
||
interpolate = options.interpolate || reNoMatch,
|
||
source = "__p += '";
|
||
|
||
// Compile the regexp to match each delimiter.
|
||
var reDelimiters = RegExp(
|
||
(options.escape || reNoMatch).source + '|' +
|
||
interpolate.source + '|' +
|
||
(interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
|
||
(options.evaluate || reNoMatch).source + '|$'
|
||
, 'g');
|
||
|
||
// Use a sourceURL for easier debugging.
|
||
// The sourceURL gets injected into the source that's eval-ed, so be careful
|
||
// with lookup (in case of e.g. prototype pollution), and strip newlines if any.
|
||
// A newline wouldn't be a valid sourceURL anyway, and it'd enable code injection.
|
||
var sourceURL = hasOwnProperty.call(options, 'sourceURL')
|
||
? ('//# sourceURL=' +
|
||
(options.sourceURL + '').replace(/[\r\n]/g, ' ') +
|
||
'\n')
|
||
: '';
|
||
|
||
string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
|
||
interpolateValue || (interpolateValue = esTemplateValue);
|
||
|
||
// Escape characters that can't be included in string literals.
|
||
source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
|
||
|
||
// Replace delimiters with snippets.
|
||
if (escapeValue) {
|
||
isEscaping = true;
|
||
source += "' +\n__e(" + escapeValue + ") +\n'";
|
||
}
|
||
if (evaluateValue) {
|
||
isEvaluating = true;
|
||
source += "';\n" + evaluateValue + ";\n__p += '";
|
||
}
|
||
if (interpolateValue) {
|
||
source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
|
||
}
|
||
index = offset + match.length;
|
||
|
||
// The JS engine embedded in Adobe products needs `match` returned in
|
||
// order to produce the correct `offset` value.
|
||
return match;
|
||
});
|
||
|
||
source += "';\n";
|
||
|
||
// If `variable` is not specified wrap a with-statement around the generated
|
||
// code to add the data object to the top of the scope chain.
|
||
// Like with sourceURL, we take care to not check the option's prototype,
|
||
// as this configuration is a code injection vector.
|
||
var variable = hasOwnProperty.call(options, 'variable') && options.variable;
|
||
if (!variable) {
|
||
source = 'with (obj) {\n' + source + '\n}\n';
|
||
}
|
||
// Cleanup code by stripping empty strings.
|
||
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
|
||
.replace(reEmptyStringMiddle, '$1')
|
||
.replace(reEmptyStringTrailing, '$1;');
|
||
|
||
// Frame code as the function body.
|
||
source = 'function(' + (variable || 'obj') + ') {\n' +
|
||
(variable
|
||
? ''
|
||
: 'obj || (obj = {});\n'
|
||
) +
|
||
"var __t, __p = ''" +
|
||
(isEscaping
|
||
? ', __e = _.escape'
|
||
: ''
|
||
) +
|
||
(isEvaluating
|
||
? ', __j = Array.prototype.join;\n' +
|
||
"function print() { __p += __j.call(arguments, '') }\n"
|
||
: ';\n'
|
||
) +
|
||
source +
|
||
'return __p\n}';
|
||
|
||
var result = attempt(function() {
|
||
return Function(importsKeys, sourceURL + 'return ' + source)
|
||
.apply(undefined, importsValues);
|
||
});
|
||
|
||
// Provide the compiled function's source by its `toString` method or
|
||
// the `source` property as a convenience for inlining compiled templates.
|
||
result.source = source;
|
||
if (isError(result)) {
|
||
throw result;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Attempts to invoke `func`, returning either the result or the caught error
|
||
* object. Any additional arguments are provided to `func` when it's invoked.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.0.0
|
||
* @category Util
|
||
* @param {Function} func The function to attempt.
|
||
* @param {...*} [args] The arguments to invoke `func` with.
|
||
* @returns {*} Returns the `func` result or error object.
|
||
* @example
|
||
*
|
||
* // Avoid throwing errors for invalid selectors.
|
||
* var elements = _.attempt(function(selector) {
|
||
* return document.querySelectorAll(selector);
|
||
* }, '>_>');
|
||
*
|
||
* if (_.isError(elements)) {
|
||
* elements = [];
|
||
* }
|
||
*/
|
||
var attempt = baseRest(function(func, args) {
|
||
try {
|
||
return apply(func, undefined, args);
|
||
} catch (e) {
|
||
return isError(e) ? e : new Error(e);
|
||
}
|
||
});
|
||
|
||
/**
|
||
* Creates a function that returns `value`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 2.4.0
|
||
* @category Util
|
||
* @param {*} value The value to return from the new function.
|
||
* @returns {Function} Returns the new constant function.
|
||
* @example
|
||
*
|
||
* var objects = _.times(2, _.constant({ 'a': 1 }));
|
||
*
|
||
* console.log(objects);
|
||
* // => [{ 'a': 1 }, { 'a': 1 }]
|
||
*
|
||
* console.log(objects[0] === objects[1]);
|
||
* // => true
|
||
*/
|
||
function constant(value) {
|
||
return function() {
|
||
return value;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* This method returns the first argument it receives.
|
||
*
|
||
* @static
|
||
* @since 0.1.0
|
||
* @memberOf _
|
||
* @category Util
|
||
* @param {*} value Any value.
|
||
* @returns {*} Returns `value`.
|
||
* @example
|
||
*
|
||
* var object = { 'a': 1 };
|
||
*
|
||
* console.log(_.identity(object) === object);
|
||
* // => true
|
||
*/
|
||
function identity(value) {
|
||
return value;
|
||
}
|
||
|
||
/**
|
||
* This method returns `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.13.0
|
||
* @category Util
|
||
* @returns {boolean} Returns `false`.
|
||
* @example
|
||
*
|
||
* _.times(2, _.stubFalse);
|
||
* // => [false, false]
|
||
*/
|
||
function stubFalse() {
|
||
return false;
|
||
}
|
||
|
||
module.exports = template;
|
||
} (lodash_template, lodash_template.exports));
|
||
|
||
var lodash_templateExports = lodash_template.exports;
|
||
var template = /*@__PURE__*/getDefaultExportFromCjs(lodash_templateExports);
|
||
|
||
var ScaffoldThemeType = /* @__PURE__ */ ((ScaffoldThemeType2) => {
|
||
ScaffoldThemeType2["Default"] = "default theme";
|
||
ScaffoldThemeType2["DefaultCustom"] = "default theme + customization";
|
||
ScaffoldThemeType2["Custom"] = "custom theme";
|
||
return ScaffoldThemeType2;
|
||
})(ScaffoldThemeType || {});
|
||
const getPackageManger = () => {
|
||
const name = process.env?.npm_config_user_agent || "npm";
|
||
if (name === "npm") {
|
||
return "npm";
|
||
}
|
||
return name.split("/")[0];
|
||
};
|
||
async function init() {
|
||
oe(picocolorsExports.bold(picocolorsExports.cyan("Welcome to VitePress!")));
|
||
const options = await he(
|
||
{
|
||
root: () => te({
|
||
message: "Where should VitePress initialize the config?",
|
||
initialValue: "./",
|
||
validate(value) {
|
||
}
|
||
}),
|
||
title: () => te({
|
||
message: "Site title:",
|
||
placeholder: "My Awesome Project"
|
||
}),
|
||
description: () => te({
|
||
message: "Site description:",
|
||
placeholder: "A VitePress Site"
|
||
}),
|
||
theme: () => ie({
|
||
message: "Theme:",
|
||
options: [
|
||
{
|
||
// @ts-ignore
|
||
value: "default theme" /* Default */,
|
||
label: "Default Theme",
|
||
hint: "Out of the box, good-looking docs"
|
||
},
|
||
{
|
||
// @ts-ignore
|
||
value: "default theme + customization" /* DefaultCustom */,
|
||
label: "Default Theme + Customization",
|
||
hint: "Add custom CSS and layout slots"
|
||
},
|
||
{
|
||
// @ts-ignore
|
||
value: "custom theme" /* Custom */,
|
||
label: "Custom Theme",
|
||
hint: "Build your own or use external"
|
||
}
|
||
]
|
||
}),
|
||
useTs: () => se({ message: "Use TypeScript for config and theme files?" }),
|
||
injectNpmScripts: () => se({
|
||
message: "Add VitePress npm scripts to package.json?"
|
||
})
|
||
},
|
||
{
|
||
onCancel: () => {
|
||
ue("Cancelled.");
|
||
process.exit(0);
|
||
}
|
||
}
|
||
);
|
||
$e(scaffold(options));
|
||
}
|
||
function scaffold({
|
||
root = "./",
|
||
title = "My Awesome Project",
|
||
description = "A VitePress Site",
|
||
theme,
|
||
useTs,
|
||
injectNpmScripts
|
||
}) {
|
||
const resolvedRoot = path$q.resolve(root);
|
||
const templateDir = path$q.resolve(
|
||
path$q.dirname(fileURLToPath$1(import.meta.url)),
|
||
"../../template"
|
||
);
|
||
const data = {
|
||
title: JSON.stringify(title),
|
||
description: JSON.stringify(description),
|
||
useTs,
|
||
defaultTheme: theme === "default theme" /* Default */ || theme === "default theme + customization" /* DefaultCustom */
|
||
};
|
||
const pkgPath = path$q.resolve("package.json");
|
||
const userPkg = fs$a.existsSync(pkgPath) ? JSON.parse(fs$a.readFileSync(pkgPath, "utf-8")) : {};
|
||
const useMjs = userPkg.type !== "module";
|
||
const renderFile = (file) => {
|
||
const filePath = path$q.resolve(templateDir, file);
|
||
let targetPath = path$q.resolve(resolvedRoot, file);
|
||
if (useMjs && file === ".vitepress/config.js") {
|
||
targetPath = targetPath.replace(/\.js$/, ".mjs");
|
||
}
|
||
if (useTs) {
|
||
targetPath = targetPath.replace(/\.(m?)js$/, ".$1ts");
|
||
}
|
||
const src = fs$a.readFileSync(filePath, "utf-8");
|
||
const compiled = template(src)(data);
|
||
fs$a.outputFileSync(targetPath, compiled);
|
||
};
|
||
const filesToScaffold = [
|
||
"index.md",
|
||
"api-examples.md",
|
||
"markdown-examples.md",
|
||
".vitepress/config.js"
|
||
];
|
||
if (theme === "default theme + customization" /* DefaultCustom */) {
|
||
filesToScaffold.push(
|
||
".vitepress/theme/index.js",
|
||
".vitepress/theme/style.css"
|
||
);
|
||
} else if (theme === "custom theme" /* Custom */) {
|
||
filesToScaffold.push(
|
||
".vitepress/theme/index.js",
|
||
".vitepress/theme/style.css",
|
||
".vitepress/theme/Layout.vue"
|
||
);
|
||
}
|
||
for (const file of filesToScaffold) {
|
||
renderFile(file);
|
||
}
|
||
const dir = root === "./" ? "" : ` ${root.replace(/^\.\//, "").replace(/[/\\]$/, "")}`;
|
||
const gitignorePrefix = dir ? `${dir}/.vitepress` : ".vitepress";
|
||
const tips = [];
|
||
if (fs$a.existsSync(".git")) {
|
||
tips.push(
|
||
`Make sure to add ${picocolorsExports.cyan(`${gitignorePrefix}/dist`)} and ${picocolorsExports.cyan(`${gitignorePrefix}/cache`)} to your ${picocolorsExports.cyan(`.gitignore`)} file.`
|
||
);
|
||
}
|
||
if (theme !== "default theme" /* Default */ && !userPkg.dependencies?.["vue"] && !userPkg.devDependencies?.["vue"]) {
|
||
tips.push(
|
||
`Since you've chosen to customize the theme, you should also explicitly install ${picocolorsExports.cyan(`vue`)} as a dev dependency.`
|
||
);
|
||
}
|
||
const tip = tips.length ? picocolorsExports.yellow([`
|
||
|
||
Tips:`, ...tips].join("\n- ")) : ``;
|
||
if (injectNpmScripts) {
|
||
const scripts = {
|
||
"docs:dev": `vitepress dev${dir}`,
|
||
"docs:build": `vitepress build${dir}`,
|
||
"docs:preview": `vitepress preview${dir}`
|
||
};
|
||
Object.assign(userPkg.scripts || (userPkg.scripts = {}), scripts);
|
||
fs$a.writeFileSync(pkgPath, JSON.stringify(userPkg, null, 2));
|
||
return `Done! Now run ${picocolorsExports.cyan(
|
||
`${getPackageManger()} run docs:dev`
|
||
)} and start writing.${tip}`;
|
||
} else {
|
||
const execCommand = getPackageManger() === "bun" ? "bunx" : "npx";
|
||
return `You're all set! Now run ${picocolorsExports.cyan(
|
||
`${execCommand} vitepress dev${dir}`
|
||
)} and start writing.${tip}`;
|
||
}
|
||
}
|
||
|
||
var compression$2 = {exports: {}};
|
||
|
||
var negotiator = {exports: {}};
|
||
|
||
var charset = {exports: {}};
|
||
|
||
/**
|
||
* negotiator
|
||
* Copyright(c) 2012 Isaac Z. Schlueter
|
||
* Copyright(c) 2014 Federico Romero
|
||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* Module exports.
|
||
* @public
|
||
*/
|
||
|
||
charset.exports = preferredCharsets$1;
|
||
charset.exports.preferredCharsets = preferredCharsets$1;
|
||
|
||
/**
|
||
* Module variables.
|
||
* @private
|
||
*/
|
||
|
||
var simpleCharsetRegExp = /^\s*([^\s;]+)\s*(?:;(.*))?$/;
|
||
|
||
/**
|
||
* Parse the Accept-Charset header.
|
||
* @private
|
||
*/
|
||
|
||
function parseAcceptCharset(accept) {
|
||
var accepts = accept.split(',');
|
||
|
||
for (var i = 0, j = 0; i < accepts.length; i++) {
|
||
var charset = parseCharset(accepts[i].trim(), i);
|
||
|
||
if (charset) {
|
||
accepts[j++] = charset;
|
||
}
|
||
}
|
||
|
||
// trim accepts
|
||
accepts.length = j;
|
||
|
||
return accepts;
|
||
}
|
||
|
||
/**
|
||
* Parse a charset from the Accept-Charset header.
|
||
* @private
|
||
*/
|
||
|
||
function parseCharset(str, i) {
|
||
var match = simpleCharsetRegExp.exec(str);
|
||
if (!match) return null;
|
||
|
||
var charset = match[1];
|
||
var q = 1;
|
||
if (match[2]) {
|
||
var params = match[2].split(';');
|
||
for (var j = 0; j < params.length; j++) {
|
||
var p = params[j].trim().split('=');
|
||
if (p[0] === 'q') {
|
||
q = parseFloat(p[1]);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return {
|
||
charset: charset,
|
||
q: q,
|
||
i: i
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Get the priority of a charset.
|
||
* @private
|
||
*/
|
||
|
||
function getCharsetPriority(charset, accepted, index) {
|
||
var priority = {o: -1, q: 0, s: 0};
|
||
|
||
for (var i = 0; i < accepted.length; i++) {
|
||
var spec = specify$3(charset, accepted[i], index);
|
||
|
||
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
||
priority = spec;
|
||
}
|
||
}
|
||
|
||
return priority;
|
||
}
|
||
|
||
/**
|
||
* Get the specificity of the charset.
|
||
* @private
|
||
*/
|
||
|
||
function specify$3(charset, spec, index) {
|
||
var s = 0;
|
||
if(spec.charset.toLowerCase() === charset.toLowerCase()){
|
||
s |= 1;
|
||
} else if (spec.charset !== '*' ) {
|
||
return null
|
||
}
|
||
|
||
return {
|
||
i: index,
|
||
o: spec.i,
|
||
q: spec.q,
|
||
s: s
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Get the preferred charsets from an Accept-Charset header.
|
||
* @public
|
||
*/
|
||
|
||
function preferredCharsets$1(accept, provided) {
|
||
// RFC 2616 sec 14.2: no header = *
|
||
var accepts = parseAcceptCharset(accept === undefined ? '*' : accept || '');
|
||
|
||
if (!provided) {
|
||
// sorted list of all charsets
|
||
return accepts
|
||
.filter(isQuality$3)
|
||
.sort(compareSpecs$3)
|
||
.map(getFullCharset);
|
||
}
|
||
|
||
var priorities = provided.map(function getPriority(type, index) {
|
||
return getCharsetPriority(type, accepts, index);
|
||
});
|
||
|
||
// sorted list of accepted charsets
|
||
return priorities.filter(isQuality$3).sort(compareSpecs$3).map(function getCharset(priority) {
|
||
return provided[priorities.indexOf(priority)];
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Compare two specs.
|
||
* @private
|
||
*/
|
||
|
||
function compareSpecs$3(a, b) {
|
||
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
|
||
}
|
||
|
||
/**
|
||
* Get full charset string.
|
||
* @private
|
||
*/
|
||
|
||
function getFullCharset(spec) {
|
||
return spec.charset;
|
||
}
|
||
|
||
/**
|
||
* Check if a spec has any quality.
|
||
* @private
|
||
*/
|
||
|
||
function isQuality$3(spec) {
|
||
return spec.q > 0;
|
||
}
|
||
|
||
var charsetExports = charset.exports;
|
||
|
||
var encoding = {exports: {}};
|
||
|
||
/**
|
||
* negotiator
|
||
* Copyright(c) 2012 Isaac Z. Schlueter
|
||
* Copyright(c) 2014 Federico Romero
|
||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* Module exports.
|
||
* @public
|
||
*/
|
||
|
||
encoding.exports = preferredEncodings$1;
|
||
encoding.exports.preferredEncodings = preferredEncodings$1;
|
||
|
||
/**
|
||
* Module variables.
|
||
* @private
|
||
*/
|
||
|
||
var simpleEncodingRegExp = /^\s*([^\s;]+)\s*(?:;(.*))?$/;
|
||
|
||
/**
|
||
* Parse the Accept-Encoding header.
|
||
* @private
|
||
*/
|
||
|
||
function parseAcceptEncoding(accept) {
|
||
var accepts = accept.split(',');
|
||
var hasIdentity = false;
|
||
var minQuality = 1;
|
||
|
||
for (var i = 0, j = 0; i < accepts.length; i++) {
|
||
var encoding = parseEncoding(accepts[i].trim(), i);
|
||
|
||
if (encoding) {
|
||
accepts[j++] = encoding;
|
||
hasIdentity = hasIdentity || specify$2('identity', encoding);
|
||
minQuality = Math.min(minQuality, encoding.q || 1);
|
||
}
|
||
}
|
||
|
||
if (!hasIdentity) {
|
||
/*
|
||
* If identity doesn't explicitly appear in the accept-encoding header,
|
||
* it's added to the list of acceptable encoding with the lowest q
|
||
*/
|
||
accepts[j++] = {
|
||
encoding: 'identity',
|
||
q: minQuality,
|
||
i: i
|
||
};
|
||
}
|
||
|
||
// trim accepts
|
||
accepts.length = j;
|
||
|
||
return accepts;
|
||
}
|
||
|
||
/**
|
||
* Parse an encoding from the Accept-Encoding header.
|
||
* @private
|
||
*/
|
||
|
||
function parseEncoding(str, i) {
|
||
var match = simpleEncodingRegExp.exec(str);
|
||
if (!match) return null;
|
||
|
||
var encoding = match[1];
|
||
var q = 1;
|
||
if (match[2]) {
|
||
var params = match[2].split(';');
|
||
for (var j = 0; j < params.length; j++) {
|
||
var p = params[j].trim().split('=');
|
||
if (p[0] === 'q') {
|
||
q = parseFloat(p[1]);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return {
|
||
encoding: encoding,
|
||
q: q,
|
||
i: i
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Get the priority of an encoding.
|
||
* @private
|
||
*/
|
||
|
||
function getEncodingPriority(encoding, accepted, index) {
|
||
var priority = {o: -1, q: 0, s: 0};
|
||
|
||
for (var i = 0; i < accepted.length; i++) {
|
||
var spec = specify$2(encoding, accepted[i], index);
|
||
|
||
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
||
priority = spec;
|
||
}
|
||
}
|
||
|
||
return priority;
|
||
}
|
||
|
||
/**
|
||
* Get the specificity of the encoding.
|
||
* @private
|
||
*/
|
||
|
||
function specify$2(encoding, spec, index) {
|
||
var s = 0;
|
||
if(spec.encoding.toLowerCase() === encoding.toLowerCase()){
|
||
s |= 1;
|
||
} else if (spec.encoding !== '*' ) {
|
||
return null
|
||
}
|
||
|
||
return {
|
||
i: index,
|
||
o: spec.i,
|
||
q: spec.q,
|
||
s: s
|
||
}
|
||
}
|
||
/**
|
||
* Get the preferred encodings from an Accept-Encoding header.
|
||
* @public
|
||
*/
|
||
|
||
function preferredEncodings$1(accept, provided) {
|
||
var accepts = parseAcceptEncoding(accept || '');
|
||
|
||
if (!provided) {
|
||
// sorted list of all encodings
|
||
return accepts
|
||
.filter(isQuality$2)
|
||
.sort(compareSpecs$2)
|
||
.map(getFullEncoding);
|
||
}
|
||
|
||
var priorities = provided.map(function getPriority(type, index) {
|
||
return getEncodingPriority(type, accepts, index);
|
||
});
|
||
|
||
// sorted list of accepted encodings
|
||
return priorities.filter(isQuality$2).sort(compareSpecs$2).map(function getEncoding(priority) {
|
||
return provided[priorities.indexOf(priority)];
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Compare two specs.
|
||
* @private
|
||
*/
|
||
|
||
function compareSpecs$2(a, b) {
|
||
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
|
||
}
|
||
|
||
/**
|
||
* Get full encoding string.
|
||
* @private
|
||
*/
|
||
|
||
function getFullEncoding(spec) {
|
||
return spec.encoding;
|
||
}
|
||
|
||
/**
|
||
* Check if a spec has any quality.
|
||
* @private
|
||
*/
|
||
|
||
function isQuality$2(spec) {
|
||
return spec.q > 0;
|
||
}
|
||
|
||
var encodingExports = encoding.exports;
|
||
|
||
var language = {exports: {}};
|
||
|
||
/**
|
||
* negotiator
|
||
* Copyright(c) 2012 Isaac Z. Schlueter
|
||
* Copyright(c) 2014 Federico Romero
|
||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* Module exports.
|
||
* @public
|
||
*/
|
||
|
||
language.exports = preferredLanguages$1;
|
||
language.exports.preferredLanguages = preferredLanguages$1;
|
||
|
||
/**
|
||
* Module variables.
|
||
* @private
|
||
*/
|
||
|
||
var simpleLanguageRegExp = /^\s*([^\s\-;]+)(?:-([^\s;]+))?\s*(?:;(.*))?$/;
|
||
|
||
/**
|
||
* Parse the Accept-Language header.
|
||
* @private
|
||
*/
|
||
|
||
function parseAcceptLanguage(accept) {
|
||
var accepts = accept.split(',');
|
||
|
||
for (var i = 0, j = 0; i < accepts.length; i++) {
|
||
var language = parseLanguage(accepts[i].trim(), i);
|
||
|
||
if (language) {
|
||
accepts[j++] = language;
|
||
}
|
||
}
|
||
|
||
// trim accepts
|
||
accepts.length = j;
|
||
|
||
return accepts;
|
||
}
|
||
|
||
/**
|
||
* Parse a language from the Accept-Language header.
|
||
* @private
|
||
*/
|
||
|
||
function parseLanguage(str, i) {
|
||
var match = simpleLanguageRegExp.exec(str);
|
||
if (!match) return null;
|
||
|
||
var prefix = match[1];
|
||
var suffix = match[2];
|
||
var full = prefix;
|
||
|
||
if (suffix) full += "-" + suffix;
|
||
|
||
var q = 1;
|
||
if (match[3]) {
|
||
var params = match[3].split(';');
|
||
for (var j = 0; j < params.length; j++) {
|
||
var p = params[j].split('=');
|
||
if (p[0] === 'q') q = parseFloat(p[1]);
|
||
}
|
||
}
|
||
|
||
return {
|
||
prefix: prefix,
|
||
suffix: suffix,
|
||
q: q,
|
||
i: i,
|
||
full: full
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Get the priority of a language.
|
||
* @private
|
||
*/
|
||
|
||
function getLanguagePriority(language, accepted, index) {
|
||
var priority = {o: -1, q: 0, s: 0};
|
||
|
||
for (var i = 0; i < accepted.length; i++) {
|
||
var spec = specify$1(language, accepted[i], index);
|
||
|
||
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
||
priority = spec;
|
||
}
|
||
}
|
||
|
||
return priority;
|
||
}
|
||
|
||
/**
|
||
* Get the specificity of the language.
|
||
* @private
|
||
*/
|
||
|
||
function specify$1(language, spec, index) {
|
||
var p = parseLanguage(language);
|
||
if (!p) return null;
|
||
var s = 0;
|
||
if(spec.full.toLowerCase() === p.full.toLowerCase()){
|
||
s |= 4;
|
||
} else if (spec.prefix.toLowerCase() === p.full.toLowerCase()) {
|
||
s |= 2;
|
||
} else if (spec.full.toLowerCase() === p.prefix.toLowerCase()) {
|
||
s |= 1;
|
||
} else if (spec.full !== '*' ) {
|
||
return null
|
||
}
|
||
|
||
return {
|
||
i: index,
|
||
o: spec.i,
|
||
q: spec.q,
|
||
s: s
|
||
}
|
||
}
|
||
/**
|
||
* Get the preferred languages from an Accept-Language header.
|
||
* @public
|
||
*/
|
||
|
||
function preferredLanguages$1(accept, provided) {
|
||
// RFC 2616 sec 14.4: no header = *
|
||
var accepts = parseAcceptLanguage(accept === undefined ? '*' : accept || '');
|
||
|
||
if (!provided) {
|
||
// sorted list of all languages
|
||
return accepts
|
||
.filter(isQuality$1)
|
||
.sort(compareSpecs$1)
|
||
.map(getFullLanguage);
|
||
}
|
||
|
||
var priorities = provided.map(function getPriority(type, index) {
|
||
return getLanguagePriority(type, accepts, index);
|
||
});
|
||
|
||
// sorted list of accepted languages
|
||
return priorities.filter(isQuality$1).sort(compareSpecs$1).map(function getLanguage(priority) {
|
||
return provided[priorities.indexOf(priority)];
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Compare two specs.
|
||
* @private
|
||
*/
|
||
|
||
function compareSpecs$1(a, b) {
|
||
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
|
||
}
|
||
|
||
/**
|
||
* Get full language string.
|
||
* @private
|
||
*/
|
||
|
||
function getFullLanguage(spec) {
|
||
return spec.full;
|
||
}
|
||
|
||
/**
|
||
* Check if a spec has any quality.
|
||
* @private
|
||
*/
|
||
|
||
function isQuality$1(spec) {
|
||
return spec.q > 0;
|
||
}
|
||
|
||
var languageExports = language.exports;
|
||
|
||
var mediaType = {exports: {}};
|
||
|
||
/**
|
||
* negotiator
|
||
* Copyright(c) 2012 Isaac Z. Schlueter
|
||
* Copyright(c) 2014 Federico Romero
|
||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* Module exports.
|
||
* @public
|
||
*/
|
||
|
||
mediaType.exports = preferredMediaTypes$1;
|
||
mediaType.exports.preferredMediaTypes = preferredMediaTypes$1;
|
||
|
||
/**
|
||
* Module variables.
|
||
* @private
|
||
*/
|
||
|
||
var simpleMediaTypeRegExp = /^\s*([^\s\/;]+)\/([^;\s]+)\s*(?:;(.*))?$/;
|
||
|
||
/**
|
||
* Parse the Accept header.
|
||
* @private
|
||
*/
|
||
|
||
function parseAccept(accept) {
|
||
var accepts = splitMediaTypes(accept);
|
||
|
||
for (var i = 0, j = 0; i < accepts.length; i++) {
|
||
var mediaType = parseMediaType(accepts[i].trim(), i);
|
||
|
||
if (mediaType) {
|
||
accepts[j++] = mediaType;
|
||
}
|
||
}
|
||
|
||
// trim accepts
|
||
accepts.length = j;
|
||
|
||
return accepts;
|
||
}
|
||
|
||
/**
|
||
* Parse a media type from the Accept header.
|
||
* @private
|
||
*/
|
||
|
||
function parseMediaType(str, i) {
|
||
var match = simpleMediaTypeRegExp.exec(str);
|
||
if (!match) return null;
|
||
|
||
var params = Object.create(null);
|
||
var q = 1;
|
||
var subtype = match[2];
|
||
var type = match[1];
|
||
|
||
if (match[3]) {
|
||
var kvps = splitParameters(match[3]).map(splitKeyValuePair);
|
||
|
||
for (var j = 0; j < kvps.length; j++) {
|
||
var pair = kvps[j];
|
||
var key = pair[0].toLowerCase();
|
||
var val = pair[1];
|
||
|
||
// get the value, unwrapping quotes
|
||
var value = val && val[0] === '"' && val[val.length - 1] === '"'
|
||
? val.substr(1, val.length - 2)
|
||
: val;
|
||
|
||
if (key === 'q') {
|
||
q = parseFloat(value);
|
||
break;
|
||
}
|
||
|
||
// store parameter
|
||
params[key] = value;
|
||
}
|
||
}
|
||
|
||
return {
|
||
type: type,
|
||
subtype: subtype,
|
||
params: params,
|
||
q: q,
|
||
i: i
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Get the priority of a media type.
|
||
* @private
|
||
*/
|
||
|
||
function getMediaTypePriority(type, accepted, index) {
|
||
var priority = {o: -1, q: 0, s: 0};
|
||
|
||
for (var i = 0; i < accepted.length; i++) {
|
||
var spec = specify(type, accepted[i], index);
|
||
|
||
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
||
priority = spec;
|
||
}
|
||
}
|
||
|
||
return priority;
|
||
}
|
||
|
||
/**
|
||
* Get the specificity of the media type.
|
||
* @private
|
||
*/
|
||
|
||
function specify(type, spec, index) {
|
||
var p = parseMediaType(type);
|
||
var s = 0;
|
||
|
||
if (!p) {
|
||
return null;
|
||
}
|
||
|
||
if(spec.type.toLowerCase() == p.type.toLowerCase()) {
|
||
s |= 4;
|
||
} else if(spec.type != '*') {
|
||
return null;
|
||
}
|
||
|
||
if(spec.subtype.toLowerCase() == p.subtype.toLowerCase()) {
|
||
s |= 2;
|
||
} else if(spec.subtype != '*') {
|
||
return null;
|
||
}
|
||
|
||
var keys = Object.keys(spec.params);
|
||
if (keys.length > 0) {
|
||
if (keys.every(function (k) {
|
||
return spec.params[k] == '*' || (spec.params[k] || '').toLowerCase() == (p.params[k] || '').toLowerCase();
|
||
})) {
|
||
s |= 1;
|
||
} else {
|
||
return null
|
||
}
|
||
}
|
||
|
||
return {
|
||
i: index,
|
||
o: spec.i,
|
||
q: spec.q,
|
||
s: s,
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Get the preferred media types from an Accept header.
|
||
* @public
|
||
*/
|
||
|
||
function preferredMediaTypes$1(accept, provided) {
|
||
// RFC 2616 sec 14.2: no header = */*
|
||
var accepts = parseAccept(accept === undefined ? '*/*' : accept || '');
|
||
|
||
if (!provided) {
|
||
// sorted list of all types
|
||
return accepts
|
||
.filter(isQuality)
|
||
.sort(compareSpecs)
|
||
.map(getFullType);
|
||
}
|
||
|
||
var priorities = provided.map(function getPriority(type, index) {
|
||
return getMediaTypePriority(type, accepts, index);
|
||
});
|
||
|
||
// sorted list of accepted types
|
||
return priorities.filter(isQuality).sort(compareSpecs).map(function getType(priority) {
|
||
return provided[priorities.indexOf(priority)];
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Compare two specs.
|
||
* @private
|
||
*/
|
||
|
||
function compareSpecs(a, b) {
|
||
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
|
||
}
|
||
|
||
/**
|
||
* Get full type string.
|
||
* @private
|
||
*/
|
||
|
||
function getFullType(spec) {
|
||
return spec.type + '/' + spec.subtype;
|
||
}
|
||
|
||
/**
|
||
* Check if a spec has any quality.
|
||
* @private
|
||
*/
|
||
|
||
function isQuality(spec) {
|
||
return spec.q > 0;
|
||
}
|
||
|
||
/**
|
||
* Count the number of quotes in a string.
|
||
* @private
|
||
*/
|
||
|
||
function quoteCount(string) {
|
||
var count = 0;
|
||
var index = 0;
|
||
|
||
while ((index = string.indexOf('"', index)) !== -1) {
|
||
count++;
|
||
index++;
|
||
}
|
||
|
||
return count;
|
||
}
|
||
|
||
/**
|
||
* Split a key value pair.
|
||
* @private
|
||
*/
|
||
|
||
function splitKeyValuePair(str) {
|
||
var index = str.indexOf('=');
|
||
var key;
|
||
var val;
|
||
|
||
if (index === -1) {
|
||
key = str;
|
||
} else {
|
||
key = str.substr(0, index);
|
||
val = str.substr(index + 1);
|
||
}
|
||
|
||
return [key, val];
|
||
}
|
||
|
||
/**
|
||
* Split an Accept header into media types.
|
||
* @private
|
||
*/
|
||
|
||
function splitMediaTypes(accept) {
|
||
var accepts = accept.split(',');
|
||
|
||
for (var i = 1, j = 0; i < accepts.length; i++) {
|
||
if (quoteCount(accepts[j]) % 2 == 0) {
|
||
accepts[++j] = accepts[i];
|
||
} else {
|
||
accepts[j] += ',' + accepts[i];
|
||
}
|
||
}
|
||
|
||
// trim accepts
|
||
accepts.length = j + 1;
|
||
|
||
return accepts;
|
||
}
|
||
|
||
/**
|
||
* Split a string of parameters.
|
||
* @private
|
||
*/
|
||
|
||
function splitParameters(str) {
|
||
var parameters = str.split(';');
|
||
|
||
for (var i = 1, j = 0; i < parameters.length; i++) {
|
||
if (quoteCount(parameters[j]) % 2 == 0) {
|
||
parameters[++j] = parameters[i];
|
||
} else {
|
||
parameters[j] += ';' + parameters[i];
|
||
}
|
||
}
|
||
|
||
// trim parameters
|
||
parameters.length = j + 1;
|
||
|
||
for (var i = 0; i < parameters.length; i++) {
|
||
parameters[i] = parameters[i].trim();
|
||
}
|
||
|
||
return parameters;
|
||
}
|
||
|
||
var mediaTypeExports = mediaType.exports;
|
||
|
||
/*!
|
||
* negotiator
|
||
* Copyright(c) 2012 Federico Romero
|
||
* Copyright(c) 2012-2014 Isaac Z. Schlueter
|
||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||
* MIT Licensed
|
||
*/
|
||
|
||
var preferredCharsets = charsetExports;
|
||
var preferredEncodings = encodingExports;
|
||
var preferredLanguages = languageExports;
|
||
var preferredMediaTypes = mediaTypeExports;
|
||
|
||
/**
|
||
* Module exports.
|
||
* @public
|
||
*/
|
||
|
||
negotiator.exports = Negotiator$1;
|
||
negotiator.exports.Negotiator = Negotiator$1;
|
||
|
||
/**
|
||
* Create a Negotiator instance from a request.
|
||
* @param {object} request
|
||
* @public
|
||
*/
|
||
|
||
function Negotiator$1(request) {
|
||
if (!(this instanceof Negotiator$1)) {
|
||
return new Negotiator$1(request);
|
||
}
|
||
|
||
this.request = request;
|
||
}
|
||
|
||
Negotiator$1.prototype.charset = function charset(available) {
|
||
var set = this.charsets(available);
|
||
return set && set[0];
|
||
};
|
||
|
||
Negotiator$1.prototype.charsets = function charsets(available) {
|
||
return preferredCharsets(this.request.headers['accept-charset'], available);
|
||
};
|
||
|
||
Negotiator$1.prototype.encoding = function encoding(available) {
|
||
var set = this.encodings(available);
|
||
return set && set[0];
|
||
};
|
||
|
||
Negotiator$1.prototype.encodings = function encodings(available) {
|
||
return preferredEncodings(this.request.headers['accept-encoding'], available);
|
||
};
|
||
|
||
Negotiator$1.prototype.language = function language(available) {
|
||
var set = this.languages(available);
|
||
return set && set[0];
|
||
};
|
||
|
||
Negotiator$1.prototype.languages = function languages(available) {
|
||
return preferredLanguages(this.request.headers['accept-language'], available);
|
||
};
|
||
|
||
Negotiator$1.prototype.mediaType = function mediaType(available) {
|
||
var set = this.mediaTypes(available);
|
||
return set && set[0];
|
||
};
|
||
|
||
Negotiator$1.prototype.mediaTypes = function mediaTypes(available) {
|
||
return preferredMediaTypes(this.request.headers.accept, available);
|
||
};
|
||
|
||
// Backwards compatibility
|
||
Negotiator$1.prototype.preferredCharset = Negotiator$1.prototype.charset;
|
||
Negotiator$1.prototype.preferredCharsets = Negotiator$1.prototype.charsets;
|
||
Negotiator$1.prototype.preferredEncoding = Negotiator$1.prototype.encoding;
|
||
Negotiator$1.prototype.preferredEncodings = Negotiator$1.prototype.encodings;
|
||
Negotiator$1.prototype.preferredLanguage = Negotiator$1.prototype.language;
|
||
Negotiator$1.prototype.preferredLanguages = Negotiator$1.prototype.languages;
|
||
Negotiator$1.prototype.preferredMediaType = Negotiator$1.prototype.mediaType;
|
||
Negotiator$1.prototype.preferredMediaTypes = Negotiator$1.prototype.mediaTypes;
|
||
|
||
var negotiatorExports = negotiator.exports;
|
||
|
||
var mimeTypes = {};
|
||
|
||
var require$$0 = {
|
||
"application/1d-interleaved-parityfec": {
|
||
source: "iana"
|
||
},
|
||
"application/3gpdash-qoe-report+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/3gpp-ims+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/3gpphal+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/3gpphalforms+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/a2l": {
|
||
source: "iana"
|
||
},
|
||
"application/ace+cbor": {
|
||
source: "iana"
|
||
},
|
||
"application/activemessage": {
|
||
source: "iana"
|
||
},
|
||
"application/activity+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/alto-costmap+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/alto-costmapfilter+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/alto-directory+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/alto-endpointcost+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/alto-endpointcostparams+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/alto-endpointprop+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/alto-endpointpropparams+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/alto-error+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/alto-networkmap+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/alto-networkmapfilter+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/alto-updatestreamcontrol+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/alto-updatestreamparams+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/aml": {
|
||
source: "iana"
|
||
},
|
||
"application/andrew-inset": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ez"
|
||
]
|
||
},
|
||
"application/applefile": {
|
||
source: "iana"
|
||
},
|
||
"application/applixware": {
|
||
source: "apache",
|
||
extensions: [
|
||
"aw"
|
||
]
|
||
},
|
||
"application/at+jwt": {
|
||
source: "iana"
|
||
},
|
||
"application/atf": {
|
||
source: "iana"
|
||
},
|
||
"application/atfx": {
|
||
source: "iana"
|
||
},
|
||
"application/atom+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"atom"
|
||
]
|
||
},
|
||
"application/atomcat+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"atomcat"
|
||
]
|
||
},
|
||
"application/atomdeleted+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"atomdeleted"
|
||
]
|
||
},
|
||
"application/atomicmail": {
|
||
source: "iana"
|
||
},
|
||
"application/atomsvc+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"atomsvc"
|
||
]
|
||
},
|
||
"application/atsc-dwd+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"dwd"
|
||
]
|
||
},
|
||
"application/atsc-dynamic-event-message": {
|
||
source: "iana"
|
||
},
|
||
"application/atsc-held+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"held"
|
||
]
|
||
},
|
||
"application/atsc-rdt+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/atsc-rsat+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"rsat"
|
||
]
|
||
},
|
||
"application/atxml": {
|
||
source: "iana"
|
||
},
|
||
"application/auth-policy+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/bacnet-xdd+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/batch-smtp": {
|
||
source: "iana"
|
||
},
|
||
"application/bdoc": {
|
||
compressible: false,
|
||
extensions: [
|
||
"bdoc"
|
||
]
|
||
},
|
||
"application/beep+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/calendar+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/calendar+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xcs"
|
||
]
|
||
},
|
||
"application/call-completion": {
|
||
source: "iana"
|
||
},
|
||
"application/cals-1840": {
|
||
source: "iana"
|
||
},
|
||
"application/captive+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/cbor": {
|
||
source: "iana"
|
||
},
|
||
"application/cbor-seq": {
|
||
source: "iana"
|
||
},
|
||
"application/cccex": {
|
||
source: "iana"
|
||
},
|
||
"application/ccmp+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/ccxml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"ccxml"
|
||
]
|
||
},
|
||
"application/cdfx+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"cdfx"
|
||
]
|
||
},
|
||
"application/cdmi-capability": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cdmia"
|
||
]
|
||
},
|
||
"application/cdmi-container": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cdmic"
|
||
]
|
||
},
|
||
"application/cdmi-domain": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cdmid"
|
||
]
|
||
},
|
||
"application/cdmi-object": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cdmio"
|
||
]
|
||
},
|
||
"application/cdmi-queue": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cdmiq"
|
||
]
|
||
},
|
||
"application/cdni": {
|
||
source: "iana"
|
||
},
|
||
"application/cea": {
|
||
source: "iana"
|
||
},
|
||
"application/cea-2018+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/cellml+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/cfw": {
|
||
source: "iana"
|
||
},
|
||
"application/city+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/clr": {
|
||
source: "iana"
|
||
},
|
||
"application/clue+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/clue_info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/cms": {
|
||
source: "iana"
|
||
},
|
||
"application/cnrp+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/coap-group+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/coap-payload": {
|
||
source: "iana"
|
||
},
|
||
"application/commonground": {
|
||
source: "iana"
|
||
},
|
||
"application/conference-info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/cose": {
|
||
source: "iana"
|
||
},
|
||
"application/cose-key": {
|
||
source: "iana"
|
||
},
|
||
"application/cose-key-set": {
|
||
source: "iana"
|
||
},
|
||
"application/cpl+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"cpl"
|
||
]
|
||
},
|
||
"application/csrattrs": {
|
||
source: "iana"
|
||
},
|
||
"application/csta+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/cstadata+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/csvm+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/cu-seeme": {
|
||
source: "apache",
|
||
extensions: [
|
||
"cu"
|
||
]
|
||
},
|
||
"application/cwt": {
|
||
source: "iana"
|
||
},
|
||
"application/cybercash": {
|
||
source: "iana"
|
||
},
|
||
"application/dart": {
|
||
compressible: true
|
||
},
|
||
"application/dash+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"mpd"
|
||
]
|
||
},
|
||
"application/dash-patch+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"mpp"
|
||
]
|
||
},
|
||
"application/dashdelta": {
|
||
source: "iana"
|
||
},
|
||
"application/davmount+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"davmount"
|
||
]
|
||
},
|
||
"application/dca-rft": {
|
||
source: "iana"
|
||
},
|
||
"application/dcd": {
|
||
source: "iana"
|
||
},
|
||
"application/dec-dx": {
|
||
source: "iana"
|
||
},
|
||
"application/dialog-info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/dicom": {
|
||
source: "iana"
|
||
},
|
||
"application/dicom+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/dicom+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/dii": {
|
||
source: "iana"
|
||
},
|
||
"application/dit": {
|
||
source: "iana"
|
||
},
|
||
"application/dns": {
|
||
source: "iana"
|
||
},
|
||
"application/dns+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/dns-message": {
|
||
source: "iana"
|
||
},
|
||
"application/docbook+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"dbk"
|
||
]
|
||
},
|
||
"application/dots+cbor": {
|
||
source: "iana"
|
||
},
|
||
"application/dskpp+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/dssc+der": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dssc"
|
||
]
|
||
},
|
||
"application/dssc+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xdssc"
|
||
]
|
||
},
|
||
"application/dvcs": {
|
||
source: "iana"
|
||
},
|
||
"application/ecmascript": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"es",
|
||
"ecma"
|
||
]
|
||
},
|
||
"application/edi-consent": {
|
||
source: "iana"
|
||
},
|
||
"application/edi-x12": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/edifact": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/efi": {
|
||
source: "iana"
|
||
},
|
||
"application/elm+json": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/elm+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/emergencycalldata.cap+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/emergencycalldata.comment+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/emergencycalldata.control+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/emergencycalldata.deviceinfo+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/emergencycalldata.ecall.msd": {
|
||
source: "iana"
|
||
},
|
||
"application/emergencycalldata.providerinfo+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/emergencycalldata.serviceinfo+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/emergencycalldata.subscriberinfo+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/emergencycalldata.veds+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/emma+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"emma"
|
||
]
|
||
},
|
||
"application/emotionml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"emotionml"
|
||
]
|
||
},
|
||
"application/encaprtp": {
|
||
source: "iana"
|
||
},
|
||
"application/epp+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/epub+zip": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"epub"
|
||
]
|
||
},
|
||
"application/eshop": {
|
||
source: "iana"
|
||
},
|
||
"application/exi": {
|
||
source: "iana",
|
||
extensions: [
|
||
"exi"
|
||
]
|
||
},
|
||
"application/expect-ct-report+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/express": {
|
||
source: "iana",
|
||
extensions: [
|
||
"exp"
|
||
]
|
||
},
|
||
"application/fastinfoset": {
|
||
source: "iana"
|
||
},
|
||
"application/fastsoap": {
|
||
source: "iana"
|
||
},
|
||
"application/fdt+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"fdt"
|
||
]
|
||
},
|
||
"application/fhir+json": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/fhir+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/fido.trusted-apps+json": {
|
||
compressible: true
|
||
},
|
||
"application/fits": {
|
||
source: "iana"
|
||
},
|
||
"application/flexfec": {
|
||
source: "iana"
|
||
},
|
||
"application/font-sfnt": {
|
||
source: "iana"
|
||
},
|
||
"application/font-tdpfr": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pfr"
|
||
]
|
||
},
|
||
"application/font-woff": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/framework-attributes+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/geo+json": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"geojson"
|
||
]
|
||
},
|
||
"application/geo+json-seq": {
|
||
source: "iana"
|
||
},
|
||
"application/geopackage+sqlite3": {
|
||
source: "iana"
|
||
},
|
||
"application/geoxacml+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/gltf-buffer": {
|
||
source: "iana"
|
||
},
|
||
"application/gml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"gml"
|
||
]
|
||
},
|
||
"application/gpx+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"gpx"
|
||
]
|
||
},
|
||
"application/gxf": {
|
||
source: "apache",
|
||
extensions: [
|
||
"gxf"
|
||
]
|
||
},
|
||
"application/gzip": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"gz"
|
||
]
|
||
},
|
||
"application/h224": {
|
||
source: "iana"
|
||
},
|
||
"application/held+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/hjson": {
|
||
extensions: [
|
||
"hjson"
|
||
]
|
||
},
|
||
"application/http": {
|
||
source: "iana"
|
||
},
|
||
"application/hyperstudio": {
|
||
source: "iana",
|
||
extensions: [
|
||
"stk"
|
||
]
|
||
},
|
||
"application/ibe-key-request+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/ibe-pkg-reply+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/ibe-pp-data": {
|
||
source: "iana"
|
||
},
|
||
"application/iges": {
|
||
source: "iana"
|
||
},
|
||
"application/im-iscomposing+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/index": {
|
||
source: "iana"
|
||
},
|
||
"application/index.cmd": {
|
||
source: "iana"
|
||
},
|
||
"application/index.obj": {
|
||
source: "iana"
|
||
},
|
||
"application/index.response": {
|
||
source: "iana"
|
||
},
|
||
"application/index.vnd": {
|
||
source: "iana"
|
||
},
|
||
"application/inkml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"ink",
|
||
"inkml"
|
||
]
|
||
},
|
||
"application/iotp": {
|
||
source: "iana"
|
||
},
|
||
"application/ipfix": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ipfix"
|
||
]
|
||
},
|
||
"application/ipp": {
|
||
source: "iana"
|
||
},
|
||
"application/isup": {
|
||
source: "iana"
|
||
},
|
||
"application/its+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"its"
|
||
]
|
||
},
|
||
"application/java-archive": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"jar",
|
||
"war",
|
||
"ear"
|
||
]
|
||
},
|
||
"application/java-serialized-object": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"ser"
|
||
]
|
||
},
|
||
"application/java-vm": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"class"
|
||
]
|
||
},
|
||
"application/javascript": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true,
|
||
extensions: [
|
||
"js",
|
||
"mjs"
|
||
]
|
||
},
|
||
"application/jf2feed+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/jose": {
|
||
source: "iana"
|
||
},
|
||
"application/jose+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/jrd+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/jscalendar+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/json": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true,
|
||
extensions: [
|
||
"json",
|
||
"map"
|
||
]
|
||
},
|
||
"application/json-patch+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/json-seq": {
|
||
source: "iana"
|
||
},
|
||
"application/json5": {
|
||
extensions: [
|
||
"json5"
|
||
]
|
||
},
|
||
"application/jsonml+json": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"jsonml"
|
||
]
|
||
},
|
||
"application/jwk+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/jwk-set+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/jwt": {
|
||
source: "iana"
|
||
},
|
||
"application/kpml-request+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/kpml-response+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/ld+json": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"jsonld"
|
||
]
|
||
},
|
||
"application/lgr+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"lgr"
|
||
]
|
||
},
|
||
"application/link-format": {
|
||
source: "iana"
|
||
},
|
||
"application/load-control+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/lost+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"lostxml"
|
||
]
|
||
},
|
||
"application/lostsync+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/lpf+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/lxf": {
|
||
source: "iana"
|
||
},
|
||
"application/mac-binhex40": {
|
||
source: "iana",
|
||
extensions: [
|
||
"hqx"
|
||
]
|
||
},
|
||
"application/mac-compactpro": {
|
||
source: "apache",
|
||
extensions: [
|
||
"cpt"
|
||
]
|
||
},
|
||
"application/macwriteii": {
|
||
source: "iana"
|
||
},
|
||
"application/mads+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"mads"
|
||
]
|
||
},
|
||
"application/manifest+json": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true,
|
||
extensions: [
|
||
"webmanifest"
|
||
]
|
||
},
|
||
"application/marc": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mrc"
|
||
]
|
||
},
|
||
"application/marcxml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"mrcx"
|
||
]
|
||
},
|
||
"application/mathematica": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ma",
|
||
"nb",
|
||
"mb"
|
||
]
|
||
},
|
||
"application/mathml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"mathml"
|
||
]
|
||
},
|
||
"application/mathml-content+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mathml-presentation+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mbms-associated-procedure-description+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mbms-deregister+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mbms-envelope+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mbms-msk+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mbms-msk-response+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mbms-protection-description+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mbms-reception-report+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mbms-register+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mbms-register-response+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mbms-schedule+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mbms-user-service-description+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mbox": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mbox"
|
||
]
|
||
},
|
||
"application/media-policy-dataset+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"mpf"
|
||
]
|
||
},
|
||
"application/media_control+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mediaservercontrol+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"mscml"
|
||
]
|
||
},
|
||
"application/merge-patch+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/metalink+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"metalink"
|
||
]
|
||
},
|
||
"application/metalink4+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"meta4"
|
||
]
|
||
},
|
||
"application/mets+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"mets"
|
||
]
|
||
},
|
||
"application/mf4": {
|
||
source: "iana"
|
||
},
|
||
"application/mikey": {
|
||
source: "iana"
|
||
},
|
||
"application/mipc": {
|
||
source: "iana"
|
||
},
|
||
"application/missing-blocks+cbor-seq": {
|
||
source: "iana"
|
||
},
|
||
"application/mmt-aei+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"maei"
|
||
]
|
||
},
|
||
"application/mmt-usd+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"musd"
|
||
]
|
||
},
|
||
"application/mods+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"mods"
|
||
]
|
||
},
|
||
"application/moss-keys": {
|
||
source: "iana"
|
||
},
|
||
"application/moss-signature": {
|
||
source: "iana"
|
||
},
|
||
"application/mosskey-data": {
|
||
source: "iana"
|
||
},
|
||
"application/mosskey-request": {
|
||
source: "iana"
|
||
},
|
||
"application/mp21": {
|
||
source: "iana",
|
||
extensions: [
|
||
"m21",
|
||
"mp21"
|
||
]
|
||
},
|
||
"application/mp4": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mp4s",
|
||
"m4p"
|
||
]
|
||
},
|
||
"application/mpeg4-generic": {
|
||
source: "iana"
|
||
},
|
||
"application/mpeg4-iod": {
|
||
source: "iana"
|
||
},
|
||
"application/mpeg4-iod-xmt": {
|
||
source: "iana"
|
||
},
|
||
"application/mrb-consumer+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/mrb-publish+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/msc-ivr+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/msc-mixer+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/msword": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"doc",
|
||
"dot"
|
||
]
|
||
},
|
||
"application/mud+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/multipart-core": {
|
||
source: "iana"
|
||
},
|
||
"application/mxf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mxf"
|
||
]
|
||
},
|
||
"application/n-quads": {
|
||
source: "iana",
|
||
extensions: [
|
||
"nq"
|
||
]
|
||
},
|
||
"application/n-triples": {
|
||
source: "iana",
|
||
extensions: [
|
||
"nt"
|
||
]
|
||
},
|
||
"application/nasdata": {
|
||
source: "iana"
|
||
},
|
||
"application/news-checkgroups": {
|
||
source: "iana",
|
||
charset: "US-ASCII"
|
||
},
|
||
"application/news-groupinfo": {
|
||
source: "iana",
|
||
charset: "US-ASCII"
|
||
},
|
||
"application/news-transmission": {
|
||
source: "iana"
|
||
},
|
||
"application/nlsml+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/node": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cjs"
|
||
]
|
||
},
|
||
"application/nss": {
|
||
source: "iana"
|
||
},
|
||
"application/oauth-authz-req+jwt": {
|
||
source: "iana"
|
||
},
|
||
"application/oblivious-dns-message": {
|
||
source: "iana"
|
||
},
|
||
"application/ocsp-request": {
|
||
source: "iana"
|
||
},
|
||
"application/ocsp-response": {
|
||
source: "iana"
|
||
},
|
||
"application/octet-stream": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"bin",
|
||
"dms",
|
||
"lrf",
|
||
"mar",
|
||
"so",
|
||
"dist",
|
||
"distz",
|
||
"pkg",
|
||
"bpk",
|
||
"dump",
|
||
"elc",
|
||
"deploy",
|
||
"exe",
|
||
"dll",
|
||
"deb",
|
||
"dmg",
|
||
"iso",
|
||
"img",
|
||
"msi",
|
||
"msp",
|
||
"msm",
|
||
"buffer"
|
||
]
|
||
},
|
||
"application/oda": {
|
||
source: "iana",
|
||
extensions: [
|
||
"oda"
|
||
]
|
||
},
|
||
"application/odm+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/odx": {
|
||
source: "iana"
|
||
},
|
||
"application/oebps-package+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"opf"
|
||
]
|
||
},
|
||
"application/ogg": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"ogx"
|
||
]
|
||
},
|
||
"application/omdoc+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"omdoc"
|
||
]
|
||
},
|
||
"application/onenote": {
|
||
source: "apache",
|
||
extensions: [
|
||
"onetoc",
|
||
"onetoc2",
|
||
"onetmp",
|
||
"onepkg"
|
||
]
|
||
},
|
||
"application/opc-nodeset+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/oscore": {
|
||
source: "iana"
|
||
},
|
||
"application/oxps": {
|
||
source: "iana",
|
||
extensions: [
|
||
"oxps"
|
||
]
|
||
},
|
||
"application/p21": {
|
||
source: "iana"
|
||
},
|
||
"application/p21+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/p2p-overlay+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"relo"
|
||
]
|
||
},
|
||
"application/parityfec": {
|
||
source: "iana"
|
||
},
|
||
"application/passport": {
|
||
source: "iana"
|
||
},
|
||
"application/patch-ops-error+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xer"
|
||
]
|
||
},
|
||
"application/pdf": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"pdf"
|
||
]
|
||
},
|
||
"application/pdx": {
|
||
source: "iana"
|
||
},
|
||
"application/pem-certificate-chain": {
|
||
source: "iana"
|
||
},
|
||
"application/pgp-encrypted": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"pgp"
|
||
]
|
||
},
|
||
"application/pgp-keys": {
|
||
source: "iana",
|
||
extensions: [
|
||
"asc"
|
||
]
|
||
},
|
||
"application/pgp-signature": {
|
||
source: "iana",
|
||
extensions: [
|
||
"asc",
|
||
"sig"
|
||
]
|
||
},
|
||
"application/pics-rules": {
|
||
source: "apache",
|
||
extensions: [
|
||
"prf"
|
||
]
|
||
},
|
||
"application/pidf+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/pidf-diff+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/pkcs10": {
|
||
source: "iana",
|
||
extensions: [
|
||
"p10"
|
||
]
|
||
},
|
||
"application/pkcs12": {
|
||
source: "iana"
|
||
},
|
||
"application/pkcs7-mime": {
|
||
source: "iana",
|
||
extensions: [
|
||
"p7m",
|
||
"p7c"
|
||
]
|
||
},
|
||
"application/pkcs7-signature": {
|
||
source: "iana",
|
||
extensions: [
|
||
"p7s"
|
||
]
|
||
},
|
||
"application/pkcs8": {
|
||
source: "iana",
|
||
extensions: [
|
||
"p8"
|
||
]
|
||
},
|
||
"application/pkcs8-encrypted": {
|
||
source: "iana"
|
||
},
|
||
"application/pkix-attr-cert": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ac"
|
||
]
|
||
},
|
||
"application/pkix-cert": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cer"
|
||
]
|
||
},
|
||
"application/pkix-crl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"crl"
|
||
]
|
||
},
|
||
"application/pkix-pkipath": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pkipath"
|
||
]
|
||
},
|
||
"application/pkixcmp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pki"
|
||
]
|
||
},
|
||
"application/pls+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"pls"
|
||
]
|
||
},
|
||
"application/poc-settings+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/postscript": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"ai",
|
||
"eps",
|
||
"ps"
|
||
]
|
||
},
|
||
"application/ppsp-tracker+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/problem+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/problem+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/provenance+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"provx"
|
||
]
|
||
},
|
||
"application/prs.alvestrand.titrax-sheet": {
|
||
source: "iana"
|
||
},
|
||
"application/prs.cww": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cww"
|
||
]
|
||
},
|
||
"application/prs.cyn": {
|
||
source: "iana",
|
||
charset: "7-BIT"
|
||
},
|
||
"application/prs.hpub+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/prs.nprend": {
|
||
source: "iana"
|
||
},
|
||
"application/prs.plucker": {
|
||
source: "iana"
|
||
},
|
||
"application/prs.rdf-xml-crypt": {
|
||
source: "iana"
|
||
},
|
||
"application/prs.xsf+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/pskc+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"pskcxml"
|
||
]
|
||
},
|
||
"application/pvd+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/qsig": {
|
||
source: "iana"
|
||
},
|
||
"application/raml+yaml": {
|
||
compressible: true,
|
||
extensions: [
|
||
"raml"
|
||
]
|
||
},
|
||
"application/raptorfec": {
|
||
source: "iana"
|
||
},
|
||
"application/rdap+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/rdf+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"rdf",
|
||
"owl"
|
||
]
|
||
},
|
||
"application/reginfo+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"rif"
|
||
]
|
||
},
|
||
"application/relax-ng-compact-syntax": {
|
||
source: "iana",
|
||
extensions: [
|
||
"rnc"
|
||
]
|
||
},
|
||
"application/remote-printing": {
|
||
source: "iana"
|
||
},
|
||
"application/reputon+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/resource-lists+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"rl"
|
||
]
|
||
},
|
||
"application/resource-lists-diff+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"rld"
|
||
]
|
||
},
|
||
"application/rfc+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/riscos": {
|
||
source: "iana"
|
||
},
|
||
"application/rlmi+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/rls-services+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"rs"
|
||
]
|
||
},
|
||
"application/route-apd+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"rapd"
|
||
]
|
||
},
|
||
"application/route-s-tsid+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"sls"
|
||
]
|
||
},
|
||
"application/route-usd+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"rusd"
|
||
]
|
||
},
|
||
"application/rpki-ghostbusters": {
|
||
source: "iana",
|
||
extensions: [
|
||
"gbr"
|
||
]
|
||
},
|
||
"application/rpki-manifest": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mft"
|
||
]
|
||
},
|
||
"application/rpki-publication": {
|
||
source: "iana"
|
||
},
|
||
"application/rpki-roa": {
|
||
source: "iana",
|
||
extensions: [
|
||
"roa"
|
||
]
|
||
},
|
||
"application/rpki-updown": {
|
||
source: "iana"
|
||
},
|
||
"application/rsd+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"rsd"
|
||
]
|
||
},
|
||
"application/rss+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"rss"
|
||
]
|
||
},
|
||
"application/rtf": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"rtf"
|
||
]
|
||
},
|
||
"application/rtploopback": {
|
||
source: "iana"
|
||
},
|
||
"application/rtx": {
|
||
source: "iana"
|
||
},
|
||
"application/samlassertion+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/samlmetadata+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/sarif+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/sarif-external-properties+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/sbe": {
|
||
source: "iana"
|
||
},
|
||
"application/sbml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"sbml"
|
||
]
|
||
},
|
||
"application/scaip+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/scim+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/scvp-cv-request": {
|
||
source: "iana",
|
||
extensions: [
|
||
"scq"
|
||
]
|
||
},
|
||
"application/scvp-cv-response": {
|
||
source: "iana",
|
||
extensions: [
|
||
"scs"
|
||
]
|
||
},
|
||
"application/scvp-vp-request": {
|
||
source: "iana",
|
||
extensions: [
|
||
"spq"
|
||
]
|
||
},
|
||
"application/scvp-vp-response": {
|
||
source: "iana",
|
||
extensions: [
|
||
"spp"
|
||
]
|
||
},
|
||
"application/sdp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"sdp"
|
||
]
|
||
},
|
||
"application/secevent+jwt": {
|
||
source: "iana"
|
||
},
|
||
"application/senml+cbor": {
|
||
source: "iana"
|
||
},
|
||
"application/senml+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/senml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"senmlx"
|
||
]
|
||
},
|
||
"application/senml-etch+cbor": {
|
||
source: "iana"
|
||
},
|
||
"application/senml-etch+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/senml-exi": {
|
||
source: "iana"
|
||
},
|
||
"application/sensml+cbor": {
|
||
source: "iana"
|
||
},
|
||
"application/sensml+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/sensml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"sensmlx"
|
||
]
|
||
},
|
||
"application/sensml-exi": {
|
||
source: "iana"
|
||
},
|
||
"application/sep+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/sep-exi": {
|
||
source: "iana"
|
||
},
|
||
"application/session-info": {
|
||
source: "iana"
|
||
},
|
||
"application/set-payment": {
|
||
source: "iana"
|
||
},
|
||
"application/set-payment-initiation": {
|
||
source: "iana",
|
||
extensions: [
|
||
"setpay"
|
||
]
|
||
},
|
||
"application/set-registration": {
|
||
source: "iana"
|
||
},
|
||
"application/set-registration-initiation": {
|
||
source: "iana",
|
||
extensions: [
|
||
"setreg"
|
||
]
|
||
},
|
||
"application/sgml": {
|
||
source: "iana"
|
||
},
|
||
"application/sgml-open-catalog": {
|
||
source: "iana"
|
||
},
|
||
"application/shf+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"shf"
|
||
]
|
||
},
|
||
"application/sieve": {
|
||
source: "iana",
|
||
extensions: [
|
||
"siv",
|
||
"sieve"
|
||
]
|
||
},
|
||
"application/simple-filter+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/simple-message-summary": {
|
||
source: "iana"
|
||
},
|
||
"application/simplesymbolcontainer": {
|
||
source: "iana"
|
||
},
|
||
"application/sipc": {
|
||
source: "iana"
|
||
},
|
||
"application/slate": {
|
||
source: "iana"
|
||
},
|
||
"application/smil": {
|
||
source: "iana"
|
||
},
|
||
"application/smil+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"smi",
|
||
"smil"
|
||
]
|
||
},
|
||
"application/smpte336m": {
|
||
source: "iana"
|
||
},
|
||
"application/soap+fastinfoset": {
|
||
source: "iana"
|
||
},
|
||
"application/soap+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/sparql-query": {
|
||
source: "iana",
|
||
extensions: [
|
||
"rq"
|
||
]
|
||
},
|
||
"application/sparql-results+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"srx"
|
||
]
|
||
},
|
||
"application/spdx+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/spirits-event+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/sql": {
|
||
source: "iana"
|
||
},
|
||
"application/srgs": {
|
||
source: "iana",
|
||
extensions: [
|
||
"gram"
|
||
]
|
||
},
|
||
"application/srgs+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"grxml"
|
||
]
|
||
},
|
||
"application/sru+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"sru"
|
||
]
|
||
},
|
||
"application/ssdl+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"ssdl"
|
||
]
|
||
},
|
||
"application/ssml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"ssml"
|
||
]
|
||
},
|
||
"application/stix+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/swid+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"swidtag"
|
||
]
|
||
},
|
||
"application/tamp-apex-update": {
|
||
source: "iana"
|
||
},
|
||
"application/tamp-apex-update-confirm": {
|
||
source: "iana"
|
||
},
|
||
"application/tamp-community-update": {
|
||
source: "iana"
|
||
},
|
||
"application/tamp-community-update-confirm": {
|
||
source: "iana"
|
||
},
|
||
"application/tamp-error": {
|
||
source: "iana"
|
||
},
|
||
"application/tamp-sequence-adjust": {
|
||
source: "iana"
|
||
},
|
||
"application/tamp-sequence-adjust-confirm": {
|
||
source: "iana"
|
||
},
|
||
"application/tamp-status-query": {
|
||
source: "iana"
|
||
},
|
||
"application/tamp-status-response": {
|
||
source: "iana"
|
||
},
|
||
"application/tamp-update": {
|
||
source: "iana"
|
||
},
|
||
"application/tamp-update-confirm": {
|
||
source: "iana"
|
||
},
|
||
"application/tar": {
|
||
compressible: true
|
||
},
|
||
"application/taxii+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/td+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/tei+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"tei",
|
||
"teicorpus"
|
||
]
|
||
},
|
||
"application/tetra_isi": {
|
||
source: "iana"
|
||
},
|
||
"application/thraud+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"tfi"
|
||
]
|
||
},
|
||
"application/timestamp-query": {
|
||
source: "iana"
|
||
},
|
||
"application/timestamp-reply": {
|
||
source: "iana"
|
||
},
|
||
"application/timestamped-data": {
|
||
source: "iana",
|
||
extensions: [
|
||
"tsd"
|
||
]
|
||
},
|
||
"application/tlsrpt+gzip": {
|
||
source: "iana"
|
||
},
|
||
"application/tlsrpt+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/tnauthlist": {
|
||
source: "iana"
|
||
},
|
||
"application/token-introspection+jwt": {
|
||
source: "iana"
|
||
},
|
||
"application/toml": {
|
||
compressible: true,
|
||
extensions: [
|
||
"toml"
|
||
]
|
||
},
|
||
"application/trickle-ice-sdpfrag": {
|
||
source: "iana"
|
||
},
|
||
"application/trig": {
|
||
source: "iana",
|
||
extensions: [
|
||
"trig"
|
||
]
|
||
},
|
||
"application/ttml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"ttml"
|
||
]
|
||
},
|
||
"application/tve-trigger": {
|
||
source: "iana"
|
||
},
|
||
"application/tzif": {
|
||
source: "iana"
|
||
},
|
||
"application/tzif-leap": {
|
||
source: "iana"
|
||
},
|
||
"application/ubjson": {
|
||
compressible: false,
|
||
extensions: [
|
||
"ubj"
|
||
]
|
||
},
|
||
"application/ulpfec": {
|
||
source: "iana"
|
||
},
|
||
"application/urc-grpsheet+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/urc-ressheet+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"rsheet"
|
||
]
|
||
},
|
||
"application/urc-targetdesc+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"td"
|
||
]
|
||
},
|
||
"application/urc-uisocketdesc+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vcard+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vcard+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vemmi": {
|
||
source: "iana"
|
||
},
|
||
"application/vividence.scriptfile": {
|
||
source: "apache"
|
||
},
|
||
"application/vnd.1000minds.decision-model+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"1km"
|
||
]
|
||
},
|
||
"application/vnd.3gpp-prose+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp-prose-pc3ch+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp-v2x-local-service-information": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3gpp.5gnas": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3gpp.access-transfer-events+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.bsf+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.gmop+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.gtpc": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3gpp.interworking-data": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3gpp.lpp": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3gpp.mc-signalling-ear": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3gpp.mcdata-affiliation-command+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcdata-info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcdata-payload": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3gpp.mcdata-service-config+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcdata-signalling": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3gpp.mcdata-ue-config+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcdata-user-profile+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcptt-affiliation-command+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcptt-floor-request+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcptt-info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcptt-location-info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcptt-mbms-usage-info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcptt-service-config+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcptt-signed+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcptt-ue-config+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcptt-ue-init-config+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcptt-user-profile+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcvideo-affiliation-command+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcvideo-affiliation-info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcvideo-info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcvideo-location-info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcvideo-mbms-usage-info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcvideo-service-config+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcvideo-transmission-request+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcvideo-ue-config+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mcvideo-user-profile+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.mid-call+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.ngap": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3gpp.pfcp": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3gpp.pic-bw-large": {
|
||
source: "iana",
|
||
extensions: [
|
||
"plb"
|
||
]
|
||
},
|
||
"application/vnd.3gpp.pic-bw-small": {
|
||
source: "iana",
|
||
extensions: [
|
||
"psb"
|
||
]
|
||
},
|
||
"application/vnd.3gpp.pic-bw-var": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pvb"
|
||
]
|
||
},
|
||
"application/vnd.3gpp.s1ap": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3gpp.sms": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3gpp.sms+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.srvcc-ext+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.srvcc-info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.state-and-event-info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp.ussd+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp2.bcmcsinfo+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.3gpp2.sms": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3gpp2.tcap": {
|
||
source: "iana",
|
||
extensions: [
|
||
"tcap"
|
||
]
|
||
},
|
||
"application/vnd.3lightssoftware.imagescal": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.3m.post-it-notes": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pwn"
|
||
]
|
||
},
|
||
"application/vnd.accpac.simply.aso": {
|
||
source: "iana",
|
||
extensions: [
|
||
"aso"
|
||
]
|
||
},
|
||
"application/vnd.accpac.simply.imp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"imp"
|
||
]
|
||
},
|
||
"application/vnd.acucobol": {
|
||
source: "iana",
|
||
extensions: [
|
||
"acu"
|
||
]
|
||
},
|
||
"application/vnd.acucorp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"atc",
|
||
"acutc"
|
||
]
|
||
},
|
||
"application/vnd.adobe.air-application-installer-package+zip": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"air"
|
||
]
|
||
},
|
||
"application/vnd.adobe.flash.movie": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.adobe.formscentral.fcdt": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fcdt"
|
||
]
|
||
},
|
||
"application/vnd.adobe.fxp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fxp",
|
||
"fxpl"
|
||
]
|
||
},
|
||
"application/vnd.adobe.partial-upload": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.adobe.xdp+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xdp"
|
||
]
|
||
},
|
||
"application/vnd.adobe.xfdf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xfdf"
|
||
]
|
||
},
|
||
"application/vnd.aether.imp": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.afpc.afplinedata": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.afpc.afplinedata-pagedef": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.afpc.cmoca-cmresource": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.afpc.foca-charset": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.afpc.foca-codedfont": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.afpc.foca-codepage": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.afpc.modca": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.afpc.modca-cmtable": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.afpc.modca-formdef": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.afpc.modca-mediummap": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.afpc.modca-objectcontainer": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.afpc.modca-overlay": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.afpc.modca-pagesegment": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.age": {
|
||
source: "iana",
|
||
extensions: [
|
||
"age"
|
||
]
|
||
},
|
||
"application/vnd.ah-barcode": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ahead.space": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ahead"
|
||
]
|
||
},
|
||
"application/vnd.airzip.filesecure.azf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"azf"
|
||
]
|
||
},
|
||
"application/vnd.airzip.filesecure.azs": {
|
||
source: "iana",
|
||
extensions: [
|
||
"azs"
|
||
]
|
||
},
|
||
"application/vnd.amadeus+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.amazon.ebook": {
|
||
source: "apache",
|
||
extensions: [
|
||
"azw"
|
||
]
|
||
},
|
||
"application/vnd.amazon.mobi8-ebook": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.americandynamics.acc": {
|
||
source: "iana",
|
||
extensions: [
|
||
"acc"
|
||
]
|
||
},
|
||
"application/vnd.amiga.ami": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ami"
|
||
]
|
||
},
|
||
"application/vnd.amundsen.maze+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.android.ota": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.android.package-archive": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"apk"
|
||
]
|
||
},
|
||
"application/vnd.anki": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.anser-web-certificate-issue-initiation": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cii"
|
||
]
|
||
},
|
||
"application/vnd.anser-web-funds-transfer-initiation": {
|
||
source: "apache",
|
||
extensions: [
|
||
"fti"
|
||
]
|
||
},
|
||
"application/vnd.antix.game-component": {
|
||
source: "iana",
|
||
extensions: [
|
||
"atx"
|
||
]
|
||
},
|
||
"application/vnd.apache.arrow.file": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.apache.arrow.stream": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.apache.thrift.binary": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.apache.thrift.compact": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.apache.thrift.json": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.api+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.aplextor.warrp+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.apothekende.reservation+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.apple.installer+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"mpkg"
|
||
]
|
||
},
|
||
"application/vnd.apple.keynote": {
|
||
source: "iana",
|
||
extensions: [
|
||
"key"
|
||
]
|
||
},
|
||
"application/vnd.apple.mpegurl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"m3u8"
|
||
]
|
||
},
|
||
"application/vnd.apple.numbers": {
|
||
source: "iana",
|
||
extensions: [
|
||
"numbers"
|
||
]
|
||
},
|
||
"application/vnd.apple.pages": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pages"
|
||
]
|
||
},
|
||
"application/vnd.apple.pkpass": {
|
||
compressible: false,
|
||
extensions: [
|
||
"pkpass"
|
||
]
|
||
},
|
||
"application/vnd.arastra.swi": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.aristanetworks.swi": {
|
||
source: "iana",
|
||
extensions: [
|
||
"swi"
|
||
]
|
||
},
|
||
"application/vnd.artisan+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.artsquare": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.astraea-software.iota": {
|
||
source: "iana",
|
||
extensions: [
|
||
"iota"
|
||
]
|
||
},
|
||
"application/vnd.audiograph": {
|
||
source: "iana",
|
||
extensions: [
|
||
"aep"
|
||
]
|
||
},
|
||
"application/vnd.autopackage": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.avalon+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.avistar+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.balsamiq.bmml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"bmml"
|
||
]
|
||
},
|
||
"application/vnd.balsamiq.bmpr": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.banana-accounting": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.bbf.usp.error": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.bbf.usp.msg": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.bbf.usp.msg+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.bekitzur-stech+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.bint.med-content": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.biopax.rdf+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.blink-idb-value-wrapper": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.blueice.multipass": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mpm"
|
||
]
|
||
},
|
||
"application/vnd.bluetooth.ep.oob": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.bluetooth.le.oob": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.bmi": {
|
||
source: "iana",
|
||
extensions: [
|
||
"bmi"
|
||
]
|
||
},
|
||
"application/vnd.bpf": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.bpf3": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.businessobjects": {
|
||
source: "iana",
|
||
extensions: [
|
||
"rep"
|
||
]
|
||
},
|
||
"application/vnd.byu.uapi+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.cab-jscript": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.canon-cpdl": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.canon-lips": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.capasystems-pg+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.cendio.thinlinc.clientconf": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.century-systems.tcp_stream": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.chemdraw+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"cdxml"
|
||
]
|
||
},
|
||
"application/vnd.chess-pgn": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.chipnuts.karaoke-mmd": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mmd"
|
||
]
|
||
},
|
||
"application/vnd.ciedi": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.cinderella": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cdy"
|
||
]
|
||
},
|
||
"application/vnd.cirpack.isdn-ext": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.citationstyles.style+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"csl"
|
||
]
|
||
},
|
||
"application/vnd.claymore": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cla"
|
||
]
|
||
},
|
||
"application/vnd.cloanto.rp9": {
|
||
source: "iana",
|
||
extensions: [
|
||
"rp9"
|
||
]
|
||
},
|
||
"application/vnd.clonk.c4group": {
|
||
source: "iana",
|
||
extensions: [
|
||
"c4g",
|
||
"c4d",
|
||
"c4f",
|
||
"c4p",
|
||
"c4u"
|
||
]
|
||
},
|
||
"application/vnd.cluetrust.cartomobile-config": {
|
||
source: "iana",
|
||
extensions: [
|
||
"c11amc"
|
||
]
|
||
},
|
||
"application/vnd.cluetrust.cartomobile-config-pkg": {
|
||
source: "iana",
|
||
extensions: [
|
||
"c11amz"
|
||
]
|
||
},
|
||
"application/vnd.coffeescript": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.collabio.xodocuments.document": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.collabio.xodocuments.document-template": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.collabio.xodocuments.presentation": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.collabio.xodocuments.presentation-template": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.collabio.xodocuments.spreadsheet": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.collabio.xodocuments.spreadsheet-template": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.collection+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.collection.doc+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.collection.next+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.comicbook+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.comicbook-rar": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.commerce-battelle": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.commonspace": {
|
||
source: "iana",
|
||
extensions: [
|
||
"csp"
|
||
]
|
||
},
|
||
"application/vnd.contact.cmsg": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cdbcmsg"
|
||
]
|
||
},
|
||
"application/vnd.coreos.ignition+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.cosmocaller": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cmc"
|
||
]
|
||
},
|
||
"application/vnd.crick.clicker": {
|
||
source: "iana",
|
||
extensions: [
|
||
"clkx"
|
||
]
|
||
},
|
||
"application/vnd.crick.clicker.keyboard": {
|
||
source: "iana",
|
||
extensions: [
|
||
"clkk"
|
||
]
|
||
},
|
||
"application/vnd.crick.clicker.palette": {
|
||
source: "iana",
|
||
extensions: [
|
||
"clkp"
|
||
]
|
||
},
|
||
"application/vnd.crick.clicker.template": {
|
||
source: "iana",
|
||
extensions: [
|
||
"clkt"
|
||
]
|
||
},
|
||
"application/vnd.crick.clicker.wordbank": {
|
||
source: "iana",
|
||
extensions: [
|
||
"clkw"
|
||
]
|
||
},
|
||
"application/vnd.criticaltools.wbs+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"wbs"
|
||
]
|
||
},
|
||
"application/vnd.cryptii.pipe+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.crypto-shade-file": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.cryptomator.encrypted": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.cryptomator.vault": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ctc-posml": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pml"
|
||
]
|
||
},
|
||
"application/vnd.ctct.ws+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.cups-pdf": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.cups-postscript": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.cups-ppd": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ppd"
|
||
]
|
||
},
|
||
"application/vnd.cups-raster": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.cups-raw": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.curl": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.curl.car": {
|
||
source: "apache",
|
||
extensions: [
|
||
"car"
|
||
]
|
||
},
|
||
"application/vnd.curl.pcurl": {
|
||
source: "apache",
|
||
extensions: [
|
||
"pcurl"
|
||
]
|
||
},
|
||
"application/vnd.cyan.dean.root+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.cybank": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.cyclonedx+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.cyclonedx+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.d2l.coursepackage1p0+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.d3m-dataset": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.d3m-problem": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dart": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"dart"
|
||
]
|
||
},
|
||
"application/vnd.data-vision.rdz": {
|
||
source: "iana",
|
||
extensions: [
|
||
"rdz"
|
||
]
|
||
},
|
||
"application/vnd.datapackage+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.dataresource+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.dbf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dbf"
|
||
]
|
||
},
|
||
"application/vnd.debian.binary-package": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dece.data": {
|
||
source: "iana",
|
||
extensions: [
|
||
"uvf",
|
||
"uvvf",
|
||
"uvd",
|
||
"uvvd"
|
||
]
|
||
},
|
||
"application/vnd.dece.ttml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"uvt",
|
||
"uvvt"
|
||
]
|
||
},
|
||
"application/vnd.dece.unspecified": {
|
||
source: "iana",
|
||
extensions: [
|
||
"uvx",
|
||
"uvvx"
|
||
]
|
||
},
|
||
"application/vnd.dece.zip": {
|
||
source: "iana",
|
||
extensions: [
|
||
"uvz",
|
||
"uvvz"
|
||
]
|
||
},
|
||
"application/vnd.denovo.fcselayout-link": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fe_launch"
|
||
]
|
||
},
|
||
"application/vnd.desmume.movie": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dir-bi.plate-dl-nosuffix": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dm.delegation+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.dna": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dna"
|
||
]
|
||
},
|
||
"application/vnd.document+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.dolby.mlp": {
|
||
source: "apache",
|
||
extensions: [
|
||
"mlp"
|
||
]
|
||
},
|
||
"application/vnd.dolby.mobile.1": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dolby.mobile.2": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.doremir.scorecloud-binary-document": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dpgraph": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dpg"
|
||
]
|
||
},
|
||
"application/vnd.dreamfactory": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dfac"
|
||
]
|
||
},
|
||
"application/vnd.drive+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ds-keypoint": {
|
||
source: "apache",
|
||
extensions: [
|
||
"kpxx"
|
||
]
|
||
},
|
||
"application/vnd.dtg.local": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dtg.local.flash": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dtg.local.html": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dvb.ait": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ait"
|
||
]
|
||
},
|
||
"application/vnd.dvb.dvbisl+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.dvb.dvbj": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dvb.esgcontainer": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dvb.ipdcdftnotifaccess": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dvb.ipdcesgaccess": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dvb.ipdcesgaccess2": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dvb.ipdcesgpdd": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dvb.ipdcroaming": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dvb.iptv.alfec-base": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dvb.iptv.alfec-enhancement": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dvb.notif-aggregate-root+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.dvb.notif-container+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.dvb.notif-generic+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.dvb.notif-ia-msglist+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.dvb.notif-ia-registration-request+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.dvb.notif-ia-registration-response+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.dvb.notif-init+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.dvb.pfr": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dvb.service": {
|
||
source: "iana",
|
||
extensions: [
|
||
"svc"
|
||
]
|
||
},
|
||
"application/vnd.dxr": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.dynageo": {
|
||
source: "iana",
|
||
extensions: [
|
||
"geo"
|
||
]
|
||
},
|
||
"application/vnd.dzr": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.easykaraoke.cdgdownload": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ecdis-update": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ecip.rlp": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.eclipse.ditto+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ecowin.chart": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mag"
|
||
]
|
||
},
|
||
"application/vnd.ecowin.filerequest": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ecowin.fileupdate": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ecowin.series": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ecowin.seriesrequest": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ecowin.seriesupdate": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.efi.img": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.efi.iso": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.emclient.accessrequest+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.enliven": {
|
||
source: "iana",
|
||
extensions: [
|
||
"nml"
|
||
]
|
||
},
|
||
"application/vnd.enphase.envoy": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.eprints.data+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.epson.esf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"esf"
|
||
]
|
||
},
|
||
"application/vnd.epson.msf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"msf"
|
||
]
|
||
},
|
||
"application/vnd.epson.quickanime": {
|
||
source: "iana",
|
||
extensions: [
|
||
"qam"
|
||
]
|
||
},
|
||
"application/vnd.epson.salt": {
|
||
source: "iana",
|
||
extensions: [
|
||
"slt"
|
||
]
|
||
},
|
||
"application/vnd.epson.ssf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ssf"
|
||
]
|
||
},
|
||
"application/vnd.ericsson.quickcall": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.espass-espass+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.eszigno3+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"es3",
|
||
"et3"
|
||
]
|
||
},
|
||
"application/vnd.etsi.aoc+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.asic-e+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.etsi.asic-s+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.etsi.cug+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.iptvcommand+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.iptvdiscovery+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.iptvprofile+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.iptvsad-bc+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.iptvsad-cod+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.iptvsad-npvr+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.iptvservice+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.iptvsync+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.iptvueprofile+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.mcid+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.mheg5": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.etsi.overload-control-policy-dataset+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.pstn+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.sci+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.simservs+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.timestamp-token": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.etsi.tsl+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.etsi.tsl.der": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.eu.kasparian.car+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.eudora.data": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.evolv.ecig.profile": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.evolv.ecig.settings": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.evolv.ecig.theme": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.exstream-empower+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.exstream-package": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ezpix-album": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ez2"
|
||
]
|
||
},
|
||
"application/vnd.ezpix-package": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ez3"
|
||
]
|
||
},
|
||
"application/vnd.f-secure.mobile": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.familysearch.gedcom+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.fastcopy-disk-image": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.fdf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fdf"
|
||
]
|
||
},
|
||
"application/vnd.fdsn.mseed": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mseed"
|
||
]
|
||
},
|
||
"application/vnd.fdsn.seed": {
|
||
source: "iana",
|
||
extensions: [
|
||
"seed",
|
||
"dataless"
|
||
]
|
||
},
|
||
"application/vnd.ffsns": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ficlab.flb+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.filmit.zfc": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.fints": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.firemonkeys.cloudcell": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.flographit": {
|
||
source: "iana",
|
||
extensions: [
|
||
"gph"
|
||
]
|
||
},
|
||
"application/vnd.fluxtime.clip": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ftc"
|
||
]
|
||
},
|
||
"application/vnd.font-fontforge-sfd": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.framemaker": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fm",
|
||
"frame",
|
||
"maker",
|
||
"book"
|
||
]
|
||
},
|
||
"application/vnd.frogans.fnc": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fnc"
|
||
]
|
||
},
|
||
"application/vnd.frogans.ltf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ltf"
|
||
]
|
||
},
|
||
"application/vnd.fsc.weblaunch": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fsc"
|
||
]
|
||
},
|
||
"application/vnd.fujifilm.fb.docuworks": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.fujifilm.fb.docuworks.binder": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.fujifilm.fb.docuworks.container": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.fujifilm.fb.jfi+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.fujitsu.oasys": {
|
||
source: "iana",
|
||
extensions: [
|
||
"oas"
|
||
]
|
||
},
|
||
"application/vnd.fujitsu.oasys2": {
|
||
source: "iana",
|
||
extensions: [
|
||
"oa2"
|
||
]
|
||
},
|
||
"application/vnd.fujitsu.oasys3": {
|
||
source: "iana",
|
||
extensions: [
|
||
"oa3"
|
||
]
|
||
},
|
||
"application/vnd.fujitsu.oasysgp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fg5"
|
||
]
|
||
},
|
||
"application/vnd.fujitsu.oasysprs": {
|
||
source: "iana",
|
||
extensions: [
|
||
"bh2"
|
||
]
|
||
},
|
||
"application/vnd.fujixerox.art-ex": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.fujixerox.art4": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.fujixerox.ddd": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ddd"
|
||
]
|
||
},
|
||
"application/vnd.fujixerox.docuworks": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xdw"
|
||
]
|
||
},
|
||
"application/vnd.fujixerox.docuworks.binder": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xbd"
|
||
]
|
||
},
|
||
"application/vnd.fujixerox.docuworks.container": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.fujixerox.hbpl": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.fut-misnet": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.futoin+cbor": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.futoin+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.fuzzysheet": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fzs"
|
||
]
|
||
},
|
||
"application/vnd.genomatix.tuxedo": {
|
||
source: "iana",
|
||
extensions: [
|
||
"txd"
|
||
]
|
||
},
|
||
"application/vnd.gentics.grd+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.geo+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.geocube+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.geogebra.file": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ggb"
|
||
]
|
||
},
|
||
"application/vnd.geogebra.slides": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.geogebra.tool": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ggt"
|
||
]
|
||
},
|
||
"application/vnd.geometry-explorer": {
|
||
source: "iana",
|
||
extensions: [
|
||
"gex",
|
||
"gre"
|
||
]
|
||
},
|
||
"application/vnd.geonext": {
|
||
source: "iana",
|
||
extensions: [
|
||
"gxt"
|
||
]
|
||
},
|
||
"application/vnd.geoplan": {
|
||
source: "iana",
|
||
extensions: [
|
||
"g2w"
|
||
]
|
||
},
|
||
"application/vnd.geospace": {
|
||
source: "iana",
|
||
extensions: [
|
||
"g3w"
|
||
]
|
||
},
|
||
"application/vnd.gerber": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.globalplatform.card-content-mgt": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.globalplatform.card-content-mgt-response": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.gmx": {
|
||
source: "iana",
|
||
extensions: [
|
||
"gmx"
|
||
]
|
||
},
|
||
"application/vnd.google-apps.document": {
|
||
compressible: false,
|
||
extensions: [
|
||
"gdoc"
|
||
]
|
||
},
|
||
"application/vnd.google-apps.presentation": {
|
||
compressible: false,
|
||
extensions: [
|
||
"gslides"
|
||
]
|
||
},
|
||
"application/vnd.google-apps.spreadsheet": {
|
||
compressible: false,
|
||
extensions: [
|
||
"gsheet"
|
||
]
|
||
},
|
||
"application/vnd.google-earth.kml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"kml"
|
||
]
|
||
},
|
||
"application/vnd.google-earth.kmz": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"kmz"
|
||
]
|
||
},
|
||
"application/vnd.gov.sk.e-form+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.gov.sk.e-form+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.gov.sk.xmldatacontainer+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.grafeq": {
|
||
source: "iana",
|
||
extensions: [
|
||
"gqf",
|
||
"gqs"
|
||
]
|
||
},
|
||
"application/vnd.gridmp": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.groove-account": {
|
||
source: "iana",
|
||
extensions: [
|
||
"gac"
|
||
]
|
||
},
|
||
"application/vnd.groove-help": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ghf"
|
||
]
|
||
},
|
||
"application/vnd.groove-identity-message": {
|
||
source: "iana",
|
||
extensions: [
|
||
"gim"
|
||
]
|
||
},
|
||
"application/vnd.groove-injector": {
|
||
source: "iana",
|
||
extensions: [
|
||
"grv"
|
||
]
|
||
},
|
||
"application/vnd.groove-tool-message": {
|
||
source: "iana",
|
||
extensions: [
|
||
"gtm"
|
||
]
|
||
},
|
||
"application/vnd.groove-tool-template": {
|
||
source: "iana",
|
||
extensions: [
|
||
"tpl"
|
||
]
|
||
},
|
||
"application/vnd.groove-vcard": {
|
||
source: "iana",
|
||
extensions: [
|
||
"vcg"
|
||
]
|
||
},
|
||
"application/vnd.hal+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.hal+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"hal"
|
||
]
|
||
},
|
||
"application/vnd.handheld-entertainment+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"zmm"
|
||
]
|
||
},
|
||
"application/vnd.hbci": {
|
||
source: "iana",
|
||
extensions: [
|
||
"hbci"
|
||
]
|
||
},
|
||
"application/vnd.hc+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.hcl-bireports": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.hdt": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.heroku+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.hhe.lesson-player": {
|
||
source: "iana",
|
||
extensions: [
|
||
"les"
|
||
]
|
||
},
|
||
"application/vnd.hl7cda+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/vnd.hl7v2+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/vnd.hp-hpgl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"hpgl"
|
||
]
|
||
},
|
||
"application/vnd.hp-hpid": {
|
||
source: "iana",
|
||
extensions: [
|
||
"hpid"
|
||
]
|
||
},
|
||
"application/vnd.hp-hps": {
|
||
source: "iana",
|
||
extensions: [
|
||
"hps"
|
||
]
|
||
},
|
||
"application/vnd.hp-jlyt": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jlt"
|
||
]
|
||
},
|
||
"application/vnd.hp-pcl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pcl"
|
||
]
|
||
},
|
||
"application/vnd.hp-pclxl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pclxl"
|
||
]
|
||
},
|
||
"application/vnd.httphone": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.hydrostatix.sof-data": {
|
||
source: "iana",
|
||
extensions: [
|
||
"sfd-hdstx"
|
||
]
|
||
},
|
||
"application/vnd.hyper+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.hyper-item+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.hyperdrive+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.hzn-3d-crossword": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ibm.afplinedata": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ibm.electronic-media": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ibm.minipay": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mpy"
|
||
]
|
||
},
|
||
"application/vnd.ibm.modcap": {
|
||
source: "iana",
|
||
extensions: [
|
||
"afp",
|
||
"listafp",
|
||
"list3820"
|
||
]
|
||
},
|
||
"application/vnd.ibm.rights-management": {
|
||
source: "iana",
|
||
extensions: [
|
||
"irm"
|
||
]
|
||
},
|
||
"application/vnd.ibm.secure-container": {
|
||
source: "iana",
|
||
extensions: [
|
||
"sc"
|
||
]
|
||
},
|
||
"application/vnd.iccprofile": {
|
||
source: "iana",
|
||
extensions: [
|
||
"icc",
|
||
"icm"
|
||
]
|
||
},
|
||
"application/vnd.ieee.1905": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.igloader": {
|
||
source: "iana",
|
||
extensions: [
|
||
"igl"
|
||
]
|
||
},
|
||
"application/vnd.imagemeter.folder+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.imagemeter.image+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.immervision-ivp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ivp"
|
||
]
|
||
},
|
||
"application/vnd.immervision-ivu": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ivu"
|
||
]
|
||
},
|
||
"application/vnd.ims.imsccv1p1": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ims.imsccv1p2": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ims.imsccv1p3": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ims.lis.v2.result+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ims.lti.v2.toolconsumerprofile+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ims.lti.v2.toolproxy+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ims.lti.v2.toolproxy.id+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ims.lti.v2.toolsettings+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ims.lti.v2.toolsettings.simple+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.informedcontrol.rms+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.informix-visionary": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.infotech.project": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.infotech.project+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.innopath.wamp.notification": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.insors.igm": {
|
||
source: "iana",
|
||
extensions: [
|
||
"igm"
|
||
]
|
||
},
|
||
"application/vnd.intercon.formnet": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xpw",
|
||
"xpx"
|
||
]
|
||
},
|
||
"application/vnd.intergeo": {
|
||
source: "iana",
|
||
extensions: [
|
||
"i2g"
|
||
]
|
||
},
|
||
"application/vnd.intertrust.digibox": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.intertrust.nncp": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.intu.qbo": {
|
||
source: "iana",
|
||
extensions: [
|
||
"qbo"
|
||
]
|
||
},
|
||
"application/vnd.intu.qfx": {
|
||
source: "iana",
|
||
extensions: [
|
||
"qfx"
|
||
]
|
||
},
|
||
"application/vnd.iptc.g2.catalogitem+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.iptc.g2.conceptitem+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.iptc.g2.knowledgeitem+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.iptc.g2.newsitem+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.iptc.g2.newsmessage+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.iptc.g2.packageitem+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.iptc.g2.planningitem+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ipunplugged.rcprofile": {
|
||
source: "iana",
|
||
extensions: [
|
||
"rcprofile"
|
||
]
|
||
},
|
||
"application/vnd.irepository.package+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"irp"
|
||
]
|
||
},
|
||
"application/vnd.is-xpr": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xpr"
|
||
]
|
||
},
|
||
"application/vnd.isac.fcs": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fcs"
|
||
]
|
||
},
|
||
"application/vnd.iso11783-10+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.jam": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jam"
|
||
]
|
||
},
|
||
"application/vnd.japannet-directory-service": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.japannet-jpnstore-wakeup": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.japannet-payment-wakeup": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.japannet-registration": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.japannet-registration-wakeup": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.japannet-setstore-wakeup": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.japannet-verification": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.japannet-verification-wakeup": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.jcp.javame.midlet-rms": {
|
||
source: "iana",
|
||
extensions: [
|
||
"rms"
|
||
]
|
||
},
|
||
"application/vnd.jisp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jisp"
|
||
]
|
||
},
|
||
"application/vnd.joost.joda-archive": {
|
||
source: "iana",
|
||
extensions: [
|
||
"joda"
|
||
]
|
||
},
|
||
"application/vnd.jsk.isdn-ngn": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.kahootz": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ktz",
|
||
"ktr"
|
||
]
|
||
},
|
||
"application/vnd.kde.karbon": {
|
||
source: "iana",
|
||
extensions: [
|
||
"karbon"
|
||
]
|
||
},
|
||
"application/vnd.kde.kchart": {
|
||
source: "iana",
|
||
extensions: [
|
||
"chrt"
|
||
]
|
||
},
|
||
"application/vnd.kde.kformula": {
|
||
source: "iana",
|
||
extensions: [
|
||
"kfo"
|
||
]
|
||
},
|
||
"application/vnd.kde.kivio": {
|
||
source: "iana",
|
||
extensions: [
|
||
"flw"
|
||
]
|
||
},
|
||
"application/vnd.kde.kontour": {
|
||
source: "iana",
|
||
extensions: [
|
||
"kon"
|
||
]
|
||
},
|
||
"application/vnd.kde.kpresenter": {
|
||
source: "iana",
|
||
extensions: [
|
||
"kpr",
|
||
"kpt"
|
||
]
|
||
},
|
||
"application/vnd.kde.kspread": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ksp"
|
||
]
|
||
},
|
||
"application/vnd.kde.kword": {
|
||
source: "iana",
|
||
extensions: [
|
||
"kwd",
|
||
"kwt"
|
||
]
|
||
},
|
||
"application/vnd.kenameaapp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"htke"
|
||
]
|
||
},
|
||
"application/vnd.kidspiration": {
|
||
source: "iana",
|
||
extensions: [
|
||
"kia"
|
||
]
|
||
},
|
||
"application/vnd.kinar": {
|
||
source: "iana",
|
||
extensions: [
|
||
"kne",
|
||
"knp"
|
||
]
|
||
},
|
||
"application/vnd.koan": {
|
||
source: "iana",
|
||
extensions: [
|
||
"skp",
|
||
"skd",
|
||
"skt",
|
||
"skm"
|
||
]
|
||
},
|
||
"application/vnd.kodak-descriptor": {
|
||
source: "iana",
|
||
extensions: [
|
||
"sse"
|
||
]
|
||
},
|
||
"application/vnd.las": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.las.las+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.las.las+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"lasxml"
|
||
]
|
||
},
|
||
"application/vnd.laszip": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.leap+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.liberty-request+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.llamagraphics.life-balance.desktop": {
|
||
source: "iana",
|
||
extensions: [
|
||
"lbd"
|
||
]
|
||
},
|
||
"application/vnd.llamagraphics.life-balance.exchange+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"lbe"
|
||
]
|
||
},
|
||
"application/vnd.logipipe.circuit+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.loom": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.lotus-1-2-3": {
|
||
source: "iana",
|
||
extensions: [
|
||
"123"
|
||
]
|
||
},
|
||
"application/vnd.lotus-approach": {
|
||
source: "iana",
|
||
extensions: [
|
||
"apr"
|
||
]
|
||
},
|
||
"application/vnd.lotus-freelance": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pre"
|
||
]
|
||
},
|
||
"application/vnd.lotus-notes": {
|
||
source: "iana",
|
||
extensions: [
|
||
"nsf"
|
||
]
|
||
},
|
||
"application/vnd.lotus-organizer": {
|
||
source: "iana",
|
||
extensions: [
|
||
"org"
|
||
]
|
||
},
|
||
"application/vnd.lotus-screencam": {
|
||
source: "iana",
|
||
extensions: [
|
||
"scm"
|
||
]
|
||
},
|
||
"application/vnd.lotus-wordpro": {
|
||
source: "iana",
|
||
extensions: [
|
||
"lwp"
|
||
]
|
||
},
|
||
"application/vnd.macports.portpkg": {
|
||
source: "iana",
|
||
extensions: [
|
||
"portpkg"
|
||
]
|
||
},
|
||
"application/vnd.mapbox-vector-tile": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mvt"
|
||
]
|
||
},
|
||
"application/vnd.marlin.drm.actiontoken+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.marlin.drm.conftoken+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.marlin.drm.license+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.marlin.drm.mdcf": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.mason+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.maxar.archive.3tz+zip": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"application/vnd.maxmind.maxmind-db": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.mcd": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mcd"
|
||
]
|
||
},
|
||
"application/vnd.medcalcdata": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mc1"
|
||
]
|
||
},
|
||
"application/vnd.mediastation.cdkey": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cdkey"
|
||
]
|
||
},
|
||
"application/vnd.meridian-slingshot": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.mfer": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mwf"
|
||
]
|
||
},
|
||
"application/vnd.mfmp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mfm"
|
||
]
|
||
},
|
||
"application/vnd.micro+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.micrografx.flo": {
|
||
source: "iana",
|
||
extensions: [
|
||
"flo"
|
||
]
|
||
},
|
||
"application/vnd.micrografx.igx": {
|
||
source: "iana",
|
||
extensions: [
|
||
"igx"
|
||
]
|
||
},
|
||
"application/vnd.microsoft.portable-executable": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.microsoft.windows.thumbnail-cache": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.miele+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.mif": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mif"
|
||
]
|
||
},
|
||
"application/vnd.minisoft-hp3000-save": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.mitsubishi.misty-guard.trustweb": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.mobius.daf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"daf"
|
||
]
|
||
},
|
||
"application/vnd.mobius.dis": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dis"
|
||
]
|
||
},
|
||
"application/vnd.mobius.mbk": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mbk"
|
||
]
|
||
},
|
||
"application/vnd.mobius.mqy": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mqy"
|
||
]
|
||
},
|
||
"application/vnd.mobius.msl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"msl"
|
||
]
|
||
},
|
||
"application/vnd.mobius.plc": {
|
||
source: "iana",
|
||
extensions: [
|
||
"plc"
|
||
]
|
||
},
|
||
"application/vnd.mobius.txf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"txf"
|
||
]
|
||
},
|
||
"application/vnd.mophun.application": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mpn"
|
||
]
|
||
},
|
||
"application/vnd.mophun.certificate": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mpc"
|
||
]
|
||
},
|
||
"application/vnd.motorola.flexsuite": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.motorola.flexsuite.adsi": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.motorola.flexsuite.fis": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.motorola.flexsuite.gotap": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.motorola.flexsuite.kmr": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.motorola.flexsuite.ttc": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.motorola.flexsuite.wem": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.motorola.iprm": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.mozilla.xul+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xul"
|
||
]
|
||
},
|
||
"application/vnd.ms-3mfdocument": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ms-artgalry": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cil"
|
||
]
|
||
},
|
||
"application/vnd.ms-asf": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ms-cab-compressed": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cab"
|
||
]
|
||
},
|
||
"application/vnd.ms-color.iccprofile": {
|
||
source: "apache"
|
||
},
|
||
"application/vnd.ms-excel": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"xls",
|
||
"xlm",
|
||
"xla",
|
||
"xlc",
|
||
"xlt",
|
||
"xlw"
|
||
]
|
||
},
|
||
"application/vnd.ms-excel.addin.macroenabled.12": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xlam"
|
||
]
|
||
},
|
||
"application/vnd.ms-excel.sheet.binary.macroenabled.12": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xlsb"
|
||
]
|
||
},
|
||
"application/vnd.ms-excel.sheet.macroenabled.12": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xlsm"
|
||
]
|
||
},
|
||
"application/vnd.ms-excel.template.macroenabled.12": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xltm"
|
||
]
|
||
},
|
||
"application/vnd.ms-fontobject": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"eot"
|
||
]
|
||
},
|
||
"application/vnd.ms-htmlhelp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"chm"
|
||
]
|
||
},
|
||
"application/vnd.ms-ims": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ims"
|
||
]
|
||
},
|
||
"application/vnd.ms-lrm": {
|
||
source: "iana",
|
||
extensions: [
|
||
"lrm"
|
||
]
|
||
},
|
||
"application/vnd.ms-office.activex+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ms-officetheme": {
|
||
source: "iana",
|
||
extensions: [
|
||
"thmx"
|
||
]
|
||
},
|
||
"application/vnd.ms-opentype": {
|
||
source: "apache",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ms-outlook": {
|
||
compressible: false,
|
||
extensions: [
|
||
"msg"
|
||
]
|
||
},
|
||
"application/vnd.ms-package.obfuscated-opentype": {
|
||
source: "apache"
|
||
},
|
||
"application/vnd.ms-pki.seccat": {
|
||
source: "apache",
|
||
extensions: [
|
||
"cat"
|
||
]
|
||
},
|
||
"application/vnd.ms-pki.stl": {
|
||
source: "apache",
|
||
extensions: [
|
||
"stl"
|
||
]
|
||
},
|
||
"application/vnd.ms-playready.initiator+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ms-powerpoint": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"ppt",
|
||
"pps",
|
||
"pot"
|
||
]
|
||
},
|
||
"application/vnd.ms-powerpoint.addin.macroenabled.12": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ppam"
|
||
]
|
||
},
|
||
"application/vnd.ms-powerpoint.presentation.macroenabled.12": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pptm"
|
||
]
|
||
},
|
||
"application/vnd.ms-powerpoint.slide.macroenabled.12": {
|
||
source: "iana",
|
||
extensions: [
|
||
"sldm"
|
||
]
|
||
},
|
||
"application/vnd.ms-powerpoint.slideshow.macroenabled.12": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ppsm"
|
||
]
|
||
},
|
||
"application/vnd.ms-powerpoint.template.macroenabled.12": {
|
||
source: "iana",
|
||
extensions: [
|
||
"potm"
|
||
]
|
||
},
|
||
"application/vnd.ms-printdevicecapabilities+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ms-printing.printticket+xml": {
|
||
source: "apache",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ms-printschematicket+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ms-project": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mpp",
|
||
"mpt"
|
||
]
|
||
},
|
||
"application/vnd.ms-tnef": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ms-windows.devicepairing": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ms-windows.nwprinting.oob": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ms-windows.printerpairing": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ms-windows.wsd.oob": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ms-wmdrm.lic-chlg-req": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ms-wmdrm.lic-resp": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ms-wmdrm.meter-chlg-req": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ms-wmdrm.meter-resp": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ms-word.document.macroenabled.12": {
|
||
source: "iana",
|
||
extensions: [
|
||
"docm"
|
||
]
|
||
},
|
||
"application/vnd.ms-word.template.macroenabled.12": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dotm"
|
||
]
|
||
},
|
||
"application/vnd.ms-works": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wps",
|
||
"wks",
|
||
"wcm",
|
||
"wdb"
|
||
]
|
||
},
|
||
"application/vnd.ms-wpl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wpl"
|
||
]
|
||
},
|
||
"application/vnd.ms-xpsdocument": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"xps"
|
||
]
|
||
},
|
||
"application/vnd.msa-disk-image": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.mseq": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mseq"
|
||
]
|
||
},
|
||
"application/vnd.msign": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.multiad.creator": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.multiad.creator.cif": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.music-niff": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.musician": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mus"
|
||
]
|
||
},
|
||
"application/vnd.muvee.style": {
|
||
source: "iana",
|
||
extensions: [
|
||
"msty"
|
||
]
|
||
},
|
||
"application/vnd.mynfc": {
|
||
source: "iana",
|
||
extensions: [
|
||
"taglet"
|
||
]
|
||
},
|
||
"application/vnd.nacamar.ybrid+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.ncd.control": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ncd.reference": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.nearst.inv+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.nebumind.line": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.nervana": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.netfpx": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.neurolanguage.nlu": {
|
||
source: "iana",
|
||
extensions: [
|
||
"nlu"
|
||
]
|
||
},
|
||
"application/vnd.nimn": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.nintendo.nitro.rom": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.nintendo.snes.rom": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.nitf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ntf",
|
||
"nitf"
|
||
]
|
||
},
|
||
"application/vnd.noblenet-directory": {
|
||
source: "iana",
|
||
extensions: [
|
||
"nnd"
|
||
]
|
||
},
|
||
"application/vnd.noblenet-sealer": {
|
||
source: "iana",
|
||
extensions: [
|
||
"nns"
|
||
]
|
||
},
|
||
"application/vnd.noblenet-web": {
|
||
source: "iana",
|
||
extensions: [
|
||
"nnw"
|
||
]
|
||
},
|
||
"application/vnd.nokia.catalogs": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.nokia.conml+wbxml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.nokia.conml+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.nokia.iptv.config+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.nokia.isds-radio-presets": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.nokia.landmark+wbxml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.nokia.landmark+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.nokia.landmarkcollection+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.nokia.n-gage.ac+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"ac"
|
||
]
|
||
},
|
||
"application/vnd.nokia.n-gage.data": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ngdat"
|
||
]
|
||
},
|
||
"application/vnd.nokia.n-gage.symbian.install": {
|
||
source: "iana",
|
||
extensions: [
|
||
"n-gage"
|
||
]
|
||
},
|
||
"application/vnd.nokia.ncd": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.nokia.pcd+wbxml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.nokia.pcd+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.nokia.radio-preset": {
|
||
source: "iana",
|
||
extensions: [
|
||
"rpst"
|
||
]
|
||
},
|
||
"application/vnd.nokia.radio-presets": {
|
||
source: "iana",
|
||
extensions: [
|
||
"rpss"
|
||
]
|
||
},
|
||
"application/vnd.novadigm.edm": {
|
||
source: "iana",
|
||
extensions: [
|
||
"edm"
|
||
]
|
||
},
|
||
"application/vnd.novadigm.edx": {
|
||
source: "iana",
|
||
extensions: [
|
||
"edx"
|
||
]
|
||
},
|
||
"application/vnd.novadigm.ext": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ext"
|
||
]
|
||
},
|
||
"application/vnd.ntt-local.content-share": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ntt-local.file-transfer": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ntt-local.ogw_remote-access": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ntt-local.sip-ta_remote": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ntt-local.sip-ta_tcp_stream": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oasis.opendocument.chart": {
|
||
source: "iana",
|
||
extensions: [
|
||
"odc"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.chart-template": {
|
||
source: "iana",
|
||
extensions: [
|
||
"otc"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.database": {
|
||
source: "iana",
|
||
extensions: [
|
||
"odb"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.formula": {
|
||
source: "iana",
|
||
extensions: [
|
||
"odf"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.formula-template": {
|
||
source: "iana",
|
||
extensions: [
|
||
"odft"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.graphics": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"odg"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.graphics-template": {
|
||
source: "iana",
|
||
extensions: [
|
||
"otg"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.image": {
|
||
source: "iana",
|
||
extensions: [
|
||
"odi"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.image-template": {
|
||
source: "iana",
|
||
extensions: [
|
||
"oti"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.presentation": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"odp"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.presentation-template": {
|
||
source: "iana",
|
||
extensions: [
|
||
"otp"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.spreadsheet": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"ods"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.spreadsheet-template": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ots"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.text": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"odt"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.text-master": {
|
||
source: "iana",
|
||
extensions: [
|
||
"odm"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.text-template": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ott"
|
||
]
|
||
},
|
||
"application/vnd.oasis.opendocument.text-web": {
|
||
source: "iana",
|
||
extensions: [
|
||
"oth"
|
||
]
|
||
},
|
||
"application/vnd.obn": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ocf+cbor": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oci.image.manifest.v1+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oftn.l10n+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oipf.contentaccessdownload+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oipf.contentaccessstreaming+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oipf.cspg-hexbinary": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oipf.dae.svg+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oipf.dae.xhtml+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oipf.mippvcontrolmessage+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oipf.pae.gem": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oipf.spdiscovery+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oipf.spdlist+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oipf.ueprofile+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oipf.userprofile+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.olpc-sugar": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xo"
|
||
]
|
||
},
|
||
"application/vnd.oma-scws-config": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma-scws-http-request": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma-scws-http-response": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma.bcast.associated-procedure-parameter+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.bcast.drm-trigger+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.bcast.imd+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.bcast.ltkm": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma.bcast.notification+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.bcast.provisioningtrigger": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma.bcast.sgboot": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma.bcast.sgdd+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.bcast.sgdu": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma.bcast.simple-symbol-container": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma.bcast.smartcard-trigger+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.bcast.sprov+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.bcast.stkm": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma.cab-address-book+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.cab-feature-handler+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.cab-pcc+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.cab-subs-invite+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.cab-user-prefs+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.dcd": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma.dcdc": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma.dd2+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"dd2"
|
||
]
|
||
},
|
||
"application/vnd.oma.drm.risd+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.group-usage-list+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.lwm2m+cbor": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma.lwm2m+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.lwm2m+tlv": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma.pal+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.poc.detailed-progress-report+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.poc.final-report+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.poc.groups+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.poc.invocation-descriptor+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.poc.optimized-progress-report+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.push": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.oma.scidm.messages+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oma.xcap-directory+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.omads-email+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/vnd.omads-file+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/vnd.omads-folder+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/vnd.omaloc-supl-init": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.onepager": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.onepagertamp": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.onepagertamx": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.onepagertat": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.onepagertatp": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.onepagertatx": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.openblox.game+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"obgx"
|
||
]
|
||
},
|
||
"application/vnd.openblox.game-binary": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.openeye.oeb": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.openofficeorg.extension": {
|
||
source: "apache",
|
||
extensions: [
|
||
"oxt"
|
||
]
|
||
},
|
||
"application/vnd.openstreetmap.data+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"osm"
|
||
]
|
||
},
|
||
"application/vnd.opentimestamps.ots": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.custom-properties+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.customxmlproperties+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.drawing+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.drawingml.chart+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.extended-properties+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.comments+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.presentation": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"pptx"
|
||
]
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.presprops+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.slide": {
|
||
source: "iana",
|
||
extensions: [
|
||
"sldx"
|
||
]
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.slide+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.slideshow": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ppsx"
|
||
]
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.tags+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.template": {
|
||
source: "iana",
|
||
extensions: [
|
||
"potx"
|
||
]
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.template.main+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"xlsx"
|
||
]
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.template": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xltx"
|
||
]
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.theme+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.themeoverride+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.vmldrawing": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"docx"
|
||
]
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.template": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dotx"
|
||
]
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-package.core-properties+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.openxmlformats-package.relationships+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oracle.resource+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.orange.indata": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.osa.netdeploy": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.osgeo.mapguide.package": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mgp"
|
||
]
|
||
},
|
||
"application/vnd.osgi.bundle": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.osgi.dp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dp"
|
||
]
|
||
},
|
||
"application/vnd.osgi.subsystem": {
|
||
source: "iana",
|
||
extensions: [
|
||
"esa"
|
||
]
|
||
},
|
||
"application/vnd.otps.ct-kip+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.oxli.countgraph": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.pagerduty+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.palm": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pdb",
|
||
"pqa",
|
||
"oprc"
|
||
]
|
||
},
|
||
"application/vnd.panoply": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.paos.xml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.patentdive": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.patientecommsdoc": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.pawaafile": {
|
||
source: "iana",
|
||
extensions: [
|
||
"paw"
|
||
]
|
||
},
|
||
"application/vnd.pcos": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.pg.format": {
|
||
source: "iana",
|
||
extensions: [
|
||
"str"
|
||
]
|
||
},
|
||
"application/vnd.pg.osasli": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ei6"
|
||
]
|
||
},
|
||
"application/vnd.piaccess.application-licence": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.picsel": {
|
||
source: "iana",
|
||
extensions: [
|
||
"efif"
|
||
]
|
||
},
|
||
"application/vnd.pmi.widget": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wg"
|
||
]
|
||
},
|
||
"application/vnd.poc.group-advertisement+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.pocketlearn": {
|
||
source: "iana",
|
||
extensions: [
|
||
"plf"
|
||
]
|
||
},
|
||
"application/vnd.powerbuilder6": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pbd"
|
||
]
|
||
},
|
||
"application/vnd.powerbuilder6-s": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.powerbuilder7": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.powerbuilder7-s": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.powerbuilder75": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.powerbuilder75-s": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.preminet": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.previewsystems.box": {
|
||
source: "iana",
|
||
extensions: [
|
||
"box"
|
||
]
|
||
},
|
||
"application/vnd.proteus.magazine": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mgz"
|
||
]
|
||
},
|
||
"application/vnd.psfs": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.publishare-delta-tree": {
|
||
source: "iana",
|
||
extensions: [
|
||
"qps"
|
||
]
|
||
},
|
||
"application/vnd.pvi.ptid1": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ptid"
|
||
]
|
||
},
|
||
"application/vnd.pwg-multiplexed": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.pwg-xhtml-print+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.qualcomm.brew-app-res": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.quarantainenet": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.quark.quarkxpress": {
|
||
source: "iana",
|
||
extensions: [
|
||
"qxd",
|
||
"qxt",
|
||
"qwd",
|
||
"qwt",
|
||
"qxl",
|
||
"qxb"
|
||
]
|
||
},
|
||
"application/vnd.quobject-quoxdocument": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.radisys.moml+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml-audit+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml-audit-conf+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml-audit-conn+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml-audit-dialog+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml-audit-stream+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml-conf+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml-dialog+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml-dialog-base+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml-dialog-fax-detect+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml-dialog-fax-sendrecv+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml-dialog-group+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml-dialog-speech+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.radisys.msml-dialog-transform+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.rainstor.data": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.rapid": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.rar": {
|
||
source: "iana",
|
||
extensions: [
|
||
"rar"
|
||
]
|
||
},
|
||
"application/vnd.realvnc.bed": {
|
||
source: "iana",
|
||
extensions: [
|
||
"bed"
|
||
]
|
||
},
|
||
"application/vnd.recordare.musicxml": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mxl"
|
||
]
|
||
},
|
||
"application/vnd.recordare.musicxml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"musicxml"
|
||
]
|
||
},
|
||
"application/vnd.renlearn.rlprint": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.resilient.logic": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.restful+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.rig.cryptonote": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cryptonote"
|
||
]
|
||
},
|
||
"application/vnd.rim.cod": {
|
||
source: "apache",
|
||
extensions: [
|
||
"cod"
|
||
]
|
||
},
|
||
"application/vnd.rn-realmedia": {
|
||
source: "apache",
|
||
extensions: [
|
||
"rm"
|
||
]
|
||
},
|
||
"application/vnd.rn-realmedia-vbr": {
|
||
source: "apache",
|
||
extensions: [
|
||
"rmvb"
|
||
]
|
||
},
|
||
"application/vnd.route66.link66+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"link66"
|
||
]
|
||
},
|
||
"application/vnd.rs-274x": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ruckus.download": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.s3sms": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sailingtracker.track": {
|
||
source: "iana",
|
||
extensions: [
|
||
"st"
|
||
]
|
||
},
|
||
"application/vnd.sar": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sbm.cid": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sbm.mid2": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.scribus": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sealed.3df": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sealed.csf": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sealed.doc": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sealed.eml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sealed.mht": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sealed.net": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sealed.ppt": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sealed.tiff": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sealed.xls": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sealedmedia.softseal.html": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sealedmedia.softseal.pdf": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.seemail": {
|
||
source: "iana",
|
||
extensions: [
|
||
"see"
|
||
]
|
||
},
|
||
"application/vnd.seis+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.sema": {
|
||
source: "iana",
|
||
extensions: [
|
||
"sema"
|
||
]
|
||
},
|
||
"application/vnd.semd": {
|
||
source: "iana",
|
||
extensions: [
|
||
"semd"
|
||
]
|
||
},
|
||
"application/vnd.semf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"semf"
|
||
]
|
||
},
|
||
"application/vnd.shade-save-file": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.shana.informed.formdata": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ifm"
|
||
]
|
||
},
|
||
"application/vnd.shana.informed.formtemplate": {
|
||
source: "iana",
|
||
extensions: [
|
||
"itp"
|
||
]
|
||
},
|
||
"application/vnd.shana.informed.interchange": {
|
||
source: "iana",
|
||
extensions: [
|
||
"iif"
|
||
]
|
||
},
|
||
"application/vnd.shana.informed.package": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ipk"
|
||
]
|
||
},
|
||
"application/vnd.shootproof+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.shopkick+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.shp": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.shx": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sigrok.session": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.simtech-mindmapper": {
|
||
source: "iana",
|
||
extensions: [
|
||
"twd",
|
||
"twds"
|
||
]
|
||
},
|
||
"application/vnd.siren+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.smaf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mmf"
|
||
]
|
||
},
|
||
"application/vnd.smart.notebook": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.smart.teacher": {
|
||
source: "iana",
|
||
extensions: [
|
||
"teacher"
|
||
]
|
||
},
|
||
"application/vnd.snesdev-page-table": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.software602.filler.form+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"fo"
|
||
]
|
||
},
|
||
"application/vnd.software602.filler.form-xml-zip": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.solent.sdkm+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"sdkm",
|
||
"sdkd"
|
||
]
|
||
},
|
||
"application/vnd.spotfire.dxp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dxp"
|
||
]
|
||
},
|
||
"application/vnd.spotfire.sfs": {
|
||
source: "iana",
|
||
extensions: [
|
||
"sfs"
|
||
]
|
||
},
|
||
"application/vnd.sqlite3": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sss-cod": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sss-dtf": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sss-ntf": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.stardivision.calc": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sdc"
|
||
]
|
||
},
|
||
"application/vnd.stardivision.draw": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sda"
|
||
]
|
||
},
|
||
"application/vnd.stardivision.impress": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sdd"
|
||
]
|
||
},
|
||
"application/vnd.stardivision.math": {
|
||
source: "apache",
|
||
extensions: [
|
||
"smf"
|
||
]
|
||
},
|
||
"application/vnd.stardivision.writer": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sdw",
|
||
"vor"
|
||
]
|
||
},
|
||
"application/vnd.stardivision.writer-global": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sgl"
|
||
]
|
||
},
|
||
"application/vnd.stepmania.package": {
|
||
source: "iana",
|
||
extensions: [
|
||
"smzip"
|
||
]
|
||
},
|
||
"application/vnd.stepmania.stepchart": {
|
||
source: "iana",
|
||
extensions: [
|
||
"sm"
|
||
]
|
||
},
|
||
"application/vnd.street-stream": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sun.wadl+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"wadl"
|
||
]
|
||
},
|
||
"application/vnd.sun.xml.calc": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sxc"
|
||
]
|
||
},
|
||
"application/vnd.sun.xml.calc.template": {
|
||
source: "apache",
|
||
extensions: [
|
||
"stc"
|
||
]
|
||
},
|
||
"application/vnd.sun.xml.draw": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sxd"
|
||
]
|
||
},
|
||
"application/vnd.sun.xml.draw.template": {
|
||
source: "apache",
|
||
extensions: [
|
||
"std"
|
||
]
|
||
},
|
||
"application/vnd.sun.xml.impress": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sxi"
|
||
]
|
||
},
|
||
"application/vnd.sun.xml.impress.template": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sti"
|
||
]
|
||
},
|
||
"application/vnd.sun.xml.math": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sxm"
|
||
]
|
||
},
|
||
"application/vnd.sun.xml.writer": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sxw"
|
||
]
|
||
},
|
||
"application/vnd.sun.xml.writer.global": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sxg"
|
||
]
|
||
},
|
||
"application/vnd.sun.xml.writer.template": {
|
||
source: "apache",
|
||
extensions: [
|
||
"stw"
|
||
]
|
||
},
|
||
"application/vnd.sus-calendar": {
|
||
source: "iana",
|
||
extensions: [
|
||
"sus",
|
||
"susp"
|
||
]
|
||
},
|
||
"application/vnd.svd": {
|
||
source: "iana",
|
||
extensions: [
|
||
"svd"
|
||
]
|
||
},
|
||
"application/vnd.swiftview-ics": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.sycle+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.syft+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.symbian.install": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sis",
|
||
"sisx"
|
||
]
|
||
},
|
||
"application/vnd.syncml+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true,
|
||
extensions: [
|
||
"xsm"
|
||
]
|
||
},
|
||
"application/vnd.syncml.dm+wbxml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
extensions: [
|
||
"bdm"
|
||
]
|
||
},
|
||
"application/vnd.syncml.dm+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true,
|
||
extensions: [
|
||
"xdm"
|
||
]
|
||
},
|
||
"application/vnd.syncml.dm.notification": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.syncml.dmddf+wbxml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.syncml.dmddf+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true,
|
||
extensions: [
|
||
"ddf"
|
||
]
|
||
},
|
||
"application/vnd.syncml.dmtnds+wbxml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.syncml.dmtnds+xml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true
|
||
},
|
||
"application/vnd.syncml.ds.notification": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.tableschema+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.tao.intent-module-archive": {
|
||
source: "iana",
|
||
extensions: [
|
||
"tao"
|
||
]
|
||
},
|
||
"application/vnd.tcpdump.pcap": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pcap",
|
||
"cap",
|
||
"dmp"
|
||
]
|
||
},
|
||
"application/vnd.think-cell.ppttc+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.tmd.mediaflex.api+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.tml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.tmobile-livetv": {
|
||
source: "iana",
|
||
extensions: [
|
||
"tmo"
|
||
]
|
||
},
|
||
"application/vnd.tri.onesource": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.trid.tpt": {
|
||
source: "iana",
|
||
extensions: [
|
||
"tpt"
|
||
]
|
||
},
|
||
"application/vnd.triscape.mxs": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mxs"
|
||
]
|
||
},
|
||
"application/vnd.trueapp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"tra"
|
||
]
|
||
},
|
||
"application/vnd.truedoc": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ubisoft.webplayer": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ufdl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ufd",
|
||
"ufdl"
|
||
]
|
||
},
|
||
"application/vnd.uiq.theme": {
|
||
source: "iana",
|
||
extensions: [
|
||
"utz"
|
||
]
|
||
},
|
||
"application/vnd.umajin": {
|
||
source: "iana",
|
||
extensions: [
|
||
"umj"
|
||
]
|
||
},
|
||
"application/vnd.unity": {
|
||
source: "iana",
|
||
extensions: [
|
||
"unityweb"
|
||
]
|
||
},
|
||
"application/vnd.uoml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"uoml"
|
||
]
|
||
},
|
||
"application/vnd.uplanet.alert": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.uplanet.alert-wbxml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.uplanet.bearer-choice": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.uplanet.bearer-choice-wbxml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.uplanet.cacheop": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.uplanet.cacheop-wbxml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.uplanet.channel": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.uplanet.channel-wbxml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.uplanet.list": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.uplanet.list-wbxml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.uplanet.listcmd": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.uplanet.listcmd-wbxml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.uplanet.signal": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.uri-map": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.valve.source.material": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.vcx": {
|
||
source: "iana",
|
||
extensions: [
|
||
"vcx"
|
||
]
|
||
},
|
||
"application/vnd.vd-study": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.vectorworks": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.vel+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.verimatrix.vcas": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.veritone.aion+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.veryant.thin": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.ves.encrypted": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.vidsoft.vidconference": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.visio": {
|
||
source: "iana",
|
||
extensions: [
|
||
"vsd",
|
||
"vst",
|
||
"vss",
|
||
"vsw"
|
||
]
|
||
},
|
||
"application/vnd.visionary": {
|
||
source: "iana",
|
||
extensions: [
|
||
"vis"
|
||
]
|
||
},
|
||
"application/vnd.vividence.scriptfile": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.vsf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"vsf"
|
||
]
|
||
},
|
||
"application/vnd.wap.sic": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.wap.slc": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.wap.wbxml": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
extensions: [
|
||
"wbxml"
|
||
]
|
||
},
|
||
"application/vnd.wap.wmlc": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wmlc"
|
||
]
|
||
},
|
||
"application/vnd.wap.wmlscriptc": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wmlsc"
|
||
]
|
||
},
|
||
"application/vnd.webturbo": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wtb"
|
||
]
|
||
},
|
||
"application/vnd.wfa.dpp": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.wfa.p2p": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.wfa.wsc": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.windows.devicepairing": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.wmc": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.wmf.bootstrap": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.wolfram.mathematica": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.wolfram.mathematica.package": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.wolfram.player": {
|
||
source: "iana",
|
||
extensions: [
|
||
"nbp"
|
||
]
|
||
},
|
||
"application/vnd.wordperfect": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wpd"
|
||
]
|
||
},
|
||
"application/vnd.wqd": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wqd"
|
||
]
|
||
},
|
||
"application/vnd.wrq-hp3000-labelled": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.wt.stf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"stf"
|
||
]
|
||
},
|
||
"application/vnd.wv.csp+wbxml": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.wv.csp+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.wv.ssp+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.xacml+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.xara": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xar"
|
||
]
|
||
},
|
||
"application/vnd.xfdl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xfdl"
|
||
]
|
||
},
|
||
"application/vnd.xfdl.webform": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.xmi+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vnd.xmpie.cpkg": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.xmpie.dpkg": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.xmpie.plan": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.xmpie.ppkg": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.xmpie.xlim": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.yamaha.hv-dic": {
|
||
source: "iana",
|
||
extensions: [
|
||
"hvd"
|
||
]
|
||
},
|
||
"application/vnd.yamaha.hv-script": {
|
||
source: "iana",
|
||
extensions: [
|
||
"hvs"
|
||
]
|
||
},
|
||
"application/vnd.yamaha.hv-voice": {
|
||
source: "iana",
|
||
extensions: [
|
||
"hvp"
|
||
]
|
||
},
|
||
"application/vnd.yamaha.openscoreformat": {
|
||
source: "iana",
|
||
extensions: [
|
||
"osf"
|
||
]
|
||
},
|
||
"application/vnd.yamaha.openscoreformat.osfpvg+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"osfpvg"
|
||
]
|
||
},
|
||
"application/vnd.yamaha.remote-setup": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.yamaha.smaf-audio": {
|
||
source: "iana",
|
||
extensions: [
|
||
"saf"
|
||
]
|
||
},
|
||
"application/vnd.yamaha.smaf-phrase": {
|
||
source: "iana",
|
||
extensions: [
|
||
"spf"
|
||
]
|
||
},
|
||
"application/vnd.yamaha.through-ngn": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.yamaha.tunnel-udpencap": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.yaoweme": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.yellowriver-custom-menu": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cmp"
|
||
]
|
||
},
|
||
"application/vnd.youtube.yt": {
|
||
source: "iana"
|
||
},
|
||
"application/vnd.zul": {
|
||
source: "iana",
|
||
extensions: [
|
||
"zir",
|
||
"zirz"
|
||
]
|
||
},
|
||
"application/vnd.zzazz.deck+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"zaz"
|
||
]
|
||
},
|
||
"application/voicexml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"vxml"
|
||
]
|
||
},
|
||
"application/voucher-cms+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/vq-rtcpxr": {
|
||
source: "iana"
|
||
},
|
||
"application/wasm": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"wasm"
|
||
]
|
||
},
|
||
"application/watcherinfo+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"wif"
|
||
]
|
||
},
|
||
"application/webpush-options+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/whoispp-query": {
|
||
source: "iana"
|
||
},
|
||
"application/whoispp-response": {
|
||
source: "iana"
|
||
},
|
||
"application/widget": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wgt"
|
||
]
|
||
},
|
||
"application/winhlp": {
|
||
source: "apache",
|
||
extensions: [
|
||
"hlp"
|
||
]
|
||
},
|
||
"application/wita": {
|
||
source: "iana"
|
||
},
|
||
"application/wordperfect5.1": {
|
||
source: "iana"
|
||
},
|
||
"application/wsdl+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"wsdl"
|
||
]
|
||
},
|
||
"application/wspolicy+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"wspolicy"
|
||
]
|
||
},
|
||
"application/x-7z-compressed": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"7z"
|
||
]
|
||
},
|
||
"application/x-abiword": {
|
||
source: "apache",
|
||
extensions: [
|
||
"abw"
|
||
]
|
||
},
|
||
"application/x-ace-compressed": {
|
||
source: "apache",
|
||
extensions: [
|
||
"ace"
|
||
]
|
||
},
|
||
"application/x-amf": {
|
||
source: "apache"
|
||
},
|
||
"application/x-apple-diskimage": {
|
||
source: "apache",
|
||
extensions: [
|
||
"dmg"
|
||
]
|
||
},
|
||
"application/x-arj": {
|
||
compressible: false,
|
||
extensions: [
|
||
"arj"
|
||
]
|
||
},
|
||
"application/x-authorware-bin": {
|
||
source: "apache",
|
||
extensions: [
|
||
"aab",
|
||
"x32",
|
||
"u32",
|
||
"vox"
|
||
]
|
||
},
|
||
"application/x-authorware-map": {
|
||
source: "apache",
|
||
extensions: [
|
||
"aam"
|
||
]
|
||
},
|
||
"application/x-authorware-seg": {
|
||
source: "apache",
|
||
extensions: [
|
||
"aas"
|
||
]
|
||
},
|
||
"application/x-bcpio": {
|
||
source: "apache",
|
||
extensions: [
|
||
"bcpio"
|
||
]
|
||
},
|
||
"application/x-bdoc": {
|
||
compressible: false,
|
||
extensions: [
|
||
"bdoc"
|
||
]
|
||
},
|
||
"application/x-bittorrent": {
|
||
source: "apache",
|
||
extensions: [
|
||
"torrent"
|
||
]
|
||
},
|
||
"application/x-blorb": {
|
||
source: "apache",
|
||
extensions: [
|
||
"blb",
|
||
"blorb"
|
||
]
|
||
},
|
||
"application/x-bzip": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"bz"
|
||
]
|
||
},
|
||
"application/x-bzip2": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"bz2",
|
||
"boz"
|
||
]
|
||
},
|
||
"application/x-cbr": {
|
||
source: "apache",
|
||
extensions: [
|
||
"cbr",
|
||
"cba",
|
||
"cbt",
|
||
"cbz",
|
||
"cb7"
|
||
]
|
||
},
|
||
"application/x-cdlink": {
|
||
source: "apache",
|
||
extensions: [
|
||
"vcd"
|
||
]
|
||
},
|
||
"application/x-cfs-compressed": {
|
||
source: "apache",
|
||
extensions: [
|
||
"cfs"
|
||
]
|
||
},
|
||
"application/x-chat": {
|
||
source: "apache",
|
||
extensions: [
|
||
"chat"
|
||
]
|
||
},
|
||
"application/x-chess-pgn": {
|
||
source: "apache",
|
||
extensions: [
|
||
"pgn"
|
||
]
|
||
},
|
||
"application/x-chrome-extension": {
|
||
extensions: [
|
||
"crx"
|
||
]
|
||
},
|
||
"application/x-cocoa": {
|
||
source: "nginx",
|
||
extensions: [
|
||
"cco"
|
||
]
|
||
},
|
||
"application/x-compress": {
|
||
source: "apache"
|
||
},
|
||
"application/x-conference": {
|
||
source: "apache",
|
||
extensions: [
|
||
"nsc"
|
||
]
|
||
},
|
||
"application/x-cpio": {
|
||
source: "apache",
|
||
extensions: [
|
||
"cpio"
|
||
]
|
||
},
|
||
"application/x-csh": {
|
||
source: "apache",
|
||
extensions: [
|
||
"csh"
|
||
]
|
||
},
|
||
"application/x-deb": {
|
||
compressible: false
|
||
},
|
||
"application/x-debian-package": {
|
||
source: "apache",
|
||
extensions: [
|
||
"deb",
|
||
"udeb"
|
||
]
|
||
},
|
||
"application/x-dgc-compressed": {
|
||
source: "apache",
|
||
extensions: [
|
||
"dgc"
|
||
]
|
||
},
|
||
"application/x-director": {
|
||
source: "apache",
|
||
extensions: [
|
||
"dir",
|
||
"dcr",
|
||
"dxr",
|
||
"cst",
|
||
"cct",
|
||
"cxt",
|
||
"w3d",
|
||
"fgd",
|
||
"swa"
|
||
]
|
||
},
|
||
"application/x-doom": {
|
||
source: "apache",
|
||
extensions: [
|
||
"wad"
|
||
]
|
||
},
|
||
"application/x-dtbncx+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"ncx"
|
||
]
|
||
},
|
||
"application/x-dtbook+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"dtb"
|
||
]
|
||
},
|
||
"application/x-dtbresource+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"res"
|
||
]
|
||
},
|
||
"application/x-dvi": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"dvi"
|
||
]
|
||
},
|
||
"application/x-envoy": {
|
||
source: "apache",
|
||
extensions: [
|
||
"evy"
|
||
]
|
||
},
|
||
"application/x-eva": {
|
||
source: "apache",
|
||
extensions: [
|
||
"eva"
|
||
]
|
||
},
|
||
"application/x-font-bdf": {
|
||
source: "apache",
|
||
extensions: [
|
||
"bdf"
|
||
]
|
||
},
|
||
"application/x-font-dos": {
|
||
source: "apache"
|
||
},
|
||
"application/x-font-framemaker": {
|
||
source: "apache"
|
||
},
|
||
"application/x-font-ghostscript": {
|
||
source: "apache",
|
||
extensions: [
|
||
"gsf"
|
||
]
|
||
},
|
||
"application/x-font-libgrx": {
|
||
source: "apache"
|
||
},
|
||
"application/x-font-linux-psf": {
|
||
source: "apache",
|
||
extensions: [
|
||
"psf"
|
||
]
|
||
},
|
||
"application/x-font-pcf": {
|
||
source: "apache",
|
||
extensions: [
|
||
"pcf"
|
||
]
|
||
},
|
||
"application/x-font-snf": {
|
||
source: "apache",
|
||
extensions: [
|
||
"snf"
|
||
]
|
||
},
|
||
"application/x-font-speedo": {
|
||
source: "apache"
|
||
},
|
||
"application/x-font-sunos-news": {
|
||
source: "apache"
|
||
},
|
||
"application/x-font-type1": {
|
||
source: "apache",
|
||
extensions: [
|
||
"pfa",
|
||
"pfb",
|
||
"pfm",
|
||
"afm"
|
||
]
|
||
},
|
||
"application/x-font-vfont": {
|
||
source: "apache"
|
||
},
|
||
"application/x-freearc": {
|
||
source: "apache",
|
||
extensions: [
|
||
"arc"
|
||
]
|
||
},
|
||
"application/x-futuresplash": {
|
||
source: "apache",
|
||
extensions: [
|
||
"spl"
|
||
]
|
||
},
|
||
"application/x-gca-compressed": {
|
||
source: "apache",
|
||
extensions: [
|
||
"gca"
|
||
]
|
||
},
|
||
"application/x-glulx": {
|
||
source: "apache",
|
||
extensions: [
|
||
"ulx"
|
||
]
|
||
},
|
||
"application/x-gnumeric": {
|
||
source: "apache",
|
||
extensions: [
|
||
"gnumeric"
|
||
]
|
||
},
|
||
"application/x-gramps-xml": {
|
||
source: "apache",
|
||
extensions: [
|
||
"gramps"
|
||
]
|
||
},
|
||
"application/x-gtar": {
|
||
source: "apache",
|
||
extensions: [
|
||
"gtar"
|
||
]
|
||
},
|
||
"application/x-gzip": {
|
||
source: "apache"
|
||
},
|
||
"application/x-hdf": {
|
||
source: "apache",
|
||
extensions: [
|
||
"hdf"
|
||
]
|
||
},
|
||
"application/x-httpd-php": {
|
||
compressible: true,
|
||
extensions: [
|
||
"php"
|
||
]
|
||
},
|
||
"application/x-install-instructions": {
|
||
source: "apache",
|
||
extensions: [
|
||
"install"
|
||
]
|
||
},
|
||
"application/x-iso9660-image": {
|
||
source: "apache",
|
||
extensions: [
|
||
"iso"
|
||
]
|
||
},
|
||
"application/x-iwork-keynote-sffkey": {
|
||
extensions: [
|
||
"key"
|
||
]
|
||
},
|
||
"application/x-iwork-numbers-sffnumbers": {
|
||
extensions: [
|
||
"numbers"
|
||
]
|
||
},
|
||
"application/x-iwork-pages-sffpages": {
|
||
extensions: [
|
||
"pages"
|
||
]
|
||
},
|
||
"application/x-java-archive-diff": {
|
||
source: "nginx",
|
||
extensions: [
|
||
"jardiff"
|
||
]
|
||
},
|
||
"application/x-java-jnlp-file": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"jnlp"
|
||
]
|
||
},
|
||
"application/x-javascript": {
|
||
compressible: true
|
||
},
|
||
"application/x-keepass2": {
|
||
extensions: [
|
||
"kdbx"
|
||
]
|
||
},
|
||
"application/x-latex": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"latex"
|
||
]
|
||
},
|
||
"application/x-lua-bytecode": {
|
||
extensions: [
|
||
"luac"
|
||
]
|
||
},
|
||
"application/x-lzh-compressed": {
|
||
source: "apache",
|
||
extensions: [
|
||
"lzh",
|
||
"lha"
|
||
]
|
||
},
|
||
"application/x-makeself": {
|
||
source: "nginx",
|
||
extensions: [
|
||
"run"
|
||
]
|
||
},
|
||
"application/x-mie": {
|
||
source: "apache",
|
||
extensions: [
|
||
"mie"
|
||
]
|
||
},
|
||
"application/x-mobipocket-ebook": {
|
||
source: "apache",
|
||
extensions: [
|
||
"prc",
|
||
"mobi"
|
||
]
|
||
},
|
||
"application/x-mpegurl": {
|
||
compressible: false
|
||
},
|
||
"application/x-ms-application": {
|
||
source: "apache",
|
||
extensions: [
|
||
"application"
|
||
]
|
||
},
|
||
"application/x-ms-shortcut": {
|
||
source: "apache",
|
||
extensions: [
|
||
"lnk"
|
||
]
|
||
},
|
||
"application/x-ms-wmd": {
|
||
source: "apache",
|
||
extensions: [
|
||
"wmd"
|
||
]
|
||
},
|
||
"application/x-ms-wmz": {
|
||
source: "apache",
|
||
extensions: [
|
||
"wmz"
|
||
]
|
||
},
|
||
"application/x-ms-xbap": {
|
||
source: "apache",
|
||
extensions: [
|
||
"xbap"
|
||
]
|
||
},
|
||
"application/x-msaccess": {
|
||
source: "apache",
|
||
extensions: [
|
||
"mdb"
|
||
]
|
||
},
|
||
"application/x-msbinder": {
|
||
source: "apache",
|
||
extensions: [
|
||
"obd"
|
||
]
|
||
},
|
||
"application/x-mscardfile": {
|
||
source: "apache",
|
||
extensions: [
|
||
"crd"
|
||
]
|
||
},
|
||
"application/x-msclip": {
|
||
source: "apache",
|
||
extensions: [
|
||
"clp"
|
||
]
|
||
},
|
||
"application/x-msdos-program": {
|
||
extensions: [
|
||
"exe"
|
||
]
|
||
},
|
||
"application/x-msdownload": {
|
||
source: "apache",
|
||
extensions: [
|
||
"exe",
|
||
"dll",
|
||
"com",
|
||
"bat",
|
||
"msi"
|
||
]
|
||
},
|
||
"application/x-msmediaview": {
|
||
source: "apache",
|
||
extensions: [
|
||
"mvb",
|
||
"m13",
|
||
"m14"
|
||
]
|
||
},
|
||
"application/x-msmetafile": {
|
||
source: "apache",
|
||
extensions: [
|
||
"wmf",
|
||
"wmz",
|
||
"emf",
|
||
"emz"
|
||
]
|
||
},
|
||
"application/x-msmoney": {
|
||
source: "apache",
|
||
extensions: [
|
||
"mny"
|
||
]
|
||
},
|
||
"application/x-mspublisher": {
|
||
source: "apache",
|
||
extensions: [
|
||
"pub"
|
||
]
|
||
},
|
||
"application/x-msschedule": {
|
||
source: "apache",
|
||
extensions: [
|
||
"scd"
|
||
]
|
||
},
|
||
"application/x-msterminal": {
|
||
source: "apache",
|
||
extensions: [
|
||
"trm"
|
||
]
|
||
},
|
||
"application/x-mswrite": {
|
||
source: "apache",
|
||
extensions: [
|
||
"wri"
|
||
]
|
||
},
|
||
"application/x-netcdf": {
|
||
source: "apache",
|
||
extensions: [
|
||
"nc",
|
||
"cdf"
|
||
]
|
||
},
|
||
"application/x-ns-proxy-autoconfig": {
|
||
compressible: true,
|
||
extensions: [
|
||
"pac"
|
||
]
|
||
},
|
||
"application/x-nzb": {
|
||
source: "apache",
|
||
extensions: [
|
||
"nzb"
|
||
]
|
||
},
|
||
"application/x-perl": {
|
||
source: "nginx",
|
||
extensions: [
|
||
"pl",
|
||
"pm"
|
||
]
|
||
},
|
||
"application/x-pilot": {
|
||
source: "nginx",
|
||
extensions: [
|
||
"prc",
|
||
"pdb"
|
||
]
|
||
},
|
||
"application/x-pkcs12": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"p12",
|
||
"pfx"
|
||
]
|
||
},
|
||
"application/x-pkcs7-certificates": {
|
||
source: "apache",
|
||
extensions: [
|
||
"p7b",
|
||
"spc"
|
||
]
|
||
},
|
||
"application/x-pkcs7-certreqresp": {
|
||
source: "apache",
|
||
extensions: [
|
||
"p7r"
|
||
]
|
||
},
|
||
"application/x-pki-message": {
|
||
source: "iana"
|
||
},
|
||
"application/x-rar-compressed": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"rar"
|
||
]
|
||
},
|
||
"application/x-redhat-package-manager": {
|
||
source: "nginx",
|
||
extensions: [
|
||
"rpm"
|
||
]
|
||
},
|
||
"application/x-research-info-systems": {
|
||
source: "apache",
|
||
extensions: [
|
||
"ris"
|
||
]
|
||
},
|
||
"application/x-sea": {
|
||
source: "nginx",
|
||
extensions: [
|
||
"sea"
|
||
]
|
||
},
|
||
"application/x-sh": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"sh"
|
||
]
|
||
},
|
||
"application/x-shar": {
|
||
source: "apache",
|
||
extensions: [
|
||
"shar"
|
||
]
|
||
},
|
||
"application/x-shockwave-flash": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"swf"
|
||
]
|
||
},
|
||
"application/x-silverlight-app": {
|
||
source: "apache",
|
||
extensions: [
|
||
"xap"
|
||
]
|
||
},
|
||
"application/x-sql": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sql"
|
||
]
|
||
},
|
||
"application/x-stuffit": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"sit"
|
||
]
|
||
},
|
||
"application/x-stuffitx": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sitx"
|
||
]
|
||
},
|
||
"application/x-subrip": {
|
||
source: "apache",
|
||
extensions: [
|
||
"srt"
|
||
]
|
||
},
|
||
"application/x-sv4cpio": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sv4cpio"
|
||
]
|
||
},
|
||
"application/x-sv4crc": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sv4crc"
|
||
]
|
||
},
|
||
"application/x-t3vm-image": {
|
||
source: "apache",
|
||
extensions: [
|
||
"t3"
|
||
]
|
||
},
|
||
"application/x-tads": {
|
||
source: "apache",
|
||
extensions: [
|
||
"gam"
|
||
]
|
||
},
|
||
"application/x-tar": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"tar"
|
||
]
|
||
},
|
||
"application/x-tcl": {
|
||
source: "apache",
|
||
extensions: [
|
||
"tcl",
|
||
"tk"
|
||
]
|
||
},
|
||
"application/x-tex": {
|
||
source: "apache",
|
||
extensions: [
|
||
"tex"
|
||
]
|
||
},
|
||
"application/x-tex-tfm": {
|
||
source: "apache",
|
||
extensions: [
|
||
"tfm"
|
||
]
|
||
},
|
||
"application/x-texinfo": {
|
||
source: "apache",
|
||
extensions: [
|
||
"texinfo",
|
||
"texi"
|
||
]
|
||
},
|
||
"application/x-tgif": {
|
||
source: "apache",
|
||
extensions: [
|
||
"obj"
|
||
]
|
||
},
|
||
"application/x-ustar": {
|
||
source: "apache",
|
||
extensions: [
|
||
"ustar"
|
||
]
|
||
},
|
||
"application/x-virtualbox-hdd": {
|
||
compressible: true,
|
||
extensions: [
|
||
"hdd"
|
||
]
|
||
},
|
||
"application/x-virtualbox-ova": {
|
||
compressible: true,
|
||
extensions: [
|
||
"ova"
|
||
]
|
||
},
|
||
"application/x-virtualbox-ovf": {
|
||
compressible: true,
|
||
extensions: [
|
||
"ovf"
|
||
]
|
||
},
|
||
"application/x-virtualbox-vbox": {
|
||
compressible: true,
|
||
extensions: [
|
||
"vbox"
|
||
]
|
||
},
|
||
"application/x-virtualbox-vbox-extpack": {
|
||
compressible: false,
|
||
extensions: [
|
||
"vbox-extpack"
|
||
]
|
||
},
|
||
"application/x-virtualbox-vdi": {
|
||
compressible: true,
|
||
extensions: [
|
||
"vdi"
|
||
]
|
||
},
|
||
"application/x-virtualbox-vhd": {
|
||
compressible: true,
|
||
extensions: [
|
||
"vhd"
|
||
]
|
||
},
|
||
"application/x-virtualbox-vmdk": {
|
||
compressible: true,
|
||
extensions: [
|
||
"vmdk"
|
||
]
|
||
},
|
||
"application/x-wais-source": {
|
||
source: "apache",
|
||
extensions: [
|
||
"src"
|
||
]
|
||
},
|
||
"application/x-web-app-manifest+json": {
|
||
compressible: true,
|
||
extensions: [
|
||
"webapp"
|
||
]
|
||
},
|
||
"application/x-www-form-urlencoded": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/x-x509-ca-cert": {
|
||
source: "iana",
|
||
extensions: [
|
||
"der",
|
||
"crt",
|
||
"pem"
|
||
]
|
||
},
|
||
"application/x-x509-ca-ra-cert": {
|
||
source: "iana"
|
||
},
|
||
"application/x-x509-next-ca-cert": {
|
||
source: "iana"
|
||
},
|
||
"application/x-xfig": {
|
||
source: "apache",
|
||
extensions: [
|
||
"fig"
|
||
]
|
||
},
|
||
"application/x-xliff+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"xlf"
|
||
]
|
||
},
|
||
"application/x-xpinstall": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"xpi"
|
||
]
|
||
},
|
||
"application/x-xz": {
|
||
source: "apache",
|
||
extensions: [
|
||
"xz"
|
||
]
|
||
},
|
||
"application/x-zmachine": {
|
||
source: "apache",
|
||
extensions: [
|
||
"z1",
|
||
"z2",
|
||
"z3",
|
||
"z4",
|
||
"z5",
|
||
"z6",
|
||
"z7",
|
||
"z8"
|
||
]
|
||
},
|
||
"application/x400-bp": {
|
||
source: "iana"
|
||
},
|
||
"application/xacml+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/xaml+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"xaml"
|
||
]
|
||
},
|
||
"application/xcap-att+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xav"
|
||
]
|
||
},
|
||
"application/xcap-caps+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xca"
|
||
]
|
||
},
|
||
"application/xcap-diff+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xdf"
|
||
]
|
||
},
|
||
"application/xcap-el+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xel"
|
||
]
|
||
},
|
||
"application/xcap-error+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/xcap-ns+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xns"
|
||
]
|
||
},
|
||
"application/xcon-conference-info+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/xcon-conference-info-diff+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/xenc+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xenc"
|
||
]
|
||
},
|
||
"application/xhtml+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xhtml",
|
||
"xht"
|
||
]
|
||
},
|
||
"application/xhtml-voice+xml": {
|
||
source: "apache",
|
||
compressible: true
|
||
},
|
||
"application/xliff+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xlf"
|
||
]
|
||
},
|
||
"application/xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xml",
|
||
"xsl",
|
||
"xsd",
|
||
"rng"
|
||
]
|
||
},
|
||
"application/xml-dtd": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"dtd"
|
||
]
|
||
},
|
||
"application/xml-external-parsed-entity": {
|
||
source: "iana"
|
||
},
|
||
"application/xml-patch+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/xmpp+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/xop+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xop"
|
||
]
|
||
},
|
||
"application/xproc+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"xpl"
|
||
]
|
||
},
|
||
"application/xslt+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xsl",
|
||
"xslt"
|
||
]
|
||
},
|
||
"application/xspf+xml": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"xspf"
|
||
]
|
||
},
|
||
"application/xv+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"mxml",
|
||
"xhvml",
|
||
"xvml",
|
||
"xvm"
|
||
]
|
||
},
|
||
"application/yang": {
|
||
source: "iana",
|
||
extensions: [
|
||
"yang"
|
||
]
|
||
},
|
||
"application/yang-data+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/yang-data+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/yang-patch+json": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/yang-patch+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"application/yin+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"yin"
|
||
]
|
||
},
|
||
"application/zip": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"zip"
|
||
]
|
||
},
|
||
"application/zlib": {
|
||
source: "iana"
|
||
},
|
||
"application/zstd": {
|
||
source: "iana"
|
||
},
|
||
"audio/1d-interleaved-parityfec": {
|
||
source: "iana"
|
||
},
|
||
"audio/32kadpcm": {
|
||
source: "iana"
|
||
},
|
||
"audio/3gpp": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"3gpp"
|
||
]
|
||
},
|
||
"audio/3gpp2": {
|
||
source: "iana"
|
||
},
|
||
"audio/aac": {
|
||
source: "iana"
|
||
},
|
||
"audio/ac3": {
|
||
source: "iana"
|
||
},
|
||
"audio/adpcm": {
|
||
source: "apache",
|
||
extensions: [
|
||
"adp"
|
||
]
|
||
},
|
||
"audio/amr": {
|
||
source: "iana",
|
||
extensions: [
|
||
"amr"
|
||
]
|
||
},
|
||
"audio/amr-wb": {
|
||
source: "iana"
|
||
},
|
||
"audio/amr-wb+": {
|
||
source: "iana"
|
||
},
|
||
"audio/aptx": {
|
||
source: "iana"
|
||
},
|
||
"audio/asc": {
|
||
source: "iana"
|
||
},
|
||
"audio/atrac-advanced-lossless": {
|
||
source: "iana"
|
||
},
|
||
"audio/atrac-x": {
|
||
source: "iana"
|
||
},
|
||
"audio/atrac3": {
|
||
source: "iana"
|
||
},
|
||
"audio/basic": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"au",
|
||
"snd"
|
||
]
|
||
},
|
||
"audio/bv16": {
|
||
source: "iana"
|
||
},
|
||
"audio/bv32": {
|
||
source: "iana"
|
||
},
|
||
"audio/clearmode": {
|
||
source: "iana"
|
||
},
|
||
"audio/cn": {
|
||
source: "iana"
|
||
},
|
||
"audio/dat12": {
|
||
source: "iana"
|
||
},
|
||
"audio/dls": {
|
||
source: "iana"
|
||
},
|
||
"audio/dsr-es201108": {
|
||
source: "iana"
|
||
},
|
||
"audio/dsr-es202050": {
|
||
source: "iana"
|
||
},
|
||
"audio/dsr-es202211": {
|
||
source: "iana"
|
||
},
|
||
"audio/dsr-es202212": {
|
||
source: "iana"
|
||
},
|
||
"audio/dv": {
|
||
source: "iana"
|
||
},
|
||
"audio/dvi4": {
|
||
source: "iana"
|
||
},
|
||
"audio/eac3": {
|
||
source: "iana"
|
||
},
|
||
"audio/encaprtp": {
|
||
source: "iana"
|
||
},
|
||
"audio/evrc": {
|
||
source: "iana"
|
||
},
|
||
"audio/evrc-qcp": {
|
||
source: "iana"
|
||
},
|
||
"audio/evrc0": {
|
||
source: "iana"
|
||
},
|
||
"audio/evrc1": {
|
||
source: "iana"
|
||
},
|
||
"audio/evrcb": {
|
||
source: "iana"
|
||
},
|
||
"audio/evrcb0": {
|
||
source: "iana"
|
||
},
|
||
"audio/evrcb1": {
|
||
source: "iana"
|
||
},
|
||
"audio/evrcnw": {
|
||
source: "iana"
|
||
},
|
||
"audio/evrcnw0": {
|
||
source: "iana"
|
||
},
|
||
"audio/evrcnw1": {
|
||
source: "iana"
|
||
},
|
||
"audio/evrcwb": {
|
||
source: "iana"
|
||
},
|
||
"audio/evrcwb0": {
|
||
source: "iana"
|
||
},
|
||
"audio/evrcwb1": {
|
||
source: "iana"
|
||
},
|
||
"audio/evs": {
|
||
source: "iana"
|
||
},
|
||
"audio/flexfec": {
|
||
source: "iana"
|
||
},
|
||
"audio/fwdred": {
|
||
source: "iana"
|
||
},
|
||
"audio/g711-0": {
|
||
source: "iana"
|
||
},
|
||
"audio/g719": {
|
||
source: "iana"
|
||
},
|
||
"audio/g722": {
|
||
source: "iana"
|
||
},
|
||
"audio/g7221": {
|
||
source: "iana"
|
||
},
|
||
"audio/g723": {
|
||
source: "iana"
|
||
},
|
||
"audio/g726-16": {
|
||
source: "iana"
|
||
},
|
||
"audio/g726-24": {
|
||
source: "iana"
|
||
},
|
||
"audio/g726-32": {
|
||
source: "iana"
|
||
},
|
||
"audio/g726-40": {
|
||
source: "iana"
|
||
},
|
||
"audio/g728": {
|
||
source: "iana"
|
||
},
|
||
"audio/g729": {
|
||
source: "iana"
|
||
},
|
||
"audio/g7291": {
|
||
source: "iana"
|
||
},
|
||
"audio/g729d": {
|
||
source: "iana"
|
||
},
|
||
"audio/g729e": {
|
||
source: "iana"
|
||
},
|
||
"audio/gsm": {
|
||
source: "iana"
|
||
},
|
||
"audio/gsm-efr": {
|
||
source: "iana"
|
||
},
|
||
"audio/gsm-hr-08": {
|
||
source: "iana"
|
||
},
|
||
"audio/ilbc": {
|
||
source: "iana"
|
||
},
|
||
"audio/ip-mr_v2.5": {
|
||
source: "iana"
|
||
},
|
||
"audio/isac": {
|
||
source: "apache"
|
||
},
|
||
"audio/l16": {
|
||
source: "iana"
|
||
},
|
||
"audio/l20": {
|
||
source: "iana"
|
||
},
|
||
"audio/l24": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"audio/l8": {
|
||
source: "iana"
|
||
},
|
||
"audio/lpc": {
|
||
source: "iana"
|
||
},
|
||
"audio/melp": {
|
||
source: "iana"
|
||
},
|
||
"audio/melp1200": {
|
||
source: "iana"
|
||
},
|
||
"audio/melp2400": {
|
||
source: "iana"
|
||
},
|
||
"audio/melp600": {
|
||
source: "iana"
|
||
},
|
||
"audio/mhas": {
|
||
source: "iana"
|
||
},
|
||
"audio/midi": {
|
||
source: "apache",
|
||
extensions: [
|
||
"mid",
|
||
"midi",
|
||
"kar",
|
||
"rmi"
|
||
]
|
||
},
|
||
"audio/mobile-xmf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mxmf"
|
||
]
|
||
},
|
||
"audio/mp3": {
|
||
compressible: false,
|
||
extensions: [
|
||
"mp3"
|
||
]
|
||
},
|
||
"audio/mp4": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"m4a",
|
||
"mp4a"
|
||
]
|
||
},
|
||
"audio/mp4a-latm": {
|
||
source: "iana"
|
||
},
|
||
"audio/mpa": {
|
||
source: "iana"
|
||
},
|
||
"audio/mpa-robust": {
|
||
source: "iana"
|
||
},
|
||
"audio/mpeg": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"mpga",
|
||
"mp2",
|
||
"mp2a",
|
||
"mp3",
|
||
"m2a",
|
||
"m3a"
|
||
]
|
||
},
|
||
"audio/mpeg4-generic": {
|
||
source: "iana"
|
||
},
|
||
"audio/musepack": {
|
||
source: "apache"
|
||
},
|
||
"audio/ogg": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"oga",
|
||
"ogg",
|
||
"spx",
|
||
"opus"
|
||
]
|
||
},
|
||
"audio/opus": {
|
||
source: "iana"
|
||
},
|
||
"audio/parityfec": {
|
||
source: "iana"
|
||
},
|
||
"audio/pcma": {
|
||
source: "iana"
|
||
},
|
||
"audio/pcma-wb": {
|
||
source: "iana"
|
||
},
|
||
"audio/pcmu": {
|
||
source: "iana"
|
||
},
|
||
"audio/pcmu-wb": {
|
||
source: "iana"
|
||
},
|
||
"audio/prs.sid": {
|
||
source: "iana"
|
||
},
|
||
"audio/qcelp": {
|
||
source: "iana"
|
||
},
|
||
"audio/raptorfec": {
|
||
source: "iana"
|
||
},
|
||
"audio/red": {
|
||
source: "iana"
|
||
},
|
||
"audio/rtp-enc-aescm128": {
|
||
source: "iana"
|
||
},
|
||
"audio/rtp-midi": {
|
||
source: "iana"
|
||
},
|
||
"audio/rtploopback": {
|
||
source: "iana"
|
||
},
|
||
"audio/rtx": {
|
||
source: "iana"
|
||
},
|
||
"audio/s3m": {
|
||
source: "apache",
|
||
extensions: [
|
||
"s3m"
|
||
]
|
||
},
|
||
"audio/scip": {
|
||
source: "iana"
|
||
},
|
||
"audio/silk": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sil"
|
||
]
|
||
},
|
||
"audio/smv": {
|
||
source: "iana"
|
||
},
|
||
"audio/smv-qcp": {
|
||
source: "iana"
|
||
},
|
||
"audio/smv0": {
|
||
source: "iana"
|
||
},
|
||
"audio/sofa": {
|
||
source: "iana"
|
||
},
|
||
"audio/sp-midi": {
|
||
source: "iana"
|
||
},
|
||
"audio/speex": {
|
||
source: "iana"
|
||
},
|
||
"audio/t140c": {
|
||
source: "iana"
|
||
},
|
||
"audio/t38": {
|
||
source: "iana"
|
||
},
|
||
"audio/telephone-event": {
|
||
source: "iana"
|
||
},
|
||
"audio/tetra_acelp": {
|
||
source: "iana"
|
||
},
|
||
"audio/tetra_acelp_bb": {
|
||
source: "iana"
|
||
},
|
||
"audio/tone": {
|
||
source: "iana"
|
||
},
|
||
"audio/tsvcis": {
|
||
source: "iana"
|
||
},
|
||
"audio/uemclip": {
|
||
source: "iana"
|
||
},
|
||
"audio/ulpfec": {
|
||
source: "iana"
|
||
},
|
||
"audio/usac": {
|
||
source: "iana"
|
||
},
|
||
"audio/vdvi": {
|
||
source: "iana"
|
||
},
|
||
"audio/vmr-wb": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.3gpp.iufp": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.4sb": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.audiokoz": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.celp": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.cisco.nse": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.cmles.radio-events": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.cns.anp1": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.cns.inf1": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.dece.audio": {
|
||
source: "iana",
|
||
extensions: [
|
||
"uva",
|
||
"uvva"
|
||
]
|
||
},
|
||
"audio/vnd.digital-winds": {
|
||
source: "iana",
|
||
extensions: [
|
||
"eol"
|
||
]
|
||
},
|
||
"audio/vnd.dlna.adts": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.dolby.heaac.1": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.dolby.heaac.2": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.dolby.mlp": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.dolby.mps": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.dolby.pl2": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.dolby.pl2x": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.dolby.pl2z": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.dolby.pulse.1": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.dra": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dra"
|
||
]
|
||
},
|
||
"audio/vnd.dts": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dts"
|
||
]
|
||
},
|
||
"audio/vnd.dts.hd": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dtshd"
|
||
]
|
||
},
|
||
"audio/vnd.dts.uhd": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.dvb.file": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.everad.plj": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.hns.audio": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.lucent.voice": {
|
||
source: "iana",
|
||
extensions: [
|
||
"lvp"
|
||
]
|
||
},
|
||
"audio/vnd.ms-playready.media.pya": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pya"
|
||
]
|
||
},
|
||
"audio/vnd.nokia.mobile-xmf": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.nortel.vbk": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.nuera.ecelp4800": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ecelp4800"
|
||
]
|
||
},
|
||
"audio/vnd.nuera.ecelp7470": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ecelp7470"
|
||
]
|
||
},
|
||
"audio/vnd.nuera.ecelp9600": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ecelp9600"
|
||
]
|
||
},
|
||
"audio/vnd.octel.sbc": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.presonus.multitrack": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.qcelp": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.rhetorex.32kadpcm": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.rip": {
|
||
source: "iana",
|
||
extensions: [
|
||
"rip"
|
||
]
|
||
},
|
||
"audio/vnd.rn-realaudio": {
|
||
compressible: false
|
||
},
|
||
"audio/vnd.sealedmedia.softseal.mpeg": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.vmx.cvsd": {
|
||
source: "iana"
|
||
},
|
||
"audio/vnd.wave": {
|
||
compressible: false
|
||
},
|
||
"audio/vorbis": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"audio/vorbis-config": {
|
||
source: "iana"
|
||
},
|
||
"audio/wav": {
|
||
compressible: false,
|
||
extensions: [
|
||
"wav"
|
||
]
|
||
},
|
||
"audio/wave": {
|
||
compressible: false,
|
||
extensions: [
|
||
"wav"
|
||
]
|
||
},
|
||
"audio/webm": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"weba"
|
||
]
|
||
},
|
||
"audio/x-aac": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"aac"
|
||
]
|
||
},
|
||
"audio/x-aiff": {
|
||
source: "apache",
|
||
extensions: [
|
||
"aif",
|
||
"aiff",
|
||
"aifc"
|
||
]
|
||
},
|
||
"audio/x-caf": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"caf"
|
||
]
|
||
},
|
||
"audio/x-flac": {
|
||
source: "apache",
|
||
extensions: [
|
||
"flac"
|
||
]
|
||
},
|
||
"audio/x-m4a": {
|
||
source: "nginx",
|
||
extensions: [
|
||
"m4a"
|
||
]
|
||
},
|
||
"audio/x-matroska": {
|
||
source: "apache",
|
||
extensions: [
|
||
"mka"
|
||
]
|
||
},
|
||
"audio/x-mpegurl": {
|
||
source: "apache",
|
||
extensions: [
|
||
"m3u"
|
||
]
|
||
},
|
||
"audio/x-ms-wax": {
|
||
source: "apache",
|
||
extensions: [
|
||
"wax"
|
||
]
|
||
},
|
||
"audio/x-ms-wma": {
|
||
source: "apache",
|
||
extensions: [
|
||
"wma"
|
||
]
|
||
},
|
||
"audio/x-pn-realaudio": {
|
||
source: "apache",
|
||
extensions: [
|
||
"ram",
|
||
"ra"
|
||
]
|
||
},
|
||
"audio/x-pn-realaudio-plugin": {
|
||
source: "apache",
|
||
extensions: [
|
||
"rmp"
|
||
]
|
||
},
|
||
"audio/x-realaudio": {
|
||
source: "nginx",
|
||
extensions: [
|
||
"ra"
|
||
]
|
||
},
|
||
"audio/x-tta": {
|
||
source: "apache"
|
||
},
|
||
"audio/x-wav": {
|
||
source: "apache",
|
||
extensions: [
|
||
"wav"
|
||
]
|
||
},
|
||
"audio/xm": {
|
||
source: "apache",
|
||
extensions: [
|
||
"xm"
|
||
]
|
||
},
|
||
"chemical/x-cdx": {
|
||
source: "apache",
|
||
extensions: [
|
||
"cdx"
|
||
]
|
||
},
|
||
"chemical/x-cif": {
|
||
source: "apache",
|
||
extensions: [
|
||
"cif"
|
||
]
|
||
},
|
||
"chemical/x-cmdf": {
|
||
source: "apache",
|
||
extensions: [
|
||
"cmdf"
|
||
]
|
||
},
|
||
"chemical/x-cml": {
|
||
source: "apache",
|
||
extensions: [
|
||
"cml"
|
||
]
|
||
},
|
||
"chemical/x-csml": {
|
||
source: "apache",
|
||
extensions: [
|
||
"csml"
|
||
]
|
||
},
|
||
"chemical/x-pdb": {
|
||
source: "apache"
|
||
},
|
||
"chemical/x-xyz": {
|
||
source: "apache",
|
||
extensions: [
|
||
"xyz"
|
||
]
|
||
},
|
||
"font/collection": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ttc"
|
||
]
|
||
},
|
||
"font/otf": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"otf"
|
||
]
|
||
},
|
||
"font/sfnt": {
|
||
source: "iana"
|
||
},
|
||
"font/ttf": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"ttf"
|
||
]
|
||
},
|
||
"font/woff": {
|
||
source: "iana",
|
||
extensions: [
|
||
"woff"
|
||
]
|
||
},
|
||
"font/woff2": {
|
||
source: "iana",
|
||
extensions: [
|
||
"woff2"
|
||
]
|
||
},
|
||
"image/aces": {
|
||
source: "iana",
|
||
extensions: [
|
||
"exr"
|
||
]
|
||
},
|
||
"image/apng": {
|
||
compressible: false,
|
||
extensions: [
|
||
"apng"
|
||
]
|
||
},
|
||
"image/avci": {
|
||
source: "iana",
|
||
extensions: [
|
||
"avci"
|
||
]
|
||
},
|
||
"image/avcs": {
|
||
source: "iana",
|
||
extensions: [
|
||
"avcs"
|
||
]
|
||
},
|
||
"image/avif": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"avif"
|
||
]
|
||
},
|
||
"image/bmp": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"bmp"
|
||
]
|
||
},
|
||
"image/cgm": {
|
||
source: "iana",
|
||
extensions: [
|
||
"cgm"
|
||
]
|
||
},
|
||
"image/dicom-rle": {
|
||
source: "iana",
|
||
extensions: [
|
||
"drle"
|
||
]
|
||
},
|
||
"image/emf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"emf"
|
||
]
|
||
},
|
||
"image/fits": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fits"
|
||
]
|
||
},
|
||
"image/g3fax": {
|
||
source: "iana",
|
||
extensions: [
|
||
"g3"
|
||
]
|
||
},
|
||
"image/gif": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"gif"
|
||
]
|
||
},
|
||
"image/heic": {
|
||
source: "iana",
|
||
extensions: [
|
||
"heic"
|
||
]
|
||
},
|
||
"image/heic-sequence": {
|
||
source: "iana",
|
||
extensions: [
|
||
"heics"
|
||
]
|
||
},
|
||
"image/heif": {
|
||
source: "iana",
|
||
extensions: [
|
||
"heif"
|
||
]
|
||
},
|
||
"image/heif-sequence": {
|
||
source: "iana",
|
||
extensions: [
|
||
"heifs"
|
||
]
|
||
},
|
||
"image/hej2k": {
|
||
source: "iana",
|
||
extensions: [
|
||
"hej2"
|
||
]
|
||
},
|
||
"image/hsj2": {
|
||
source: "iana",
|
||
extensions: [
|
||
"hsj2"
|
||
]
|
||
},
|
||
"image/ief": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ief"
|
||
]
|
||
},
|
||
"image/jls": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jls"
|
||
]
|
||
},
|
||
"image/jp2": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"jp2",
|
||
"jpg2"
|
||
]
|
||
},
|
||
"image/jpeg": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"jpeg",
|
||
"jpg",
|
||
"jpe"
|
||
]
|
||
},
|
||
"image/jph": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jph"
|
||
]
|
||
},
|
||
"image/jphc": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jhc"
|
||
]
|
||
},
|
||
"image/jpm": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"jpm"
|
||
]
|
||
},
|
||
"image/jpx": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"jpx",
|
||
"jpf"
|
||
]
|
||
},
|
||
"image/jxr": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jxr"
|
||
]
|
||
},
|
||
"image/jxra": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jxra"
|
||
]
|
||
},
|
||
"image/jxrs": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jxrs"
|
||
]
|
||
},
|
||
"image/jxs": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jxs"
|
||
]
|
||
},
|
||
"image/jxsc": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jxsc"
|
||
]
|
||
},
|
||
"image/jxsi": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jxsi"
|
||
]
|
||
},
|
||
"image/jxss": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jxss"
|
||
]
|
||
},
|
||
"image/ktx": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ktx"
|
||
]
|
||
},
|
||
"image/ktx2": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ktx2"
|
||
]
|
||
},
|
||
"image/naplps": {
|
||
source: "iana"
|
||
},
|
||
"image/pjpeg": {
|
||
compressible: false
|
||
},
|
||
"image/png": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"png"
|
||
]
|
||
},
|
||
"image/prs.btif": {
|
||
source: "iana",
|
||
extensions: [
|
||
"btif"
|
||
]
|
||
},
|
||
"image/prs.pti": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pti"
|
||
]
|
||
},
|
||
"image/pwg-raster": {
|
||
source: "iana"
|
||
},
|
||
"image/sgi": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sgi"
|
||
]
|
||
},
|
||
"image/svg+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"svg",
|
||
"svgz"
|
||
]
|
||
},
|
||
"image/t38": {
|
||
source: "iana",
|
||
extensions: [
|
||
"t38"
|
||
]
|
||
},
|
||
"image/tiff": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"tif",
|
||
"tiff"
|
||
]
|
||
},
|
||
"image/tiff-fx": {
|
||
source: "iana",
|
||
extensions: [
|
||
"tfx"
|
||
]
|
||
},
|
||
"image/vnd.adobe.photoshop": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"psd"
|
||
]
|
||
},
|
||
"image/vnd.airzip.accelerator.azv": {
|
||
source: "iana",
|
||
extensions: [
|
||
"azv"
|
||
]
|
||
},
|
||
"image/vnd.cns.inf2": {
|
||
source: "iana"
|
||
},
|
||
"image/vnd.dece.graphic": {
|
||
source: "iana",
|
||
extensions: [
|
||
"uvi",
|
||
"uvvi",
|
||
"uvg",
|
||
"uvvg"
|
||
]
|
||
},
|
||
"image/vnd.djvu": {
|
||
source: "iana",
|
||
extensions: [
|
||
"djvu",
|
||
"djv"
|
||
]
|
||
},
|
||
"image/vnd.dvb.subtitle": {
|
||
source: "iana",
|
||
extensions: [
|
||
"sub"
|
||
]
|
||
},
|
||
"image/vnd.dwg": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dwg"
|
||
]
|
||
},
|
||
"image/vnd.dxf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dxf"
|
||
]
|
||
},
|
||
"image/vnd.fastbidsheet": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fbs"
|
||
]
|
||
},
|
||
"image/vnd.fpx": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fpx"
|
||
]
|
||
},
|
||
"image/vnd.fst": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fst"
|
||
]
|
||
},
|
||
"image/vnd.fujixerox.edmics-mmr": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mmr"
|
||
]
|
||
},
|
||
"image/vnd.fujixerox.edmics-rlc": {
|
||
source: "iana",
|
||
extensions: [
|
||
"rlc"
|
||
]
|
||
},
|
||
"image/vnd.globalgraphics.pgb": {
|
||
source: "iana"
|
||
},
|
||
"image/vnd.microsoft.icon": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"ico"
|
||
]
|
||
},
|
||
"image/vnd.mix": {
|
||
source: "iana"
|
||
},
|
||
"image/vnd.mozilla.apng": {
|
||
source: "iana"
|
||
},
|
||
"image/vnd.ms-dds": {
|
||
compressible: true,
|
||
extensions: [
|
||
"dds"
|
||
]
|
||
},
|
||
"image/vnd.ms-modi": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mdi"
|
||
]
|
||
},
|
||
"image/vnd.ms-photo": {
|
||
source: "apache",
|
||
extensions: [
|
||
"wdp"
|
||
]
|
||
},
|
||
"image/vnd.net-fpx": {
|
||
source: "iana",
|
||
extensions: [
|
||
"npx"
|
||
]
|
||
},
|
||
"image/vnd.pco.b16": {
|
||
source: "iana",
|
||
extensions: [
|
||
"b16"
|
||
]
|
||
},
|
||
"image/vnd.radiance": {
|
||
source: "iana"
|
||
},
|
||
"image/vnd.sealed.png": {
|
||
source: "iana"
|
||
},
|
||
"image/vnd.sealedmedia.softseal.gif": {
|
||
source: "iana"
|
||
},
|
||
"image/vnd.sealedmedia.softseal.jpg": {
|
||
source: "iana"
|
||
},
|
||
"image/vnd.svf": {
|
||
source: "iana"
|
||
},
|
||
"image/vnd.tencent.tap": {
|
||
source: "iana",
|
||
extensions: [
|
||
"tap"
|
||
]
|
||
},
|
||
"image/vnd.valve.source.texture": {
|
||
source: "iana",
|
||
extensions: [
|
||
"vtf"
|
||
]
|
||
},
|
||
"image/vnd.wap.wbmp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wbmp"
|
||
]
|
||
},
|
||
"image/vnd.xiff": {
|
||
source: "iana",
|
||
extensions: [
|
||
"xif"
|
||
]
|
||
},
|
||
"image/vnd.zbrush.pcx": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pcx"
|
||
]
|
||
},
|
||
"image/webp": {
|
||
source: "apache",
|
||
extensions: [
|
||
"webp"
|
||
]
|
||
},
|
||
"image/wmf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wmf"
|
||
]
|
||
},
|
||
"image/x-3ds": {
|
||
source: "apache",
|
||
extensions: [
|
||
"3ds"
|
||
]
|
||
},
|
||
"image/x-cmu-raster": {
|
||
source: "apache",
|
||
extensions: [
|
||
"ras"
|
||
]
|
||
},
|
||
"image/x-cmx": {
|
||
source: "apache",
|
||
extensions: [
|
||
"cmx"
|
||
]
|
||
},
|
||
"image/x-freehand": {
|
||
source: "apache",
|
||
extensions: [
|
||
"fh",
|
||
"fhc",
|
||
"fh4",
|
||
"fh5",
|
||
"fh7"
|
||
]
|
||
},
|
||
"image/x-icon": {
|
||
source: "apache",
|
||
compressible: true,
|
||
extensions: [
|
||
"ico"
|
||
]
|
||
},
|
||
"image/x-jng": {
|
||
source: "nginx",
|
||
extensions: [
|
||
"jng"
|
||
]
|
||
},
|
||
"image/x-mrsid-image": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sid"
|
||
]
|
||
},
|
||
"image/x-ms-bmp": {
|
||
source: "nginx",
|
||
compressible: true,
|
||
extensions: [
|
||
"bmp"
|
||
]
|
||
},
|
||
"image/x-pcx": {
|
||
source: "apache",
|
||
extensions: [
|
||
"pcx"
|
||
]
|
||
},
|
||
"image/x-pict": {
|
||
source: "apache",
|
||
extensions: [
|
||
"pic",
|
||
"pct"
|
||
]
|
||
},
|
||
"image/x-portable-anymap": {
|
||
source: "apache",
|
||
extensions: [
|
||
"pnm"
|
||
]
|
||
},
|
||
"image/x-portable-bitmap": {
|
||
source: "apache",
|
||
extensions: [
|
||
"pbm"
|
||
]
|
||
},
|
||
"image/x-portable-graymap": {
|
||
source: "apache",
|
||
extensions: [
|
||
"pgm"
|
||
]
|
||
},
|
||
"image/x-portable-pixmap": {
|
||
source: "apache",
|
||
extensions: [
|
||
"ppm"
|
||
]
|
||
},
|
||
"image/x-rgb": {
|
||
source: "apache",
|
||
extensions: [
|
||
"rgb"
|
||
]
|
||
},
|
||
"image/x-tga": {
|
||
source: "apache",
|
||
extensions: [
|
||
"tga"
|
||
]
|
||
},
|
||
"image/x-xbitmap": {
|
||
source: "apache",
|
||
extensions: [
|
||
"xbm"
|
||
]
|
||
},
|
||
"image/x-xcf": {
|
||
compressible: false
|
||
},
|
||
"image/x-xpixmap": {
|
||
source: "apache",
|
||
extensions: [
|
||
"xpm"
|
||
]
|
||
},
|
||
"image/x-xwindowdump": {
|
||
source: "apache",
|
||
extensions: [
|
||
"xwd"
|
||
]
|
||
},
|
||
"message/cpim": {
|
||
source: "iana"
|
||
},
|
||
"message/delivery-status": {
|
||
source: "iana"
|
||
},
|
||
"message/disposition-notification": {
|
||
source: "iana",
|
||
extensions: [
|
||
"disposition-notification"
|
||
]
|
||
},
|
||
"message/external-body": {
|
||
source: "iana"
|
||
},
|
||
"message/feedback-report": {
|
||
source: "iana"
|
||
},
|
||
"message/global": {
|
||
source: "iana",
|
||
extensions: [
|
||
"u8msg"
|
||
]
|
||
},
|
||
"message/global-delivery-status": {
|
||
source: "iana",
|
||
extensions: [
|
||
"u8dsn"
|
||
]
|
||
},
|
||
"message/global-disposition-notification": {
|
||
source: "iana",
|
||
extensions: [
|
||
"u8mdn"
|
||
]
|
||
},
|
||
"message/global-headers": {
|
||
source: "iana",
|
||
extensions: [
|
||
"u8hdr"
|
||
]
|
||
},
|
||
"message/http": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"message/imdn+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"message/news": {
|
||
source: "iana"
|
||
},
|
||
"message/partial": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"message/rfc822": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"eml",
|
||
"mime"
|
||
]
|
||
},
|
||
"message/s-http": {
|
||
source: "iana"
|
||
},
|
||
"message/sip": {
|
||
source: "iana"
|
||
},
|
||
"message/sipfrag": {
|
||
source: "iana"
|
||
},
|
||
"message/tracking-status": {
|
||
source: "iana"
|
||
},
|
||
"message/vnd.si.simp": {
|
||
source: "iana"
|
||
},
|
||
"message/vnd.wfa.wsc": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wsc"
|
||
]
|
||
},
|
||
"model/3mf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"3mf"
|
||
]
|
||
},
|
||
"model/e57": {
|
||
source: "iana"
|
||
},
|
||
"model/gltf+json": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"gltf"
|
||
]
|
||
},
|
||
"model/gltf-binary": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"glb"
|
||
]
|
||
},
|
||
"model/iges": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"igs",
|
||
"iges"
|
||
]
|
||
},
|
||
"model/mesh": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"msh",
|
||
"mesh",
|
||
"silo"
|
||
]
|
||
},
|
||
"model/mtl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mtl"
|
||
]
|
||
},
|
||
"model/obj": {
|
||
source: "iana",
|
||
extensions: [
|
||
"obj"
|
||
]
|
||
},
|
||
"model/step": {
|
||
source: "iana"
|
||
},
|
||
"model/step+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"stpx"
|
||
]
|
||
},
|
||
"model/step+zip": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"stpz"
|
||
]
|
||
},
|
||
"model/step-xml+zip": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"stpxz"
|
||
]
|
||
},
|
||
"model/stl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"stl"
|
||
]
|
||
},
|
||
"model/vnd.collada+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"dae"
|
||
]
|
||
},
|
||
"model/vnd.dwf": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dwf"
|
||
]
|
||
},
|
||
"model/vnd.flatland.3dml": {
|
||
source: "iana"
|
||
},
|
||
"model/vnd.gdl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"gdl"
|
||
]
|
||
},
|
||
"model/vnd.gs-gdl": {
|
||
source: "apache"
|
||
},
|
||
"model/vnd.gs.gdl": {
|
||
source: "iana"
|
||
},
|
||
"model/vnd.gtw": {
|
||
source: "iana",
|
||
extensions: [
|
||
"gtw"
|
||
]
|
||
},
|
||
"model/vnd.moml+xml": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"model/vnd.mts": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mts"
|
||
]
|
||
},
|
||
"model/vnd.opengex": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ogex"
|
||
]
|
||
},
|
||
"model/vnd.parasolid.transmit.binary": {
|
||
source: "iana",
|
||
extensions: [
|
||
"x_b"
|
||
]
|
||
},
|
||
"model/vnd.parasolid.transmit.text": {
|
||
source: "iana",
|
||
extensions: [
|
||
"x_t"
|
||
]
|
||
},
|
||
"model/vnd.pytha.pyox": {
|
||
source: "iana"
|
||
},
|
||
"model/vnd.rosette.annotated-data-model": {
|
||
source: "iana"
|
||
},
|
||
"model/vnd.sap.vds": {
|
||
source: "iana",
|
||
extensions: [
|
||
"vds"
|
||
]
|
||
},
|
||
"model/vnd.usdz+zip": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"usdz"
|
||
]
|
||
},
|
||
"model/vnd.valve.source.compiled-map": {
|
||
source: "iana",
|
||
extensions: [
|
||
"bsp"
|
||
]
|
||
},
|
||
"model/vnd.vtu": {
|
||
source: "iana",
|
||
extensions: [
|
||
"vtu"
|
||
]
|
||
},
|
||
"model/vrml": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"wrl",
|
||
"vrml"
|
||
]
|
||
},
|
||
"model/x3d+binary": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"x3db",
|
||
"x3dbz"
|
||
]
|
||
},
|
||
"model/x3d+fastinfoset": {
|
||
source: "iana",
|
||
extensions: [
|
||
"x3db"
|
||
]
|
||
},
|
||
"model/x3d+vrml": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"x3dv",
|
||
"x3dvz"
|
||
]
|
||
},
|
||
"model/x3d+xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"x3d",
|
||
"x3dz"
|
||
]
|
||
},
|
||
"model/x3d-vrml": {
|
||
source: "iana",
|
||
extensions: [
|
||
"x3dv"
|
||
]
|
||
},
|
||
"multipart/alternative": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"multipart/appledouble": {
|
||
source: "iana"
|
||
},
|
||
"multipart/byteranges": {
|
||
source: "iana"
|
||
},
|
||
"multipart/digest": {
|
||
source: "iana"
|
||
},
|
||
"multipart/encrypted": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"multipart/form-data": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"multipart/header-set": {
|
||
source: "iana"
|
||
},
|
||
"multipart/mixed": {
|
||
source: "iana"
|
||
},
|
||
"multipart/multilingual": {
|
||
source: "iana"
|
||
},
|
||
"multipart/parallel": {
|
||
source: "iana"
|
||
},
|
||
"multipart/related": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"multipart/report": {
|
||
source: "iana"
|
||
},
|
||
"multipart/signed": {
|
||
source: "iana",
|
||
compressible: false
|
||
},
|
||
"multipart/vnd.bint.med-plus": {
|
||
source: "iana"
|
||
},
|
||
"multipart/voice-message": {
|
||
source: "iana"
|
||
},
|
||
"multipart/x-mixed-replace": {
|
||
source: "iana"
|
||
},
|
||
"text/1d-interleaved-parityfec": {
|
||
source: "iana"
|
||
},
|
||
"text/cache-manifest": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"appcache",
|
||
"manifest"
|
||
]
|
||
},
|
||
"text/calendar": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ics",
|
||
"ifb"
|
||
]
|
||
},
|
||
"text/calender": {
|
||
compressible: true
|
||
},
|
||
"text/cmd": {
|
||
compressible: true
|
||
},
|
||
"text/coffeescript": {
|
||
extensions: [
|
||
"coffee",
|
||
"litcoffee"
|
||
]
|
||
},
|
||
"text/cql": {
|
||
source: "iana"
|
||
},
|
||
"text/cql-expression": {
|
||
source: "iana"
|
||
},
|
||
"text/cql-identifier": {
|
||
source: "iana"
|
||
},
|
||
"text/css": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true,
|
||
extensions: [
|
||
"css"
|
||
]
|
||
},
|
||
"text/csv": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"csv"
|
||
]
|
||
},
|
||
"text/csv-schema": {
|
||
source: "iana"
|
||
},
|
||
"text/directory": {
|
||
source: "iana"
|
||
},
|
||
"text/dns": {
|
||
source: "iana"
|
||
},
|
||
"text/ecmascript": {
|
||
source: "iana"
|
||
},
|
||
"text/encaprtp": {
|
||
source: "iana"
|
||
},
|
||
"text/enriched": {
|
||
source: "iana"
|
||
},
|
||
"text/fhirpath": {
|
||
source: "iana"
|
||
},
|
||
"text/flexfec": {
|
||
source: "iana"
|
||
},
|
||
"text/fwdred": {
|
||
source: "iana"
|
||
},
|
||
"text/gff3": {
|
||
source: "iana"
|
||
},
|
||
"text/grammar-ref-list": {
|
||
source: "iana"
|
||
},
|
||
"text/html": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"html",
|
||
"htm",
|
||
"shtml"
|
||
]
|
||
},
|
||
"text/jade": {
|
||
extensions: [
|
||
"jade"
|
||
]
|
||
},
|
||
"text/javascript": {
|
||
source: "iana",
|
||
compressible: true
|
||
},
|
||
"text/jcr-cnd": {
|
||
source: "iana"
|
||
},
|
||
"text/jsx": {
|
||
compressible: true,
|
||
extensions: [
|
||
"jsx"
|
||
]
|
||
},
|
||
"text/less": {
|
||
compressible: true,
|
||
extensions: [
|
||
"less"
|
||
]
|
||
},
|
||
"text/markdown": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"markdown",
|
||
"md"
|
||
]
|
||
},
|
||
"text/mathml": {
|
||
source: "nginx",
|
||
extensions: [
|
||
"mml"
|
||
]
|
||
},
|
||
"text/mdx": {
|
||
compressible: true,
|
||
extensions: [
|
||
"mdx"
|
||
]
|
||
},
|
||
"text/mizar": {
|
||
source: "iana"
|
||
},
|
||
"text/n3": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true,
|
||
extensions: [
|
||
"n3"
|
||
]
|
||
},
|
||
"text/parameters": {
|
||
source: "iana",
|
||
charset: "UTF-8"
|
||
},
|
||
"text/parityfec": {
|
||
source: "iana"
|
||
},
|
||
"text/plain": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"txt",
|
||
"text",
|
||
"conf",
|
||
"def",
|
||
"list",
|
||
"log",
|
||
"in",
|
||
"ini"
|
||
]
|
||
},
|
||
"text/provenance-notation": {
|
||
source: "iana",
|
||
charset: "UTF-8"
|
||
},
|
||
"text/prs.fallenstein.rst": {
|
||
source: "iana"
|
||
},
|
||
"text/prs.lines.tag": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dsc"
|
||
]
|
||
},
|
||
"text/prs.prop.logic": {
|
||
source: "iana"
|
||
},
|
||
"text/raptorfec": {
|
||
source: "iana"
|
||
},
|
||
"text/red": {
|
||
source: "iana"
|
||
},
|
||
"text/rfc822-headers": {
|
||
source: "iana"
|
||
},
|
||
"text/richtext": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"rtx"
|
||
]
|
||
},
|
||
"text/rtf": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"rtf"
|
||
]
|
||
},
|
||
"text/rtp-enc-aescm128": {
|
||
source: "iana"
|
||
},
|
||
"text/rtploopback": {
|
||
source: "iana"
|
||
},
|
||
"text/rtx": {
|
||
source: "iana"
|
||
},
|
||
"text/sgml": {
|
||
source: "iana",
|
||
extensions: [
|
||
"sgml",
|
||
"sgm"
|
||
]
|
||
},
|
||
"text/shaclc": {
|
||
source: "iana"
|
||
},
|
||
"text/shex": {
|
||
source: "iana",
|
||
extensions: [
|
||
"shex"
|
||
]
|
||
},
|
||
"text/slim": {
|
||
extensions: [
|
||
"slim",
|
||
"slm"
|
||
]
|
||
},
|
||
"text/spdx": {
|
||
source: "iana",
|
||
extensions: [
|
||
"spdx"
|
||
]
|
||
},
|
||
"text/strings": {
|
||
source: "iana"
|
||
},
|
||
"text/stylus": {
|
||
extensions: [
|
||
"stylus",
|
||
"styl"
|
||
]
|
||
},
|
||
"text/t140": {
|
||
source: "iana"
|
||
},
|
||
"text/tab-separated-values": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"tsv"
|
||
]
|
||
},
|
||
"text/troff": {
|
||
source: "iana",
|
||
extensions: [
|
||
"t",
|
||
"tr",
|
||
"roff",
|
||
"man",
|
||
"me",
|
||
"ms"
|
||
]
|
||
},
|
||
"text/turtle": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
extensions: [
|
||
"ttl"
|
||
]
|
||
},
|
||
"text/ulpfec": {
|
||
source: "iana"
|
||
},
|
||
"text/uri-list": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"uri",
|
||
"uris",
|
||
"urls"
|
||
]
|
||
},
|
||
"text/vcard": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"vcard"
|
||
]
|
||
},
|
||
"text/vnd.a": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.abc": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.ascii-art": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.curl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"curl"
|
||
]
|
||
},
|
||
"text/vnd.curl.dcurl": {
|
||
source: "apache",
|
||
extensions: [
|
||
"dcurl"
|
||
]
|
||
},
|
||
"text/vnd.curl.mcurl": {
|
||
source: "apache",
|
||
extensions: [
|
||
"mcurl"
|
||
]
|
||
},
|
||
"text/vnd.curl.scurl": {
|
||
source: "apache",
|
||
extensions: [
|
||
"scurl"
|
||
]
|
||
},
|
||
"text/vnd.debian.copyright": {
|
||
source: "iana",
|
||
charset: "UTF-8"
|
||
},
|
||
"text/vnd.dmclientscript": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.dvb.subtitle": {
|
||
source: "iana",
|
||
extensions: [
|
||
"sub"
|
||
]
|
||
},
|
||
"text/vnd.esmertec.theme-descriptor": {
|
||
source: "iana",
|
||
charset: "UTF-8"
|
||
},
|
||
"text/vnd.familysearch.gedcom": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ged"
|
||
]
|
||
},
|
||
"text/vnd.ficlab.flt": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.fly": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fly"
|
||
]
|
||
},
|
||
"text/vnd.fmi.flexstor": {
|
||
source: "iana",
|
||
extensions: [
|
||
"flx"
|
||
]
|
||
},
|
||
"text/vnd.gml": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.graphviz": {
|
||
source: "iana",
|
||
extensions: [
|
||
"gv"
|
||
]
|
||
},
|
||
"text/vnd.hans": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.hgl": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.in3d.3dml": {
|
||
source: "iana",
|
||
extensions: [
|
||
"3dml"
|
||
]
|
||
},
|
||
"text/vnd.in3d.spot": {
|
||
source: "iana",
|
||
extensions: [
|
||
"spot"
|
||
]
|
||
},
|
||
"text/vnd.iptc.newsml": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.iptc.nitf": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.latex-z": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.motorola.reflex": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.ms-mediapackage": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.net2phone.commcenter.command": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.radisys.msml-basic-layout": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.senx.warpscript": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.si.uricatalogue": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.sosi": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.sun.j2me.app-descriptor": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
extensions: [
|
||
"jad"
|
||
]
|
||
},
|
||
"text/vnd.trolltech.linguist": {
|
||
source: "iana",
|
||
charset: "UTF-8"
|
||
},
|
||
"text/vnd.wap.si": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.wap.sl": {
|
||
source: "iana"
|
||
},
|
||
"text/vnd.wap.wml": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wml"
|
||
]
|
||
},
|
||
"text/vnd.wap.wmlscript": {
|
||
source: "iana",
|
||
extensions: [
|
||
"wmls"
|
||
]
|
||
},
|
||
"text/vtt": {
|
||
source: "iana",
|
||
charset: "UTF-8",
|
||
compressible: true,
|
||
extensions: [
|
||
"vtt"
|
||
]
|
||
},
|
||
"text/x-asm": {
|
||
source: "apache",
|
||
extensions: [
|
||
"s",
|
||
"asm"
|
||
]
|
||
},
|
||
"text/x-c": {
|
||
source: "apache",
|
||
extensions: [
|
||
"c",
|
||
"cc",
|
||
"cxx",
|
||
"cpp",
|
||
"h",
|
||
"hh",
|
||
"dic"
|
||
]
|
||
},
|
||
"text/x-component": {
|
||
source: "nginx",
|
||
extensions: [
|
||
"htc"
|
||
]
|
||
},
|
||
"text/x-fortran": {
|
||
source: "apache",
|
||
extensions: [
|
||
"f",
|
||
"for",
|
||
"f77",
|
||
"f90"
|
||
]
|
||
},
|
||
"text/x-gwt-rpc": {
|
||
compressible: true
|
||
},
|
||
"text/x-handlebars-template": {
|
||
extensions: [
|
||
"hbs"
|
||
]
|
||
},
|
||
"text/x-java-source": {
|
||
source: "apache",
|
||
extensions: [
|
||
"java"
|
||
]
|
||
},
|
||
"text/x-jquery-tmpl": {
|
||
compressible: true
|
||
},
|
||
"text/x-lua": {
|
||
extensions: [
|
||
"lua"
|
||
]
|
||
},
|
||
"text/x-markdown": {
|
||
compressible: true,
|
||
extensions: [
|
||
"mkd"
|
||
]
|
||
},
|
||
"text/x-nfo": {
|
||
source: "apache",
|
||
extensions: [
|
||
"nfo"
|
||
]
|
||
},
|
||
"text/x-opml": {
|
||
source: "apache",
|
||
extensions: [
|
||
"opml"
|
||
]
|
||
},
|
||
"text/x-org": {
|
||
compressible: true,
|
||
extensions: [
|
||
"org"
|
||
]
|
||
},
|
||
"text/x-pascal": {
|
||
source: "apache",
|
||
extensions: [
|
||
"p",
|
||
"pas"
|
||
]
|
||
},
|
||
"text/x-processing": {
|
||
compressible: true,
|
||
extensions: [
|
||
"pde"
|
||
]
|
||
},
|
||
"text/x-sass": {
|
||
extensions: [
|
||
"sass"
|
||
]
|
||
},
|
||
"text/x-scss": {
|
||
extensions: [
|
||
"scss"
|
||
]
|
||
},
|
||
"text/x-setext": {
|
||
source: "apache",
|
||
extensions: [
|
||
"etx"
|
||
]
|
||
},
|
||
"text/x-sfv": {
|
||
source: "apache",
|
||
extensions: [
|
||
"sfv"
|
||
]
|
||
},
|
||
"text/x-suse-ymp": {
|
||
compressible: true,
|
||
extensions: [
|
||
"ymp"
|
||
]
|
||
},
|
||
"text/x-uuencode": {
|
||
source: "apache",
|
||
extensions: [
|
||
"uu"
|
||
]
|
||
},
|
||
"text/x-vcalendar": {
|
||
source: "apache",
|
||
extensions: [
|
||
"vcs"
|
||
]
|
||
},
|
||
"text/x-vcard": {
|
||
source: "apache",
|
||
extensions: [
|
||
"vcf"
|
||
]
|
||
},
|
||
"text/xml": {
|
||
source: "iana",
|
||
compressible: true,
|
||
extensions: [
|
||
"xml"
|
||
]
|
||
},
|
||
"text/xml-external-parsed-entity": {
|
||
source: "iana"
|
||
},
|
||
"text/yaml": {
|
||
compressible: true,
|
||
extensions: [
|
||
"yaml",
|
||
"yml"
|
||
]
|
||
},
|
||
"video/1d-interleaved-parityfec": {
|
||
source: "iana"
|
||
},
|
||
"video/3gpp": {
|
||
source: "iana",
|
||
extensions: [
|
||
"3gp",
|
||
"3gpp"
|
||
]
|
||
},
|
||
"video/3gpp-tt": {
|
||
source: "iana"
|
||
},
|
||
"video/3gpp2": {
|
||
source: "iana",
|
||
extensions: [
|
||
"3g2"
|
||
]
|
||
},
|
||
"video/av1": {
|
||
source: "iana"
|
||
},
|
||
"video/bmpeg": {
|
||
source: "iana"
|
||
},
|
||
"video/bt656": {
|
||
source: "iana"
|
||
},
|
||
"video/celb": {
|
||
source: "iana"
|
||
},
|
||
"video/dv": {
|
||
source: "iana"
|
||
},
|
||
"video/encaprtp": {
|
||
source: "iana"
|
||
},
|
||
"video/ffv1": {
|
||
source: "iana"
|
||
},
|
||
"video/flexfec": {
|
||
source: "iana"
|
||
},
|
||
"video/h261": {
|
||
source: "iana",
|
||
extensions: [
|
||
"h261"
|
||
]
|
||
},
|
||
"video/h263": {
|
||
source: "iana",
|
||
extensions: [
|
||
"h263"
|
||
]
|
||
},
|
||
"video/h263-1998": {
|
||
source: "iana"
|
||
},
|
||
"video/h263-2000": {
|
||
source: "iana"
|
||
},
|
||
"video/h264": {
|
||
source: "iana",
|
||
extensions: [
|
||
"h264"
|
||
]
|
||
},
|
||
"video/h264-rcdo": {
|
||
source: "iana"
|
||
},
|
||
"video/h264-svc": {
|
||
source: "iana"
|
||
},
|
||
"video/h265": {
|
||
source: "iana"
|
||
},
|
||
"video/iso.segment": {
|
||
source: "iana",
|
||
extensions: [
|
||
"m4s"
|
||
]
|
||
},
|
||
"video/jpeg": {
|
||
source: "iana",
|
||
extensions: [
|
||
"jpgv"
|
||
]
|
||
},
|
||
"video/jpeg2000": {
|
||
source: "iana"
|
||
},
|
||
"video/jpm": {
|
||
source: "apache",
|
||
extensions: [
|
||
"jpm",
|
||
"jpgm"
|
||
]
|
||
},
|
||
"video/jxsv": {
|
||
source: "iana"
|
||
},
|
||
"video/mj2": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mj2",
|
||
"mjp2"
|
||
]
|
||
},
|
||
"video/mp1s": {
|
||
source: "iana"
|
||
},
|
||
"video/mp2p": {
|
||
source: "iana"
|
||
},
|
||
"video/mp2t": {
|
||
source: "iana",
|
||
extensions: [
|
||
"ts"
|
||
]
|
||
},
|
||
"video/mp4": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"mp4",
|
||
"mp4v",
|
||
"mpg4"
|
||
]
|
||
},
|
||
"video/mp4v-es": {
|
||
source: "iana"
|
||
},
|
||
"video/mpeg": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"mpeg",
|
||
"mpg",
|
||
"mpe",
|
||
"m1v",
|
||
"m2v"
|
||
]
|
||
},
|
||
"video/mpeg4-generic": {
|
||
source: "iana"
|
||
},
|
||
"video/mpv": {
|
||
source: "iana"
|
||
},
|
||
"video/nv": {
|
||
source: "iana"
|
||
},
|
||
"video/ogg": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"ogv"
|
||
]
|
||
},
|
||
"video/parityfec": {
|
||
source: "iana"
|
||
},
|
||
"video/pointer": {
|
||
source: "iana"
|
||
},
|
||
"video/quicktime": {
|
||
source: "iana",
|
||
compressible: false,
|
||
extensions: [
|
||
"qt",
|
||
"mov"
|
||
]
|
||
},
|
||
"video/raptorfec": {
|
||
source: "iana"
|
||
},
|
||
"video/raw": {
|
||
source: "iana"
|
||
},
|
||
"video/rtp-enc-aescm128": {
|
||
source: "iana"
|
||
},
|
||
"video/rtploopback": {
|
||
source: "iana"
|
||
},
|
||
"video/rtx": {
|
||
source: "iana"
|
||
},
|
||
"video/scip": {
|
||
source: "iana"
|
||
},
|
||
"video/smpte291": {
|
||
source: "iana"
|
||
},
|
||
"video/smpte292m": {
|
||
source: "iana"
|
||
},
|
||
"video/ulpfec": {
|
||
source: "iana"
|
||
},
|
||
"video/vc1": {
|
||
source: "iana"
|
||
},
|
||
"video/vc2": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.cctv": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.dece.hd": {
|
||
source: "iana",
|
||
extensions: [
|
||
"uvh",
|
||
"uvvh"
|
||
]
|
||
},
|
||
"video/vnd.dece.mobile": {
|
||
source: "iana",
|
||
extensions: [
|
||
"uvm",
|
||
"uvvm"
|
||
]
|
||
},
|
||
"video/vnd.dece.mp4": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.dece.pd": {
|
||
source: "iana",
|
||
extensions: [
|
||
"uvp",
|
||
"uvvp"
|
||
]
|
||
},
|
||
"video/vnd.dece.sd": {
|
||
source: "iana",
|
||
extensions: [
|
||
"uvs",
|
||
"uvvs"
|
||
]
|
||
},
|
||
"video/vnd.dece.video": {
|
||
source: "iana",
|
||
extensions: [
|
||
"uvv",
|
||
"uvvv"
|
||
]
|
||
},
|
||
"video/vnd.directv.mpeg": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.directv.mpeg-tts": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.dlna.mpeg-tts": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.dvb.file": {
|
||
source: "iana",
|
||
extensions: [
|
||
"dvb"
|
||
]
|
||
},
|
||
"video/vnd.fvt": {
|
||
source: "iana",
|
||
extensions: [
|
||
"fvt"
|
||
]
|
||
},
|
||
"video/vnd.hns.video": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.iptvforum.1dparityfec-1010": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.iptvforum.1dparityfec-2005": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.iptvforum.2dparityfec-1010": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.iptvforum.2dparityfec-2005": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.iptvforum.ttsavc": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.iptvforum.ttsmpeg2": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.motorola.video": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.motorola.videop": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.mpegurl": {
|
||
source: "iana",
|
||
extensions: [
|
||
"mxu",
|
||
"m4u"
|
||
]
|
||
},
|
||
"video/vnd.ms-playready.media.pyv": {
|
||
source: "iana",
|
||
extensions: [
|
||
"pyv"
|
||
]
|
||
},
|
||
"video/vnd.nokia.interleaved-multimedia": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.nokia.mp4vr": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.nokia.videovoip": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.objectvideo": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.radgamettools.bink": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.radgamettools.smacker": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.sealed.mpeg1": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.sealed.mpeg4": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.sealed.swf": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.sealedmedia.softseal.mov": {
|
||
source: "iana"
|
||
},
|
||
"video/vnd.uvvu.mp4": {
|
||
source: "iana",
|
||
extensions: [
|
||
"uvu",
|
||
"uvvu"
|
||
]
|
||
},
|
||
"video/vnd.vivo": {
|
||
source: "iana",
|
||
extensions: [
|
||
"viv"
|
||
]
|
||
},
|
||
"video/vnd.youtube.yt": {
|
||
source: "iana"
|
||
},
|
||
"video/vp8": {
|
||
source: "iana"
|
||
},
|
||
"video/vp9": {
|
||
source: "iana"
|
||
},
|
||
"video/webm": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"webm"
|
||
]
|
||
},
|
||
"video/x-f4v": {
|
||
source: "apache",
|
||
extensions: [
|
||
"f4v"
|
||
]
|
||
},
|
||
"video/x-fli": {
|
||
source: "apache",
|
||
extensions: [
|
||
"fli"
|
||
]
|
||
},
|
||
"video/x-flv": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"flv"
|
||
]
|
||
},
|
||
"video/x-m4v": {
|
||
source: "apache",
|
||
extensions: [
|
||
"m4v"
|
||
]
|
||
},
|
||
"video/x-matroska": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"mkv",
|
||
"mk3d",
|
||
"mks"
|
||
]
|
||
},
|
||
"video/x-mng": {
|
||
source: "apache",
|
||
extensions: [
|
||
"mng"
|
||
]
|
||
},
|
||
"video/x-ms-asf": {
|
||
source: "apache",
|
||
extensions: [
|
||
"asf",
|
||
"asx"
|
||
]
|
||
},
|
||
"video/x-ms-vob": {
|
||
source: "apache",
|
||
extensions: [
|
||
"vob"
|
||
]
|
||
},
|
||
"video/x-ms-wm": {
|
||
source: "apache",
|
||
extensions: [
|
||
"wm"
|
||
]
|
||
},
|
||
"video/x-ms-wmv": {
|
||
source: "apache",
|
||
compressible: false,
|
||
extensions: [
|
||
"wmv"
|
||
]
|
||
},
|
||
"video/x-ms-wmx": {
|
||
source: "apache",
|
||
extensions: [
|
||
"wmx"
|
||
]
|
||
},
|
||
"video/x-ms-wvx": {
|
||
source: "apache",
|
||
extensions: [
|
||
"wvx"
|
||
]
|
||
},
|
||
"video/x-msvideo": {
|
||
source: "apache",
|
||
extensions: [
|
||
"avi"
|
||
]
|
||
},
|
||
"video/x-sgi-movie": {
|
||
source: "apache",
|
||
extensions: [
|
||
"movie"
|
||
]
|
||
},
|
||
"video/x-smv": {
|
||
source: "apache",
|
||
extensions: [
|
||
"smv"
|
||
]
|
||
},
|
||
"x-conference/x-cooltalk": {
|
||
source: "apache",
|
||
extensions: [
|
||
"ice"
|
||
]
|
||
},
|
||
"x-shader/x-fragment": {
|
||
compressible: true
|
||
},
|
||
"x-shader/x-vertex": {
|
||
compressible: true
|
||
}
|
||
};
|
||
|
||
/*!
|
||
* mime-db
|
||
* Copyright(c) 2014 Jonathan Ong
|
||
* Copyright(c) 2015-2022 Douglas Christopher Wilson
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* Module exports.
|
||
*/
|
||
|
||
var mimeDb = require$$0;
|
||
|
||
/*!
|
||
* mime-types
|
||
* Copyright(c) 2014 Jonathan Ong
|
||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||
* MIT Licensed
|
||
*/
|
||
|
||
(function (exports) {
|
||
|
||
/**
|
||
* Module dependencies.
|
||
* @private
|
||
*/
|
||
|
||
var db = mimeDb;
|
||
var extname = path$q.extname;
|
||
|
||
/**
|
||
* Module variables.
|
||
* @private
|
||
*/
|
||
|
||
var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/;
|
||
var TEXT_TYPE_REGEXP = /^text\//i;
|
||
|
||
/**
|
||
* Module exports.
|
||
* @public
|
||
*/
|
||
|
||
exports.charset = charset;
|
||
exports.charsets = { lookup: charset };
|
||
exports.contentType = contentType;
|
||
exports.extension = extension;
|
||
exports.extensions = Object.create(null);
|
||
exports.lookup = lookup;
|
||
exports.types = Object.create(null);
|
||
|
||
// Populate the extensions/types maps
|
||
populateMaps(exports.extensions, exports.types);
|
||
|
||
/**
|
||
* Get the default charset for a MIME type.
|
||
*
|
||
* @param {string} type
|
||
* @return {boolean|string}
|
||
*/
|
||
|
||
function charset (type) {
|
||
if (!type || typeof type !== 'string') {
|
||
return false
|
||
}
|
||
|
||
// TODO: use media-typer
|
||
var match = EXTRACT_TYPE_REGEXP.exec(type);
|
||
var mime = match && db[match[1].toLowerCase()];
|
||
|
||
if (mime && mime.charset) {
|
||
return mime.charset
|
||
}
|
||
|
||
// default text/* to utf-8
|
||
if (match && TEXT_TYPE_REGEXP.test(match[1])) {
|
||
return 'UTF-8'
|
||
}
|
||
|
||
return false
|
||
}
|
||
|
||
/**
|
||
* Create a full Content-Type header given a MIME type or extension.
|
||
*
|
||
* @param {string} str
|
||
* @return {boolean|string}
|
||
*/
|
||
|
||
function contentType (str) {
|
||
// TODO: should this even be in this module?
|
||
if (!str || typeof str !== 'string') {
|
||
return false
|
||
}
|
||
|
||
var mime = str.indexOf('/') === -1
|
||
? exports.lookup(str)
|
||
: str;
|
||
|
||
if (!mime) {
|
||
return false
|
||
}
|
||
|
||
// TODO: use content-type or other module
|
||
if (mime.indexOf('charset') === -1) {
|
||
var charset = exports.charset(mime);
|
||
if (charset) mime += '; charset=' + charset.toLowerCase();
|
||
}
|
||
|
||
return mime
|
||
}
|
||
|
||
/**
|
||
* Get the default extension for a MIME type.
|
||
*
|
||
* @param {string} type
|
||
* @return {boolean|string}
|
||
*/
|
||
|
||
function extension (type) {
|
||
if (!type || typeof type !== 'string') {
|
||
return false
|
||
}
|
||
|
||
// TODO: use media-typer
|
||
var match = EXTRACT_TYPE_REGEXP.exec(type);
|
||
|
||
// get extensions
|
||
var exts = match && exports.extensions[match[1].toLowerCase()];
|
||
|
||
if (!exts || !exts.length) {
|
||
return false
|
||
}
|
||
|
||
return exts[0]
|
||
}
|
||
|
||
/**
|
||
* Lookup the MIME type for a file path/extension.
|
||
*
|
||
* @param {string} path
|
||
* @return {boolean|string}
|
||
*/
|
||
|
||
function lookup (path) {
|
||
if (!path || typeof path !== 'string') {
|
||
return false
|
||
}
|
||
|
||
// get the extension ("ext" or ".ext" or full path)
|
||
var extension = extname('x.' + path)
|
||
.toLowerCase()
|
||
.substr(1);
|
||
|
||
if (!extension) {
|
||
return false
|
||
}
|
||
|
||
return exports.types[extension] || false
|
||
}
|
||
|
||
/**
|
||
* Populate the extensions and types maps.
|
||
* @private
|
||
*/
|
||
|
||
function populateMaps (extensions, types) {
|
||
// source preference (least -> most)
|
||
var preference = ['nginx', 'apache', undefined, 'iana'];
|
||
|
||
Object.keys(db).forEach(function forEachMimeType (type) {
|
||
var mime = db[type];
|
||
var exts = mime.extensions;
|
||
|
||
if (!exts || !exts.length) {
|
||
return
|
||
}
|
||
|
||
// mime -> extensions
|
||
extensions[type] = exts;
|
||
|
||
// extension -> mime
|
||
for (var i = 0; i < exts.length; i++) {
|
||
var extension = exts[i];
|
||
|
||
if (types[extension]) {
|
||
var from = preference.indexOf(db[types[extension]].source);
|
||
var to = preference.indexOf(mime.source);
|
||
|
||
if (types[extension] !== 'application/octet-stream' &&
|
||
(from > to || (from === to && types[extension].substr(0, 12) === 'application/'))) {
|
||
// skip the remapping
|
||
continue
|
||
}
|
||
}
|
||
|
||
// set the extension -> mime
|
||
types[extension] = type;
|
||
}
|
||
});
|
||
}
|
||
} (mimeTypes));
|
||
|
||
/*!
|
||
* accepts
|
||
* Copyright(c) 2014 Jonathan Ong
|
||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* Module dependencies.
|
||
* @private
|
||
*/
|
||
|
||
var Negotiator = negotiatorExports;
|
||
var mime = mimeTypes;
|
||
|
||
/**
|
||
* Module exports.
|
||
* @public
|
||
*/
|
||
|
||
var accepts$1 = Accepts;
|
||
|
||
/**
|
||
* Create a new Accepts object for the given req.
|
||
*
|
||
* @param {object} req
|
||
* @public
|
||
*/
|
||
|
||
function Accepts (req) {
|
||
if (!(this instanceof Accepts)) {
|
||
return new Accepts(req)
|
||
}
|
||
|
||
this.headers = req.headers;
|
||
this.negotiator = new Negotiator(req);
|
||
}
|
||
|
||
/**
|
||
* Check if the given `type(s)` is acceptable, returning
|
||
* the best match when true, otherwise `undefined`, in which
|
||
* case you should respond with 406 "Not Acceptable".
|
||
*
|
||
* The `type` value may be a single mime type string
|
||
* such as "application/json", the extension name
|
||
* such as "json" or an array `["json", "html", "text/plain"]`. When a list
|
||
* or array is given the _best_ match, if any is returned.
|
||
*
|
||
* Examples:
|
||
*
|
||
* // Accept: text/html
|
||
* this.types('html');
|
||
* // => "html"
|
||
*
|
||
* // Accept: text/*, application/json
|
||
* this.types('html');
|
||
* // => "html"
|
||
* this.types('text/html');
|
||
* // => "text/html"
|
||
* this.types('json', 'text');
|
||
* // => "json"
|
||
* this.types('application/json');
|
||
* // => "application/json"
|
||
*
|
||
* // Accept: text/*, application/json
|
||
* this.types('image/png');
|
||
* this.types('png');
|
||
* // => undefined
|
||
*
|
||
* // Accept: text/*;q=.5, application/json
|
||
* this.types(['html', 'json']);
|
||
* this.types('html', 'json');
|
||
* // => "json"
|
||
*
|
||
* @param {String|Array} types...
|
||
* @return {String|Array|Boolean}
|
||
* @public
|
||
*/
|
||
|
||
Accepts.prototype.type =
|
||
Accepts.prototype.types = function (types_) {
|
||
var types = types_;
|
||
|
||
// support flattened arguments
|
||
if (types && !Array.isArray(types)) {
|
||
types = new Array(arguments.length);
|
||
for (var i = 0; i < types.length; i++) {
|
||
types[i] = arguments[i];
|
||
}
|
||
}
|
||
|
||
// no types, return all requested types
|
||
if (!types || types.length === 0) {
|
||
return this.negotiator.mediaTypes()
|
||
}
|
||
|
||
// no accept header, return first given type
|
||
if (!this.headers.accept) {
|
||
return types[0]
|
||
}
|
||
|
||
var mimes = types.map(extToMime);
|
||
var accepts = this.negotiator.mediaTypes(mimes.filter(validMime));
|
||
var first = accepts[0];
|
||
|
||
return first
|
||
? types[mimes.indexOf(first)]
|
||
: false
|
||
};
|
||
|
||
/**
|
||
* Return accepted encodings or best fit based on `encodings`.
|
||
*
|
||
* Given `Accept-Encoding: gzip, deflate`
|
||
* an array sorted by quality is returned:
|
||
*
|
||
* ['gzip', 'deflate']
|
||
*
|
||
* @param {String|Array} encodings...
|
||
* @return {String|Array}
|
||
* @public
|
||
*/
|
||
|
||
Accepts.prototype.encoding =
|
||
Accepts.prototype.encodings = function (encodings_) {
|
||
var encodings = encodings_;
|
||
|
||
// support flattened arguments
|
||
if (encodings && !Array.isArray(encodings)) {
|
||
encodings = new Array(arguments.length);
|
||
for (var i = 0; i < encodings.length; i++) {
|
||
encodings[i] = arguments[i];
|
||
}
|
||
}
|
||
|
||
// no encodings, return all requested encodings
|
||
if (!encodings || encodings.length === 0) {
|
||
return this.negotiator.encodings()
|
||
}
|
||
|
||
return this.negotiator.encodings(encodings)[0] || false
|
||
};
|
||
|
||
/**
|
||
* Return accepted charsets or best fit based on `charsets`.
|
||
*
|
||
* Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5`
|
||
* an array sorted by quality is returned:
|
||
*
|
||
* ['utf-8', 'utf-7', 'iso-8859-1']
|
||
*
|
||
* @param {String|Array} charsets...
|
||
* @return {String|Array}
|
||
* @public
|
||
*/
|
||
|
||
Accepts.prototype.charset =
|
||
Accepts.prototype.charsets = function (charsets_) {
|
||
var charsets = charsets_;
|
||
|
||
// support flattened arguments
|
||
if (charsets && !Array.isArray(charsets)) {
|
||
charsets = new Array(arguments.length);
|
||
for (var i = 0; i < charsets.length; i++) {
|
||
charsets[i] = arguments[i];
|
||
}
|
||
}
|
||
|
||
// no charsets, return all requested charsets
|
||
if (!charsets || charsets.length === 0) {
|
||
return this.negotiator.charsets()
|
||
}
|
||
|
||
return this.negotiator.charsets(charsets)[0] || false
|
||
};
|
||
|
||
/**
|
||
* Return accepted languages or best fit based on `langs`.
|
||
*
|
||
* Given `Accept-Language: en;q=0.8, es, pt`
|
||
* an array sorted by quality is returned:
|
||
*
|
||
* ['es', 'pt', 'en']
|
||
*
|
||
* @param {String|Array} langs...
|
||
* @return {Array|String}
|
||
* @public
|
||
*/
|
||
|
||
Accepts.prototype.lang =
|
||
Accepts.prototype.langs =
|
||
Accepts.prototype.language =
|
||
Accepts.prototype.languages = function (languages_) {
|
||
var languages = languages_;
|
||
|
||
// support flattened arguments
|
||
if (languages && !Array.isArray(languages)) {
|
||
languages = new Array(arguments.length);
|
||
for (var i = 0; i < languages.length; i++) {
|
||
languages[i] = arguments[i];
|
||
}
|
||
}
|
||
|
||
// no languages, return all requested languages
|
||
if (!languages || languages.length === 0) {
|
||
return this.negotiator.languages()
|
||
}
|
||
|
||
return this.negotiator.languages(languages)[0] || false
|
||
};
|
||
|
||
/**
|
||
* Convert extnames to mime.
|
||
*
|
||
* @param {String} type
|
||
* @return {String}
|
||
* @private
|
||
*/
|
||
|
||
function extToMime (type) {
|
||
return type.indexOf('/') === -1
|
||
? mime.lookup(type)
|
||
: type
|
||
}
|
||
|
||
/**
|
||
* Check if mime is valid.
|
||
*
|
||
* @param {String} type
|
||
* @return {String}
|
||
* @private
|
||
*/
|
||
|
||
function validMime (type) {
|
||
return typeof type === 'string'
|
||
}
|
||
|
||
var safeBuffer = {exports: {}};
|
||
|
||
/* eslint-disable node/no-deprecated-api */
|
||
|
||
(function (module, exports) {
|
||
var buffer = require$$0$9;
|
||
var Buffer = buffer.Buffer;
|
||
|
||
// alternative to using Object.keys for old browsers
|
||
function copyProps (src, dst) {
|
||
for (var key in src) {
|
||
dst[key] = src[key];
|
||
}
|
||
}
|
||
if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) {
|
||
module.exports = buffer;
|
||
} else {
|
||
// Copy properties from require('buffer')
|
||
copyProps(buffer, exports);
|
||
exports.Buffer = SafeBuffer;
|
||
}
|
||
|
||
function SafeBuffer (arg, encodingOrOffset, length) {
|
||
return Buffer(arg, encodingOrOffset, length)
|
||
}
|
||
|
||
// Copy static methods from Buffer
|
||
copyProps(Buffer, SafeBuffer);
|
||
|
||
SafeBuffer.from = function (arg, encodingOrOffset, length) {
|
||
if (typeof arg === 'number') {
|
||
throw new TypeError('Argument must not be a number')
|
||
}
|
||
return Buffer(arg, encodingOrOffset, length)
|
||
};
|
||
|
||
SafeBuffer.alloc = function (size, fill, encoding) {
|
||
if (typeof size !== 'number') {
|
||
throw new TypeError('Argument must be a number')
|
||
}
|
||
var buf = Buffer(size);
|
||
if (fill !== undefined) {
|
||
if (typeof encoding === 'string') {
|
||
buf.fill(fill, encoding);
|
||
} else {
|
||
buf.fill(fill);
|
||
}
|
||
} else {
|
||
buf.fill(0);
|
||
}
|
||
return buf
|
||
};
|
||
|
||
SafeBuffer.allocUnsafe = function (size) {
|
||
if (typeof size !== 'number') {
|
||
throw new TypeError('Argument must be a number')
|
||
}
|
||
return Buffer(size)
|
||
};
|
||
|
||
SafeBuffer.allocUnsafeSlow = function (size) {
|
||
if (typeof size !== 'number') {
|
||
throw new TypeError('Argument must be a number')
|
||
}
|
||
return buffer.SlowBuffer(size)
|
||
};
|
||
} (safeBuffer, safeBuffer.exports));
|
||
|
||
var safeBufferExports = safeBuffer.exports;
|
||
|
||
var bytes$2 = {exports: {}};
|
||
|
||
/*!
|
||
* bytes
|
||
* Copyright(c) 2012-2014 TJ Holowaychuk
|
||
* Copyright(c) 2015 Jed Watson
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* Module exports.
|
||
* @public
|
||
*/
|
||
|
||
bytes$2.exports = bytes$1;
|
||
bytes$2.exports.format = format;
|
||
bytes$2.exports.parse = parse$3;
|
||
|
||
/**
|
||
* Module variables.
|
||
* @private
|
||
*/
|
||
|
||
var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g;
|
||
|
||
var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/;
|
||
|
||
var map = {
|
||
b: 1,
|
||
kb: 1 << 10,
|
||
mb: 1 << 20,
|
||
gb: 1 << 30,
|
||
tb: ((1 << 30) * 1024)
|
||
};
|
||
|
||
var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb)$/i;
|
||
|
||
/**
|
||
* Convert the given value in bytes into a string or parse to string to an integer in bytes.
|
||
*
|
||
* @param {string|number} value
|
||
* @param {{
|
||
* case: [string],
|
||
* decimalPlaces: [number]
|
||
* fixedDecimals: [boolean]
|
||
* thousandsSeparator: [string]
|
||
* unitSeparator: [string]
|
||
* }} [options] bytes options.
|
||
*
|
||
* @returns {string|number|null}
|
||
*/
|
||
|
||
function bytes$1(value, options) {
|
||
if (typeof value === 'string') {
|
||
return parse$3(value);
|
||
}
|
||
|
||
if (typeof value === 'number') {
|
||
return format(value, options);
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* Format the given value in bytes into a string.
|
||
*
|
||
* If the value is negative, it is kept as such. If it is a float,
|
||
* it is rounded.
|
||
*
|
||
* @param {number} value
|
||
* @param {object} [options]
|
||
* @param {number} [options.decimalPlaces=2]
|
||
* @param {number} [options.fixedDecimals=false]
|
||
* @param {string} [options.thousandsSeparator=]
|
||
* @param {string} [options.unit=]
|
||
* @param {string} [options.unitSeparator=]
|
||
*
|
||
* @returns {string|null}
|
||
* @public
|
||
*/
|
||
|
||
function format(value, options) {
|
||
if (!Number.isFinite(value)) {
|
||
return null;
|
||
}
|
||
|
||
var mag = Math.abs(value);
|
||
var thousandsSeparator = (options && options.thousandsSeparator) || '';
|
||
var unitSeparator = (options && options.unitSeparator) || '';
|
||
var decimalPlaces = (options && options.decimalPlaces !== undefined) ? options.decimalPlaces : 2;
|
||
var fixedDecimals = Boolean(options && options.fixedDecimals);
|
||
var unit = (options && options.unit) || '';
|
||
|
||
if (!unit || !map[unit.toLowerCase()]) {
|
||
if (mag >= map.tb) {
|
||
unit = 'TB';
|
||
} else if (mag >= map.gb) {
|
||
unit = 'GB';
|
||
} else if (mag >= map.mb) {
|
||
unit = 'MB';
|
||
} else if (mag >= map.kb) {
|
||
unit = 'KB';
|
||
} else {
|
||
unit = 'B';
|
||
}
|
||
}
|
||
|
||
var val = value / map[unit.toLowerCase()];
|
||
var str = val.toFixed(decimalPlaces);
|
||
|
||
if (!fixedDecimals) {
|
||
str = str.replace(formatDecimalsRegExp, '$1');
|
||
}
|
||
|
||
if (thousandsSeparator) {
|
||
str = str.replace(formatThousandsRegExp, thousandsSeparator);
|
||
}
|
||
|
||
return str + unitSeparator + unit;
|
||
}
|
||
|
||
/**
|
||
* Parse the string value into an integer in bytes.
|
||
*
|
||
* If no unit is given, it is assumed the value is in bytes.
|
||
*
|
||
* @param {number|string} val
|
||
*
|
||
* @returns {number|null}
|
||
* @public
|
||
*/
|
||
|
||
function parse$3(val) {
|
||
if (typeof val === 'number' && !isNaN(val)) {
|
||
return val;
|
||
}
|
||
|
||
if (typeof val !== 'string') {
|
||
return null;
|
||
}
|
||
|
||
// Test if the string passed is valid
|
||
var results = parseRegExp.exec(val);
|
||
var floatValue;
|
||
var unit = 'b';
|
||
|
||
if (!results) {
|
||
// Nothing could be extracted from the given string
|
||
floatValue = parseInt(val, 10);
|
||
unit = 'b';
|
||
} else {
|
||
// Retrieve the value and the unit
|
||
floatValue = parseFloat(results[1]);
|
||
unit = results[4].toLowerCase();
|
||
}
|
||
|
||
return Math.floor(map[unit] * floatValue);
|
||
}
|
||
|
||
var bytesExports = bytes$2.exports;
|
||
|
||
/*!
|
||
* compressible
|
||
* Copyright(c) 2013 Jonathan Ong
|
||
* Copyright(c) 2014 Jeremiah Senkpiel
|
||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* Module dependencies.
|
||
* @private
|
||
*/
|
||
|
||
var db = mimeDb;
|
||
|
||
/**
|
||
* Module variables.
|
||
* @private
|
||
*/
|
||
|
||
var COMPRESSIBLE_TYPE_REGEXP = /^text\/|\+(?:json|text|xml)$/i;
|
||
var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/;
|
||
|
||
/**
|
||
* Module exports.
|
||
* @public
|
||
*/
|
||
|
||
var compressible_1 = compressible$1;
|
||
|
||
/**
|
||
* Checks if a type is compressible.
|
||
*
|
||
* @param {string} type
|
||
* @return {Boolean} compressible
|
||
* @public
|
||
*/
|
||
|
||
function compressible$1 (type) {
|
||
if (!type || typeof type !== 'string') {
|
||
return false
|
||
}
|
||
|
||
// strip parameters
|
||
var match = EXTRACT_TYPE_REGEXP.exec(type);
|
||
var mime = match && match[1].toLowerCase();
|
||
var data = db[mime];
|
||
|
||
// return database information
|
||
if (data && data.compressible !== undefined) {
|
||
return data.compressible
|
||
}
|
||
|
||
// fallback to regexp or unknown
|
||
return COMPRESSIBLE_TYPE_REGEXP.test(mime) || undefined
|
||
}
|
||
|
||
var src = {exports: {}};
|
||
|
||
var node = {exports: {}};
|
||
|
||
var debug$1 = {exports: {}};
|
||
|
||
/**
|
||
* Helpers.
|
||
*/
|
||
|
||
var ms;
|
||
var hasRequiredMs;
|
||
|
||
function requireMs () {
|
||
if (hasRequiredMs) return ms;
|
||
hasRequiredMs = 1;
|
||
var s = 1000;
|
||
var m = s * 60;
|
||
var h = m * 60;
|
||
var d = h * 24;
|
||
var y = d * 365.25;
|
||
|
||
/**
|
||
* Parse or format the given `val`.
|
||
*
|
||
* Options:
|
||
*
|
||
* - `long` verbose formatting [false]
|
||
*
|
||
* @param {String|Number} val
|
||
* @param {Object} [options]
|
||
* @throws {Error} throw an error if val is not a non-empty string or a number
|
||
* @return {String|Number}
|
||
* @api public
|
||
*/
|
||
|
||
ms = function(val, options) {
|
||
options = options || {};
|
||
var type = typeof val;
|
||
if (type === 'string' && val.length > 0) {
|
||
return parse(val);
|
||
} else if (type === 'number' && isNaN(val) === false) {
|
||
return options.long ? fmtLong(val) : fmtShort(val);
|
||
}
|
||
throw new Error(
|
||
'val is not a non-empty string or a valid number. val=' +
|
||
JSON.stringify(val)
|
||
);
|
||
};
|
||
|
||
/**
|
||
* Parse the given `str` and return milliseconds.
|
||
*
|
||
* @param {String} str
|
||
* @return {Number}
|
||
* @api private
|
||
*/
|
||
|
||
function parse(str) {
|
||
str = String(str);
|
||
if (str.length > 100) {
|
||
return;
|
||
}
|
||
var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
|
||
str
|
||
);
|
||
if (!match) {
|
||
return;
|
||
}
|
||
var n = parseFloat(match[1]);
|
||
var type = (match[2] || 'ms').toLowerCase();
|
||
switch (type) {
|
||
case 'years':
|
||
case 'year':
|
||
case 'yrs':
|
||
case 'yr':
|
||
case 'y':
|
||
return n * y;
|
||
case 'days':
|
||
case 'day':
|
||
case 'd':
|
||
return n * d;
|
||
case 'hours':
|
||
case 'hour':
|
||
case 'hrs':
|
||
case 'hr':
|
||
case 'h':
|
||
return n * h;
|
||
case 'minutes':
|
||
case 'minute':
|
||
case 'mins':
|
||
case 'min':
|
||
case 'm':
|
||
return n * m;
|
||
case 'seconds':
|
||
case 'second':
|
||
case 'secs':
|
||
case 'sec':
|
||
case 's':
|
||
return n * s;
|
||
case 'milliseconds':
|
||
case 'millisecond':
|
||
case 'msecs':
|
||
case 'msec':
|
||
case 'ms':
|
||
return n;
|
||
default:
|
||
return undefined;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Short format for `ms`.
|
||
*
|
||
* @param {Number} ms
|
||
* @return {String}
|
||
* @api private
|
||
*/
|
||
|
||
function fmtShort(ms) {
|
||
if (ms >= d) {
|
||
return Math.round(ms / d) + 'd';
|
||
}
|
||
if (ms >= h) {
|
||
return Math.round(ms / h) + 'h';
|
||
}
|
||
if (ms >= m) {
|
||
return Math.round(ms / m) + 'm';
|
||
}
|
||
if (ms >= s) {
|
||
return Math.round(ms / s) + 's';
|
||
}
|
||
return ms + 'ms';
|
||
}
|
||
|
||
/**
|
||
* Long format for `ms`.
|
||
*
|
||
* @param {Number} ms
|
||
* @return {String}
|
||
* @api private
|
||
*/
|
||
|
||
function fmtLong(ms) {
|
||
return plural(ms, d, 'day') ||
|
||
plural(ms, h, 'hour') ||
|
||
plural(ms, m, 'minute') ||
|
||
plural(ms, s, 'second') ||
|
||
ms + ' ms';
|
||
}
|
||
|
||
/**
|
||
* Pluralization helper.
|
||
*/
|
||
|
||
function plural(ms, n, name) {
|
||
if (ms < n) {
|
||
return;
|
||
}
|
||
if (ms < n * 1.5) {
|
||
return Math.floor(ms / n) + ' ' + name;
|
||
}
|
||
return Math.ceil(ms / n) + ' ' + name + 's';
|
||
}
|
||
return ms;
|
||
}
|
||
|
||
var hasRequiredDebug;
|
||
|
||
function requireDebug () {
|
||
if (hasRequiredDebug) return debug$1.exports;
|
||
hasRequiredDebug = 1;
|
||
(function (module, exports) {
|
||
/**
|
||
* This is the common logic for both the Node.js and web browser
|
||
* implementations of `debug()`.
|
||
*
|
||
* Expose `debug()` as the module.
|
||
*/
|
||
|
||
exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
|
||
exports.coerce = coerce;
|
||
exports.disable = disable;
|
||
exports.enable = enable;
|
||
exports.enabled = enabled;
|
||
exports.humanize = requireMs();
|
||
|
||
/**
|
||
* The currently active debug mode names, and names to skip.
|
||
*/
|
||
|
||
exports.names = [];
|
||
exports.skips = [];
|
||
|
||
/**
|
||
* Map of special "%n" handling functions, for the debug "format" argument.
|
||
*
|
||
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
|
||
*/
|
||
|
||
exports.formatters = {};
|
||
|
||
/**
|
||
* Previous log timestamp.
|
||
*/
|
||
|
||
var prevTime;
|
||
|
||
/**
|
||
* Select a color.
|
||
* @param {String} namespace
|
||
* @return {Number}
|
||
* @api private
|
||
*/
|
||
|
||
function selectColor(namespace) {
|
||
var hash = 0, i;
|
||
|
||
for (i in namespace) {
|
||
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
|
||
hash |= 0; // Convert to 32bit integer
|
||
}
|
||
|
||
return exports.colors[Math.abs(hash) % exports.colors.length];
|
||
}
|
||
|
||
/**
|
||
* Create a debugger with the given `namespace`.
|
||
*
|
||
* @param {String} namespace
|
||
* @return {Function}
|
||
* @api public
|
||
*/
|
||
|
||
function createDebug(namespace) {
|
||
|
||
function debug() {
|
||
// disabled?
|
||
if (!debug.enabled) return;
|
||
|
||
var self = debug;
|
||
|
||
// set `diff` timestamp
|
||
var curr = +new Date();
|
||
var ms = curr - (prevTime || curr);
|
||
self.diff = ms;
|
||
self.prev = prevTime;
|
||
self.curr = curr;
|
||
prevTime = curr;
|
||
|
||
// turn the `arguments` into a proper Array
|
||
var args = new Array(arguments.length);
|
||
for (var i = 0; i < args.length; i++) {
|
||
args[i] = arguments[i];
|
||
}
|
||
|
||
args[0] = exports.coerce(args[0]);
|
||
|
||
if ('string' !== typeof args[0]) {
|
||
// anything else let's inspect with %O
|
||
args.unshift('%O');
|
||
}
|
||
|
||
// apply any `formatters` transformations
|
||
var index = 0;
|
||
args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
|
||
// if we encounter an escaped % then don't increase the array index
|
||
if (match === '%%') return match;
|
||
index++;
|
||
var formatter = exports.formatters[format];
|
||
if ('function' === typeof formatter) {
|
||
var val = args[index];
|
||
match = formatter.call(self, val);
|
||
|
||
// now we need to remove `args[index]` since it's inlined in the `format`
|
||
args.splice(index, 1);
|
||
index--;
|
||
}
|
||
return match;
|
||
});
|
||
|
||
// apply env-specific formatting (colors, etc.)
|
||
exports.formatArgs.call(self, args);
|
||
|
||
var logFn = debug.log || exports.log || console.log.bind(console);
|
||
logFn.apply(self, args);
|
||
}
|
||
|
||
debug.namespace = namespace;
|
||
debug.enabled = exports.enabled(namespace);
|
||
debug.useColors = exports.useColors();
|
||
debug.color = selectColor(namespace);
|
||
|
||
// env-specific initialization logic for debug instances
|
||
if ('function' === typeof exports.init) {
|
||
exports.init(debug);
|
||
}
|
||
|
||
return debug;
|
||
}
|
||
|
||
/**
|
||
* Enables a debug mode by namespaces. This can include modes
|
||
* separated by a colon and wildcards.
|
||
*
|
||
* @param {String} namespaces
|
||
* @api public
|
||
*/
|
||
|
||
function enable(namespaces) {
|
||
exports.save(namespaces);
|
||
|
||
exports.names = [];
|
||
exports.skips = [];
|
||
|
||
var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
|
||
var len = split.length;
|
||
|
||
for (var i = 0; i < len; i++) {
|
||
if (!split[i]) continue; // ignore empty strings
|
||
namespaces = split[i].replace(/\*/g, '.*?');
|
||
if (namespaces[0] === '-') {
|
||
exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
|
||
} else {
|
||
exports.names.push(new RegExp('^' + namespaces + '$'));
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Disable debug output.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
function disable() {
|
||
exports.enable('');
|
||
}
|
||
|
||
/**
|
||
* Returns true if the given mode name is enabled, false otherwise.
|
||
*
|
||
* @param {String} name
|
||
* @return {Boolean}
|
||
* @api public
|
||
*/
|
||
|
||
function enabled(name) {
|
||
var i, len;
|
||
for (i = 0, len = exports.skips.length; i < len; i++) {
|
||
if (exports.skips[i].test(name)) {
|
||
return false;
|
||
}
|
||
}
|
||
for (i = 0, len = exports.names.length; i < len; i++) {
|
||
if (exports.names[i].test(name)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Coerce `val`.
|
||
*
|
||
* @param {Mixed} val
|
||
* @return {Mixed}
|
||
* @api private
|
||
*/
|
||
|
||
function coerce(val) {
|
||
if (val instanceof Error) return val.stack || val.message;
|
||
return val;
|
||
}
|
||
} (debug$1, debug$1.exports));
|
||
return debug$1.exports;
|
||
}
|
||
|
||
/**
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var hasRequiredNode;
|
||
|
||
function requireNode () {
|
||
if (hasRequiredNode) return node.exports;
|
||
hasRequiredNode = 1;
|
||
(function (module, exports) {
|
||
var tty = require$$0$5;
|
||
var util = require$$0$4;
|
||
|
||
/**
|
||
* This is the Node.js implementation of `debug()`.
|
||
*
|
||
* Expose `debug()` as the module.
|
||
*/
|
||
|
||
exports = module.exports = requireDebug();
|
||
exports.init = init;
|
||
exports.log = log;
|
||
exports.formatArgs = formatArgs;
|
||
exports.save = save;
|
||
exports.load = load;
|
||
exports.useColors = useColors;
|
||
|
||
/**
|
||
* Colors.
|
||
*/
|
||
|
||
exports.colors = [6, 2, 3, 4, 5, 1];
|
||
|
||
/**
|
||
* Build up the default `inspectOpts` object from the environment variables.
|
||
*
|
||
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
|
||
*/
|
||
|
||
exports.inspectOpts = Object.keys(process.env).filter(function (key) {
|
||
return /^debug_/i.test(key);
|
||
}).reduce(function (obj, key) {
|
||
// camel-case
|
||
var prop = key
|
||
.substring(6)
|
||
.toLowerCase()
|
||
.replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
|
||
|
||
// coerce string value into JS value
|
||
var val = process.env[key];
|
||
if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
|
||
else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
|
||
else if (val === 'null') val = null;
|
||
else val = Number(val);
|
||
|
||
obj[prop] = val;
|
||
return obj;
|
||
}, {});
|
||
|
||
/**
|
||
* The file descriptor to write the `debug()` calls to.
|
||
* Set the `DEBUG_FD` env variable to override with another value. i.e.:
|
||
*
|
||
* $ DEBUG_FD=3 node script.js 3>debug.log
|
||
*/
|
||
|
||
var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
|
||
|
||
if (1 !== fd && 2 !== fd) {
|
||
util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')();
|
||
}
|
||
|
||
var stream = 1 === fd ? process.stdout :
|
||
2 === fd ? process.stderr :
|
||
createWritableStdioStream(fd);
|
||
|
||
/**
|
||
* Is stdout a TTY? Colored output is enabled when `true`.
|
||
*/
|
||
|
||
function useColors() {
|
||
return 'colors' in exports.inspectOpts
|
||
? Boolean(exports.inspectOpts.colors)
|
||
: tty.isatty(fd);
|
||
}
|
||
|
||
/**
|
||
* Map %o to `util.inspect()`, all on a single line.
|
||
*/
|
||
|
||
exports.formatters.o = function(v) {
|
||
this.inspectOpts.colors = this.useColors;
|
||
return util.inspect(v, this.inspectOpts)
|
||
.split('\n').map(function(str) {
|
||
return str.trim()
|
||
}).join(' ');
|
||
};
|
||
|
||
/**
|
||
* Map %o to `util.inspect()`, allowing multiple lines if needed.
|
||
*/
|
||
|
||
exports.formatters.O = function(v) {
|
||
this.inspectOpts.colors = this.useColors;
|
||
return util.inspect(v, this.inspectOpts);
|
||
};
|
||
|
||
/**
|
||
* Adds ANSI color escape codes if enabled.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
function formatArgs(args) {
|
||
var name = this.namespace;
|
||
var useColors = this.useColors;
|
||
|
||
if (useColors) {
|
||
var c = this.color;
|
||
var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m';
|
||
|
||
args[0] = prefix + args[0].split('\n').join('\n' + prefix);
|
||
args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
|
||
} else {
|
||
args[0] = new Date().toUTCString()
|
||
+ ' ' + name + ' ' + args[0];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Invokes `util.format()` with the specified arguments and writes to `stream`.
|
||
*/
|
||
|
||
function log() {
|
||
return stream.write(util.format.apply(util, arguments) + '\n');
|
||
}
|
||
|
||
/**
|
||
* Save `namespaces`.
|
||
*
|
||
* @param {String} namespaces
|
||
* @api private
|
||
*/
|
||
|
||
function save(namespaces) {
|
||
if (null == namespaces) {
|
||
// If you set a process.env field to null or undefined, it gets cast to the
|
||
// string 'null' or 'undefined'. Just delete instead.
|
||
delete process.env.DEBUG;
|
||
} else {
|
||
process.env.DEBUG = namespaces;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Load `namespaces`.
|
||
*
|
||
* @return {String} returns the previously persisted debug modes
|
||
* @api private
|
||
*/
|
||
|
||
function load() {
|
||
return process.env.DEBUG;
|
||
}
|
||
|
||
/**
|
||
* Copied from `node/src/node.js`.
|
||
*
|
||
* XXX: It's lame that node doesn't expose this API out-of-the-box. It also
|
||
* relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
|
||
*/
|
||
|
||
function createWritableStdioStream (fd) {
|
||
var stream;
|
||
var tty_wrap = process.binding('tty_wrap');
|
||
|
||
// Note stream._type is used for test-module-load-list.js
|
||
|
||
switch (tty_wrap.guessHandleType(fd)) {
|
||
case 'TTY':
|
||
stream = new tty.WriteStream(fd);
|
||
stream._type = 'tty';
|
||
|
||
// Hack to have stream not keep the event loop alive.
|
||
// See https://github.com/joyent/node/issues/1726
|
||
if (stream._handle && stream._handle.unref) {
|
||
stream._handle.unref();
|
||
}
|
||
break;
|
||
|
||
case 'FILE':
|
||
var fs = fs__default;
|
||
stream = new fs.SyncWriteStream(fd, { autoClose: false });
|
||
stream._type = 'fs';
|
||
break;
|
||
|
||
case 'PIPE':
|
||
case 'TCP':
|
||
var net = require$$4;
|
||
stream = new net.Socket({
|
||
fd: fd,
|
||
readable: false,
|
||
writable: true
|
||
});
|
||
|
||
// FIXME Should probably have an option in net.Socket to create a
|
||
// stream from an existing fd which is writable only. But for now
|
||
// we'll just add this hack and set the `readable` member to false.
|
||
// Test: ./node test/fixtures/echo.js < /etc/passwd
|
||
stream.readable = false;
|
||
stream.read = null;
|
||
stream._type = 'pipe';
|
||
|
||
// FIXME Hack to have stream not keep the event loop alive.
|
||
// See https://github.com/joyent/node/issues/1726
|
||
if (stream._handle && stream._handle.unref) {
|
||
stream._handle.unref();
|
||
}
|
||
break;
|
||
|
||
default:
|
||
// Probably an error on in uv_guess_handle()
|
||
throw new Error('Implement me. Unknown stream file type!');
|
||
}
|
||
|
||
// For supporting legacy API we put the FD here.
|
||
stream.fd = fd;
|
||
|
||
stream._isStdio = true;
|
||
|
||
return stream;
|
||
}
|
||
|
||
/**
|
||
* Init logic for `debug` instances.
|
||
*
|
||
* Create a new `inspectOpts` object in case `useColors` is set
|
||
* differently for a particular `debug` instance.
|
||
*/
|
||
|
||
function init (debug) {
|
||
debug.inspectOpts = {};
|
||
|
||
var keys = Object.keys(exports.inspectOpts);
|
||
for (var i = 0; i < keys.length; i++) {
|
||
debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Enable namespaces listed in `process.env.DEBUG` initially.
|
||
*/
|
||
|
||
exports.enable(load());
|
||
} (node, node.exports));
|
||
return node.exports;
|
||
}
|
||
|
||
var browser = {exports: {}};
|
||
|
||
/**
|
||
* This is the web browser implementation of `debug()`.
|
||
*
|
||
* Expose `debug()` as the module.
|
||
*/
|
||
|
||
var hasRequiredBrowser;
|
||
|
||
function requireBrowser () {
|
||
if (hasRequiredBrowser) return browser.exports;
|
||
hasRequiredBrowser = 1;
|
||
(function (module, exports) {
|
||
exports = module.exports = requireDebug();
|
||
exports.log = log;
|
||
exports.formatArgs = formatArgs;
|
||
exports.save = save;
|
||
exports.load = load;
|
||
exports.useColors = useColors;
|
||
exports.storage = 'undefined' != typeof chrome
|
||
&& 'undefined' != typeof chrome.storage
|
||
? chrome.storage.local
|
||
: localstorage();
|
||
|
||
/**
|
||
* Colors.
|
||
*/
|
||
|
||
exports.colors = [
|
||
'lightseagreen',
|
||
'forestgreen',
|
||
'goldenrod',
|
||
'dodgerblue',
|
||
'darkorchid',
|
||
'crimson'
|
||
];
|
||
|
||
/**
|
||
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
|
||
* and the Firebug extension (any Firefox version) are known
|
||
* to support "%c" CSS customizations.
|
||
*
|
||
* TODO: add a `localStorage` variable to explicitly enable/disable colors
|
||
*/
|
||
|
||
function useColors() {
|
||
// NB: In an Electron preload script, document will be defined but not fully
|
||
// initialized. Since we know we're in Chrome, we'll just detect this case
|
||
// explicitly
|
||
if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
|
||
return true;
|
||
}
|
||
|
||
// is webkit? http://stackoverflow.com/a/16459606/376773
|
||
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
|
||
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
|
||
// is firebug? http://stackoverflow.com/a/398120/376773
|
||
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
|
||
// is firefox >= v31?
|
||
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
||
(typeof navigator !== 'undefined' && undefined && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
|
||
// double check webkit in userAgent just in case we are in a worker
|
||
(typeof navigator !== 'undefined' && undefined && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
|
||
}
|
||
|
||
/**
|
||
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
|
||
*/
|
||
|
||
exports.formatters.j = function(v) {
|
||
try {
|
||
return JSON.stringify(v);
|
||
} catch (err) {
|
||
return '[UnexpectedJSONParseError]: ' + err.message;
|
||
}
|
||
};
|
||
|
||
|
||
/**
|
||
* Colorize log arguments if enabled.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
function formatArgs(args) {
|
||
var useColors = this.useColors;
|
||
|
||
args[0] = (useColors ? '%c' : '')
|
||
+ this.namespace
|
||
+ (useColors ? ' %c' : ' ')
|
||
+ args[0]
|
||
+ (useColors ? '%c ' : ' ')
|
||
+ '+' + exports.humanize(this.diff);
|
||
|
||
if (!useColors) return;
|
||
|
||
var c = 'color: ' + this.color;
|
||
args.splice(1, 0, c, 'color: inherit');
|
||
|
||
// the final "%c" is somewhat tricky, because there could be other
|
||
// arguments passed either before or after the %c, so we need to
|
||
// figure out the correct index to insert the CSS into
|
||
var index = 0;
|
||
var lastC = 0;
|
||
args[0].replace(/%[a-zA-Z%]/g, function(match) {
|
||
if ('%%' === match) return;
|
||
index++;
|
||
if ('%c' === match) {
|
||
// we only are interested in the *last* %c
|
||
// (the user may have provided their own)
|
||
lastC = index;
|
||
}
|
||
});
|
||
|
||
args.splice(lastC, 0, c);
|
||
}
|
||
|
||
/**
|
||
* Invokes `console.log()` when available.
|
||
* No-op when `console.log` is not a "function".
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
function log() {
|
||
// this hackery is required for IE8/9, where
|
||
// the `console.log` function doesn't have 'apply'
|
||
return 'object' === typeof console
|
||
&& console.log
|
||
&& Function.prototype.apply.call(console.log, console, arguments);
|
||
}
|
||
|
||
/**
|
||
* Save `namespaces`.
|
||
*
|
||
* @param {String} namespaces
|
||
* @api private
|
||
*/
|
||
|
||
function save(namespaces) {
|
||
try {
|
||
if (null == namespaces) {
|
||
exports.storage.removeItem('debug');
|
||
} else {
|
||
exports.storage.debug = namespaces;
|
||
}
|
||
} catch(e) {}
|
||
}
|
||
|
||
/**
|
||
* Load `namespaces`.
|
||
*
|
||
* @return {String} returns the previously persisted debug modes
|
||
* @api private
|
||
*/
|
||
|
||
function load() {
|
||
var r;
|
||
try {
|
||
r = exports.storage.debug;
|
||
} catch(e) {}
|
||
|
||
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
|
||
if (!r && typeof process !== 'undefined' && 'env' in process) {
|
||
r = process.env.DEBUG;
|
||
}
|
||
|
||
return r;
|
||
}
|
||
|
||
/**
|
||
* Enable namespaces listed in `localStorage.debug` initially.
|
||
*/
|
||
|
||
exports.enable(load());
|
||
|
||
/**
|
||
* Localstorage attempts to return the localstorage.
|
||
*
|
||
* This is necessary because safari throws
|
||
* when a user disables cookies/localstorage
|
||
* and you attempt to access it.
|
||
*
|
||
* @return {LocalStorage}
|
||
* @api private
|
||
*/
|
||
|
||
function localstorage() {
|
||
try {
|
||
return window.localStorage;
|
||
} catch (e) {}
|
||
}
|
||
} (browser, browser.exports));
|
||
return browser.exports;
|
||
}
|
||
|
||
/**
|
||
* Detect Electron renderer process, which is node, but we should
|
||
* treat as a browser.
|
||
*/
|
||
|
||
if (typeof process !== 'undefined' && process.type === 'renderer') {
|
||
src.exports = requireBrowser();
|
||
} else {
|
||
src.exports = requireNode();
|
||
}
|
||
|
||
var srcExports = src.exports;
|
||
|
||
/*!
|
||
* on-headers
|
||
* Copyright(c) 2014 Douglas Christopher Wilson
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* Module exports.
|
||
* @public
|
||
*/
|
||
|
||
var onHeaders_1 = onHeaders$1;
|
||
|
||
/**
|
||
* Create a replacement writeHead method.
|
||
*
|
||
* @param {function} prevWriteHead
|
||
* @param {function} listener
|
||
* @private
|
||
*/
|
||
|
||
function createWriteHead (prevWriteHead, listener) {
|
||
var fired = false;
|
||
|
||
// return function with core name and argument list
|
||
return function writeHead (statusCode) {
|
||
// set headers from arguments
|
||
var args = setWriteHeadHeaders.apply(this, arguments);
|
||
|
||
// fire listener
|
||
if (!fired) {
|
||
fired = true;
|
||
listener.call(this);
|
||
|
||
// pass-along an updated status code
|
||
if (typeof args[0] === 'number' && this.statusCode !== args[0]) {
|
||
args[0] = this.statusCode;
|
||
args.length = 1;
|
||
}
|
||
}
|
||
|
||
return prevWriteHead.apply(this, args)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Execute a listener when a response is about to write headers.
|
||
*
|
||
* @param {object} res
|
||
* @return {function} listener
|
||
* @public
|
||
*/
|
||
|
||
function onHeaders$1 (res, listener) {
|
||
if (!res) {
|
||
throw new TypeError('argument res is required')
|
||
}
|
||
|
||
if (typeof listener !== 'function') {
|
||
throw new TypeError('argument listener must be a function')
|
||
}
|
||
|
||
res.writeHead = createWriteHead(res.writeHead, listener);
|
||
}
|
||
|
||
/**
|
||
* Set headers contained in array on the response object.
|
||
*
|
||
* @param {object} res
|
||
* @param {array} headers
|
||
* @private
|
||
*/
|
||
|
||
function setHeadersFromArray (res, headers) {
|
||
for (var i = 0; i < headers.length; i++) {
|
||
res.setHeader(headers[i][0], headers[i][1]);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Set headers contained in object on the response object.
|
||
*
|
||
* @param {object} res
|
||
* @param {object} headers
|
||
* @private
|
||
*/
|
||
|
||
function setHeadersFromObject (res, headers) {
|
||
var keys = Object.keys(headers);
|
||
for (var i = 0; i < keys.length; i++) {
|
||
var k = keys[i];
|
||
if (k) res.setHeader(k, headers[k]);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Set headers and other properties on the response object.
|
||
*
|
||
* @param {number} statusCode
|
||
* @private
|
||
*/
|
||
|
||
function setWriteHeadHeaders (statusCode) {
|
||
var length = arguments.length;
|
||
var headerIndex = length > 1 && typeof arguments[1] === 'string'
|
||
? 2
|
||
: 1;
|
||
|
||
var headers = length >= headerIndex + 1
|
||
? arguments[headerIndex]
|
||
: undefined;
|
||
|
||
this.statusCode = statusCode;
|
||
|
||
if (Array.isArray(headers)) {
|
||
// handle array case
|
||
setHeadersFromArray(this, headers);
|
||
} else if (headers) {
|
||
// handle object case
|
||
setHeadersFromObject(this, headers);
|
||
}
|
||
|
||
// copy leading arguments
|
||
var args = new Array(Math.min(length, headerIndex));
|
||
for (var i = 0; i < args.length; i++) {
|
||
args[i] = arguments[i];
|
||
}
|
||
|
||
return args
|
||
}
|
||
|
||
var vary$2 = {exports: {}};
|
||
|
||
/*!
|
||
* vary
|
||
* Copyright(c) 2014-2017 Douglas Christopher Wilson
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* Module exports.
|
||
*/
|
||
|
||
vary$2.exports = vary$1;
|
||
vary$2.exports.append = append;
|
||
|
||
/**
|
||
* RegExp to match field-name in RFC 7230 sec 3.2
|
||
*
|
||
* field-name = token
|
||
* token = 1*tchar
|
||
* tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
|
||
* / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
|
||
* / DIGIT / ALPHA
|
||
* ; any VCHAR, except delimiters
|
||
*/
|
||
|
||
var FIELD_NAME_REGEXP = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
||
|
||
/**
|
||
* Append a field to a vary header.
|
||
*
|
||
* @param {String} header
|
||
* @param {String|Array} field
|
||
* @return {String}
|
||
* @public
|
||
*/
|
||
|
||
function append (header, field) {
|
||
if (typeof header !== 'string') {
|
||
throw new TypeError('header argument is required')
|
||
}
|
||
|
||
if (!field) {
|
||
throw new TypeError('field argument is required')
|
||
}
|
||
|
||
// get fields array
|
||
var fields = !Array.isArray(field)
|
||
? parse$2(String(field))
|
||
: field;
|
||
|
||
// assert on invalid field names
|
||
for (var j = 0; j < fields.length; j++) {
|
||
if (!FIELD_NAME_REGEXP.test(fields[j])) {
|
||
throw new TypeError('field argument contains an invalid header name')
|
||
}
|
||
}
|
||
|
||
// existing, unspecified vary
|
||
if (header === '*') {
|
||
return header
|
||
}
|
||
|
||
// enumerate current values
|
||
var val = header;
|
||
var vals = parse$2(header.toLowerCase());
|
||
|
||
// unspecified vary
|
||
if (fields.indexOf('*') !== -1 || vals.indexOf('*') !== -1) {
|
||
return '*'
|
||
}
|
||
|
||
for (var i = 0; i < fields.length; i++) {
|
||
var fld = fields[i].toLowerCase();
|
||
|
||
// append value (case-preserving)
|
||
if (vals.indexOf(fld) === -1) {
|
||
vals.push(fld);
|
||
val = val
|
||
? val + ', ' + fields[i]
|
||
: fields[i];
|
||
}
|
||
}
|
||
|
||
return val
|
||
}
|
||
|
||
/**
|
||
* Parse a vary header into an array.
|
||
*
|
||
* @param {String} header
|
||
* @return {Array}
|
||
* @private
|
||
*/
|
||
|
||
function parse$2 (header) {
|
||
var end = 0;
|
||
var list = [];
|
||
var start = 0;
|
||
|
||
// gather tokens
|
||
for (var i = 0, len = header.length; i < len; i++) {
|
||
switch (header.charCodeAt(i)) {
|
||
case 0x20: /* */
|
||
if (start === end) {
|
||
start = end = i + 1;
|
||
}
|
||
break
|
||
case 0x2c: /* , */
|
||
list.push(header.substring(start, end));
|
||
start = end = i + 1;
|
||
break
|
||
default:
|
||
end = i + 1;
|
||
break
|
||
}
|
||
}
|
||
|
||
// final token
|
||
list.push(header.substring(start, end));
|
||
|
||
return list
|
||
}
|
||
|
||
/**
|
||
* Mark that a request is varied on a header field.
|
||
*
|
||
* @param {Object} res
|
||
* @param {String|Array} field
|
||
* @public
|
||
*/
|
||
|
||
function vary$1 (res, field) {
|
||
if (!res || !res.getHeader || !res.setHeader) {
|
||
// quack quack
|
||
throw new TypeError('res argument is required')
|
||
}
|
||
|
||
// get existing header
|
||
var val = res.getHeader('Vary') || '';
|
||
var header = Array.isArray(val)
|
||
? val.join(', ')
|
||
: String(val);
|
||
|
||
// set new header
|
||
if ((val = append(header, field))) {
|
||
res.setHeader('Vary', val);
|
||
}
|
||
}
|
||
|
||
var varyExports = vary$2.exports;
|
||
|
||
/*!
|
||
* compression
|
||
* Copyright(c) 2010 Sencha Inc.
|
||
* Copyright(c) 2011 TJ Holowaychuk
|
||
* Copyright(c) 2014 Jonathan Ong
|
||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* Module dependencies.
|
||
* @private
|
||
*/
|
||
|
||
var accepts = accepts$1;
|
||
var Buffer$1 = safeBufferExports.Buffer;
|
||
var bytes = bytesExports;
|
||
var compressible = compressible_1;
|
||
var debug = srcExports('compression');
|
||
var onHeaders = onHeaders_1;
|
||
var vary = varyExports;
|
||
var zlib = require$$1$1;
|
||
|
||
/**
|
||
* Module exports.
|
||
*/
|
||
|
||
compression$2.exports = compression;
|
||
compression$2.exports.filter = shouldCompress;
|
||
|
||
/**
|
||
* Module variables.
|
||
* @private
|
||
*/
|
||
|
||
var cacheControlNoTransformRegExp = /(?:^|,)\s*?no-transform\s*?(?:,|$)/;
|
||
|
||
/**
|
||
* Compress response data with gzip / deflate.
|
||
*
|
||
* @param {Object} [options]
|
||
* @return {Function} middleware
|
||
* @public
|
||
*/
|
||
|
||
function compression (options) {
|
||
var opts = options || {};
|
||
|
||
// options
|
||
var filter = opts.filter || shouldCompress;
|
||
var threshold = bytes.parse(opts.threshold);
|
||
|
||
if (threshold == null) {
|
||
threshold = 1024;
|
||
}
|
||
|
||
return function compression (req, res, next) {
|
||
var ended = false;
|
||
var length;
|
||
var listeners = [];
|
||
var stream;
|
||
|
||
var _end = res.end;
|
||
var _on = res.on;
|
||
var _write = res.write;
|
||
|
||
// flush
|
||
res.flush = function flush () {
|
||
if (stream) {
|
||
stream.flush();
|
||
}
|
||
};
|
||
|
||
// proxy
|
||
|
||
res.write = function write (chunk, encoding) {
|
||
if (ended) {
|
||
return false
|
||
}
|
||
|
||
if (!this._header) {
|
||
this._implicitHeader();
|
||
}
|
||
|
||
return stream
|
||
? stream.write(toBuffer(chunk, encoding))
|
||
: _write.call(this, chunk, encoding)
|
||
};
|
||
|
||
res.end = function end (chunk, encoding) {
|
||
if (ended) {
|
||
return false
|
||
}
|
||
|
||
if (!this._header) {
|
||
// estimate the length
|
||
if (!this.getHeader('Content-Length')) {
|
||
length = chunkLength(chunk, encoding);
|
||
}
|
||
|
||
this._implicitHeader();
|
||
}
|
||
|
||
if (!stream) {
|
||
return _end.call(this, chunk, encoding)
|
||
}
|
||
|
||
// mark ended
|
||
ended = true;
|
||
|
||
// write Buffer for Node.js 0.8
|
||
return chunk
|
||
? stream.end(toBuffer(chunk, encoding))
|
||
: stream.end()
|
||
};
|
||
|
||
res.on = function on (type, listener) {
|
||
if (!listeners || type !== 'drain') {
|
||
return _on.call(this, type, listener)
|
||
}
|
||
|
||
if (stream) {
|
||
return stream.on(type, listener)
|
||
}
|
||
|
||
// buffer listeners for future stream
|
||
listeners.push([type, listener]);
|
||
|
||
return this
|
||
};
|
||
|
||
function nocompress (msg) {
|
||
debug('no compression: %s', msg);
|
||
addListeners(res, _on, listeners);
|
||
listeners = null;
|
||
}
|
||
|
||
onHeaders(res, function onResponseHeaders () {
|
||
// determine if request is filtered
|
||
if (!filter(req, res)) {
|
||
nocompress('filtered');
|
||
return
|
||
}
|
||
|
||
// determine if the entity should be transformed
|
||
if (!shouldTransform(req, res)) {
|
||
nocompress('no transform');
|
||
return
|
||
}
|
||
|
||
// vary
|
||
vary(res, 'Accept-Encoding');
|
||
|
||
// content-length below threshold
|
||
if (Number(res.getHeader('Content-Length')) < threshold || length < threshold) {
|
||
nocompress('size below threshold');
|
||
return
|
||
}
|
||
|
||
var encoding = res.getHeader('Content-Encoding') || 'identity';
|
||
|
||
// already encoded
|
||
if (encoding !== 'identity') {
|
||
nocompress('already encoded');
|
||
return
|
||
}
|
||
|
||
// head
|
||
if (req.method === 'HEAD') {
|
||
nocompress('HEAD request');
|
||
return
|
||
}
|
||
|
||
// compression method
|
||
var accept = accepts(req);
|
||
var method = accept.encoding(['gzip', 'deflate', 'identity']);
|
||
|
||
// we really don't prefer deflate
|
||
if (method === 'deflate' && accept.encoding(['gzip'])) {
|
||
method = accept.encoding(['gzip', 'identity']);
|
||
}
|
||
|
||
// negotiation failed
|
||
if (!method || method === 'identity') {
|
||
nocompress('not acceptable');
|
||
return
|
||
}
|
||
|
||
// compression stream
|
||
debug('%s compression', method);
|
||
stream = method === 'gzip'
|
||
? zlib.createGzip(opts)
|
||
: zlib.createDeflate(opts);
|
||
|
||
// add buffered listeners to stream
|
||
addListeners(stream, stream.on, listeners);
|
||
|
||
// header fields
|
||
res.setHeader('Content-Encoding', method);
|
||
res.removeHeader('Content-Length');
|
||
|
||
// compression
|
||
stream.on('data', function onStreamData (chunk) {
|
||
if (_write.call(res, chunk) === false) {
|
||
stream.pause();
|
||
}
|
||
});
|
||
|
||
stream.on('end', function onStreamEnd () {
|
||
_end.call(res);
|
||
});
|
||
|
||
_on.call(res, 'drain', function onResponseDrain () {
|
||
stream.resume();
|
||
});
|
||
});
|
||
|
||
next();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Add bufferred listeners to stream
|
||
* @private
|
||
*/
|
||
|
||
function addListeners (stream, on, listeners) {
|
||
for (var i = 0; i < listeners.length; i++) {
|
||
on.apply(stream, listeners[i]);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Get the length of a given chunk
|
||
*/
|
||
|
||
function chunkLength (chunk, encoding) {
|
||
if (!chunk) {
|
||
return 0
|
||
}
|
||
|
||
return !Buffer$1.isBuffer(chunk)
|
||
? Buffer$1.byteLength(chunk, encoding)
|
||
: chunk.length
|
||
}
|
||
|
||
/**
|
||
* Default filter function.
|
||
* @private
|
||
*/
|
||
|
||
function shouldCompress (req, res) {
|
||
var type = res.getHeader('Content-Type');
|
||
|
||
if (type === undefined || !compressible(type)) {
|
||
debug('%s not compressible', type);
|
||
return false
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
/**
|
||
* Determine if the entity should be transformed.
|
||
* @private
|
||
*/
|
||
|
||
function shouldTransform (req, res) {
|
||
var cacheControl = res.getHeader('Cache-Control');
|
||
|
||
// Don't compress for Cache-Control: no-transform
|
||
// https://tools.ietf.org/html/rfc7234#section-5.2.2.4
|
||
return !cacheControl ||
|
||
!cacheControlNoTransformRegExp.test(cacheControl)
|
||
}
|
||
|
||
/**
|
||
* Coerce arguments to Buffer
|
||
* @private
|
||
*/
|
||
|
||
function toBuffer (chunk, encoding) {
|
||
return !Buffer$1.isBuffer(chunk)
|
||
? Buffer$1.from(chunk, encoding)
|
||
: chunk
|
||
}
|
||
|
||
var compressionExports = compression$2.exports;
|
||
var compression$1 = /*@__PURE__*/getDefaultExportFromCjs(compressionExports);
|
||
|
||
function parse$1 (str, loose) {
|
||
if (str instanceof RegExp) return { keys:false, pattern:str };
|
||
var c, o, tmp, ext, keys=[], pattern='', arr = str.split('/');
|
||
arr[0] || arr.shift();
|
||
|
||
while (tmp = arr.shift()) {
|
||
c = tmp[0];
|
||
if (c === '*') {
|
||
keys.push('wild');
|
||
pattern += '/(.*)';
|
||
} else if (c === ':') {
|
||
o = tmp.indexOf('?', 1);
|
||
ext = tmp.indexOf('.', 1);
|
||
keys.push( tmp.substring(1, !!~o ? o : !!~ext ? ext : tmp.length) );
|
||
pattern += !!~o && !~ext ? '(?:/([^/]+?))?' : '/([^/]+?)';
|
||
if (!!~ext) pattern += (!!~o ? '?' : '') + '\\' + tmp.substring(ext);
|
||
} else {
|
||
pattern += '/' + tmp;
|
||
}
|
||
}
|
||
|
||
return {
|
||
keys: keys,
|
||
pattern: new RegExp('^' + pattern + (loose ? '(?=$|\/)' : '\/?$'), 'i')
|
||
};
|
||
}
|
||
|
||
const MAP = {
|
||
"": 0,
|
||
GET: 1,
|
||
HEAD: 2,
|
||
PATCH: 3,
|
||
OPTIONS: 4,
|
||
CONNECT: 5,
|
||
DELETE: 6,
|
||
TRACE: 7,
|
||
POST: 8,
|
||
PUT: 9,
|
||
};
|
||
|
||
class Trouter {
|
||
constructor() {
|
||
this.routes = [];
|
||
|
||
this.all = this.add.bind(this, '');
|
||
this.get = this.add.bind(this, 'GET');
|
||
this.head = this.add.bind(this, 'HEAD');
|
||
this.patch = this.add.bind(this, 'PATCH');
|
||
this.options = this.add.bind(this, 'OPTIONS');
|
||
this.connect = this.add.bind(this, 'CONNECT');
|
||
this.delete = this.add.bind(this, 'DELETE');
|
||
this.trace = this.add.bind(this, 'TRACE');
|
||
this.post = this.add.bind(this, 'POST');
|
||
this.put = this.add.bind(this, 'PUT');
|
||
}
|
||
|
||
use(route, ...fns) {
|
||
let handlers = [].concat.apply([], fns);
|
||
let { keys, pattern } = parse$1(route, true);
|
||
this.routes.push({ keys, pattern, method: '', handlers, midx: MAP[''] });
|
||
return this;
|
||
}
|
||
|
||
add(method, route, ...fns) {
|
||
let { keys, pattern } = parse$1(route);
|
||
let handlers = [].concat.apply([], fns);
|
||
this.routes.push({ keys, pattern, method, handlers, midx: MAP[method] });
|
||
return this;
|
||
}
|
||
|
||
find(method, url) {
|
||
let midx = MAP[method];
|
||
let isHEAD = (midx === 2);
|
||
let i=0, j=0, k, tmp, arr=this.routes;
|
||
let matches=[], params={}, handlers=[];
|
||
for (; i < arr.length; i++) {
|
||
tmp = arr[i];
|
||
if (tmp.midx === midx || tmp.midx === 0 || (isHEAD && tmp.midx===1) ) {
|
||
if (tmp.keys === false) {
|
||
matches = tmp.pattern.exec(url);
|
||
if (matches === null) continue;
|
||
if (matches.groups !== void 0) for (k in matches.groups) params[k]=matches.groups[k];
|
||
tmp.handlers.length > 1 ? (handlers=handlers.concat(tmp.handlers)) : handlers.push(tmp.handlers[0]);
|
||
} else if (tmp.keys.length > 0) {
|
||
matches = tmp.pattern.exec(url);
|
||
if (matches === null) continue;
|
||
for (j=0; j < tmp.keys.length;) params[tmp.keys[j]]=matches[++j];
|
||
tmp.handlers.length > 1 ? (handlers=handlers.concat(tmp.handlers)) : handlers.push(tmp.handlers[0]);
|
||
} else if (tmp.pattern.test(url)) {
|
||
tmp.handlers.length > 1 ? (handlers=handlers.concat(tmp.handlers)) : handlers.push(tmp.handlers[0]);
|
||
}
|
||
} // else not a match
|
||
}
|
||
|
||
return { params, handlers };
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @typedef ParsedURL
|
||
* @type {import('.').ParsedURL}
|
||
*/
|
||
|
||
/**
|
||
* @typedef Request
|
||
* @property {string} url
|
||
* @property {ParsedURL} _parsedUrl
|
||
*/
|
||
|
||
/**
|
||
* @param {Request} req
|
||
* @returns {ParsedURL|void}
|
||
*/
|
||
function parse(req) {
|
||
let raw = req.url;
|
||
if (raw == null) return;
|
||
|
||
let prev = req._parsedUrl;
|
||
if (prev && prev.raw === raw) return prev;
|
||
|
||
let pathname=raw, search='', query;
|
||
|
||
if (raw.length > 1) {
|
||
let idx = raw.indexOf('?', 1);
|
||
|
||
if (idx !== -1) {
|
||
search = raw.substring(idx);
|
||
pathname = raw.substring(0, idx);
|
||
if (search.length > 1) {
|
||
query = qs.parse(search.substring(1));
|
||
}
|
||
}
|
||
}
|
||
|
||
return req._parsedUrl = { pathname, search, query, raw };
|
||
}
|
||
|
||
function onError(err, req, res) {
|
||
let code = typeof err.status === 'number' && err.status;
|
||
code = res.statusCode = (code && code >= 100 ? code : 500);
|
||
if (typeof err === 'string' || Buffer.isBuffer(err)) res.end(err);
|
||
else res.end(err.message || http.STATUS_CODES[code]);
|
||
}
|
||
|
||
const mount = fn => fn instanceof Polka ? fn.attach : fn;
|
||
|
||
class Polka extends Trouter {
|
||
constructor(opts={}) {
|
||
super();
|
||
this.parse = parse;
|
||
this.server = opts.server;
|
||
this.handler = this.handler.bind(this);
|
||
this.onError = opts.onError || onError; // catch-all handler
|
||
this.onNoMatch = opts.onNoMatch || this.onError.bind(null, { status: 404 });
|
||
this.attach = (req, res) => setImmediate(this.handler, req, res);
|
||
}
|
||
|
||
use(base, ...fns) {
|
||
if (base === '/') {
|
||
super.use(base, fns.map(mount));
|
||
} else if (typeof base === 'function' || base instanceof Polka) {
|
||
super.use('/', [base, ...fns].map(mount));
|
||
} else {
|
||
super.use(base,
|
||
(req, _, next) => {
|
||
if (typeof base === 'string') {
|
||
let len = base.length;
|
||
base.startsWith('/') || len++;
|
||
req.url = req.url.substring(len) || '/';
|
||
req.path = req.path.substring(len) || '/';
|
||
} else {
|
||
req.url = req.url.replace(base, '') || '/';
|
||
req.path = req.path.replace(base, '') || '/';
|
||
}
|
||
if (req.url.charAt(0) !== '/') {
|
||
req.url = '/' + req.url;
|
||
}
|
||
next();
|
||
},
|
||
fns.map(mount),
|
||
(req, _, next) => {
|
||
req.path = req._parsedUrl.pathname;
|
||
req.url = req.path + req._parsedUrl.search;
|
||
next();
|
||
}
|
||
);
|
||
}
|
||
return this; // chainable
|
||
}
|
||
|
||
listen() {
|
||
(this.server = this.server || http.createServer()).on('request', this.attach);
|
||
this.server.listen.apply(this.server, arguments);
|
||
return this;
|
||
}
|
||
|
||
handler(req, res, next) {
|
||
let info = this.parse(req), path = info.pathname;
|
||
let obj = this.find(req.method, req.path=path);
|
||
|
||
req.url = path + info.search;
|
||
req.originalUrl = req.originalUrl || req.url;
|
||
req.query = info.query || {};
|
||
req.search = info.search;
|
||
req.params = obj.params;
|
||
|
||
if (path.length > 1 && path.indexOf('%', 1) !== -1) {
|
||
for (let k in req.params) {
|
||
try { req.params[k] = decodeURIComponent(req.params[k]); }
|
||
catch (e) { /* malform uri segment */ }
|
||
}
|
||
}
|
||
|
||
let i=0, arr=obj.handlers.concat(this.onNoMatch), len=arr.length;
|
||
let loop = async () => res.finished || (i < len) && arr[i++](req, res, next);
|
||
(next = next || (err => err ? this.onError(err, req, res, next) : loop().catch(next)))(); // init
|
||
}
|
||
}
|
||
|
||
function polka (opts) {
|
||
return new Polka(opts);
|
||
}
|
||
|
||
function totalist(dir, callback, pre='') {
|
||
dir = resolve$1('.', dir);
|
||
let arr = readdirSync$1(dir);
|
||
let i=0, abs, stats;
|
||
for (; i < arr.length; i++) {
|
||
abs = join(dir, arr[i]);
|
||
stats = statSync$1(abs);
|
||
stats.isDirectory()
|
||
? totalist(abs, callback, join(pre, arr[i]))
|
||
: callback(join(pre, arr[i]), abs, stats);
|
||
}
|
||
}
|
||
|
||
const mimes = {
|
||
"3g2": "video/3gpp2",
|
||
"3gp": "video/3gpp",
|
||
"3gpp": "video/3gpp",
|
||
"3mf": "model/3mf",
|
||
"aac": "audio/aac",
|
||
"ac": "application/pkix-attr-cert",
|
||
"adp": "audio/adpcm",
|
||
"adts": "audio/aac",
|
||
"ai": "application/postscript",
|
||
"aml": "application/automationml-aml+xml",
|
||
"amlx": "application/automationml-amlx+zip",
|
||
"amr": "audio/amr",
|
||
"apng": "image/apng",
|
||
"appcache": "text/cache-manifest",
|
||
"appinstaller": "application/appinstaller",
|
||
"appx": "application/appx",
|
||
"appxbundle": "application/appxbundle",
|
||
"asc": "application/pgp-keys",
|
||
"atom": "application/atom+xml",
|
||
"atomcat": "application/atomcat+xml",
|
||
"atomdeleted": "application/atomdeleted+xml",
|
||
"atomsvc": "application/atomsvc+xml",
|
||
"au": "audio/basic",
|
||
"avci": "image/avci",
|
||
"avcs": "image/avcs",
|
||
"avif": "image/avif",
|
||
"aw": "application/applixware",
|
||
"bdoc": "application/bdoc",
|
||
"bin": "application/octet-stream",
|
||
"bmp": "image/bmp",
|
||
"bpk": "application/octet-stream",
|
||
"btf": "image/prs.btif",
|
||
"btif": "image/prs.btif",
|
||
"buffer": "application/octet-stream",
|
||
"ccxml": "application/ccxml+xml",
|
||
"cdfx": "application/cdfx+xml",
|
||
"cdmia": "application/cdmi-capability",
|
||
"cdmic": "application/cdmi-container",
|
||
"cdmid": "application/cdmi-domain",
|
||
"cdmio": "application/cdmi-object",
|
||
"cdmiq": "application/cdmi-queue",
|
||
"cer": "application/pkix-cert",
|
||
"cgm": "image/cgm",
|
||
"cjs": "application/node",
|
||
"class": "application/java-vm",
|
||
"coffee": "text/coffeescript",
|
||
"conf": "text/plain",
|
||
"cpl": "application/cpl+xml",
|
||
"cpt": "application/mac-compactpro",
|
||
"crl": "application/pkix-crl",
|
||
"css": "text/css",
|
||
"csv": "text/csv",
|
||
"cu": "application/cu-seeme",
|
||
"cwl": "application/cwl",
|
||
"cww": "application/prs.cww",
|
||
"davmount": "application/davmount+xml",
|
||
"dbk": "application/docbook+xml",
|
||
"deb": "application/octet-stream",
|
||
"def": "text/plain",
|
||
"deploy": "application/octet-stream",
|
||
"dib": "image/bmp",
|
||
"disposition-notification": "message/disposition-notification",
|
||
"dist": "application/octet-stream",
|
||
"distz": "application/octet-stream",
|
||
"dll": "application/octet-stream",
|
||
"dmg": "application/octet-stream",
|
||
"dms": "application/octet-stream",
|
||
"doc": "application/msword",
|
||
"dot": "application/msword",
|
||
"dpx": "image/dpx",
|
||
"drle": "image/dicom-rle",
|
||
"dsc": "text/prs.lines.tag",
|
||
"dssc": "application/dssc+der",
|
||
"dtd": "application/xml-dtd",
|
||
"dump": "application/octet-stream",
|
||
"dwd": "application/atsc-dwd+xml",
|
||
"ear": "application/java-archive",
|
||
"ecma": "application/ecmascript",
|
||
"elc": "application/octet-stream",
|
||
"emf": "image/emf",
|
||
"eml": "message/rfc822",
|
||
"emma": "application/emma+xml",
|
||
"emotionml": "application/emotionml+xml",
|
||
"eps": "application/postscript",
|
||
"epub": "application/epub+zip",
|
||
"exe": "application/octet-stream",
|
||
"exi": "application/exi",
|
||
"exp": "application/express",
|
||
"exr": "image/aces",
|
||
"ez": "application/andrew-inset",
|
||
"fdf": "application/fdf",
|
||
"fdt": "application/fdt+xml",
|
||
"fits": "image/fits",
|
||
"g3": "image/g3fax",
|
||
"gbr": "application/rpki-ghostbusters",
|
||
"geojson": "application/geo+json",
|
||
"gif": "image/gif",
|
||
"glb": "model/gltf-binary",
|
||
"gltf": "model/gltf+json",
|
||
"gml": "application/gml+xml",
|
||
"gpx": "application/gpx+xml",
|
||
"gram": "application/srgs",
|
||
"grxml": "application/srgs+xml",
|
||
"gxf": "application/gxf",
|
||
"gz": "application/gzip",
|
||
"h261": "video/h261",
|
||
"h263": "video/h263",
|
||
"h264": "video/h264",
|
||
"heic": "image/heic",
|
||
"heics": "image/heic-sequence",
|
||
"heif": "image/heif",
|
||
"heifs": "image/heif-sequence",
|
||
"hej2": "image/hej2k",
|
||
"held": "application/atsc-held+xml",
|
||
"hjson": "application/hjson",
|
||
"hlp": "application/winhlp",
|
||
"hqx": "application/mac-binhex40",
|
||
"hsj2": "image/hsj2",
|
||
"htm": "text/html",
|
||
"html": "text/html",
|
||
"ics": "text/calendar",
|
||
"ief": "image/ief",
|
||
"ifb": "text/calendar",
|
||
"iges": "model/iges",
|
||
"igs": "model/iges",
|
||
"img": "application/octet-stream",
|
||
"in": "text/plain",
|
||
"ini": "text/plain",
|
||
"ink": "application/inkml+xml",
|
||
"inkml": "application/inkml+xml",
|
||
"ipfix": "application/ipfix",
|
||
"iso": "application/octet-stream",
|
||
"its": "application/its+xml",
|
||
"jade": "text/jade",
|
||
"jar": "application/java-archive",
|
||
"jhc": "image/jphc",
|
||
"jls": "image/jls",
|
||
"jp2": "image/jp2",
|
||
"jpe": "image/jpeg",
|
||
"jpeg": "image/jpeg",
|
||
"jpf": "image/jpx",
|
||
"jpg": "image/jpeg",
|
||
"jpg2": "image/jp2",
|
||
"jpgm": "image/jpm",
|
||
"jpgv": "video/jpeg",
|
||
"jph": "image/jph",
|
||
"jpm": "image/jpm",
|
||
"jpx": "image/jpx",
|
||
"js": "text/javascript",
|
||
"json": "application/json",
|
||
"json5": "application/json5",
|
||
"jsonld": "application/ld+json",
|
||
"jsonml": "application/jsonml+json",
|
||
"jsx": "text/jsx",
|
||
"jt": "model/jt",
|
||
"jxr": "image/jxr",
|
||
"jxra": "image/jxra",
|
||
"jxrs": "image/jxrs",
|
||
"jxs": "image/jxs",
|
||
"jxsc": "image/jxsc",
|
||
"jxsi": "image/jxsi",
|
||
"jxss": "image/jxss",
|
||
"kar": "audio/midi",
|
||
"ktx": "image/ktx",
|
||
"ktx2": "image/ktx2",
|
||
"less": "text/less",
|
||
"lgr": "application/lgr+xml",
|
||
"list": "text/plain",
|
||
"litcoffee": "text/coffeescript",
|
||
"log": "text/plain",
|
||
"lostxml": "application/lost+xml",
|
||
"lrf": "application/octet-stream",
|
||
"m1v": "video/mpeg",
|
||
"m21": "application/mp21",
|
||
"m2a": "audio/mpeg",
|
||
"m2v": "video/mpeg",
|
||
"m3a": "audio/mpeg",
|
||
"m4a": "audio/mp4",
|
||
"m4p": "application/mp4",
|
||
"m4s": "video/iso.segment",
|
||
"ma": "application/mathematica",
|
||
"mads": "application/mads+xml",
|
||
"maei": "application/mmt-aei+xml",
|
||
"man": "text/troff",
|
||
"manifest": "text/cache-manifest",
|
||
"map": "application/json",
|
||
"mar": "application/octet-stream",
|
||
"markdown": "text/markdown",
|
||
"mathml": "application/mathml+xml",
|
||
"mb": "application/mathematica",
|
||
"mbox": "application/mbox",
|
||
"md": "text/markdown",
|
||
"mdx": "text/mdx",
|
||
"me": "text/troff",
|
||
"mesh": "model/mesh",
|
||
"meta4": "application/metalink4+xml",
|
||
"metalink": "application/metalink+xml",
|
||
"mets": "application/mets+xml",
|
||
"mft": "application/rpki-manifest",
|
||
"mid": "audio/midi",
|
||
"midi": "audio/midi",
|
||
"mime": "message/rfc822",
|
||
"mj2": "video/mj2",
|
||
"mjp2": "video/mj2",
|
||
"mjs": "text/javascript",
|
||
"mml": "text/mathml",
|
||
"mods": "application/mods+xml",
|
||
"mov": "video/quicktime",
|
||
"mp2": "audio/mpeg",
|
||
"mp21": "application/mp21",
|
||
"mp2a": "audio/mpeg",
|
||
"mp3": "audio/mpeg",
|
||
"mp4": "video/mp4",
|
||
"mp4a": "audio/mp4",
|
||
"mp4s": "application/mp4",
|
||
"mp4v": "video/mp4",
|
||
"mpd": "application/dash+xml",
|
||
"mpe": "video/mpeg",
|
||
"mpeg": "video/mpeg",
|
||
"mpf": "application/media-policy-dataset+xml",
|
||
"mpg": "video/mpeg",
|
||
"mpg4": "video/mp4",
|
||
"mpga": "audio/mpeg",
|
||
"mpp": "application/dash-patch+xml",
|
||
"mrc": "application/marc",
|
||
"mrcx": "application/marcxml+xml",
|
||
"ms": "text/troff",
|
||
"mscml": "application/mediaservercontrol+xml",
|
||
"msh": "model/mesh",
|
||
"msi": "application/octet-stream",
|
||
"msix": "application/msix",
|
||
"msixbundle": "application/msixbundle",
|
||
"msm": "application/octet-stream",
|
||
"msp": "application/octet-stream",
|
||
"mtl": "model/mtl",
|
||
"musd": "application/mmt-usd+xml",
|
||
"mxf": "application/mxf",
|
||
"mxmf": "audio/mobile-xmf",
|
||
"mxml": "application/xv+xml",
|
||
"n3": "text/n3",
|
||
"nb": "application/mathematica",
|
||
"nq": "application/n-quads",
|
||
"nt": "application/n-triples",
|
||
"obj": "model/obj",
|
||
"oda": "application/oda",
|
||
"oga": "audio/ogg",
|
||
"ogg": "audio/ogg",
|
||
"ogv": "video/ogg",
|
||
"ogx": "application/ogg",
|
||
"omdoc": "application/omdoc+xml",
|
||
"onepkg": "application/onenote",
|
||
"onetmp": "application/onenote",
|
||
"onetoc": "application/onenote",
|
||
"onetoc2": "application/onenote",
|
||
"opf": "application/oebps-package+xml",
|
||
"opus": "audio/ogg",
|
||
"otf": "font/otf",
|
||
"owl": "application/rdf+xml",
|
||
"oxps": "application/oxps",
|
||
"p10": "application/pkcs10",
|
||
"p7c": "application/pkcs7-mime",
|
||
"p7m": "application/pkcs7-mime",
|
||
"p7s": "application/pkcs7-signature",
|
||
"p8": "application/pkcs8",
|
||
"pdf": "application/pdf",
|
||
"pfr": "application/font-tdpfr",
|
||
"pgp": "application/pgp-encrypted",
|
||
"pkg": "application/octet-stream",
|
||
"pki": "application/pkixcmp",
|
||
"pkipath": "application/pkix-pkipath",
|
||
"pls": "application/pls+xml",
|
||
"png": "image/png",
|
||
"prc": "model/prc",
|
||
"prf": "application/pics-rules",
|
||
"provx": "application/provenance+xml",
|
||
"ps": "application/postscript",
|
||
"pskcxml": "application/pskc+xml",
|
||
"pti": "image/prs.pti",
|
||
"qt": "video/quicktime",
|
||
"raml": "application/raml+yaml",
|
||
"rapd": "application/route-apd+xml",
|
||
"rdf": "application/rdf+xml",
|
||
"relo": "application/p2p-overlay+xml",
|
||
"rif": "application/reginfo+xml",
|
||
"rl": "application/resource-lists+xml",
|
||
"rld": "application/resource-lists-diff+xml",
|
||
"rmi": "audio/midi",
|
||
"rnc": "application/relax-ng-compact-syntax",
|
||
"rng": "application/xml",
|
||
"roa": "application/rpki-roa",
|
||
"roff": "text/troff",
|
||
"rq": "application/sparql-query",
|
||
"rs": "application/rls-services+xml",
|
||
"rsat": "application/atsc-rsat+xml",
|
||
"rsd": "application/rsd+xml",
|
||
"rsheet": "application/urc-ressheet+xml",
|
||
"rss": "application/rss+xml",
|
||
"rtf": "text/rtf",
|
||
"rtx": "text/richtext",
|
||
"rusd": "application/route-usd+xml",
|
||
"s3m": "audio/s3m",
|
||
"sbml": "application/sbml+xml",
|
||
"scq": "application/scvp-cv-request",
|
||
"scs": "application/scvp-cv-response",
|
||
"sdp": "application/sdp",
|
||
"senmlx": "application/senml+xml",
|
||
"sensmlx": "application/sensml+xml",
|
||
"ser": "application/java-serialized-object",
|
||
"setpay": "application/set-payment-initiation",
|
||
"setreg": "application/set-registration-initiation",
|
||
"sgi": "image/sgi",
|
||
"sgm": "text/sgml",
|
||
"sgml": "text/sgml",
|
||
"shex": "text/shex",
|
||
"shf": "application/shf+xml",
|
||
"shtml": "text/html",
|
||
"sieve": "application/sieve",
|
||
"sig": "application/pgp-signature",
|
||
"sil": "audio/silk",
|
||
"silo": "model/mesh",
|
||
"siv": "application/sieve",
|
||
"slim": "text/slim",
|
||
"slm": "text/slim",
|
||
"sls": "application/route-s-tsid+xml",
|
||
"smi": "application/smil+xml",
|
||
"smil": "application/smil+xml",
|
||
"snd": "audio/basic",
|
||
"so": "application/octet-stream",
|
||
"spdx": "text/spdx",
|
||
"spp": "application/scvp-vp-response",
|
||
"spq": "application/scvp-vp-request",
|
||
"spx": "audio/ogg",
|
||
"sql": "application/sql",
|
||
"sru": "application/sru+xml",
|
||
"srx": "application/sparql-results+xml",
|
||
"ssdl": "application/ssdl+xml",
|
||
"ssml": "application/ssml+xml",
|
||
"stk": "application/hyperstudio",
|
||
"stl": "model/stl",
|
||
"stpx": "model/step+xml",
|
||
"stpxz": "model/step-xml+zip",
|
||
"stpz": "model/step+zip",
|
||
"styl": "text/stylus",
|
||
"stylus": "text/stylus",
|
||
"svg": "image/svg+xml",
|
||
"svgz": "image/svg+xml",
|
||
"swidtag": "application/swid+xml",
|
||
"t": "text/troff",
|
||
"t38": "image/t38",
|
||
"td": "application/urc-targetdesc+xml",
|
||
"tei": "application/tei+xml",
|
||
"teicorpus": "application/tei+xml",
|
||
"text": "text/plain",
|
||
"tfi": "application/thraud+xml",
|
||
"tfx": "image/tiff-fx",
|
||
"tif": "image/tiff",
|
||
"tiff": "image/tiff",
|
||
"toml": "application/toml",
|
||
"tr": "text/troff",
|
||
"trig": "application/trig",
|
||
"ts": "video/mp2t",
|
||
"tsd": "application/timestamped-data",
|
||
"tsv": "text/tab-separated-values",
|
||
"ttc": "font/collection",
|
||
"ttf": "font/ttf",
|
||
"ttl": "text/turtle",
|
||
"ttml": "application/ttml+xml",
|
||
"txt": "text/plain",
|
||
"u3d": "model/u3d",
|
||
"u8dsn": "message/global-delivery-status",
|
||
"u8hdr": "message/global-headers",
|
||
"u8mdn": "message/global-disposition-notification",
|
||
"u8msg": "message/global",
|
||
"ubj": "application/ubjson",
|
||
"uri": "text/uri-list",
|
||
"uris": "text/uri-list",
|
||
"urls": "text/uri-list",
|
||
"vcard": "text/vcard",
|
||
"vrml": "model/vrml",
|
||
"vtt": "text/vtt",
|
||
"vxml": "application/voicexml+xml",
|
||
"war": "application/java-archive",
|
||
"wasm": "application/wasm",
|
||
"wav": "audio/wav",
|
||
"weba": "audio/webm",
|
||
"webm": "video/webm",
|
||
"webmanifest": "application/manifest+json",
|
||
"webp": "image/webp",
|
||
"wgsl": "text/wgsl",
|
||
"wgt": "application/widget",
|
||
"wif": "application/watcherinfo+xml",
|
||
"wmf": "image/wmf",
|
||
"woff": "font/woff",
|
||
"woff2": "font/woff2",
|
||
"wrl": "model/vrml",
|
||
"wsdl": "application/wsdl+xml",
|
||
"wspolicy": "application/wspolicy+xml",
|
||
"x3d": "model/x3d+xml",
|
||
"x3db": "model/x3d+fastinfoset",
|
||
"x3dbz": "model/x3d+binary",
|
||
"x3dv": "model/x3d-vrml",
|
||
"x3dvz": "model/x3d+vrml",
|
||
"x3dz": "model/x3d+xml",
|
||
"xaml": "application/xaml+xml",
|
||
"xav": "application/xcap-att+xml",
|
||
"xca": "application/xcap-caps+xml",
|
||
"xcs": "application/calendar+xml",
|
||
"xdf": "application/xcap-diff+xml",
|
||
"xdssc": "application/dssc+xml",
|
||
"xel": "application/xcap-el+xml",
|
||
"xenc": "application/xenc+xml",
|
||
"xer": "application/patch-ops-error+xml",
|
||
"xfdf": "application/xfdf",
|
||
"xht": "application/xhtml+xml",
|
||
"xhtml": "application/xhtml+xml",
|
||
"xhvml": "application/xv+xml",
|
||
"xlf": "application/xliff+xml",
|
||
"xm": "audio/xm",
|
||
"xml": "text/xml",
|
||
"xns": "application/xcap-ns+xml",
|
||
"xop": "application/xop+xml",
|
||
"xpl": "application/xproc+xml",
|
||
"xsd": "application/xml",
|
||
"xsf": "application/prs.xsf+xml",
|
||
"xsl": "application/xml",
|
||
"xslt": "application/xml",
|
||
"xspf": "application/xspf+xml",
|
||
"xvm": "application/xv+xml",
|
||
"xvml": "application/xv+xml",
|
||
"yaml": "text/yaml",
|
||
"yang": "application/yang",
|
||
"yin": "application/yin+xml",
|
||
"yml": "text/yaml",
|
||
"zip": "application/zip"
|
||
};
|
||
|
||
function lookup(extn) {
|
||
let tmp = ('' + extn).trim().toLowerCase();
|
||
let idx = tmp.lastIndexOf('.');
|
||
return mimes[!~idx ? tmp : tmp.substring(++idx)];
|
||
}
|
||
|
||
const noop = () => {};
|
||
|
||
function isMatch(uri, arr) {
|
||
for (let i=0; i < arr.length; i++) {
|
||
if (arr[i].test(uri)) return true;
|
||
}
|
||
}
|
||
|
||
function toAssume(uri, extns) {
|
||
let i=0, x, len=uri.length - 1;
|
||
if (uri.charCodeAt(len) === 47) {
|
||
uri = uri.substring(0, len);
|
||
}
|
||
|
||
let arr=[], tmp=`${uri}/index`;
|
||
for (; i < extns.length; i++) {
|
||
x = extns[i] ? `.${extns[i]}` : '';
|
||
if (uri) arr.push(uri + x);
|
||
arr.push(tmp + x);
|
||
}
|
||
|
||
return arr;
|
||
}
|
||
|
||
function viaCache(cache, uri, extns) {
|
||
let i=0, data, arr=toAssume(uri, extns);
|
||
for (; i < arr.length; i++) {
|
||
if (data = cache[arr[i]]) return data;
|
||
}
|
||
}
|
||
|
||
function viaLocal(dir, isEtag, uri, extns) {
|
||
let i=0, arr=toAssume(uri, extns);
|
||
let abs, stats, name, headers;
|
||
for (; i < arr.length; i++) {
|
||
abs = normalize$3(join(dir, name=arr[i]));
|
||
if (abs.startsWith(dir) && fs$t.existsSync(abs)) {
|
||
stats = fs$t.statSync(abs);
|
||
if (stats.isDirectory()) continue;
|
||
headers = toHeaders(name, stats, isEtag);
|
||
headers['Cache-Control'] = isEtag ? 'no-cache' : 'no-store';
|
||
return { abs, stats, headers };
|
||
}
|
||
}
|
||
}
|
||
|
||
function is404(req, res) {
|
||
return (res.statusCode=404,res.end());
|
||
}
|
||
|
||
function send(req, res, file, stats, headers) {
|
||
let code=200, tmp, opts={};
|
||
headers = { ...headers };
|
||
|
||
for (let key in headers) {
|
||
tmp = res.getHeader(key);
|
||
if (tmp) headers[key] = tmp;
|
||
}
|
||
|
||
if (tmp = res.getHeader('content-type')) {
|
||
headers['Content-Type'] = tmp;
|
||
}
|
||
|
||
if (req.headers.range) {
|
||
code = 206;
|
||
let [x, y] = req.headers.range.replace('bytes=', '').split('-');
|
||
let end = opts.end = parseInt(y, 10) || stats.size - 1;
|
||
let start = opts.start = parseInt(x, 10) || 0;
|
||
|
||
if (end >= stats.size) {
|
||
end = stats.size - 1;
|
||
}
|
||
|
||
if (start >= stats.size) {
|
||
res.setHeader('Content-Range', `bytes */${stats.size}`);
|
||
res.statusCode = 416;
|
||
return res.end();
|
||
}
|
||
|
||
headers['Content-Range'] = `bytes ${start}-${end}/${stats.size}`;
|
||
headers['Content-Length'] = (end - start + 1);
|
||
headers['Accept-Ranges'] = 'bytes';
|
||
}
|
||
|
||
res.writeHead(code, headers);
|
||
fs$t.createReadStream(file, opts).pipe(res);
|
||
}
|
||
|
||
const ENCODING = {
|
||
'.br': 'br',
|
||
'.gz': 'gzip',
|
||
};
|
||
|
||
function toHeaders(name, stats, isEtag) {
|
||
let enc = ENCODING[name.slice(-3)];
|
||
|
||
let ctype = lookup(name.slice(0, enc && -3)) || '';
|
||
if (ctype === 'text/html') ctype += ';charset=utf-8';
|
||
|
||
let headers = {
|
||
'Content-Length': stats.size,
|
||
'Content-Type': ctype,
|
||
'Last-Modified': stats.mtime.toUTCString(),
|
||
};
|
||
|
||
if (enc) headers['Content-Encoding'] = enc;
|
||
if (isEtag) headers['ETag'] = `W/"${stats.size}-${stats.mtime.getTime()}"`;
|
||
|
||
return headers;
|
||
}
|
||
|
||
function sirv (dir, opts={}) {
|
||
dir = resolve$1(dir || '.');
|
||
|
||
let isNotFound = opts.onNoMatch || is404;
|
||
let setHeaders = opts.setHeaders || noop;
|
||
|
||
let extensions = opts.extensions || ['html', 'htm'];
|
||
let gzips = opts.gzip && extensions.map(x => `${x}.gz`).concat('gz');
|
||
let brots = opts.brotli && extensions.map(x => `${x}.br`).concat('br');
|
||
|
||
const FILES = {};
|
||
|
||
let fallback = '/';
|
||
let isEtag = !!opts.etag;
|
||
let isSPA = !!opts.single;
|
||
if (typeof opts.single === 'string') {
|
||
let idx = opts.single.lastIndexOf('.');
|
||
fallback += !!~idx ? opts.single.substring(0, idx) : opts.single;
|
||
}
|
||
|
||
let ignores = [];
|
||
if (opts.ignores !== false) {
|
||
ignores.push(/[/]([A-Za-z\s\d~$._-]+\.\w+){1,}$/); // any extn
|
||
if (opts.dotfiles) ignores.push(/\/\.\w/);
|
||
else ignores.push(/\/\.well-known/);
|
||
[].concat(opts.ignores || []).forEach(x => {
|
||
ignores.push(new RegExp(x, 'i'));
|
||
});
|
||
}
|
||
|
||
let cc = opts.maxAge != null && `public,max-age=${opts.maxAge}`;
|
||
if (cc && opts.immutable) cc += ',immutable';
|
||
else if (cc && opts.maxAge === 0) cc += ',must-revalidate';
|
||
|
||
if (!opts.dev) {
|
||
totalist(dir, (name, abs, stats) => {
|
||
if (/\.well-known[\\+\/]/.test(name)) ; // keep
|
||
else if (!opts.dotfiles && /(^\.|[\\+|\/+]\.)/.test(name)) return;
|
||
|
||
let headers = toHeaders(name, stats, isEtag);
|
||
if (cc) headers['Cache-Control'] = cc;
|
||
|
||
FILES['/' + name.normalize().replace(/\\+/g, '/')] = { abs, stats, headers };
|
||
});
|
||
}
|
||
|
||
let lookup = opts.dev ? viaLocal.bind(0, dir, isEtag) : viaCache.bind(0, FILES);
|
||
|
||
return function (req, res, next) {
|
||
let extns = [''];
|
||
let pathname = parse(req).pathname;
|
||
let val = req.headers['accept-encoding'] || '';
|
||
if (gzips && val.includes('gzip')) extns.unshift(...gzips);
|
||
if (brots && /(br|brotli)/i.test(val)) extns.unshift(...brots);
|
||
extns.push(...extensions); // [...br, ...gz, orig, ...exts]
|
||
|
||
if (pathname.indexOf('%') !== -1) {
|
||
try { pathname = decodeURI(pathname); }
|
||
catch (err) { /* malform uri */ }
|
||
}
|
||
|
||
let data = lookup(pathname, extns) || isSPA && !isMatch(pathname, ignores) && lookup(fallback, extns);
|
||
if (!data) return next ? next() : isNotFound(req, res);
|
||
|
||
if (isEtag && req.headers['if-none-match'] === data.headers['ETag']) {
|
||
res.writeHead(304);
|
||
return res.end();
|
||
}
|
||
|
||
if (gzips || brots) {
|
||
res.setHeader('Vary', 'Accept-Encoding');
|
||
}
|
||
|
||
setHeaders(res, pathname, data.stats);
|
||
send(req, res, data.abs, data.stats, data.headers);
|
||
};
|
||
}
|
||
|
||
function trimChar(str, char) {
|
||
while (str.charAt(0) === char) {
|
||
str = str.substring(1);
|
||
}
|
||
while (str.charAt(str.length - 1) === char) {
|
||
str = str.substring(0, str.length - 1);
|
||
}
|
||
return str;
|
||
}
|
||
async function serve(options = {}) {
|
||
const port = options.port ?? 4173;
|
||
const config = await resolveConfig(options.root, "serve", "production");
|
||
const base = trimChar(options?.base ?? config?.site?.base ?? "", "/");
|
||
const notAnAsset = (pathname) => !pathname.includes(`/${config.assetsDir}/`);
|
||
const notFound = fs$a.readFileSync(path$q.resolve(config.outDir, "./404.html"));
|
||
const onNoMatch = (req, res) => {
|
||
res.statusCode = 404;
|
||
if (notAnAsset(req.path))
|
||
res.write(notFound.toString());
|
||
res.end();
|
||
};
|
||
const compress = compression$1();
|
||
const serve2 = sirv(config.outDir, {
|
||
etag: true,
|
||
maxAge: 31536e3,
|
||
immutable: true,
|
||
setHeaders(res, pathname) {
|
||
if (notAnAsset(pathname)) {
|
||
res.setHeader("cache-control", "no-cache");
|
||
}
|
||
}
|
||
});
|
||
if (base) {
|
||
return polka({ onNoMatch }).use(base, compress, serve2).listen(port, () => {
|
||
config.logger.info(
|
||
`Built site served at http://localhost:${port}/${base}/`
|
||
);
|
||
});
|
||
} else {
|
||
return polka({ onNoMatch }).use(compress, serve2).listen(port, () => {
|
||
config.logger.info(`Built site served at http://localhost:${port}/`);
|
||
});
|
||
}
|
||
}
|
||
|
||
async function createServer(root = process.cwd(), serverOptions = {}, recreateServer) {
|
||
const config = await resolveConfig(root);
|
||
if (serverOptions.base) {
|
||
config.site.base = serverOptions.base;
|
||
delete serverOptions.base;
|
||
}
|
||
return createServer$1({
|
||
root: config.srcDir,
|
||
base: config.site.base,
|
||
cacheDir: config.cacheDir,
|
||
plugins: await createVitePressPlugin(config, false, {}, {}, recreateServer),
|
||
server: serverOptions,
|
||
customLogger: config.logger,
|
||
configFile: config.vite?.configFile
|
||
});
|
||
}
|
||
|
||
export { ScaffoldThemeType as S, getDefaultExportFromCjs as a, build as b, createMarkdownRenderer as c, defineLoader as d, defineConfig as e, fs$a as f, glob as g, defineConfigWithTheme as h, resolveUserConfig as i, mergeConfig as j, resolveSiteData as k, resolvePages as l, matter$1 as m, init as n, serve as o, createServer as p, c$2 as q, resolveConfig as r, scaffold as s, clearCache as t, version as v };
|