From 4bbb6218194e4e97cf551c86ed4212338a95371f Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Mon, 20 Sep 2021 11:54:58 -0700 Subject: [PATCH] tools: re-implement lint-md without unified-args `unified-args` ignores settings in the preset, expecting them to be in remarkrc files or passed on the command line instead. Realizing that we always send the same configuration options via the command-line anyway, this removes `unified-args`. This means the preset settings are now respected and it removes nearly 30000 lines of code in the resulting rollup file. I wasn't sure I was going to want to keep rollup so I started re-implementing this without it, but ended up putting a minimal rollup back as it still saves about 90000 lines of code vs. checking in `node_modules`. --- .eslintignore | 3 +- .github/workflows/linters.yml | 2 +- Makefile | 7 +- tools/lint-md/.gitignore | 1 + tools/{ => lint-md}/lint-md.mjs | 72056 +++++----------- tools/lint-md/lint-md.src.mjs | 25 + ...list-released-versions-from-changelogs.mjs | 2 +- .../package-lock.json | 1557 +- tools/lint-md/package.json | 22 + tools/node-lint-md-cli-rollup/.gitignore | 3 - tools/node-lint-md-cli-rollup/LICENSE | 32 - tools/node-lint-md-cli-rollup/package.json | 24 - .../node-lint-md-cli-rollup/rollup.config.js | 57 - .../node-lint-md-cli-rollup/src/cli-entry.mjs | 27 - vcbuild.bat | 2 +- 15 files changed, 22658 insertions(+), 51162 deletions(-) create mode 100644 tools/lint-md/.gitignore rename tools/{ => lint-md}/lint-md.mjs (50%) create mode 100644 tools/lint-md/lint-md.src.mjs rename tools/{node-lint-md-cli-rollup/src => lint-md}/list-released-versions-from-changelogs.mjs (92%) rename tools/{node-lint-md-cli-rollup => lint-md}/package-lock.json (77%) create mode 100644 tools/lint-md/package.json delete mode 100644 tools/node-lint-md-cli-rollup/.gitignore delete mode 100644 tools/node-lint-md-cli-rollup/LICENSE delete mode 100644 tools/node-lint-md-cli-rollup/package.json delete mode 100644 tools/node-lint-md-cli-rollup/rollup.config.js delete mode 100644 tools/node-lint-md-cli-rollup/src/cli-entry.mjs diff --git a/.eslintignore b/.eslintignore index e8b8c3f297709a..8ab4750abd1685 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,8 +4,7 @@ test/addons/??_* test/fixtures test/message/esm_display_syntax_error.mjs tools/icu -tools/lint-md.mjs -tools/node-lint-md-cli-rollup/dist +tools/lint-md/lint-md.mjs benchmark/tmp doc/**/*.js !.eslintrc.js diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 04cecbbc516052..2694e07ab3c6fd 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -55,7 +55,7 @@ jobs: - name: Get release version numbers if: ${{ github.event.pull_request && github.event.pull_request.base.ref == github.event.pull_request.base.repo.default_branch }} id: get-released-versions - run: ./tools/node-lint-md-cli-rollup/src/list-released-versions-from-changelogs.mjs + run: ./tools/lint-md/list-released-versions-from-changelogs.mjs - name: Lint docs run: | echo "::add-matcher::.github/workflows/remark-lint-problem-matcher.json" diff --git a/Makefile b/Makefile index baae6a3b46bd26..1ac93d4d5849fc 100644 --- a/Makefile +++ b/Makefile @@ -1221,12 +1221,11 @@ bench-addons-clean: .PHONY: lint-md-rollup lint-md-rollup: $(RM) tools/.*mdlintstamp - cd tools/node-lint-md-cli-rollup && npm install - cd tools/node-lint-md-cli-rollup && npm run build-node + cd tools/lint-md && npm ci && npm run build .PHONY: lint-md-clean lint-md-clean: - $(RM) -r tools/node-lint-md-cli-rollup/node_modules + $(RM) -r tools/lint-md/node_modules $(RM) tools/.*mdlintstamp .PHONY: lint-md-build @@ -1243,7 +1242,7 @@ LINT_MD_TARGETS = doc src lib benchmark test tools/doc tools/icu $(wildcard *.md LINT_MD_FILES = $(shell $(FIND) $(LINT_MD_TARGETS) -type f \ ! -path '*node_modules*' ! -path 'test/fixtures/*' -name '*.md' \ $(LINT_MD_NEWER)) -run-lint-md = tools/lint-md.mjs -q -f --no-stdout $(LINT_MD_FILES) +run-lint-md = tools/lint-md/lint-md.mjs $(LINT_MD_FILES) # Lint all changed markdown files maintained by us tools/.mdlintstamp: $(LINT_MD_FILES) $(info Running Markdown linter...) diff --git a/tools/lint-md/.gitignore b/tools/lint-md/.gitignore new file mode 100644 index 00000000000000..3c3629e647f5dd --- /dev/null +++ b/tools/lint-md/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/tools/lint-md.mjs b/tools/lint-md/lint-md.mjs similarity index 50% rename from tools/lint-md.mjs rename to tools/lint-md/lint-md.mjs index 10c0cf9386680c..85dff3eea640ef 100644 --- a/tools/lint-md.mjs +++ b/tools/lint-md/lint-md.mjs @@ -1,35316 +1,3033 @@ -import path$b from 'path'; +import fs from 'fs'; +import path$1 from 'path'; +import { fileURLToPath, pathToFileURL, URL as URL$1 } from 'url'; import process$1 from 'process'; -import { URL as URL$1, fileURLToPath, pathToFileURL } from 'url'; -import require$$0$3, { realpathSync as realpathSync$1, statSync, Stats } from 'fs'; -import process$2 from 'node:process'; -import stream, { PassThrough } from 'node:stream'; -import require$$0$2 from 'os'; -import tty$1 from 'tty'; -import require$$0$5 from 'events'; -import require$$0$4, { format as format$2, inspect as inspect$1 } from 'util'; -import require$$1 from 'stream'; -import path$c from 'node:path'; -import { pathToFileURL as pathToFileURL$1 } from 'node:url'; -import assert$2 from 'assert'; -import fs$a from 'node:fs'; -import { EventEmitter as EventEmitter$1 } from 'node:events'; +import os from 'os'; +import tty from 'tty'; -var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - -function getAugmentedNamespace(n) { - if (n.__esModule) return n; - var a = Object.defineProperty({}, '__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; +/** + * Throw a given error. + * + * @param {Error | null | undefined} [error] + */ +function bail(error) { + if (error) { + throw error + } } +var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + 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.'); } -var ansiStyles$2 = {exports: {}}; - -var colorName$1 = { - "aliceblue": [240, 248, 255], - "antiquewhite": [250, 235, 215], - "aqua": [0, 255, 255], - "aquamarine": [127, 255, 212], - "azure": [240, 255, 255], - "beige": [245, 245, 220], - "bisque": [255, 228, 196], - "black": [0, 0, 0], - "blanchedalmond": [255, 235, 205], - "blue": [0, 0, 255], - "blueviolet": [138, 43, 226], - "brown": [165, 42, 42], - "burlywood": [222, 184, 135], - "cadetblue": [95, 158, 160], - "chartreuse": [127, 255, 0], - "chocolate": [210, 105, 30], - "coral": [255, 127, 80], - "cornflowerblue": [100, 149, 237], - "cornsilk": [255, 248, 220], - "crimson": [220, 20, 60], - "cyan": [0, 255, 255], - "darkblue": [0, 0, 139], - "darkcyan": [0, 139, 139], - "darkgoldenrod": [184, 134, 11], - "darkgray": [169, 169, 169], - "darkgreen": [0, 100, 0], - "darkgrey": [169, 169, 169], - "darkkhaki": [189, 183, 107], - "darkmagenta": [139, 0, 139], - "darkolivegreen": [85, 107, 47], - "darkorange": [255, 140, 0], - "darkorchid": [153, 50, 204], - "darkred": [139, 0, 0], - "darksalmon": [233, 150, 122], - "darkseagreen": [143, 188, 143], - "darkslateblue": [72, 61, 139], - "darkslategray": [47, 79, 79], - "darkslategrey": [47, 79, 79], - "darkturquoise": [0, 206, 209], - "darkviolet": [148, 0, 211], - "deeppink": [255, 20, 147], - "deepskyblue": [0, 191, 255], - "dimgray": [105, 105, 105], - "dimgrey": [105, 105, 105], - "dodgerblue": [30, 144, 255], - "firebrick": [178, 34, 34], - "floralwhite": [255, 250, 240], - "forestgreen": [34, 139, 34], - "fuchsia": [255, 0, 255], - "gainsboro": [220, 220, 220], - "ghostwhite": [248, 248, 255], - "gold": [255, 215, 0], - "goldenrod": [218, 165, 32], - "gray": [128, 128, 128], - "green": [0, 128, 0], - "greenyellow": [173, 255, 47], - "grey": [128, 128, 128], - "honeydew": [240, 255, 240], - "hotpink": [255, 105, 180], - "indianred": [205, 92, 92], - "indigo": [75, 0, 130], - "ivory": [255, 255, 240], - "khaki": [240, 230, 140], - "lavender": [230, 230, 250], - "lavenderblush": [255, 240, 245], - "lawngreen": [124, 252, 0], - "lemonchiffon": [255, 250, 205], - "lightblue": [173, 216, 230], - "lightcoral": [240, 128, 128], - "lightcyan": [224, 255, 255], - "lightgoldenrodyellow": [250, 250, 210], - "lightgray": [211, 211, 211], - "lightgreen": [144, 238, 144], - "lightgrey": [211, 211, 211], - "lightpink": [255, 182, 193], - "lightsalmon": [255, 160, 122], - "lightseagreen": [32, 178, 170], - "lightskyblue": [135, 206, 250], - "lightslategray": [119, 136, 153], - "lightslategrey": [119, 136, 153], - "lightsteelblue": [176, 196, 222], - "lightyellow": [255, 255, 224], - "lime": [0, 255, 0], - "limegreen": [50, 205, 50], - "linen": [250, 240, 230], - "magenta": [255, 0, 255], - "maroon": [128, 0, 0], - "mediumaquamarine": [102, 205, 170], - "mediumblue": [0, 0, 205], - "mediumorchid": [186, 85, 211], - "mediumpurple": [147, 112, 219], - "mediumseagreen": [60, 179, 113], - "mediumslateblue": [123, 104, 238], - "mediumspringgreen": [0, 250, 154], - "mediumturquoise": [72, 209, 204], - "mediumvioletred": [199, 21, 133], - "midnightblue": [25, 25, 112], - "mintcream": [245, 255, 250], - "mistyrose": [255, 228, 225], - "moccasin": [255, 228, 181], - "navajowhite": [255, 222, 173], - "navy": [0, 0, 128], - "oldlace": [253, 245, 230], - "olive": [128, 128, 0], - "olivedrab": [107, 142, 35], - "orange": [255, 165, 0], - "orangered": [255, 69, 0], - "orchid": [218, 112, 214], - "palegoldenrod": [238, 232, 170], - "palegreen": [152, 251, 152], - "paleturquoise": [175, 238, 238], - "palevioletred": [219, 112, 147], - "papayawhip": [255, 239, 213], - "peachpuff": [255, 218, 185], - "peru": [205, 133, 63], - "pink": [255, 192, 203], - "plum": [221, 160, 221], - "powderblue": [176, 224, 230], - "purple": [128, 0, 128], - "rebeccapurple": [102, 51, 153], - "red": [255, 0, 0], - "rosybrown": [188, 143, 143], - "royalblue": [65, 105, 225], - "saddlebrown": [139, 69, 19], - "salmon": [250, 128, 114], - "sandybrown": [244, 164, 96], - "seagreen": [46, 139, 87], - "seashell": [255, 245, 238], - "sienna": [160, 82, 45], - "silver": [192, 192, 192], - "skyblue": [135, 206, 235], - "slateblue": [106, 90, 205], - "slategray": [112, 128, 144], - "slategrey": [112, 128, 144], - "snow": [255, 250, 250], - "springgreen": [0, 255, 127], - "steelblue": [70, 130, 180], - "tan": [210, 180, 140], - "teal": [0, 128, 128], - "thistle": [216, 191, 216], - "tomato": [255, 99, 71], - "turquoise": [64, 224, 208], - "violet": [238, 130, 238], - "wheat": [245, 222, 179], - "white": [255, 255, 255], - "whitesmoke": [245, 245, 245], - "yellow": [255, 255, 0], - "yellowgreen": [154, 205, 50] -}; +/*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh + * @license MIT + */ -/* MIT license */ - -/* eslint-disable no-mixed-operators */ -const cssKeywords$1 = colorName$1; - -// NOTE: conversions should only return primitive values (i.e. arrays, or -// values that give correct `typeof` results). -// do not use box values types (i.e. Number(), String(), etc.) - -const reverseKeywords$1 = {}; -for (const key of Object.keys(cssKeywords$1)) { - reverseKeywords$1[cssKeywords$1[key]] = key; -} - -const convert$4 = { - rgb: {channels: 3, labels: 'rgb'}, - hsl: {channels: 3, labels: 'hsl'}, - hsv: {channels: 3, labels: 'hsv'}, - hwb: {channels: 3, labels: 'hwb'}, - cmyk: {channels: 4, labels: 'cmyk'}, - xyz: {channels: 3, labels: 'xyz'}, - lab: {channels: 3, labels: 'lab'}, - lch: {channels: 3, labels: 'lch'}, - hex: {channels: 1, labels: ['hex']}, - keyword: {channels: 1, labels: ['keyword']}, - ansi16: {channels: 1, labels: ['ansi16']}, - ansi256: {channels: 1, labels: ['ansi256']}, - hcg: {channels: 3, labels: ['h', 'c', 'g']}, - apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, - gray: {channels: 1, labels: ['gray']} +var isBuffer = function isBuffer (obj) { + return obj != null && obj.constructor != null && + typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) }; -var conversions$5 = convert$4; - -// Hide .channels and .labels properties -for (const model of Object.keys(convert$4)) { - if (!('channels' in convert$4[model])) { - throw new Error('missing channels property: ' + model); - } +var hasOwn = Object.prototype.hasOwnProperty; +var toStr = Object.prototype.toString; +var defineProperty = Object.defineProperty; +var gOPD = Object.getOwnPropertyDescriptor; - if (!('labels' in convert$4[model])) { - throw new Error('missing channel labels property: ' + model); +var isArray = function isArray(arr) { + if (typeof Array.isArray === 'function') { + return Array.isArray(arr); } - if (convert$4[model].labels.length !== convert$4[model].channels) { - throw new Error('channel and label counts mismatch: ' + model); - } + return toStr.call(arr) === '[object Array]'; +}; - const {channels, labels} = convert$4[model]; - delete convert$4[model].channels; - delete convert$4[model].labels; - Object.defineProperty(convert$4[model], 'channels', {value: channels}); - Object.defineProperty(convert$4[model], 'labels', {value: labels}); -} - -convert$4.rgb.hsl = function (rgb) { - const r = rgb[0] / 255; - const g = rgb[1] / 255; - const b = rgb[2] / 255; - const min = Math.min(r, g, b); - const max = Math.max(r, g, b); - const delta = max - min; - let h; - let s; - - if (max === min) { - h = 0; - } else if (r === max) { - h = (g - b) / delta; - } else if (g === max) { - h = 2 + (b - r) / delta; - } else if (b === max) { - h = 4 + (r - g) / delta; +var isPlainObject$1 = function isPlainObject(obj) { + if (!obj || toStr.call(obj) !== '[object Object]') { + return false; } - h = Math.min(h * 60, 360); - - if (h < 0) { - h += 360; + var hasOwnConstructor = hasOwn.call(obj, 'constructor'); + var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf'); + // Not own constructor property must be Object + if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) { + return false; } - const l = (min + max) / 2; - - if (max === min) { - s = 0; - } else if (l <= 0.5) { - s = delta / (max + min); - } else { - s = delta / (2 - max - min); - } + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + var key; + for (key in obj) { /**/ } - return [h, s * 100, l * 100]; + return typeof key === 'undefined' || hasOwn.call(obj, key); }; -convert$4.rgb.hsv = function (rgb) { - let rdif; - let gdif; - let bdif; - let h; - let s; - - const r = rgb[0] / 255; - const g = rgb[1] / 255; - const b = rgb[2] / 255; - const v = Math.max(r, g, b); - const diff = v - Math.min(r, g, b); - const diffc = function (c) { - return (v - c) / 6 / diff + 1 / 2; - }; - - if (diff === 0) { - h = 0; - s = 0; +// If name is '__proto__', and Object.defineProperty is available, define __proto__ as an own property on target +var setProperty = function setProperty(target, options) { + if (defineProperty && options.name === '__proto__') { + defineProperty(target, options.name, { + enumerable: true, + configurable: true, + value: options.newValue, + writable: true + }); } else { - s = diff / v; - rdif = diffc(r); - gdif = diffc(g); - bdif = diffc(b); - - if (r === v) { - h = bdif - gdif; - } else if (g === v) { - h = (1 / 3) + rdif - bdif; - } else if (b === v) { - h = (2 / 3) + gdif - rdif; - } - - if (h < 0) { - h += 1; - } else if (h > 1) { - h -= 1; - } + target[options.name] = options.newValue; } - - return [ - h * 360, - s * 100, - v * 100 - ]; -}; - -convert$4.rgb.hwb = function (rgb) { - const r = rgb[0]; - const g = rgb[1]; - let b = rgb[2]; - const h = convert$4.rgb.hsl(rgb)[0]; - const w = 1 / 255 * Math.min(r, Math.min(g, b)); - - b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); - - return [h, w * 100, b * 100]; -}; - -convert$4.rgb.cmyk = function (rgb) { - const r = rgb[0] / 255; - const g = rgb[1] / 255; - const b = rgb[2] / 255; - - const k = Math.min(1 - r, 1 - g, 1 - b); - const c = (1 - r - k) / (1 - k) || 0; - const m = (1 - g - k) / (1 - k) || 0; - const y = (1 - b - k) / (1 - k) || 0; - - return [c * 100, m * 100, y * 100, k * 100]; }; -function comparativeDistance$1(x, y) { - /* - See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance - */ - return ( - ((x[0] - y[0]) ** 2) + - ((x[1] - y[1]) ** 2) + - ((x[2] - y[2]) ** 2) - ); -} - -convert$4.rgb.keyword = function (rgb) { - const reversed = reverseKeywords$1[rgb]; - if (reversed) { - return reversed; - } - - let currentClosestDistance = Infinity; - let currentClosestKeyword; - - for (const keyword of Object.keys(cssKeywords$1)) { - const value = cssKeywords$1[keyword]; - - // Compute comparative distance - const distance = comparativeDistance$1(rgb, value); - - // Check if its less, if so set as closest - if (distance < currentClosestDistance) { - currentClosestDistance = distance; - currentClosestKeyword = keyword; +// Return undefined instead of __proto__ if '__proto__' is not an own property +var getProperty = function getProperty(obj, name) { + if (name === '__proto__') { + if (!hasOwn.call(obj, name)) { + return void 0; + } else if (gOPD) { + // In early versions of node, obj['__proto__'] is buggy when obj has + // __proto__ as an own property. Object.getOwnPropertyDescriptor() works. + return gOPD(obj, name).value; } } - return currentClosestKeyword; -}; - -convert$4.keyword.rgb = function (keyword) { - return cssKeywords$1[keyword]; -}; - -convert$4.rgb.xyz = function (rgb) { - let r = rgb[0] / 255; - let g = rgb[1] / 255; - let b = rgb[2] / 255; - - // Assume sRGB - r = r > 0.04045 ? (((r + 0.055) / 1.055) ** 2.4) : (r / 12.92); - g = g > 0.04045 ? (((g + 0.055) / 1.055) ** 2.4) : (g / 12.92); - b = b > 0.04045 ? (((b + 0.055) / 1.055) ** 2.4) : (b / 12.92); - - const x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); - const y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); - const z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); - - return [x * 100, y * 100, z * 100]; + return obj[name]; }; -convert$4.rgb.lab = function (rgb) { - const xyz = convert$4.rgb.xyz(rgb); - let x = xyz[0]; - let y = xyz[1]; - let z = xyz[2]; - - x /= 95.047; - y /= 100; - z /= 108.883; - - x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); - - const l = (116 * y) - 16; - const a = 500 * (x - y); - const b = 200 * (y - z); - - return [l, a, b]; -}; +var extend$1 = function extend() { + var options, name, src, copy, copyIsArray, clone; + var target = arguments[0]; + var i = 1; + var length = arguments.length; + var deep = false; -convert$4.hsl.rgb = function (hsl) { - const h = hsl[0] / 360; - const s = hsl[1] / 100; - const l = hsl[2] / 100; - let t2; - let t3; - let val; - - if (s === 0) { - val = l * 255; - return [val, val, val]; + // Handle a deep copy situation + if (typeof target === 'boolean') { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; } - - if (l < 0.5) { - t2 = l * (1 + s); - } else { - t2 = l + s - l * s; + if (target == null || (typeof target !== 'object' && typeof target !== 'function')) { + target = {}; } - const t1 = 2 * l - t2; + for (; i < length; ++i) { + options = arguments[i]; + // Only deal with non-null/undefined values + if (options != null) { + // Extend the base object + for (name in options) { + src = getProperty(target, name); + copy = getProperty(options, name); - const rgb = [0, 0, 0]; - for (let i = 0; i < 3; i++) { - t3 = h + 1 / 3 * -(i - 1); - if (t3 < 0) { - t3++; - } + // Prevent never-ending loop + if (target !== copy) { + // Recurse if we're merging plain objects or arrays + if (deep && copy && (isPlainObject$1(copy) || (copyIsArray = isArray(copy)))) { + if (copyIsArray) { + copyIsArray = false; + clone = src && isArray(src) ? src : []; + } else { + clone = src && isPlainObject$1(src) ? src : {}; + } - if (t3 > 1) { - t3--; - } + // Never move original objects, clone them + setProperty(target, { name: name, newValue: extend(deep, clone, copy) }); - if (6 * t3 < 1) { - val = t1 + (t2 - t1) * 6 * t3; - } else if (2 * t3 < 1) { - val = t2; - } else if (3 * t3 < 2) { - val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; - } else { - val = t1; + // Don't bring in undefined values + } else if (typeof copy !== 'undefined') { + setProperty(target, { name: name, newValue: copy }); + } + } + } } - - rgb[i] = val * 255; - } - - return rgb; -}; - -convert$4.hsl.hsv = function (hsl) { - const h = hsl[0]; - let s = hsl[1] / 100; - let l = hsl[2] / 100; - let smin = s; - const lmin = Math.max(l, 0.01); - - l *= 2; - s *= (l <= 1) ? l : 2 - l; - smin *= lmin <= 1 ? lmin : 2 - lmin; - const v = (l + s) / 2; - const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); - - return [h, sv * 100, v * 100]; -}; - -convert$4.hsv.rgb = function (hsv) { - const h = hsv[0] / 60; - const s = hsv[1] / 100; - let v = hsv[2] / 100; - const hi = Math.floor(h) % 6; - - const f = h - Math.floor(h); - const p = 255 * v * (1 - s); - const q = 255 * v * (1 - (s * f)); - const t = 255 * v * (1 - (s * (1 - f))); - v *= 255; - - switch (hi) { - case 0: - return [v, t, p]; - case 1: - return [q, v, p]; - case 2: - return [p, v, t]; - case 3: - return [p, q, v]; - case 4: - return [t, p, v]; - case 5: - return [v, p, q]; } -}; -convert$4.hsv.hsl = function (hsv) { - const h = hsv[0]; - const s = hsv[1] / 100; - const v = hsv[2] / 100; - const vmin = Math.max(v, 0.01); - let sl; - let l; - - l = (2 - s) * v; - const lmin = (2 - s) * vmin; - sl = s * vmin; - sl /= (lmin <= 1) ? lmin : 2 - lmin; - sl = sl || 0; - l /= 2; - - return [h, sl * 100, l * 100]; + // Return the modified object + return target; }; -// http://dev.w3.org/csswg/css-color/#hwb-to-rgb -convert$4.hwb.rgb = function (hwb) { - const h = hwb[0] / 360; - let wh = hwb[1] / 100; - let bl = hwb[2] / 100; - const ratio = wh + bl; - let f; - - // Wh + bl cant be > 1 - if (ratio > 1) { - wh /= ratio; - bl /= ratio; - } - - const i = Math.floor(6 * h); - const v = 1 - bl; - f = 6 * h - i; - - if ((i & 0x01) !== 0) { - f = 1 - f; - } - - const n = wh + f * (v - wh); // Linear interpolation - - let r; - let g; - let b; - /* eslint-disable max-statements-per-line,no-multi-spaces */ - switch (i) { - default: - case 6: - case 0: r = v; g = n; b = wh; break; - case 1: r = n; g = v; b = wh; break; - case 2: r = wh; g = v; b = n; break; - case 3: r = wh; g = n; b = v; break; - case 4: r = n; g = wh; b = v; break; - case 5: r = v; g = wh; b = n; break; +function isPlainObject(value) { + if (Object.prototype.toString.call(value) !== '[object Object]') { + return false; } - /* eslint-enable max-statements-per-line,no-multi-spaces */ - - return [r * 255, g * 255, b * 255]; -}; - -convert$4.cmyk.rgb = function (cmyk) { - const c = cmyk[0] / 100; - const m = cmyk[1] / 100; - const y = cmyk[2] / 100; - const k = cmyk[3] / 100; - const r = 1 - Math.min(1, c * (1 - k) + k); - const g = 1 - Math.min(1, m * (1 - k) + k); - const b = 1 - Math.min(1, y * (1 - k) + k); - - return [r * 255, g * 255, b * 255]; -}; + const prototype = Object.getPrototypeOf(value); + return prototype === null || prototype === Object.prototype; +} -convert$4.xyz.rgb = function (xyz) { - const x = xyz[0] / 100; - const y = xyz[1] / 100; - const z = xyz[2] / 100; - let r; - let g; - let b; +/** + * @typedef {(error?: Error|null|undefined, ...output: any[]) => void} Callback + * @typedef {(...input: any[]) => any} Middleware + * + * @typedef {(...input: any[]) => void} Run Call all middleware. + * @typedef {(fn: Middleware) => Pipeline} Use Add `fn` (middleware) to the list. + * @typedef {{run: Run, use: Use}} Pipeline + */ - r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); - g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); - b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); +/** + * Create new middleware. + * + * @returns {Pipeline} + */ +function trough() { + /** @type {Middleware[]} */ + const fns = []; + /** @type {Pipeline} */ + const pipeline = {run, use}; - // Assume sRGB - r = r > 0.0031308 - ? ((1.055 * (r ** (1.0 / 2.4))) - 0.055) - : r * 12.92; + return pipeline - g = g > 0.0031308 - ? ((1.055 * (g ** (1.0 / 2.4))) - 0.055) - : g * 12.92; + /** @type {Run} */ + function run(...values) { + let middlewareIndex = -1; + /** @type {Callback} */ + const callback = values.pop(); - b = b > 0.0031308 - ? ((1.055 * (b ** (1.0 / 2.4))) - 0.055) - : b * 12.92; + if (typeof callback !== 'function') { + throw new TypeError('Expected function as last argument, not ' + callback) + } - r = Math.min(Math.max(0, r), 1); - g = Math.min(Math.max(0, g), 1); - b = Math.min(Math.max(0, b), 1); + next(null, ...values); - return [r * 255, g * 255, b * 255]; -}; + /** + * Run the next `fn`, or we’re done. + * + * @param {Error|null|undefined} error + * @param {any[]} output + */ + function next(error, ...output) { + const fn = fns[++middlewareIndex]; + let index = -1; -convert$4.xyz.lab = function (xyz) { - let x = xyz[0]; - let y = xyz[1]; - let z = xyz[2]; + if (error) { + callback(error); + return + } - x /= 95.047; - y /= 100; - z /= 108.883; + // Copy non-nullish input into values. + while (++index < values.length) { + if (output[index] === null || output[index] === undefined) { + output[index] = values[index]; + } + } - x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); + // Save the newly created `output` for the next call. + values = output; - const l = (116 * y) - 16; - const a = 500 * (x - y); - const b = 200 * (y - z); + // Next or done. + if (fn) { + wrap(fn, next)(...output); + } else { + callback(null, ...output); + } + } + } - return [l, a, b]; -}; + /** @type {Use} */ + function use(middelware) { + if (typeof middelware !== 'function') { + throw new TypeError( + 'Expected `middelware` to be a function, not ' + middelware + ) + } -convert$4.lab.xyz = function (lab) { - const l = lab[0]; - const a = lab[1]; - const b = lab[2]; - let x; - let y; - let z; - - y = (l + 16) / 116; - x = a / 500 + y; - z = y - b / 200; - - const y2 = y ** 3; - const x2 = x ** 3; - const z2 = z ** 3; - y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787; - x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787; - z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787; - - x *= 95.047; - y *= 100; - z *= 108.883; - - return [x, y, z]; -}; + fns.push(middelware); + return pipeline + } +} -convert$4.lab.lch = function (lab) { - const l = lab[0]; - const a = lab[1]; - const b = lab[2]; - let h; +/** + * Wrap `middleware`. + * Can be sync or async; return a promise, receive a callback, or return new + * values and errors. + * + * @param {Middleware} middleware + * @param {Callback} callback + */ +function wrap(middleware, callback) { + /** @type {boolean} */ + let called; - const hr = Math.atan2(b, a); - h = hr * 360 / 2 / Math.PI; + return wrapped - if (h < 0) { - h += 360; - } + /** + * Call `middleware`. + * @param {any[]} parameters + * @returns {void} + */ + function wrapped(...parameters) { + const fnExpectsCallback = middleware.length > parameters.length; + /** @type {any} */ + let result; - const c = Math.sqrt(a * a + b * b); + if (fnExpectsCallback) { + parameters.push(done); + } - return [l, c, h]; -}; + try { + result = middleware(...parameters); + } catch (error) { + /** @type {Error} */ + const exception = error; -convert$4.lch.lab = function (lch) { - const l = lch[0]; - const c = lch[1]; - const h = lch[2]; + // Well, this is quite the pickle. + // `middleware` received a callback and called it synchronously, but that + // threw an error. + // The only thing left to do is to throw the thing instead. + if (fnExpectsCallback && called) { + throw exception + } - const hr = h / 360 * 2 * Math.PI; - const a = c * Math.cos(hr); - const b = c * Math.sin(hr); + return done(exception) + } - return [l, a, b]; -}; + if (!fnExpectsCallback) { + if (result instanceof Promise) { + result.then(then, done); + } else if (result instanceof Error) { + done(result); + } else { + then(result); + } + } + } -convert$4.rgb.ansi16 = function (args, saturation = null) { - const [r, g, b] = args; - let value = saturation === null ? convert$4.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization + /** + * Call `callback`, only once. + * @type {Callback} + */ + function done(error, ...output) { + if (!called) { + called = true; + callback(error, ...output); + } + } - value = Math.round(value / 50); + /** + * Call `done` with one value. + * + * @param {any} [value] + */ + function then(value) { + done(null, value); + } +} - if (value === 0) { - return 30; - } +var own$8 = {}.hasOwnProperty; - let ansi = 30 - + ((Math.round(b / 255) << 2) - | (Math.round(g / 255) << 1) - | Math.round(r / 255)); +/** + * @typedef {import('unist').Node} Node + * @typedef {import('unist').Position} Position + * @typedef {import('unist').Point} Point + */ - if (value === 2) { - ansi += 60; - } +/** + * Stringify one point, a position (start and end points), or a node’s + * positional information. + * + * @param {Node|Position|Point} [value] + * @returns {string} + */ +function stringifyPosition(value) { + // Nothing. + if (!value || typeof value !== 'object') { + return '' + } - return ansi; -}; + // Node. + if (own$8.call(value, 'position') || own$8.call(value, 'type')) { + // @ts-ignore looks like a node. + return position(value.position) + } -convert$4.hsv.ansi16 = function (args) { - // Optimization here; we already know the value and don't need to get - // it converted for us. - return convert$4.rgb.ansi16(convert$4.hsv.rgb(args), args[2]); -}; + // Position. + if (own$8.call(value, 'start') || own$8.call(value, 'end')) { + // @ts-ignore looks like a position. + return position(value) + } -convert$4.rgb.ansi256 = function (args) { - const r = args[0]; - const g = args[1]; - const b = args[2]; + // Point. + if (own$8.call(value, 'line') || own$8.call(value, 'column')) { + // @ts-ignore looks like a point. + return point$1(value) + } - // We use the extended greyscale palette here, with the exception of - // black and white. normal palette only has 4 greyscale shades. - if (r === g && g === b) { - if (r < 8) { - return 16; - } + // ? + return '' +} - if (r > 248) { - return 231; - } +/** + * @param {Point} point + * @returns {string} + */ +function point$1(point) { + return index(point && point.line) + ':' + index(point && point.column) +} - return Math.round(((r - 8) / 247) * 24) + 232; - } +/** + * @param {Position} pos + * @returns {string} + */ +function position(pos) { + return point$1(pos && pos.start) + '-' + point$1(pos && pos.end) +} - const ansi = 16 - + (36 * Math.round(r / 255 * 5)) - + (6 * Math.round(g / 255 * 5)) - + Math.round(b / 255 * 5); +/** + * @param {number} value + * @returns {number} + */ +function index(value) { + return value && typeof value === 'number' ? value : 1 +} - return ansi; -}; +/** + * @typedef {import('unist').Node} Node + * @typedef {import('unist').Position} Position + * @typedef {import('unist').Point} Point + */ -convert$4.ansi16.rgb = function (args) { - let color = args % 10; +class VFileMessage extends Error { + /** + * Constructor of a message for `reason` at `place` from `origin`. + * When an error is passed in as `reason`, copies the `stack`. + * + * @param {string|Error} reason Reason for message (`string` or `Error`). Uses the stack and message of the error if given. + * @param {Node|Position|Point} [place] Place at which the message occurred in a file (`Node`, `Position`, or `Point`, optional). + * @param {string} [origin] Place in code the message originates from (`string`, optional). + */ + constructor(reason, place, origin) { + /** @type {[string?, string?]} */ + var parts = [null, null]; + /** @type {Position} */ + var position = { + start: {line: null, column: null}, + end: {line: null, column: null} + }; + /** @type {number} */ + var index; - // Handle greyscale - if (color === 0 || color === 7) { - if (args > 50) { - color += 3.5; - } + super(); - color = color / 10.5 * 255; + if (typeof place === 'string') { + origin = place; + place = null; + } - return [color, color, color]; - } + if (typeof origin === 'string') { + index = origin.indexOf(':'); - const mult = (~~(args > 50) + 1) * 0.5; - const r = ((color & 1) * mult) * 255; - const g = (((color >> 1) & 1) * mult) * 255; - const b = (((color >> 2) & 1) * mult) * 255; + if (index === -1) { + parts[1] = origin; + } else { + parts[0] = origin.slice(0, index); + parts[1] = origin.slice(index + 1); + } + } - return [r, g, b]; -}; + if (place) { + // Node. + if ('type' in place || 'position' in place) { + if (place.position) { + position = place.position; + } + } + // Position. + else if ('start' in place || 'end' in place) { + // @ts-ignore Looks like a position. + position = place; + } + // Point. + else if ('line' in place || 'column' in place) { + // @ts-ignore Looks like a point. + position.start = place; + } + } -convert$4.ansi256.rgb = function (args) { - // Handle greyscale - if (args >= 232) { - const c = (args - 232) * 10 + 8; - return [c, c, c]; - } + // Fields from `Error` + this.name = stringifyPosition(place) || '1:1'; + this.message = typeof reason === 'object' ? reason.message : reason; + this.stack = typeof reason === 'object' ? reason.stack : ''; - args -= 16; + /** + * Reason for message. + * @type {string} + */ + this.reason = this.message; + /** + * Starting line of error. + * @type {number?} + */ + this.line = position.start.line; + /** + * Starting column of error. + * @type {number?} + */ + this.column = position.start.column; + /** + * Namespace of warning. + * @type {string?} + */ + this.source = parts[0]; + /** + * Category of message. + * @type {string?} + */ + this.ruleId = parts[1]; + /** + * Full range information, when available. + * Has start and end properties, both set to an object with line and column, set to number?. + * @type {Position?} + */ + this.position = position; - let rem; - const r = Math.floor(args / 36) / 5 * 255; - const g = Math.floor((rem = args % 36) / 6) / 5 * 255; - const b = (rem % 6) / 5 * 255; + // The following fields are “well known”. + // Not standard. + // Feel free to add other non-standard fields to your messages. - return [r, g, b]; -}; + /* eslint-disable no-unused-expressions */ + /** + * You may add a file property with a path of a file (used throughout the VFile ecosystem). + * @type {string?} + */ + this.file; + /** + * If true, marks associated file as no longer processable. + * @type {boolean?} + */ + this.fatal; + /** + * You may add a url property with a link to documentation for the message. + * @type {string?} + */ + this.url; + /** + * You may add a note property with a long form description of the message (supported by vfile-reporter). + * @type {string?} + */ + this.note; + /* eslint-enable no-unused-expressions */ + } +} -convert$4.rgb.hex = function (args) { - const integer = ((Math.round(args[0]) & 0xFF) << 16) - + ((Math.round(args[1]) & 0xFF) << 8) - + (Math.round(args[2]) & 0xFF); +VFileMessage.prototype.file = ''; +VFileMessage.prototype.name = ''; +VFileMessage.prototype.reason = ''; +VFileMessage.prototype.message = ''; +VFileMessage.prototype.stack = ''; +VFileMessage.prototype.fatal = null; +VFileMessage.prototype.column = null; +VFileMessage.prototype.line = null; +VFileMessage.prototype.source = null; +VFileMessage.prototype.ruleId = null; +VFileMessage.prototype.position = null; - const string = integer.toString(16).toUpperCase(); - return '000000'.substring(string.length) + string; -}; +const proc = process$1; -convert$4.hex.rgb = function (args) { - const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); - if (!match) { - return [0, 0, 0]; - } - - let colorString = match[0]; - - if (match[0].length === 3) { - colorString = colorString.split('').map(char => { - return char + char; - }).join(''); - } - - const integer = parseInt(colorString, 16); - const r = (integer >> 16) & 0xFF; - const g = (integer >> 8) & 0xFF; - const b = integer & 0xFF; - - return [r, g, b]; -}; - -convert$4.rgb.hcg = function (rgb) { - const r = rgb[0] / 255; - const g = rgb[1] / 255; - const b = rgb[2] / 255; - const max = Math.max(Math.max(r, g), b); - const min = Math.min(Math.min(r, g), b); - const chroma = (max - min); - let grayscale; - let hue; - - if (chroma < 1) { - grayscale = min / (1 - chroma); - } else { - grayscale = 0; - } +/** + * @typedef URL + * @property {string} hash + * @property {string} host + * @property {string} hostname + * @property {string} href + * @property {string} origin + * @property {string} password + * @property {string} pathname + * @property {string} port + * @property {string} protocol + * @property {string} search + * @property {any} searchParams + * @property {string} username + * @property {() => string} toString + * @property {() => string} toJSON + */ - if (chroma <= 0) { - hue = 0; - } else - if (max === r) { - hue = ((g - b) / chroma) % 6; - } else - if (max === g) { - hue = 2 + (b - r) / chroma; - } else { - hue = 4 + (r - g) / chroma; - } +/** + * @param {unknown} fileURLOrPath + * @returns {fileURLOrPath is URL} + */ +// From: +function isUrl(fileURLOrPath) { + return ( + fileURLOrPath !== null && + typeof fileURLOrPath === 'object' && + // @ts-expect-error: indexable. + fileURLOrPath.href && + // @ts-expect-error: indexable. + fileURLOrPath.origin + ) +} - hue /= 6; - hue %= 1; +/** + * @typedef {import('unist').Node} Node + * @typedef {import('unist').Position} Position + * @typedef {import('unist').Point} Point + * @typedef {import('./minurl.shared.js').URL} URL + * + * @typedef {'ascii'|'utf8'|'utf-8'|'utf16le'|'ucs2'|'ucs-2'|'base64'|'latin1'|'binary'|'hex'} BufferEncoding + * Encodings supported by the buffer class. + * This is a copy of the typing from Node, copied to prevent Node globals from + * being needed. + * Copied from: + * + * @typedef {string|Uint8Array} VFileValue + * Contents of the file. + * Can either be text, or a Buffer like structure. + * This does not directly use type `Buffer`, because it can also be used in a + * browser context. + * Instead this leverages `Uint8Array` which is the base type for `Buffer`, + * and a native JavaScript construct. + * + * @typedef {VFileValue|VFileOptions|VFile|URL} VFileCompatible + * Things that can be passed to the constructor. + * + * @typedef VFileCoreOptions + * @property {VFileValue} [value] + * @property {string} [cwd] + * @property {Array.} [history] + * @property {string|URL} [path] + * @property {string} [basename] + * @property {string} [stem] + * @property {string} [extname] + * @property {string} [dirname] + * @property {Object.} [data] + * + * @typedef {{[key: string]: unknown} & VFileCoreOptions} VFileOptions + * Configuration: a bunch of keys that will be shallow copied over to the new + * file. + * + * @typedef {Object.} VFileReporterSettings + * @typedef {(files: VFile[], options: T) => string} VFileReporter + */ - return [hue * 360, chroma * 100, grayscale * 100]; -}; +// Order of setting (least specific to most), we need this because otherwise +// `{stem: 'a', path: '~/b.js'}` would throw, as a path is needed before a +// stem can be set. +const order = ['history', 'path', 'basename', 'stem', 'extname', 'dirname']; -convert$4.hsl.hcg = function (hsl) { - const s = hsl[1] / 100; - const l = hsl[2] / 100; +class VFile { + /** + * Create a new virtual file. + * + * If `options` is `string` or `Buffer`, treats it as `{value: options}`. + * If `options` is a `VFile`, shallow copies its data over to the new file. + * All other given fields are set on the newly created `VFile`. + * + * Path related properties are set in the following order (least specific to + * most specific): `history`, `path`, `basename`, `stem`, `extname`, + * `dirname`. + * + * It’s not possible to set either `dirname` or `extname` without setting + * either `history`, `path`, `basename`, or `stem` as well. + * + * @param {VFileCompatible} [value] + */ + constructor(value) { + /** @type {VFileOptions} */ + let options; - const c = l < 0.5 ? (2.0 * s * l) : (2.0 * s * (1.0 - l)); + if (!value) { + options = {}; + } else if (typeof value === 'string' || isBuffer(value)) { + // @ts-expect-error Looks like a buffer. + options = {value}; + } else if (isUrl(value)) { + options = {path: value}; + } else { + // @ts-expect-error Looks like file or options. + options = value; + } - let f = 0; - if (c < 1.0) { - f = (l - 0.5 * c) / (1.0 - c); - } + /** + * Place to store custom information. + * It’s OK to store custom data directly on the file, moving it to `data` + * gives a little more privacy. + * @type {Object.} + */ + this.data = {}; - return [hsl[0], c * 100, f * 100]; -}; + /** + * List of messages associated with the file. + * @type {Array.} + */ + this.messages = []; -convert$4.hsv.hcg = function (hsv) { - const s = hsv[1] / 100; - const v = hsv[2] / 100; + /** + * List of file paths the file moved between. + * @type {Array.} + */ + this.history = []; - const c = s * v; - let f = 0; + /** + * Base of `path`. + * Defaults to `process.cwd()` (`/` in browsers). + * @type {string} + */ + this.cwd = proc.cwd(); - if (c < 1.0) { - f = (v - c) / (1 - c); - } + /* eslint-disable no-unused-expressions */ + /** + * Raw value. + * @type {VFileValue} + */ + this.value; - return [hsv[0], c * 100, f * 100]; -}; + // The below are non-standard, they are “well-known”. + // As in, used in several tools. -convert$4.hcg.rgb = function (hcg) { - const h = hcg[0] / 360; - const c = hcg[1] / 100; - const g = hcg[2] / 100; + /** + * Whether a file was saved to disk. + * This is used by vfile reporters. + * @type {boolean} + */ + this.stored; - if (c === 0.0) { - return [g * 255, g * 255, g * 255]; - } + /** + * Sometimes files have a non-string representation. + * This can be stored in the `result` field. + * One example is when turning markdown into React nodes. + * This is used by unified to store non-string results. + * @type {unknown} + */ + this.result; - const pure = [0, 0, 0]; - const hi = (h % 1) * 6; - const v = hi % 1; - const w = 1 - v; - let mg = 0; - - /* eslint-disable max-statements-per-line */ - switch (Math.floor(hi)) { - case 0: - pure[0] = 1; pure[1] = v; pure[2] = 0; break; - case 1: - pure[0] = w; pure[1] = 1; pure[2] = 0; break; - case 2: - pure[0] = 0; pure[1] = 1; pure[2] = v; break; - case 3: - pure[0] = 0; pure[1] = w; pure[2] = 1; break; - case 4: - pure[0] = v; pure[1] = 0; pure[2] = 1; break; - default: - pure[0] = 1; pure[1] = 0; pure[2] = w; - } - /* eslint-enable max-statements-per-line */ + /** + * Sometimes files have a source map associated with them. + * This can be stored in the `map` field. + * This should be a `RawSourceMap` type from the `source-map` module. + * @type {unknown} + */ + this.map; + /* eslint-enable no-unused-expressions */ - mg = (1.0 - c) * g; + // Set path related properties in the correct order. + let index = -1; - return [ - (c * pure[0] + mg) * 255, - (c * pure[1] + mg) * 255, - (c * pure[2] + mg) * 255 - ]; -}; + while (++index < order.length) { + const prop = order[index]; -convert$4.hcg.hsv = function (hcg) { - const c = hcg[1] / 100; - const g = hcg[2] / 100; + // Note: we specifically use `in` instead of `hasOwnProperty` to accept + // `vfile`s too. + if (prop in options && options[prop] !== undefined) { + // @ts-expect-error: TS is confused by the different types for `history`. + this[prop] = prop === 'history' ? [...options[prop]] : options[prop]; + } + } - const v = c + g * (1.0 - c); - let f = 0; + /** @type {string} */ + let prop; - if (v > 0.0) { - f = c / v; - } + // Set non-path related properties. + for (prop in options) { + // @ts-expect-error: fine to set other things. + if (!order.includes(prop)) this[prop] = options[prop]; + } + } - return [hcg[0], f * 100, v * 100]; -}; + /** + * Access full path (`~/index.min.js`). + * + * @returns {string} + */ + get path() { + return this.history[this.history.length - 1] + } -convert$4.hcg.hsl = function (hcg) { - const c = hcg[1] / 100; - const g = hcg[2] / 100; + /** + * Set full path (`~/index.min.js`). + * Cannot be nullified. + * + * @param {string|URL} path + */ + set path(path) { + if (isUrl(path)) { + path = fileURLToPath(path); + } - const l = g * (1.0 - c) + 0.5 * c; - let s = 0; + assertNonEmpty(path, 'path'); - if (l > 0.0 && l < 0.5) { - s = c / (2 * l); - } else - if (l >= 0.5 && l < 1.0) { - s = c / (2 * (1 - l)); - } + if (this.path !== path) { + this.history.push(path); + } + } - return [hcg[0], s * 100, l * 100]; -}; + /** + * Access parent path (`~`). + */ + get dirname() { + return typeof this.path === 'string' ? path$1.dirname(this.path) : undefined + } -convert$4.hcg.hwb = function (hcg) { - const c = hcg[1] / 100; - const g = hcg[2] / 100; - const v = c + g * (1.0 - c); - return [hcg[0], (v - c) * 100, (1 - v) * 100]; -}; + /** + * Set parent path (`~`). + * Cannot be set if there's no `path` yet. + */ + set dirname(dirname) { + assertPath(this.basename, 'dirname'); + this.path = path$1.join(dirname || '', this.basename); + } -convert$4.hwb.hcg = function (hwb) { - const w = hwb[1] / 100; - const b = hwb[2] / 100; - const v = 1 - b; - const c = v - w; - let g = 0; + /** + * Access basename (including extname) (`index.min.js`). + */ + get basename() { + return typeof this.path === 'string' ? path$1.basename(this.path) : undefined + } - if (c < 1) { - g = (v - c) / (1 - c); - } + /** + * Set basename (`index.min.js`). + * Cannot contain path separators. + * Cannot be nullified either (use `file.path = file.dirname` instead). + */ + set basename(basename) { + assertNonEmpty(basename, 'basename'); + assertPart(basename, 'basename'); + this.path = path$1.join(this.dirname || '', basename); + } - return [hwb[0], c * 100, g * 100]; -}; + /** + * Access extname (including dot) (`.js`). + */ + get extname() { + return typeof this.path === 'string' ? path$1.extname(this.path) : undefined + } -convert$4.apple.rgb = function (apple) { - return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255]; -}; + /** + * Set extname (including dot) (`.js`). + * Cannot be set if there's no `path` yet and cannot contain path separators. + */ + set extname(extname) { + assertPart(extname, 'extname'); + assertPath(this.dirname, 'extname'); -convert$4.rgb.apple = function (rgb) { - return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535]; -}; + if (extname) { + if (extname.charCodeAt(0) !== 46 /* `.` */) { + throw new Error('`extname` must start with `.`') + } -convert$4.gray.rgb = function (args) { - return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; -}; + if (extname.includes('.', 1)) { + throw new Error('`extname` cannot contain multiple dots') + } + } -convert$4.gray.hsl = function (args) { - return [0, 0, args[0]]; -}; + this.path = path$1.join(this.dirname, this.stem + (extname || '')); + } -convert$4.gray.hsv = convert$4.gray.hsl; + /** + * Access stem (w/o extname) (`index.min`). + */ + get stem() { + return typeof this.path === 'string' + ? path$1.basename(this.path, this.extname) + : undefined + } -convert$4.gray.hwb = function (gray) { - return [0, 100, gray[0]]; -}; + /** + * Set stem (w/o extname) (`index.min`). + * Cannot be nullified, and cannot contain path separators. + */ + set stem(stem) { + assertNonEmpty(stem, 'stem'); + assertPart(stem, 'stem'); + this.path = path$1.join(this.dirname || '', stem + (this.extname || '')); + } -convert$4.gray.cmyk = function (gray) { - return [0, 0, 0, gray[0]]; -}; + /** + * Serialize the file. + * + * @param {BufferEncoding} [encoding='utf8'] If `file.value` is a buffer, `encoding` is used to serialize buffers. + * @returns {string} + */ + toString(encoding) { + // @ts-expect-error string’s don’t accept the parameter, but buffers do. + return (this.value || '').toString(encoding) + } -convert$4.gray.lab = function (gray) { - return [gray[0], 0, 0]; -}; + /** + * Create a message and associates it w/ the file. + * + * @param {string|Error} reason Reason for message (`string` or `Error`). Uses the stack and message of the error if given. + * @param {Node|Position|Point} [place] Place at which the message occurred in a file (`Node`, `Position`, or `Point`, optional). + * @param {string} [origin] Place in code the message originates from (`string`, optional). + * @returns {VFileMessage} + */ + message(reason, place, origin) { + const message = new VFileMessage(reason, place, origin); -convert$4.gray.hex = function (gray) { - const val = Math.round(gray[0] / 100 * 255) & 0xFF; - const integer = (val << 16) + (val << 8) + val; + if (this.path) { + message.name = this.path + ':' + message.name; + message.file = this.path; + } - const string = integer.toString(16).toUpperCase(); - return '000000'.substring(string.length) + string; -}; + message.fatal = false; -convert$4.rgb.gray = function (rgb) { - const val = (rgb[0] + rgb[1] + rgb[2]) / 3; - return [val / 255 * 100]; -}; + this.messages.push(message); -const conversions$4 = conversions$5; + return message + } -/* - This function routes a model to all other models. + /** + * Info: create a message, associate it with the file, and mark the fatality + * as `null`. + * Calls `message()` internally. + * + * @param {string|Error} reason Reason for message (`string` or `Error`). Uses the stack and message of the error if given. + * @param {Node|Position|Point} [place] Place at which the message occurred in a file (`Node`, `Position`, or `Point`, optional). + * @param {string} [origin] Place in code the message originates from (`string`, optional). + * @returns {VFileMessage} + */ + info(reason, place, origin) { + const message = this.message(reason, place, origin); - all functions that are routed have a property `.conversion` attached - to the returned synthetic function. This property is an array - of strings, each with the steps in between the 'from' and 'to' - color models (inclusive). + message.fatal = null; - conversions that are not possible simply are not included. -*/ + return message + } -function buildGraph$1() { - const graph = {}; - // https://jsperf.com/object-keys-vs-for-in-with-closure/3 - const models = Object.keys(conversions$4); + /** + * Fail: create a message, associate it with the file, mark the fatality as + * `true`. + * Note: fatal errors mean a file is no longer processable. + * Calls `message()` internally. + * + * @param {string|Error} reason Reason for message (`string` or `Error`). Uses the stack and message of the error if given. + * @param {Node|Position|Point} [place] Place at which the message occurred in a file (`Node`, `Position`, or `Point`, optional). + * @param {string} [origin] Place in code the message originates from (`string`, optional). + * @returns {never} + */ + fail(reason, place, origin) { + const message = this.message(reason, place, origin); - for (let len = models.length, i = 0; i < len; i++) { - graph[models[i]] = { - // http://jsperf.com/1-vs-infinity - // micro-opt, but this is simple. - distance: -1, - parent: null - }; - } + message.fatal = true; - return graph; + throw message + } } -// https://en.wikipedia.org/wiki/Breadth-first_search -function deriveBFS$1(fromModel) { - const graph = buildGraph$1(); - const queue = [fromModel]; // Unshift -> queue -> pop - - graph[fromModel].distance = 0; - - while (queue.length) { - const current = queue.pop(); - const adjacents = Object.keys(conversions$4[current]); - - for (let len = adjacents.length, i = 0; i < len; i++) { - const adjacent = adjacents[i]; - const node = graph[adjacent]; - - if (node.distance === -1) { - node.distance = graph[current].distance + 1; - node.parent = current; - queue.unshift(adjacent); - } - } - } +/** + * Assert that `part` is not a path (as in, does not contain `path.sep`). + * + * @param {string|undefined} part + * @param {string} name + * @returns {void} + */ +function assertPart(part, name) { + if (part && part.includes(path$1.sep)) { + throw new Error( + '`' + name + '` cannot be a path: did not expect `' + path$1.sep + '`' + ) + } +} - return graph; +/** + * Assert that `part` is not empty. + * + * @param {string|undefined} part + * @param {string} name + * @returns {asserts part is string} + */ +function assertNonEmpty(part, name) { + if (!part) { + throw new Error('`' + name + '` cannot be empty') + } } -function link$2(from, to) { - return function (args) { - return to(from(args)); - }; +/** + * Assert `path` exists. + * + * @param {string|undefined} path + * @param {string} name + * @returns {asserts path is string} + */ +function assertPath(path, name) { + if (!path) { + throw new Error('Setting `' + name + '` requires `path` to be set too') + } } -function wrapConversion$1(toModel, graph) { - const path = [graph[toModel].parent, toModel]; - let fn = conversions$4[graph[toModel].parent][toModel]; +/** + * @typedef {import('unist').Node} Node + * @typedef {import('vfile').VFileCompatible} VFileCompatible + * @typedef {import('vfile').VFileValue} VFileValue + * @typedef {import('..').Processor} Processor + * @typedef {import('..').Plugin} Plugin + * @typedef {import('..').Preset} Preset + * @typedef {import('..').Pluggable} Pluggable + * @typedef {import('..').PluggableList} PluggableList + * @typedef {import('..').Transformer} Transformer + * @typedef {import('..').Parser} Parser + * @typedef {import('..').Compiler} Compiler + * @typedef {import('..').RunCallback} RunCallback + * @typedef {import('..').ProcessCallback} ProcessCallback + * + * @typedef Context + * @property {Node} tree + * @property {VFile} file + */ - let cur = graph[toModel].parent; - while (graph[cur].parent) { - path.unshift(graph[cur].parent); - fn = link$2(conversions$4[graph[cur].parent][cur], fn); - cur = graph[cur].parent; - } +// Expose a frozen processor. +const unified = base().freeze(); - fn.conversion = path; - return fn; -} +const own$7 = {}.hasOwnProperty; -var route$3 = function (fromModel) { - const graph = deriveBFS$1(fromModel); - const conversion = {}; +// Function to create the first processor. +/** + * @returns {Processor} + */ +function base() { + const transformers = trough(); + /** @type {Processor['attachers']} */ + const attachers = []; + /** @type {Record} */ + let namespace = {}; + /** @type {boolean|undefined} */ + let frozen; + let freezeIndex = -1; - const models = Object.keys(graph); - for (let len = models.length, i = 0; i < len; i++) { - const toModel = models[i]; - const node = graph[toModel]; + // Data management. + // @ts-expect-error: overloads are handled. + processor.data = data; + processor.Parser = undefined; + processor.Compiler = undefined; - if (node.parent === null) { - // No possible conversion, or this node is the source model. - continue; - } + // Lock. + processor.freeze = freeze; - conversion[toModel] = wrapConversion$1(toModel, graph); - } + // Plugins. + processor.attachers = attachers; + // @ts-expect-error: overloads are handled. + processor.use = use; - return conversion; -}; + // API. + processor.parse = parse; + processor.stringify = stringify; + // @ts-expect-error: overloads are handled. + processor.run = run; + processor.runSync = runSync; + // @ts-expect-error: overloads are handled. + processor.process = process; + processor.processSync = processSync; -const conversions$3 = conversions$5; -const route$2 = route$3; + // Expose. + return processor -const convert$3 = {}; + // Create a new processor based on the processor in the current scope. + /** @type {Processor} */ + function processor() { + const destination = base(); + let index = -1; -const models$1 = Object.keys(conversions$3); + while (++index < attachers.length) { + destination.use(...attachers[index]); + } -function wrapRaw$1(fn) { - const wrappedFn = function (...args) { - const arg0 = args[0]; - if (arg0 === undefined || arg0 === null) { - return arg0; - } + destination.data(extend$1(true, {}, namespace)); - if (arg0.length > 1) { - args = arg0; - } + return destination + } - return fn(args); - }; + /** + * @param {string|Record} [key] + * @param {unknown} [value] + * @returns {unknown} + */ + function data(key, value) { + if (typeof key === 'string') { + // Set `key`. + if (arguments.length === 2) { + assertUnfrozen('data', frozen); + namespace[key] = value; + return processor + } - // Preserve .conversion property if there is one - if ('conversion' in fn) { - wrappedFn.conversion = fn.conversion; - } + // Get `key`. + return (own$7.call(namespace, key) && namespace[key]) || null + } - return wrappedFn; -} + // Set space. + if (key) { + assertUnfrozen('data', frozen); + namespace = key; + return processor + } -function wrapRounded$1(fn) { - const wrappedFn = function (...args) { - const arg0 = args[0]; + // Get space. + return namespace + } - if (arg0 === undefined || arg0 === null) { - return arg0; - } + /** @type {Processor['freeze']} */ + function freeze() { + if (frozen) { + return processor + } - if (arg0.length > 1) { - args = arg0; - } + while (++freezeIndex < attachers.length) { + const [attacher, ...options] = attachers[freezeIndex]; - const result = fn(args); - - // We're assuming the result is an array here. - // see notice in conversions.js; don't use box types - // in conversion functions. - if (typeof result === 'object') { - for (let len = result.length, i = 0; i < len; i++) { - result[i] = Math.round(result[i]); - } - } - - return result; - }; - - // Preserve .conversion property if there is one - if ('conversion' in fn) { - wrappedFn.conversion = fn.conversion; - } - - return wrappedFn; -} + if (options[0] === false) { + continue + } -models$1.forEach(fromModel => { - convert$3[fromModel] = {}; + if (options[0] === true) { + options[1] = undefined; + } - Object.defineProperty(convert$3[fromModel], 'channels', {value: conversions$3[fromModel].channels}); - Object.defineProperty(convert$3[fromModel], 'labels', {value: conversions$3[fromModel].labels}); + /** @type {Transformer|void} */ + const transformer = attacher.call(processor, ...options); - const routes = route$2(fromModel); - const routeModels = Object.keys(routes); + if (typeof transformer === 'function') { + transformers.use(transformer); + } + } - routeModels.forEach(toModel => { - const fn = routes[toModel]; + frozen = true; + freezeIndex = Number.POSITIVE_INFINITY; - convert$3[fromModel][toModel] = wrapRounded$1(fn); - convert$3[fromModel][toModel].raw = wrapRaw$1(fn); - }); -}); + return processor + } -var colorConvert$1 = convert$3; + /** + * @param {Pluggable|null|undefined} [value] + * @param {...unknown} options + * @returns {Processor} + */ + function use(value, ...options) { + /** @type {Record|undefined} */ + let settings; -(function (module) { + assertUnfrozen('use', frozen); -const wrapAnsi16 = (fn, offset) => (...args) => { - const code = fn(...args); - return `\u001B[${code + offset}m`; -}; + if (value === null || value === undefined) ; else if (typeof value === 'function') { + addPlugin(value, ...options); + } else if (typeof value === 'object') { + if (Array.isArray(value)) { + addList(value); + } else { + addPreset(value); + } + } else { + throw new TypeError('Expected usable value, not `' + value + '`') + } -const wrapAnsi256 = (fn, offset) => (...args) => { - const code = fn(...args); - return `\u001B[${38 + offset};5;${code}m`; -}; + if (settings) { + namespace.settings = Object.assign(namespace.settings || {}, settings); + } -const wrapAnsi16m = (fn, offset) => (...args) => { - const rgb = fn(...args); - return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`; -}; + return processor -const ansi2ansi = n => n; -const rgb2rgb = (r, g, b) => [r, g, b]; + /** + * @param {import('..').Pluggable} value + * @returns {void} + */ + function add(value) { + if (typeof value === 'function') { + addPlugin(value); + } else if (typeof value === 'object') { + if (Array.isArray(value)) { + const [plugin, ...options] = value; + addPlugin(plugin, ...options); + } else { + addPreset(value); + } + } else { + throw new TypeError('Expected usable value, not `' + value + '`') + } + } -const setLazyProperty = (object, property, get) => { - Object.defineProperty(object, property, { - get: () => { - const value = get(); + /** + * @param {Preset} result + * @returns {void} + */ + function addPreset(result) { + addList(result.plugins); - Object.defineProperty(object, property, { - value, - enumerable: true, - configurable: true - }); + if (result.settings) { + settings = Object.assign(settings || {}, result.settings); + } + } - return value; - }, - enumerable: true, - configurable: true - }); -}; + /** + * @param {PluggableList|null|undefined} [plugins] + * @returns {void} + */ + function addList(plugins) { + let index = -1; -/** @type {typeof import('color-convert')} */ -let colorConvert; -const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => { - if (colorConvert === undefined) { - colorConvert = colorConvert$1; - } + if (plugins === null || plugins === undefined) ; else if (Array.isArray(plugins)) { + while (++index < plugins.length) { + const thing = plugins[index]; + add(thing); + } + } else { + throw new TypeError('Expected a list of plugins, not `' + plugins + '`') + } + } - const offset = isBackground ? 10 : 0; - const styles = {}; + /** + * @param {Plugin} plugin + * @param {...unknown} [value] + * @returns {void} + */ + function addPlugin(plugin, value) { + let index = -1; + /** @type {Processor['attachers'][number]|undefined} */ + let entry; - for (const [sourceSpace, suite] of Object.entries(colorConvert)) { - const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace; - if (sourceSpace === targetSpace) { - styles[name] = wrap(identity, offset); - } else if (typeof suite === 'object') { - styles[name] = wrap(suite[targetSpace], offset); - } - } + while (++index < attachers.length) { + if (attachers[index][0] === plugin) { + entry = attachers[index]; + break + } + } - return styles; -}; + if (entry) { + if (isPlainObject(entry[1]) && isPlainObject(value)) { + value = extend$1(true, entry[1], value); + } -function assembleStyles() { - const codes = new Map(); - const styles = { - 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], - 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], - 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], - bgRedBright: [101, 49], - bgGreenBright: [102, 49], - bgYellowBright: [103, 49], - bgBlueBright: [104, 49], - bgMagentaBright: [105, 49], - bgCyanBright: [106, 49], - bgWhiteBright: [107, 49] - } - }; + entry[1] = value; + } else { + // @ts-expect-error: fine. + attachers.push([...arguments]); + } + } + } - // Alias bright black as gray (and grey) - styles.color.gray = styles.color.blackBright; - styles.bgColor.bgGray = styles.bgColor.bgBlackBright; - styles.color.grey = styles.color.blackBright; - styles.bgColor.bgGrey = styles.bgColor.bgBlackBright; + /** @type {Processor['parse']} */ + function parse(doc) { + processor.freeze(); + const file = vfile(doc); + const Parser = processor.Parser; + assertParser('parse', Parser); - for (const [groupName, group] of Object.entries(styles)) { - for (const [styleName, style] of Object.entries(group)) { - styles[styleName] = { - open: `\u001B[${style[0]}m`, - close: `\u001B[${style[1]}m` - }; + if (newable(Parser, 'parse')) { + // @ts-expect-error: `newable` checks this. + return new Parser(String(file), file).parse() + } - group[styleName] = styles[styleName]; + // @ts-expect-error: `newable` checks this. + return Parser(String(file), file) // eslint-disable-line new-cap + } - codes.set(style[0], style[1]); - } + /** @type {Processor['stringify']} */ + function stringify(node, doc) { + processor.freeze(); + const file = vfile(doc); + const Compiler = processor.Compiler; + assertCompiler('stringify', Compiler); + assertNode(node); - Object.defineProperty(styles, groupName, { - value: group, - enumerable: false - }); - } + if (newable(Compiler, 'compile')) { + // @ts-expect-error: `newable` checks this. + return new Compiler(node, file).compile() + } - Object.defineProperty(styles, 'codes', { - value: codes, - enumerable: false - }); + // @ts-expect-error: `newable` checks this. + return Compiler(node, file) // eslint-disable-line new-cap + } - styles.color.close = '\u001B[39m'; - styles.bgColor.close = '\u001B[49m'; + /** + * @param {Node} node + * @param {VFileCompatible|RunCallback} [doc] + * @param {RunCallback} [callback] + * @returns {Promise|void} + */ + function run(node, doc, callback) { + assertNode(node); + processor.freeze(); - setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false)); - setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false)); - setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false)); - setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true)); - setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true)); - setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true)); + if (!callback && typeof doc === 'function') { + callback = doc; + doc = undefined; + } - return styles; -} + if (!callback) { + return new Promise(executor) + } -// Make the export immutable -Object.defineProperty(module, 'exports', { - enumerable: true, - get: assembleStyles -}); -}(ansiStyles$2)); + executor(null, callback); -var hasFlag$4 = (flag, argv = process.argv) => { - const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--'); - const position = argv.indexOf(prefix + flag); - const terminatorPosition = argv.indexOf('--'); - return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition); -}; + /** + * @param {null|((node: Node) => void)} resolve + * @param {(error: Error) => void} reject + * @returns {void} + */ + function executor(resolve, reject) { + // @ts-expect-error: `doc` can’t be a callback anymore, we checked. + transformers.run(node, vfile(doc), done); -const os$2 = require$$0$2; -const tty = tty$1; -const hasFlag$3 = hasFlag$4; - -const {env: env$2} = process; - -let forceColor$1; -if (hasFlag$3('no-color') || - hasFlag$3('no-colors') || - hasFlag$3('color=false') || - hasFlag$3('color=never')) { - forceColor$1 = 0; -} else if (hasFlag$3('color') || - hasFlag$3('colors') || - hasFlag$3('color=true') || - hasFlag$3('color=always')) { - forceColor$1 = 1; -} - -if ('FORCE_COLOR' in env$2) { - if (env$2.FORCE_COLOR === 'true') { - forceColor$1 = 1; - } else if (env$2.FORCE_COLOR === 'false') { - forceColor$1 = 0; - } else { - forceColor$1 = env$2.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env$2.FORCE_COLOR, 10), 3); - } -} + /** + * @param {Error|null} error + * @param {Node} tree + * @param {VFile} file + * @returns {void} + */ + function done(error, tree, file) { + tree = tree || node; + if (error) { + reject(error); + } else if (resolve) { + resolve(tree); + } else { + // @ts-expect-error: `callback` is defined if `resolve` is not. + callback(null, tree, file); + } + } + } + } -function translateLevel$2(level) { - if (level === 0) { - return false; - } + /** @type {Processor['runSync']} */ + function runSync(node, file) { + /** @type {Node|undefined} */ + let result; + /** @type {boolean|undefined} */ + let complete; - return { - level, - hasBasic: true, - has256: level >= 2, - has16m: level >= 3 - }; -} + processor.run(node, file, done); -function supportsColor$2(haveStream, streamIsTTY) { - if (forceColor$1 === 0) { - return 0; - } + assertDone('runSync', 'run', complete); - if (hasFlag$3('color=16m') || - hasFlag$3('color=full') || - hasFlag$3('color=truecolor')) { - return 3; - } + // @ts-expect-error: we either bailed on an error or have a tree. + return result - if (hasFlag$3('color=256')) { - return 2; - } + /** + * @param {Error|null} [error] + * @param {Node} [tree] + * @returns {void} + */ + function done(error, tree) { + bail(error); + result = tree; + complete = true; + } + } - if (haveStream && !streamIsTTY && forceColor$1 === undefined) { - return 0; - } + /** + * @param {VFileCompatible} doc + * @param {ProcessCallback} [callback] + * @returns {Promise|undefined} + */ + function process(doc, callback) { + processor.freeze(); + assertParser('process', processor.Parser); + assertCompiler('process', processor.Compiler); - const min = forceColor$1 || 0; + if (!callback) { + return new Promise(executor) + } - if (env$2.TERM === 'dumb') { - return min; - } + executor(null, callback); - if (process.platform === 'win32') { - // Windows 10 build 10586 is the first Windows release that supports 256 colors. - // Windows 10 build 14931 is the first release that supports 16m/TrueColor. - const osRelease = os$2.release().split('.'); - if ( - Number(osRelease[0]) >= 10 && - Number(osRelease[2]) >= 10586 - ) { - return Number(osRelease[2]) >= 14931 ? 3 : 2; - } + /** + * @param {null|((file: VFile) => void)} resolve + * @param {(error?: Error|null|undefined) => void} reject + * @returns {void} + */ + function executor(resolve, reject) { + const file = vfile(doc); - return 1; - } + processor.run(processor.parse(file), file, (error, tree, file) => { + if (error || !tree || !file) { + done(error); + } else { + /** @type {unknown} */ + const result = processor.stringify(tree, file); - if ('CI' in env$2) { - if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'GITHUB_ACTIONS', 'BUILDKITE'].some(sign => sign in env$2) || env$2.CI_NAME === 'codeship') { - return 1; - } + if (result === undefined || result === null) ; else if (looksLikeAVFileValue(result)) { + file.value = result; + } else { + file.result = result; + } - return min; - } + done(error, file); + } + }); - if ('TEAMCITY_VERSION' in env$2) { - return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env$2.TEAMCITY_VERSION) ? 1 : 0; - } + /** + * @param {Error|null|undefined} [error] + * @param {VFile|undefined} [file] + * @returns {void} + */ + function done(error, file) { + if (error || !file) { + reject(error); + } else if (resolve) { + resolve(file); + } else { + // @ts-expect-error: `callback` is defined if `resolve` is not. + callback(null, file); + } + } + } + } - if (env$2.COLORTERM === 'truecolor') { - return 3; - } + /** @type {Processor['processSync']} */ + function processSync(doc) { + /** @type {boolean|undefined} */ + let complete; - if ('TERM_PROGRAM' in env$2) { - const version = parseInt((env$2.TERM_PROGRAM_VERSION || '').split('.')[0], 10); + processor.freeze(); + assertParser('processSync', processor.Parser); + assertCompiler('processSync', processor.Compiler); - switch (env$2.TERM_PROGRAM) { - case 'iTerm.app': - return version >= 3 ? 3 : 2; - case 'Apple_Terminal': - return 2; - // No default - } - } + const file = vfile(doc); - if (/-256(color)?$/i.test(env$2.TERM)) { - return 2; - } + processor.process(file, done); - if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env$2.TERM)) { - return 1; - } + assertDone('processSync', 'process', complete); - if ('COLORTERM' in env$2) { - return 1; - } + return file - return min; + /** + * @param {Error|null|undefined} [error] + * @returns {void} + */ + function done(error) { + complete = true; + bail(error); + } + } } -function getSupportLevel$1(stream) { - const level = supportsColor$2(stream, stream && stream.isTTY); - return translateLevel$2(level); +/** + * Check if `value` is a constructor. + * + * @param {unknown} value + * @param {string} name + * @returns {boolean} + */ +function newable(value, name) { + return ( + typeof value === 'function' && + // Prototypes do exist. + // type-coverage:ignore-next-line + value.prototype && + // A function with keys in its prototype is probably a constructor. + // Classes’ prototype methods are not enumerable, so we check if some value + // exists in the prototype. + // type-coverage:ignore-next-line + (keys(value.prototype) || name in value.prototype) + ) } -var supportsColor_1$1 = { - supportsColor: getSupportLevel$1, - stdout: translateLevel$2(supportsColor$2(true, tty.isatty(1))), - stderr: translateLevel$2(supportsColor$2(true, tty.isatty(2))) -}; - -const stringReplaceAll$1 = (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.substr(endIndex, index - endIndex) + substring + replacer; - endIndex = index + substringLength; - index = string.indexOf(substring, endIndex); - } while (index !== -1); - - returnValue += string.substr(endIndex); - return returnValue; -}; - -const stringEncaseCRLFWithFirstIndex$1 = (string, prefix, postfix, index) => { - let endIndex = 0; - let returnValue = ''; - do { - const gotCR = string[index - 1] === '\r'; - returnValue += string.substr(endIndex, (gotCR ? index - 1 : index) - endIndex) + prefix + (gotCR ? '\r\n' : '\n') + postfix; - endIndex = index + 1; - index = string.indexOf('\n', endIndex); - } while (index !== -1); - - returnValue += string.substr(endIndex); - return returnValue; -}; - -var util$4 = { - stringReplaceAll: stringReplaceAll$1, - stringEncaseCRLFWithFirstIndex: stringEncaseCRLFWithFirstIndex$1 -}; - -const TEMPLATE_REGEX$1 = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi; -const STYLE_REGEX$1 = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g; -const STRING_REGEX$1 = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/; -const ESCAPE_REGEX$1 = /\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi; - -const ESCAPES$1 = new Map([ - ['n', '\n'], - ['r', '\r'], - ['t', '\t'], - ['b', '\b'], - ['f', '\f'], - ['v', '\v'], - ['0', '\0'], - ['\\', '\\'], - ['e', '\u001B'], - ['a', '\u0007'] -]); - -function unescape$1(c) { - const u = c[0] === 'u'; - const bracket = c[1] === '{'; - - if ((u && !bracket && c.length === 5) || (c[0] === 'x' && c.length === 3)) { - return String.fromCharCode(parseInt(c.slice(1), 16)); - } +/** + * Check if `value` is an object with keys. + * + * @param {Record} value + * @returns {boolean} + */ +function keys(value) { + /** @type {string} */ + let key; - if (u && bracket) { - return String.fromCodePoint(parseInt(c.slice(2, -1), 16)); - } + for (key in value) { + if (own$7.call(value, key)) { + return true + } + } - return ESCAPES$1.get(c) || c; + return false } -function parseArguments$1(name, arguments_) { - const results = []; - const chunks = arguments_.trim().split(/\s*,\s*/g); - let matches; - - for (const chunk of chunks) { - const number = Number(chunk); - if (!Number.isNaN(number)) { - results.push(number); - } else if ((matches = chunk.match(STRING_REGEX$1))) { - results.push(matches[2].replace(ESCAPE_REGEX$1, (m, escape, character) => escape ? unescape$1(escape) : character)); - } else { - throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`); - } - } - - return results; +/** + * Assert a parser is available. + * + * @param {string} name + * @param {unknown} value + * @returns {asserts value is Parser} + */ +function assertParser(name, value) { + if (typeof value !== 'function') { + throw new TypeError('Cannot `' + name + '` without `Parser`') + } } -function parseStyle$1(style) { - STYLE_REGEX$1.lastIndex = 0; - - const results = []; - let matches; +/** + * Assert a compiler is available. + * + * @param {string} name + * @param {unknown} value + * @returns {asserts value is Compiler} + */ +function assertCompiler(name, value) { + if (typeof value !== 'function') { + throw new TypeError('Cannot `' + name + '` without `Compiler`') + } +} - while ((matches = STYLE_REGEX$1.exec(style)) !== null) { - const name = matches[1]; +/** + * Assert the processor is not frozen. + * + * @param {string} name + * @param {unknown} frozen + * @returns {asserts frozen is false} + */ +function assertUnfrozen(name, frozen) { + if (frozen) { + throw new Error( + 'Cannot call `' + + name + + '` on a frozen processor.\nCreate a new processor first, by calling it: use `processor()` instead of `processor`.' + ) + } +} - if (matches[2]) { - const args = parseArguments$1(name, matches[2]); - results.push([name].concat(args)); - } else { - results.push([name]); - } - } +/** + * Assert `node` is a unist node. + * + * @param {unknown} node + * @returns {asserts node is Node} + */ +function assertNode(node) { + // `isPlainObj` unfortunately uses `any` instead of `unknown`. + // type-coverage:ignore-next-line + if (!isPlainObject(node) || typeof node.type !== 'string') { + throw new TypeError('Expected node, got `' + node + '`') + // Fine. + } +} - return results; +/** + * Assert that `complete` is `true`. + * + * @param {string} name + * @param {string} asyncName + * @param {unknown} complete + * @returns {asserts complete is true} + */ +function assertDone(name, asyncName, complete) { + if (!complete) { + throw new Error( + '`' + name + '` finished async. Use `' + asyncName + '` instead' + ) + } } -function buildStyle$1(chalk, styles) { - const enabled = {}; +/** + * @param {VFileCompatible} [value] + * @returns {VFile} + */ +function vfile(value) { + return looksLikeAVFile$1(value) ? value : new VFile(value) +} - for (const layer of styles) { - for (const style of layer.styles) { - enabled[style[0]] = layer.inverse ? null : style.slice(1); - } - } +/** + * @param {VFileCompatible} [value] + * @returns {value is VFile} + */ +function looksLikeAVFile$1(value) { + return Boolean( + value && + typeof value === 'object' && + 'message' in value && + 'messages' in value + ) +} - let current = chalk; - for (const [styleName, styles] of Object.entries(enabled)) { - if (!Array.isArray(styles)) { - continue; - } +/** + * @param {unknown} [value] + * @returns {value is VFileValue} + */ +function looksLikeAVFileValue(value) { + return typeof value === 'string' || isBuffer(value) +} - if (!(styleName in current)) { - throw new Error(`Unknown Chalk style: ${styleName}`); - } +/** + * @typedef Options + * @property {boolean} [includeImageAlt=true] + */ - current = styles.length > 0 ? current[styleName](...styles) : current[styleName]; - } - - return current; -} - -var templates$1 = (chalk, temporary) => { - const styles = []; - const chunks = []; - let chunk = []; - - // eslint-disable-next-line max-params - temporary.replace(TEMPLATE_REGEX$1, (m, escapeCharacter, inverse, style, close, character) => { - if (escapeCharacter) { - chunk.push(unescape$1(escapeCharacter)); - } else if (style) { - const string = chunk.join(''); - chunk = []; - chunks.push(styles.length === 0 ? string : buildStyle$1(chalk, styles)(string)); - styles.push({inverse, styles: parseStyle$1(style)}); - } else if (close) { - if (styles.length === 0) { - throw new Error('Found extraneous } in Chalk template literal'); - } - - chunks.push(buildStyle$1(chalk, styles)(chunk.join(''))); - chunk = []; - styles.pop(); - } else { - chunk.push(character); - } - }); - - chunks.push(chunk.join('')); - - if (styles.length > 0) { - const errMessage = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`; - throw new Error(errMessage); - } - - return chunks.join(''); -}; - -const ansiStyles$1 = ansiStyles$2.exports; -const {stdout: stdoutColor, stderr: stderrColor} = supportsColor_1$1; -const { - stringReplaceAll, - stringEncaseCRLFWithFirstIndex -} = util$4; - -const {isArray: isArray$2} = Array; - -// `supportsColor.level` → `ansiStyles.color[name]` mapping -const levelMapping = [ - 'ansi', - 'ansi', - 'ansi256', - 'ansi16m' -]; +/** + * Get the text content of a node. + * Prefer the node’s plain-text fields, otherwise serialize its children, + * and if the given value is an array, serialize the nodes in it. + * + * @param {unknown} node + * @param {Options} [options] + * @returns {string} + */ +function toString(node, options) { + var {includeImageAlt = true} = options || {}; + return one(node, includeImageAlt) +} -const styles = Object.create(null); +/** + * @param {unknown} node + * @param {boolean} includeImageAlt + * @returns {string} + */ +function one(node, includeImageAlt) { + return ( + (node && + typeof node === 'object' && + // @ts-ignore looks like a literal. + (node.value || + // @ts-ignore looks like an image. + (includeImageAlt ? node.alt : '') || + // @ts-ignore looks like a parent. + ('children' in node && all(node.children, includeImageAlt)) || + (Array.isArray(node) && all(node, includeImageAlt)))) || + '' + ) +} -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'); - } +/** + * @param {Array.} values + * @param {boolean} includeImageAlt + * @returns {string} + */ +function all(values, includeImageAlt) { + /** @type {Array.} */ + var result = []; + var index = -1; - // Detect level if not set manually - const colorLevel = stdoutColor ? stdoutColor.level : 0; - object.level = options.level === undefined ? colorLevel : options.level; -}; + while (++index < values.length) { + result[index] = one(values[index], includeImageAlt); + } -class ChalkClass { - constructor(options) { - // eslint-disable-next-line no-constructor-return - return chalkFactory(options); - } + return result.join('') } -const chalkFactory = options => { - const chalk = {}; - applyOptions(chalk, options); - - chalk.template = (...arguments_) => chalkTag(chalk.template, ...arguments_); - - Object.setPrototypeOf(chalk, Chalk.prototype); - Object.setPrototypeOf(chalk.template, chalk); +/** + * Like `Array#splice`, but smarter for giant arrays. + * + * `Array#splice` takes all items to be inserted as individual argument which + * causes a stack overflow in V8 when trying to insert 100k items for instance. + * + * Otherwise, this does not return the removed items, and takes `items` as an + * array instead of rest parameters. + * + * @template {unknown} T + * @param {T[]} list + * @param {number} start + * @param {number} remove + * @param {T[]} items + * @returns {void} + */ +function splice(list, start, remove, items) { + const end = list.length; + let chunkStart = 0; + /** @type {unknown[]} */ - chalk.template.constructor = () => { - throw new Error('`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.'); - }; + let parameters; // Make start between zero and `end` (included). - chalk.template.Instance = ChalkClass; + if (start < 0) { + start = -start > end ? 0 : end + start; + } else { + start = start > end ? end : start; + } - return chalk.template; -}; + remove = remove > 0 ? remove : 0; // No need to chunk the items if there’s only a couple (10k) items. -function Chalk(options) { - return chalkFactory(options); -} + if (items.length < 10000) { + parameters = Array.from(items); + parameters.unshift(start, remove) // @ts-expect-error Hush, it’s fine. + ;[].splice.apply(list, parameters); + } else { + // Delete `remove` items starting from `start` + if (remove) [].splice.apply(list, [start, remove]); // Insert the items in chunks to not cause stack overflows. -for (const [styleName, style] of Object.entries(ansiStyles$1)) { - styles[styleName] = { - get() { - const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty); - Object.defineProperty(this, styleName, {value: builder}); - return builder; - } - }; + while (chunkStart < items.length) { + parameters = items.slice(chunkStart, chunkStart + 10000); + parameters.unshift(start, 0) // @ts-expect-error Hush, it’s fine. + ;[].splice.apply(list, parameters); + chunkStart += 10000; + start += 10000; + } + } } +/** + * Append `items` (an array) at the end of `list` (another array). + * When `list` was empty, returns `items` instead. + * + * This prevents a potentially expensive operation when `list` is empty, + * and adds items in batches to prevent V8 from hanging. + * + * @template {unknown} T + * @param {T[]} list + * @param {T[]} items + * @returns {T[]} + */ -styles.visible = { - get() { - const builder = createBuilder(this, this._styler, true); - Object.defineProperty(this, 'visible', {value: builder}); - return builder; - } -}; - -const usedModels = ['rgb', 'hex', 'keyword', 'hsl', 'hsv', 'hwb', 'ansi', 'ansi256']; +function push(list, items) { + if (list.length > 0) { + splice(list, list.length, 0, items); + return list + } -for (const model of usedModels) { - styles[model] = { - get() { - const {level} = this; - return function (...arguments_) { - const styler = createStyler(ansiStyles$1.color[levelMapping[level]][model](...arguments_), ansiStyles$1.color.close, this._styler); - return createBuilder(this, styler, this._isEmpty); - }; - } - }; + return items } -for (const model of usedModels) { - const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1); - styles[bgModel] = { - get() { - const {level} = this; - return function (...arguments_) { - const styler = createStyler(ansiStyles$1.bgColor[levelMapping[level]][model](...arguments_), ansiStyles$1.bgColor.close, this._styler); - return createBuilder(this, styler, this._isEmpty); - }; - } - }; -} +/** + * @typedef {import('micromark-util-types').NormalizedExtension} NormalizedExtension + * @typedef {import('micromark-util-types').Extension} Extension + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').HtmlExtension} HtmlExtension + */ -const proto = Object.defineProperties(() => {}, { - ...styles, - level: { - enumerable: true, - get() { - return this._generator.level; - }, - set(level) { - this._generator.level = level; - } - } -}); +const hasOwnProperty = {}.hasOwnProperty; -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; - } +/** + * Combine several syntax extensions into one. + * + * @param {Extension[]} extensions List of syntax extensions. + * @returns {NormalizedExtension} A single combined extension. + */ +function combineExtensions(extensions) { + /** @type {NormalizedExtension} */ + const all = {}; + let index = -1; - return { - open, - close, - openAll, - closeAll, - parent - }; -}; + while (++index < extensions.length) { + syntaxExtension(all, extensions[index]); + } -const createBuilder = (self, _styler, _isEmpty) => { - const builder = (...arguments_) => { - if (isArray$2(arguments_[0]) && isArray$2(arguments_[0].raw)) { - // Called as a template literal, for example: chalk.red`2 + 3 = {bold ${2+3}}` - return applyStyle(builder, chalkTag(builder, ...arguments_)); - } + return all +} - // Single argument is hot path, implicit coercion is faster than anything - // eslint-disable-next-line no-implicit-coercion - return applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' ')); - }; +/** + * Merge `extension` into `all`. + * + * @param {NormalizedExtension} all Extension to merge into. + * @param {Extension} extension Extension to merge. + * @returns {void} + */ +function syntaxExtension(all, extension) { + /** @type {string} */ + let hook; - // 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); + for (hook in extension) { + const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined; + const left = maybe || (all[hook] = {}); + const right = extension[hook]; + /** @type {string} */ + let code; - builder._generator = self; - builder._styler = _styler; - builder._isEmpty = _isEmpty; + for (code in right) { + if (!hasOwnProperty.call(left, code)) left[code] = []; + const value = right[code]; + constructs( + // @ts-expect-error Looks like a list. + left[code], + Array.isArray(value) ? value : value ? [value] : [] + ); + } + } +} - return builder; -}; +/** + * Merge `list` into `existing` (both lists of constructs). + * Mutates `existing`. + * + * @param {unknown[]} existing + * @param {unknown[]} list + * @returns {void} + */ +function constructs(existing, list) { + let index = -1; + /** @type {unknown[]} */ + const before = []; -const applyStyle = (self, string) => { - if (self.level <= 0 || !string) { - return self._isEmpty ? '' : string; - } + while (++index < list.length) { +(list[index].add === 'after' ? existing : before).push(list[index]); + } - let styler = self._styler; + splice(existing, 0, 0, before); +} - if (styler === undefined) { - return string; - } +/** + * Combine several HTML extensions into one. + * + * @param {HtmlExtension[]} htmlExtensions List of HTML extensions. + * @returns {HtmlExtension} A single combined extension. + */ +function combineHtmlExtensions(htmlExtensions) { + /** @type {HtmlExtension} */ + const handlers = {}; + let index = -1; - const {openAll, closeAll} = styler; - if (string.indexOf('\u001B') !== -1) { - 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); + while (++index < htmlExtensions.length) { + htmlExtension(handlers, htmlExtensions[index]); + } - styler = styler.parent; - } - } + return handlers +} - // 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); - } +/** + * Merge `extension` into `all`. + * + * @param {HtmlExtension} all Extension to merge into. + * @param {HtmlExtension} extension Extension to merge. + * @returns {void} + */ +function htmlExtension(all, extension) { + /** @type {string} */ + let hook; - return openAll + string + closeAll; -}; + for (hook in extension) { + const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined; + const left = maybe || (all[hook] = {}); + const right = extension[hook]; + /** @type {string} */ + let type; -let template; -const chalkTag = (chalk, ...strings) => { - const [firstString] = strings; + if (right) { + for (type in right) { + left[type] = right[type]; + } + } + } +} - if (!isArray$2(firstString) || !isArray$2(firstString.raw)) { - // If chalk() was called by itself or with a string, - // return the string itself as a string. - return strings.join(' '); - } +// This module is generated by `script/`. +// +// CommonMark handles attention (emphasis, strong) markers based on what comes +// before or after them. +// One such difference is if those characters are Unicode punctuation. +// This script is generated from the Unicode data. +const unicodePunctuationRegex = + /[!-/:-@[-`{-~\u00A1\u00A7\u00AB\u00B6\u00B7\u00BB\u00BF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\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\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\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]/; - const arguments_ = strings.slice(1); - const parts = [firstString.raw[0]]; +/** + * @typedef {import('micromark-util-types').Code} Code + */ +/** + * Check whether the character code represents an ASCII alpha (`a` through `z`, + * case insensitive). + * + * An **ASCII alpha** is an ASCII upper alpha or ASCII lower alpha. + * + * An **ASCII upper alpha** is a character in the inclusive range U+0041 (`A`) + * to U+005A (`Z`). + * + * An **ASCII lower alpha** is a character in the inclusive range U+0061 (`a`) + * to U+007A (`z`). + */ - for (let i = 1; i < firstString.length; i++) { - parts.push( - String(arguments_[i - 1]).replace(/[{}\\]/g, '\\$&'), - String(firstString.raw[i]) - ); - } +const asciiAlpha = regexCheck(/[A-Za-z]/); +/** + * Check whether the character code represents an ASCII digit (`0` through `9`). + * + * An **ASCII digit** is a character in the inclusive range U+0030 (`0`) to + * U+0039 (`9`). + */ - if (template === undefined) { - template = templates$1; - } +const asciiDigit = regexCheck(/\d/); +/** + * Check whether the character code represents an ASCII hex digit (`a` through + * `f`, case insensitive, or `0` through `9`). + * + * An **ASCII hex digit** is an ASCII digit (see `asciiDigit`), ASCII upper hex + * digit, or an ASCII lower hex digit. + * + * An **ASCII upper hex digit** is a character in the inclusive range U+0041 + * (`A`) to U+0046 (`F`). + * + * An **ASCII lower hex digit** is a character in the inclusive range U+0061 + * (`a`) to U+0066 (`f`). + */ - return template(chalk, parts.join('')); -}; +const asciiHexDigit = regexCheck(/[\dA-Fa-f]/); +/** + * Check whether the character code represents an ASCII alphanumeric (`a` + * through `z`, case insensitive, or `0` through `9`). + * + * An **ASCII alphanumeric** is an ASCII digit (see `asciiDigit`) or ASCII alpha + * (see `asciiAlpha`). + */ -Object.defineProperties(Chalk.prototype, styles); - -const chalk$1 = Chalk(); // eslint-disable-line new-cap -chalk$1.supportsColor = stdoutColor; -chalk$1.stderr = Chalk({level: stderrColor ? stderrColor.level : 0}); // eslint-disable-line new-cap -chalk$1.stderr.supportsColor = stderrColor; - -var source$1 = chalk$1; - -var chokidar = {}; - -var utils$7 = {}; - -const path$a = path$b; -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$1 = `${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: STAR$1, - START_ANCHOR -}; +const asciiAlphanumeric = regexCheck(/[\dA-Za-z]/); +/** + * Check whether the character code represents ASCII punctuation. + * + * An **ASCII punctuation** is a character in the inclusive ranges U+0021 + * EXCLAMATION MARK (`!`) to U+002F SLASH (`/`), U+003A COLON (`:`) to U+0040 AT + * SIGN (`@`), U+005B LEFT SQUARE BRACKET (`[`) to U+0060 GRAVE ACCENT + * (`` ` ``), or U+007B LEFT CURLY BRACE (`{`) to U+007E TILDE (`~`). + */ +const asciiPunctuation = regexCheck(/[!-/:-@[-`{-~]/); /** - * Windows glob regex + * Check whether the character code represents an ASCII atext. + * + * atext is an ASCII alphanumeric (see `asciiAlphanumeric`), or a character in + * the inclusive ranges U+0023 NUMBER SIGN (`#`) to U+0027 APOSTROPHE (`'`), + * U+002A ASTERISK (`*`), U+002B PLUS SIGN (`+`), U+002D DASH (`-`), U+002F + * SLASH (`/`), U+003D EQUALS TO (`=`), U+003F QUESTION MARK (`?`), U+005E + * CARET (`^`) to U+0060 GRAVE ACCENT (`` ` ``), or U+007B LEFT CURLY BRACE + * (`{`) to U+007E TILDE (`~`). + * + * See: + * **\[RFC5322]**: + * [Internet Message Format](https://tools.ietf.org/html/rfc5322). + * P. Resnick. + * IETF. */ -const WINDOWS_CHARS = { - ...POSIX_CHARS, +const asciiAtext = regexCheck(/[#-'*+\--9=?A-Z^-~]/); +/** + * Check whether a character code is an ASCII control character. + * + * An **ASCII control** is a character in the inclusive range U+0000 NULL (NUL) + * to U+001F (US), or U+007F (DEL). + * + * @param {Code} code + * @returns {code is number} + */ - 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}]|$)` -}; +function asciiControl(code) { + return ( + // Special whitespace codes (which have negative values), C0 and Control + // character DEL + code !== null && (code < 32 || code === 127) + ) +} +/** + * Check whether a character code is a markdown line ending (see + * `markdownLineEnding`) or markdown space (see `markdownSpace`). + * + * @param {Code} code + * @returns {code is number} + */ +function markdownLineEndingOrSpace(code) { + return code !== null && (code < 0 || code === 32) +} /** - * 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' -}; + * Check whether a character code is a markdown line ending. + * + * A **markdown line ending** is the virtual characters M-0003 CARRIAGE RETURN + * LINE FEED (CRLF), M-0004 LINE FEED (LF) and M-0005 CARRIAGE RETURN (CR). + * + * In micromark, the actual character U+000A LINE FEED (LF) and U+000D CARRIAGE + * RETURN (CR) are replaced by these virtual characters depending on whether + * they occurred together. + * + * @param {Code} code + * @returns {code is number} + */ -var constants$5 = { - 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: { - '***': '*', - '**/**': '**', - '**/**/**': '**' - }, +function markdownLineEnding(code) { + return code !== null && code < -2 +} +/** + * Check whether a character code is a markdown space. + * + * A **markdown space** is the concrete character U+0020 SPACE (SP) and the + * virtual characters M-0001 VIRTUAL SPACE (VS) and M-0002 HORIZONTAL TAB (HT). + * + * In micromark, the actual character U+0009 CHARACTER TABULATION (HT) is + * replaced by one M-0002 HORIZONTAL TAB (HT) and between 0 and 3 M-0001 VIRTUAL + * SPACE (VS) characters, depending on the column at which the tab occurred. + * + * @param {Code} code + * @returns {code is number} + */ - // 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, +function markdownSpace(code) { + return code === -2 || code === -1 || code === 32 +} +/** + * Check whether the character code represents Unicode whitespace. + * + * Note that this does handle micromark specific markdown whitespace characters. + * See `markdownLineEndingOrSpace` to check that. + * + * A **Unicode whitespace** is a character in the Unicode `Zs` (Separator, + * Space) category, or U+0009 CHARACTER TABULATION (HT), U+000A LINE FEED (LF), + * U+000C (FF), or U+000D CARRIAGE RETURN (CR) (**\[UNICODE]**). + * + * See: + * **\[UNICODE]**: + * [The Unicode Standard](https://www.unicode.org/versions/). + * Unicode Consortium. + */ - /** - * Create EXTGLOB_CHARS - */ +const unicodeWhitespace = regexCheck(/\s/); +/** + * Check whether the character code represents Unicode punctuation. + * + * A **Unicode punctuation** is a character in the Unicode `Pc` (Punctuation, + * Connector), `Pd` (Punctuation, Dash), `Pe` (Punctuation, Close), `Pf` + * (Punctuation, Final quote), `Pi` (Punctuation, Initial quote), `Po` + * (Punctuation, Other), or `Ps` (Punctuation, Open) categories, or an ASCII + * punctuation (see `asciiPunctuation`). + * + * See: + * **\[UNICODE]**: + * [The Unicode Standard](https://www.unicode.org/versions/). + * Unicode Consortium. + */ +// Size note: removing ASCII from the regex and using `asciiPunctuation` here +// In fact adds to the bundle size. - 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: ')' } - }; - }, +const unicodePunctuation = regexCheck(unicodePunctuationRegex); +/** + * Create a code check from a regex. + * + * @param {RegExp} regex + * @returns {(code: Code) => code is number} + */ +function regexCheck(regex) { + return check /** - * Create GLOB_CHARS + * Check whether a code matches the bound regex. + * + * @param {Code} code Character code + * @returns {code is number} Whether the character code matches the bound regex */ - globChars(win32) { - return win32 === true ? WINDOWS_CHARS : POSIX_CHARS; + function check(code) { + return code !== null && regex.test(String.fromCharCode(code)) } -}; - -(function (exports) { - -const path = path$b; -const win32 = process.platform === 'win32'; -const { - REGEX_BACKSLASH, - REGEX_REMOVE_BACKSLASH, - REGEX_SPECIAL_CHARS, - REGEX_SPECIAL_CHARS_GLOBAL -} = constants$5; - -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; -}; +/** + * @typedef {import('micromark-util-types').Effects} Effects + * @typedef {import('micromark-util-types').State} State + */ +/** + * @param {Effects} effects + * @param {State} ok + * @param {string} type + * @param {number} [max=Infinity] + * @returns {State} + */ -exports.isWindows = options => { - if (options && typeof options.windows === 'boolean') { - return options.windows; - } - return win32 === true || path.sep === '\\'; -}; +function factorySpace(effects, ok, type, max) { + const limit = max ? max - 1 : Number.POSITIVE_INFINITY; + let size = 0; + return start + /** @type {State} */ -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)}`; -}; + function start(code) { + if (markdownSpace(code)) { + effects.enter(type); + return prefix(code) + } -exports.removePrefix = (input, state = {}) => { - let output = input; - if (output.startsWith('./')) { - output = output.slice(2); - state.prefix = './'; + return ok(code) } - return output; -}; - -exports.wrapOutput = (input, state = {}, options = {}) => { - const prepend = options.contains ? '' : '^'; - const append = options.contains ? '' : '$'; + /** @type {State} */ - let output = `${prepend}(?:${input})${append}`; - if (state.negated === true) { - output = `(?:^(?!${output}).*$)`; - } - return output; -}; -}(utils$7)); - -const utils$6 = utils$7; -const { - CHAR_ASTERISK: CHAR_ASTERISK$1, /* * */ - CHAR_AT, /* @ */ - CHAR_BACKWARD_SLASH, /* \ */ - CHAR_COMMA: CHAR_COMMA$2, /* , */ - CHAR_DOT: CHAR_DOT$1, /* . */ - CHAR_EXCLAMATION_MARK, /* ! */ - CHAR_FORWARD_SLASH, /* / */ - CHAR_LEFT_CURLY_BRACE: CHAR_LEFT_CURLY_BRACE$1, /* { */ - CHAR_LEFT_PARENTHESES: CHAR_LEFT_PARENTHESES$1, /* ( */ - CHAR_LEFT_SQUARE_BRACKET: CHAR_LEFT_SQUARE_BRACKET$2, /* [ */ - CHAR_PLUS, /* + */ - CHAR_QUESTION_MARK, /* ? */ - CHAR_RIGHT_CURLY_BRACE: CHAR_RIGHT_CURLY_BRACE$1, /* } */ - CHAR_RIGHT_PARENTHESES: CHAR_RIGHT_PARENTHESES$1, /* ) */ - CHAR_RIGHT_SQUARE_BRACKET: CHAR_RIGHT_SQUARE_BRACKET$2 /* ] */ -} = constants$5; - -const isPathSeparator = code => { - return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; -}; + function prefix(code) { + if (markdownSpace(code) && size++ < limit) { + effects.consume(code); + return prefix + } -const depth = token => { - if (token.isPrefix !== true) { - token.depth = token.isGlobstar ? Infinity : 1; + effects.exit(type); + return ok(code) } -}; +} /** - * 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 + * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct + * @typedef {import('micromark-util-types').Initializer} Initializer + * @typedef {import('micromark-util-types').Token} Token + * @typedef {import('micromark-util-types').State} State */ -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 = []; +/** @type {InitialConstruct} */ +const content$1 = { + tokenize: initializeContent +}; +/** @type {Initializer} */ - 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; +function initializeContent(effects) { + const contentStart = effects.attempt( + this.parser.constructs.contentInitial, + afterContentStartConstruct, + paragraphInitial + ); + /** @type {Token} */ - if (code === CHAR_BACKWARD_SLASH) { - backslashes = token.backslashes = true; - code = advance(); + let previous; + return contentStart + /** @type {State} */ - if (code === CHAR_LEFT_CURLY_BRACE$1) { - braceEscaped = true; - } - continue; + function afterContentStartConstruct(code) { + if (code === null) { + effects.consume(code); + return } - if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE$1) { - braces++; + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return factorySpace(effects, contentStart, 'linePrefix') + } + /** @type {State} */ - while (eos() !== true && (code = advance())) { - if (code === CHAR_BACKWARD_SLASH) { - backslashes = token.backslashes = true; - advance(); - continue; - } + function paragraphInitial(code) { + effects.enter('paragraph'); + return lineStart(code) + } + /** @type {State} */ - if (code === CHAR_LEFT_CURLY_BRACE$1) { - braces++; - continue; - } + function lineStart(code) { + const token = effects.enter('chunkText', { + contentType: 'text', + previous + }); - if (braceEscaped !== true && code === CHAR_DOT$1 && (code = advance()) === CHAR_DOT$1) { - isBrace = token.isBrace = true; - isGlob = token.isGlob = true; - finished = true; + if (previous) { + previous.next = token; + } - if (scanToEnd === true) { - continue; - } + previous = token; + return data(code) + } + /** @type {State} */ - break; - } + function data(code) { + if (code === null) { + effects.exit('chunkText'); + effects.exit('paragraph'); + effects.consume(code); + return + } - if (braceEscaped !== true && code === CHAR_COMMA$2) { - isBrace = token.isBrace = true; - isGlob = token.isGlob = true; - finished = true; + if (markdownLineEnding(code)) { + effects.consume(code); + effects.exit('chunkText'); + return lineStart + } // Data. - if (scanToEnd === true) { - continue; - } + effects.consume(code); + return data + } +} - break; - } +/** + * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct + * @typedef {import('micromark-util-types').Initializer} Initializer + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').Token} Token + * @typedef {import('micromark-util-types').State} State + * @typedef {import('micromark-util-types').Point} Point + */ +/** @type {InitialConstruct} */ - if (code === CHAR_RIGHT_CURLY_BRACE$1) { - braces--; +const document$1 = { + tokenize: initializeDocument +}; +/** @type {Construct} */ - if (braces === 0) { - braceEscaped = false; - isBrace = token.isBrace = true; - finished = true; - break; - } - } - } +const containerConstruct = { + tokenize: tokenizeContainer +}; +/** @type {Initializer} */ - if (scanToEnd === true) { - continue; - } +function initializeDocument(effects) { + const self = this; + /** @type {StackItem[]} */ - break; - } + const stack = []; + let continued = 0; + /** @type {TokenizeContext|undefined} */ - if (code === CHAR_FORWARD_SLASH) { - slashes.push(index); - tokens.push(token); - token = { value: '', depth: 0, isGlob: false }; + let childFlow; + /** @type {Token|undefined} */ - if (finished === true) continue; - if (prev === CHAR_DOT$1 && index === (start + 1)) { - start += 2; - continue; - } + let childToken; + /** @type {number} */ - lastIndex = index + 1; - continue; - } + let lineStartOffset; + return start + /** @type {State} */ - if (opts.noext !== true) { - const isExtglobChar = code === CHAR_PLUS - || code === CHAR_AT - || code === CHAR_ASTERISK$1 - || code === CHAR_QUESTION_MARK - || code === CHAR_EXCLAMATION_MARK; + function start(code) { + // First we iterate through the open blocks, starting with the root + // document, and descending through last children down to the last open + // block. + // Each block imposes a condition that the line must satisfy if the block is + // to remain open. + // For example, a block quote requires a `>` character. + // A paragraph requires a non-blank line. + // In this phase we may match all or just some of the open blocks. + // But we cannot close unmatched blocks yet, because we may have a lazy + // continuation line. + if (continued < stack.length) { + const item = stack[continued]; + self.containerState = item[1]; + return effects.attempt( + item[0].continuation, + documentContinue, + checkNewContainers + )(code) + } // Done. - if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES$1) { - isGlob = token.isGlob = true; - isExtglob = token.isExtglob = true; - finished = true; - if (code === CHAR_EXCLAMATION_MARK && index === start) { - negatedExtglob = true; - } + return checkNewContainers(code) + } + /** @type {State} */ - if (scanToEnd === true) { - while (eos() !== true && (code = advance())) { - if (code === CHAR_BACKWARD_SLASH) { - backslashes = token.backslashes = true; - code = advance(); - continue; - } + function documentContinue(code) { + continued++; // Note: this field is called `_closeFlow` but it also closes containers. + // Perhaps a good idea to rename it but it’s already used in the wild by + // extensions. - if (code === CHAR_RIGHT_PARENTHESES$1) { - isGlob = token.isGlob = true; - finished = true; - break; - } - } - continue; - } - break; - } - } + if (self.containerState._closeFlow) { + self.containerState._closeFlow = undefined; - if (code === CHAR_ASTERISK$1) { - if (prev === CHAR_ASTERISK$1) isGlobstar = token.isGlobstar = true; - isGlob = token.isGlob = true; - finished = true; + if (childFlow) { + closeFlow(); + } // Note: this algorithm for moving events around is similar to the + // algorithm when dealing with lazy lines in `writeToChild`. - if (scanToEnd === true) { - continue; - } - break; - } + const indexBeforeExits = self.events.length; + let indexBeforeFlow = indexBeforeExits; + /** @type {Point|undefined} */ - if (code === CHAR_QUESTION_MARK) { - isGlob = token.isGlob = true; - finished = true; + let point; // Find the flow chunk. - if (scanToEnd === true) { - continue; + while (indexBeforeFlow--) { + if ( + self.events[indexBeforeFlow][0] === 'exit' && + self.events[indexBeforeFlow][1].type === 'chunkFlow' + ) { + point = self.events[indexBeforeFlow][1].end; + break + } } - break; - } - if (code === CHAR_LEFT_SQUARE_BRACKET$2) { - while (eos() !== true && (next = advance())) { - if (next === CHAR_BACKWARD_SLASH) { - backslashes = token.backslashes = true; - advance(); - continue; - } + exitContainers(continued); // Fix positions. - if (next === CHAR_RIGHT_SQUARE_BRACKET$2) { - isBracket = token.isBracket = true; - isGlob = token.isGlob = true; - finished = true; - break; - } - } + let index = indexBeforeExits; - if (scanToEnd === true) { - continue; - } + while (index < self.events.length) { + self.events[index][1].end = Object.assign({}, point); + index++; + } // Inject the exits earlier (they’re still also at the end). - break; - } + splice( + self.events, + indexBeforeFlow + 1, + 0, + self.events.slice(indexBeforeExits) + ); // Discard the duplicate exits. - if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) { - negated = token.negated = true; - start++; - continue; + self.events.length = index; + return checkNewContainers(code) } - if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES$1) { - isGlob = token.isGlob = true; - - if (scanToEnd === true) { - while (eos() !== true && (code = advance())) { - if (code === CHAR_LEFT_PARENTHESES$1) { - backslashes = token.backslashes = true; - code = advance(); - continue; - } + return start(code) + } + /** @type {State} */ - if (code === CHAR_RIGHT_PARENTHESES$1) { - finished = true; - break; - } - } - continue; - } - break; - } + function checkNewContainers(code) { + // Next, after consuming the continuation markers for existing blocks, we + // look for new block starts (e.g. `>` for a block quote). + // If we encounter a new block start, we close any blocks unmatched in + // step 1 before creating the new block as a child of the last matched + // block. + if (continued === stack.length) { + // No need to `check` whether there’s a container, of `exitContainers` + // would be moot. + // We can instead immediately `attempt` to parse one. + if (!childFlow) { + return documentContinued(code) + } // If we have concrete content, such as block HTML or fenced code, + // we can’t have containers “pierce” into them, so we can immediately + // start. - if (isGlob === true) { - finished = true; + if (childFlow.currentConstruct && childFlow.currentConstruct.concrete) { + return flowStart(code) + } // If we do have flow, it could still be a blank line, + // but we’d be interrupting it w/ a new container if there’s a current + // construct. - if (scanToEnd === true) { - continue; - } + self.interrupt = Boolean(childFlow.currentConstruct); + } // Check if there is a new container. - break; - } + self.containerState = {}; + return effects.check( + containerConstruct, + thereIsANewContainer, + thereIsNoNewContainer + )(code) } + /** @type {State} */ - if (opts.noext === true) { - isExtglob = false; - isGlob = false; + function thereIsANewContainer(code) { + if (childFlow) closeFlow(); + exitContainers(continued); + return documentContinued(code) } + /** @type {State} */ - let base = str; - let prefix = ''; - let glob = ''; + function thereIsNoNewContainer(code) { + self.parser.lazy[self.now().line] = continued !== stack.length; + lineStartOffset = self.now().offset; + return flowStart(code) + } + /** @type {State} */ - if (start > 0) { - prefix = str.slice(0, start); - str = str.slice(start); - lastIndex -= start; + function documentContinued(code) { + // Try new containers. + self.containerState = {}; + return effects.attempt( + containerConstruct, + containerContinue, + flowStart + )(code) } + /** @type {State} */ - 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; + function containerContinue(code) { + continued++; + stack.push([self.currentConstruct, self.containerState]); // Try another. + + return documentContinued(code) } + /** @type {State} */ - if (base && base !== '' && base !== '/' && base !== str) { - if (isPathSeparator(base.charCodeAt(base.length - 1))) { - base = base.slice(0, -1); + function flowStart(code) { + if (code === null) { + if (childFlow) closeFlow(); + exitContainers(0); + effects.consume(code); + return } - } - if (opts.unescape === true) { - if (glob) glob = utils$6.removeBackslashes(glob); + childFlow = childFlow || self.parser.flow(self.now()); + effects.enter('chunkFlow', { + contentType: 'flow', + previous: childToken, + _tokenizer: childFlow + }); + return flowContinue(code) + } + /** @type {State} */ - if (base && backslashes === true) { - base = utils$6.removeBackslashes(base); + function flowContinue(code) { + if (code === null) { + writeToChild(effects.exit('chunkFlow'), true); + exitContainers(0); + effects.consume(code); + return } - } - const state = { - prefix, - input, - start, - base, - glob, - isBrace, - isBracket, - isGlob, - isExtglob, - isGlobstar, - negated, - negatedExtglob - }; + if (markdownLineEnding(code)) { + effects.consume(code); + writeToChild(effects.exit('chunkFlow')); // Get ready for the next line. - if (opts.tokens === true) { - state.maxDepth = 0; - if (!isPathSeparator(code)) { - tokens.push(token); + continued = 0; + self.interrupt = undefined; + return start } - state.tokens = tokens; + + effects.consume(code); + return flowContinue } + /** + * @param {Token} token + * @param {boolean} [eof] + * @returns {void} + */ + + function writeToChild(token, eof) { + const stream = self.sliceStream(token); + if (eof) stream.push(null); + token.previous = childToken; + if (childToken) childToken.next = token; + childToken = token; + childFlow.defineSkip(token.start); + childFlow.write(stream); // Alright, so we just added a lazy line: + // + // ```markdown + // > a + // b. + // + // Or: + // + // > ~~~c + // d + // + // Or: + // + // > | e | + // f + // ``` + // + // The construct in the second example (fenced code) does not accept lazy + // lines, so it marked itself as done at the end of its first line, and + // then the content construct parses `d`. + // Most constructs in markdown match on the first line: if the first line + // forms a construct, a non-lazy line can’t “unmake” it. + // + // The construct in the third example is potentially a GFM table, and + // those are *weird*. + // It *could* be a table, from the first line, if the following line + // matches a condition. + // In this case, that second line is lazy, which “unmakes” the first line + // and turns the whole into one content block. + // + // We’ve now parsed the non-lazy and the lazy line, and can figure out + // whether the lazy line started a new flow block. + // If it did, we exit the current containers between the two flow blocks. - if (opts.parts === true || opts.tokens === true) { - let prevIndex; + if (self.parser.lazy[token.start.line]) { + let index = childFlow.events.length; - 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; + while (index--) { + if ( + // The token starts before the line ending… + childFlow.events[index][1].start.offset < lineStartOffset && + (!childFlow.events[index][1].end || // …or ends after it. + childFlow.events[index][1].end.offset > lineStartOffset) + ) { + // Exit: there’s still something open, which means it’s a lazy line + // part of something. + return + } + } // Note: this algorithm for moving events around is similar to the + // algorithm when closing flow in `documentContinue`. + + const indexBeforeExits = self.events.length; + let indexBeforeFlow = indexBeforeExits; + /** @type {boolean|undefined} */ + + let seen; + /** @type {Point|undefined} */ + + let point; // Find the previous chunk (the one before the lazy line). + + while (indexBeforeFlow--) { + if ( + self.events[indexBeforeFlow][0] === 'exit' && + self.events[indexBeforeFlow][1].type === 'chunkFlow' + ) { + if (seen) { + point = self.events[indexBeforeFlow][1].end; + break + } + + seen = true; } - depth(tokens[idx]); - state.maxDepth += tokens[idx].depth; - } - if (idx !== 0 || value !== '') { - parts.push(value); } - prevIndex = i; + + exitContainers(continued); // Fix positions. + + index = indexBeforeExits; + + while (index < self.events.length) { + self.events[index][1].end = Object.assign({}, point); + index++; + } // Inject the exits earlier (they’re still also at the end). + + splice( + self.events, + indexBeforeFlow + 1, + 0, + self.events.slice(indexBeforeExits) + ); // Discard the duplicate exits. + + self.events.length = index; } + } + /** + * @param {number} size + * @returns {void} + */ - if (prevIndex && prevIndex + 1 < input.length) { - const value = input.slice(prevIndex + 1); - parts.push(value); + function exitContainers(size) { + let index = stack.length; // Exit open containers. - if (opts.tokens) { - tokens[tokens.length - 1].value = value; - depth(tokens[tokens.length - 1]); - state.maxDepth += tokens[tokens.length - 1].depth; - } + while (index-- > size) { + const entry = stack[index]; + self.containerState = entry[1]; + entry[0].exit.call(self, effects); } - state.slashes = slashes; - state.parts = parts; + stack.length = size; } - return state; -}; + function closeFlow() { + childFlow.write([null]); + childToken = undefined; + childFlow = undefined; + self.containerState._closeFlow = undefined; + } +} +/** @type {Tokenizer} */ -var scan_1 = scan$1; +function tokenizeContainer(effects, ok, nok) { + return factorySpace( + effects, + effects.attempt(this.parser.constructs.document, ok, nok), + 'linePrefix', + this.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4 + ) +} -const constants$4 = constants$5; -const utils$5 = utils$7; +/** + * @typedef {import('micromark-util-types').Code} Code + */ /** - * Constants + * Classify whether a character code represents whitespace, punctuation, or + * something else. + * + * Used for attention (emphasis, strong), whose sequences can open or close + * based on the class of surrounding characters. + * + * Note that eof (`null`) is seen as whitespace. + * + * @param {Code} code + * @returns {number|undefined} */ +function classifyCharacter(code) { + if ( + code === null || + markdownLineEndingOrSpace(code) || + unicodeWhitespace(code) + ) { + return 1 + } -const { - MAX_LENGTH: MAX_LENGTH$4, - POSIX_REGEX_SOURCE, - REGEX_NON_SPECIAL_CHARS, - REGEX_SPECIAL_CHARS_BACKREF, - REPLACEMENTS -} = constants$4; + if (unicodePunctuation(code)) { + return 2 + } +} /** - * Helpers + * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext + * @typedef {import('micromark-util-types').Event} Event + * @typedef {import('micromark-util-types').Resolver} Resolver */ -const expandRange = (args, options) => { - if (typeof options.expandRange === 'function') { - return options.expandRange(...args, options); - } +/** + * Call all `resolveAll`s. + * + * @param {{resolveAll?: Resolver}[]} constructs + * @param {Event[]} events + * @param {TokenizeContext} context + * @returns {Event[]} + */ +function resolveAll(constructs, events, context) { + /** @type {Resolver[]} */ + const called = []; + let index = -1; - args.sort(); - const value = `[${args.join('-')}]`; + while (++index < constructs.length) { + const resolve = constructs[index].resolveAll; - try { - /* eslint-disable-next-line no-new */ - new RegExp(value); - } catch (ex) { - return args.map(v => utils$5.escapeRegex(v)).join('..'); + if (resolve && !called.includes(resolve)) { + events = resolve(events, context); + called.push(resolve); + } } - return value; -}; + return events +} /** - * Create the message for a syntax error + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').Resolver} Resolver + * @typedef {import('micromark-util-types').State} State + * @typedef {import('micromark-util-types').Token} Token + * @typedef {import('micromark-util-types').Event} Event + * @typedef {import('micromark-util-types').Code} Code + * @typedef {import('micromark-util-types').Point} Point */ -const syntaxError$1 = (type, char) => { - return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`; +/** @type {Construct} */ +const attention = { + name: 'attention', + tokenize: tokenizeAttention, + resolveAll: resolveAllAttention }; - /** - * Parse the given input string. - * @param {String} input - * @param {Object} options - * @return {Object} + * Take all events and resolve attention to emphasis or strong. + * + * @type {Resolver} */ -const parse$e = (input, options) => { - if (typeof input !== 'string') { - throw new TypeError('Expected a string'); - } - - input = REPLACEMENTS[input] || input; +function resolveAllAttention(events, context) { + let index = -1; + /** @type {number} */ - const opts = { ...options }; - const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH$4, opts.maxLength) : MAX_LENGTH$4; + let open; + /** @type {Token} */ - 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$5.isWindows(options); - - // create constants based on platform, for windows or posix - const PLATFORM_CHARS = constants$4.globChars(win32); - const EXTGLOB_CHARS = constants$4.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}).)*?)`; - }; + let group; + /** @type {Token} */ - 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 - }; + let text; + /** @type {Token} */ - input = utils$5.removePrefix(input, state); - len = input.length; + let openingSequence; + /** @type {Token} */ - const extglobs = []; - const braces = []; - const stack = []; - let prev = bos; - let value; + let closingSequence; + /** @type {number} */ - /** - * Tokenizing helpers - */ + let use; + /** @type {Event[]} */ - 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; - }; + let nextEvents; + /** @type {number} */ - const append = token => { - state.output += token.output != null ? token.output : token.value; - consume(token.value); - }; + let offset; // Walk through all events. + // + // Note: performance of this is fine on an mb of normal markdown, but it’s + // a bottleneck for malicious stuff. - const negate = () => { - let count = 1; + while (++index < events.length) { + // Find a token that can close. + if ( + events[index][0] === 'enter' && + events[index][1].type === 'attentionSequence' && + events[index][1]._close + ) { + open = index; // Now walk back to find an opener. - while (peek() === '!' && (peek(2) !== '(' || peek(3) === '?')) { - advance(); - state.start++; - count++; - } + while (open--) { + // Find a token that can open the closer. + if ( + events[open][0] === 'exit' && + events[open][1].type === 'attentionSequence' && + events[open][1]._open && // If the markers are the same: + context.sliceSerialize(events[open][1]).charCodeAt(0) === + context.sliceSerialize(events[index][1]).charCodeAt(0) + ) { + // If the opening can close or the closing can open, + // and the close size *is not* a multiple of three, + // but the sum of the opening and closing size *is* multiple of three, + // then don’t match. + if ( + (events[open][1]._close || events[index][1]._open) && + (events[index][1].end.offset - events[index][1].start.offset) % 3 && + !( + (events[open][1].end.offset - + events[open][1].start.offset + + events[index][1].end.offset - + events[index][1].start.offset) % + 3 + ) + ) { + continue + } // Number of markers to use from the sequence. - if (count % 2 === 0) { - return false; - } + use = + events[open][1].end.offset - events[open][1].start.offset > 1 && + events[index][1].end.offset - events[index][1].start.offset > 1 + ? 2 + : 1; + const start = Object.assign({}, events[open][1].end); + const end = Object.assign({}, events[index][1].start); + movePoint(start, -use); + movePoint(end, use); + openingSequence = { + type: use > 1 ? 'strongSequence' : 'emphasisSequence', + start, + end: Object.assign({}, events[open][1].end) + }; + closingSequence = { + type: use > 1 ? 'strongSequence' : 'emphasisSequence', + start: Object.assign({}, events[index][1].start), + end + }; + text = { + type: use > 1 ? 'strongText' : 'emphasisText', + start: Object.assign({}, events[open][1].end), + end: Object.assign({}, events[index][1].start) + }; + group = { + type: use > 1 ? 'strong' : 'emphasis', + start: Object.assign({}, openingSequence.start), + end: Object.assign({}, closingSequence.end) + }; + events[open][1].end = Object.assign({}, openingSequence.start); + events[index][1].start = Object.assign({}, closingSequence.end); + nextEvents = []; // If there are more markers in the opening, add them before. - state.negated = true; - state.start++; - return true; - }; + if (events[open][1].end.offset - events[open][1].start.offset) { + nextEvents = push(nextEvents, [ + ['enter', events[open][1], context], + ['exit', events[open][1], context] + ]); + } // Opening. - const increment = type => { - state[type]++; - stack.push(type); - }; + nextEvents = push(nextEvents, [ + ['enter', group, context], + ['enter', openingSequence, context], + ['exit', openingSequence, context], + ['enter', text, context] + ]); // Between. - const decrement = type => { - state[type]--; - stack.pop(); - }; + nextEvents = push( + nextEvents, + resolveAll( + context.parser.constructs.insideSpan.null, + events.slice(open + 1, index), + context + ) + ); // Closing. - /** - * 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. - */ + nextEvents = push(nextEvents, [ + ['exit', text, context], + ['enter', closingSequence, context], + ['exit', closingSequence, context], + ['exit', group, context] + ]); // If there are more markers in the closing, add them after. - 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 (events[index][1].end.offset - events[index][1].start.offset) { + offset = 2; + nextEvents = push(nextEvents, [ + ['enter', events[index][1], context], + ['exit', events[index][1], context] + ]); + } else { + offset = 0; + } - 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; + splice(events, open - 1, index - open + 3, nextEvents); + index = open + nextEvents.length - offset - 2; + break + } } } + } // Remove remaining sequences. - if (extglobs.length && tok.type !== 'paren') { - extglobs[extglobs.length - 1].inner += tok.value; - } + index = -1; - 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; + while (++index < events.length) { + if (events[index][1].type === 'attentionSequence') { + events[index][1].type = 'data'; } + } - 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; + return events +} +/** @type {Tokenizer} */ - if (token.inner && token.inner.length > 1 && token.inner.includes('/')) { - extglobStar = globstar(opts); - } +function tokenizeAttention(effects, ok) { + const attentionMarkers = this.parser.constructs.attentionMarkers.null; + const previous = this.previous; + const before = classifyCharacter(previous); + /** @type {NonNullable} */ - if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) { - output = token.close = `)$))${extglobStar}`; - } + let marker; + return start + /** @type {State} */ - if (token.inner.includes('*') && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) { - output = token.close = `)${rest})${extglobStar})`; - } + function start(code) { + effects.enter('attentionSequence'); + marker = code; + return sequence(code) + } + /** @type {State} */ - if (token.prev.type === 'bos') { - state.negatedExtglob = true; - } + function sequence(code) { + if (code === marker) { + effects.consume(code); + return sequence } - push({ type: 'paren', extglob: true, value, output }); - decrement('parens'); - }; - - /** - * Fast paths - */ - - if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) { - let backslashes = false; + const token = effects.exit('attentionSequence'); + const after = classifyCharacter(code); + const open = + !after || (after === 2 && before) || attentionMarkers.includes(code); + const close = + !before || (before === 2 && after) || attentionMarkers.includes(previous); + token._open = Boolean(marker === 42 ? open : open && (before || !close)); + token._close = Boolean(marker === 42 ? close : close && (after || !open)); + return ok(code) + } +} +/** + * Move a point a bit. + * + * Note: `move` only works inside lines! It’s not possible to move past other + * chunks (replacement characters, tabs, or line endings). + * + * @param {Point} point + * @param {number} offset + * @returns {void} + */ - let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => { - if (first === '\\') { - backslashes = true; - return m; - } +function movePoint(point, offset) { + point.column += offset; + point.offset += offset; + point._bufferIndex += offset; +} - 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); - } +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State + */ - if (first === '.') { - return DOT_LITERAL.repeat(chars.length); - } +/** @type {Construct} */ +const autolink = { + name: 'autolink', + tokenize: tokenizeAutolink +}; +/** @type {Tokenizer} */ - if (first === '*') { - if (esc) { - return esc + first + (rest ? star : ''); - } - return star; - } - return esc ? m : `\\${m}`; - }); +function tokenizeAutolink(effects, ok, nok) { + let size = 1; + return start + /** @type {State} */ - if (backslashes === true) { - if (opts.unescape === true) { - output = output.replace(/\\/g, ''); - } else { - output = output.replace(/\\+/g, m => { - return m.length % 2 === 0 ? '\\\\' : (m ? '\\' : ''); - }); - } - } + function start(code) { + effects.enter('autolink'); + effects.enter('autolinkMarker'); + effects.consume(code); + effects.exit('autolinkMarker'); + effects.enter('autolinkProtocol'); + return open + } + /** @type {State} */ - if (output === input && opts.contains === true) { - state.output = input; - return state; + function open(code) { + if (asciiAlpha(code)) { + effects.consume(code); + return schemeOrEmailAtext } - state.output = utils$5.wrapOutput(output, state, options); - return state; + return asciiAtext(code) ? emailAtext(code) : nok(code) } + /** @type {State} */ - /** - * Tokenize input until we reach end-of-string - */ - - while (!eos()) { - value = advance(); + function schemeOrEmailAtext(code) { + return code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code) + ? schemeInsideOrEmailAtext(code) + : emailAtext(code) + } + /** @type {State} */ - if (value === '\u0000') { - continue; + function schemeInsideOrEmailAtext(code) { + if (code === 58) { + effects.consume(code); + return urlInside } - /** - * 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 ( + (code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code)) && + size++ < 32 + ) { + effects.consume(code); + return schemeInsideOrEmailAtext } - /** - * 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 = '^'; - } + return emailAtext(code) + } + /** @type {State} */ - prev.value += value; - append({ value }); - continue; + function urlInside(code) { + if (code === 62) { + effects.exit('autolinkProtocol'); + return end(code) } - /** - * If we're inside a quoted string, continue - * until we reach the closing double quote. - */ - - if (state.quotes === 1 && value !== '"') { - value = utils$5.escapeRegex(value); - prev.value += value; - append({ value }); - continue; + if (code === null || code === 32 || code === 60 || asciiControl(code)) { + return nok(code) } - /** - * Double quotes - */ + effects.consume(code); + return urlInside + } + /** @type {State} */ - if (value === '"') { - state.quotes = state.quotes === 1 ? 0 : 1; - if (opts.keepQuotes === true) { - push({ type: 'text', value }); - } - continue; + function emailAtext(code) { + if (code === 64) { + effects.consume(code); + size = 0; + return emailAtSignOrDot } - /** - * Parentheses - */ - - if (value === '(') { - increment('parens'); - push({ type: 'paren', value }); - continue; + if (asciiAtext(code)) { + effects.consume(code); + return emailAtext } - if (value === ')') { - if (state.parens === 0 && opts.strictBrackets === true) { - throw new SyntaxError(syntaxError$1('opening', '(')); - } + return nok(code) + } + /** @type {State} */ - const extglob = extglobs[extglobs.length - 1]; - if (extglob && state.parens === extglob.parens + 1) { - extglobClose(extglobs.pop()); - continue; - } + function emailAtSignOrDot(code) { + return asciiAlphanumeric(code) ? emailLabel(code) : nok(code) + } + /** @type {State} */ - push({ type: 'paren', value, output: state.parens ? ')' : '\\)' }); - decrement('parens'); - continue; + function emailLabel(code) { + if (code === 46) { + effects.consume(code); + size = 0; + return emailAtSignOrDot } - /** - * Square brackets - */ - - if (value === '[') { - if (opts.nobracket === true || !remaining().includes(']')) { - if (opts.nobracket !== true && opts.strictBrackets === true) { - throw new SyntaxError(syntaxError$1('closing', ']')); - } - - value = `\\${value}`; - } else { - increment('brackets'); - } - - push({ type: 'bracket', value }); - continue; + if (code === 62) { + // Exit, then change the type. + effects.exit('autolinkProtocol').type = 'autolinkEmail'; + return end(code) } - 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$1('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$5.hasRegexChars(prevValue)) { - continue; - } - - const escaped = utils$5.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; - } + return emailValue(code) + } + /** @type {State} */ - // when the user specifies nothing, try to match both - prev.value = `(${capture}${escaped}|${prev.value})`; - state.output += prev.value; - continue; + function emailValue(code) { + if ((code === 45 || asciiAlphanumeric(code)) && size++ < 63) { + effects.consume(code); + return code === 45 ? emailValue : emailLabel } - /** - * Braces - */ + return nok(code) + } + /** @type {State} */ - if (value === '{' && opts.nobrace !== true) { - increment('braces'); + function end(code) { + effects.enter('autolinkMarker'); + effects.consume(code); + effects.exit('autolinkMarker'); + effects.exit('autolink'); + return ok + } +} - const open = { - type: 'brace', - value, - output: '(', - outputIndex: state.output.length, - tokensIndex: state.tokens.length - }; +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State + */ - braces.push(open); - push(open); - continue; - } +/** @type {Construct} */ +const blankLine = { + tokenize: tokenizeBlankLine, + partial: true +}; +/** @type {Tokenizer} */ - if (value === '}') { - const brace = braces[braces.length - 1]; +function tokenizeBlankLine(effects, ok, nok) { + return factorySpace(effects, afterWhitespace, 'linePrefix') + /** @type {State} */ - if (opts.nobrace === true || !brace) { - push({ type: 'text', value, output: value }); - continue; - } + function afterWhitespace(code) { + return code === null || markdownLineEnding(code) ? ok(code) : nok(code) + } +} - let output = ')'; +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').Exiter} Exiter + * @typedef {import('micromark-util-types').State} State + */ - if (brace.dots === true) { - const arr = tokens.slice(); - const range = []; +/** @type {Construct} */ +const blockQuote = { + name: 'blockQuote', + tokenize: tokenizeBlockQuoteStart, + continuation: { + tokenize: tokenizeBlockQuoteContinuation + }, + exit: exit$1 +}; +/** @type {Tokenizer} */ - 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); - } - } +function tokenizeBlockQuoteStart(effects, ok, nok) { + const self = this; + return start + /** @type {State} */ - output = expandRange(range, opts); - state.backtrack = true; - } + function start(code) { + if (code === 62) { + const state = self.containerState; - 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); - } + if (!state.open) { + effects.enter('blockQuote', { + _container: true + }); + state.open = true; } - push({ type: 'brace', value, output }); - decrement('braces'); - braces.pop(); - continue; + effects.enter('blockQuotePrefix'); + effects.enter('blockQuoteMarker'); + effects.consume(code); + effects.exit('blockQuoteMarker'); + return after } - /** - * Pipes - */ + return nok(code) + } + /** @type {State} */ - if (value === '|') { - if (extglobs.length > 0) { - extglobs[extglobs.length - 1].conditions++; - } - push({ type: 'text', value }); - continue; + function after(code) { + if (markdownSpace(code)) { + effects.enter('blockQuotePrefixWhitespace'); + effects.consume(code); + effects.exit('blockQuotePrefixWhitespace'); + effects.exit('blockQuotePrefix'); + return ok } - /** - * Commas - */ + effects.exit('blockQuotePrefix'); + return ok(code) + } +} +/** @type {Tokenizer} */ - if (value === ',') { - let output = value; +function tokenizeBlockQuoteContinuation(effects, ok, nok) { + return factorySpace( + effects, + effects.attempt(blockQuote, ok, nok), + 'linePrefix', + this.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4 + ) +} +/** @type {Exiter} */ - 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$5.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$1('closing', ']')); - state.output = utils$5.escapeLast(state.output, '['); - decrement('brackets'); - } - - while (state.parens > 0) { - if (opts.strictBrackets === true) throw new SyntaxError(syntaxError$1('closing', ')')); - state.output = utils$5.escapeLast(state.output, '('); - decrement('parens'); - } - - while (state.braces > 0) { - if (opts.strictBrackets === true) throw new SyntaxError(syntaxError$1('closing', '}')); - state.output = utils$5.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$e.fastpaths = (input, options) => { - const opts = { ...options }; - const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH$4, opts.maxLength) : MAX_LENGTH$4; - 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$5.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$4.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$5.removePrefix(input, state); - let source = create(output); - - if (source && opts.strictSlashes !== true) { - source += `${SLASH_LITERAL}?`; - } - - return source; -}; - -var parse_1$2 = parse$e; - -const path$9 = path$b; -const scan = scan_1; -const parse$d = parse_1$2; -const utils$4 = utils$7; -const constants$3 = constants$5; -const isObject$3 = 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$3 = (glob, options, returnState = false) => { - if (Array.isArray(glob)) { - const fns = glob.map(input => picomatch$3(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$3(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$4.isWindows(options); - const regex = isState - ? picomatch$3.compileRe(glob, options) - : picomatch$3.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$3(opts.ignore, ignoreOpts, returnState); - } - - const matcher = (input, returnObject = false) => { - const { isMatch, match, output } = picomatch$3.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$3.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$4.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$3.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$3.matchBase = (input, glob, options, posix = utils$4.isWindows(options)) => { - const regex = glob instanceof RegExp ? glob : picomatch$3.makeRe(glob, options); - return regex.test(path$9.basename(input)); -}; +function exit$1(effects) { + effects.exit('blockQuote'); +} /** - * 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$3.isMatch = (str, patterns, options) => picomatch$3(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$3.parse = (pattern, options) => { - if (Array.isArray(pattern)) return pattern.map(p => picomatch$3.parse(p, options)); - return parse$d(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$3.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$3.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$3.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$3.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$d.fastpaths(input, options); - } - - if (!parsed.output) { - parsed = parse$d(input, options); - } - - return picomatch$3.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$3.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$3.constants = constants$3; - -/** - * Expose "picomatch" - */ - -var picomatch_1 = picomatch$3; - -var picomatch$2 = picomatch_1; - -const fs$9 = require$$0$3; -const { Readable } = require$$1; -const sysPath$3 = path$b; -const { promisify: promisify$3 } = require$$0$4; -const picomatch$1 = picomatch$2; - -const readdir$1 = promisify$3(fs$9.readdir); -const stat$3 = promisify$3(fs$9.stat); -const lstat$2 = promisify$3(fs$9.lstat); -const realpath$2 = promisify$3(fs$9.realpath); - -/** - * @typedef {Object} EntryInfo - * @property {String} path - * @property {String} fullPath - * @property {fs.Stats=} stats - * @property {fs.Dirent=} dirent - * @property {String} basename + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State */ -const BANG$2 = '!'; -const RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR'; -const NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]); -const FILE_TYPE = 'files'; -const DIR_TYPE = 'directories'; -const FILE_DIR_TYPE = 'files_directories'; -const EVERYTHING_TYPE = 'all'; -const ALL_TYPES = [FILE_TYPE, DIR_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE]; - -const isNormalFlowError = error => NORMAL_FLOW_ERRORS.has(error.code); -const [maj, min] = process.versions.node.split('.').slice(0, 2).map(n => Number.parseInt(n, 10)); -const wantBigintFsStats = process.platform === 'win32' && (maj > 10 || (maj === 10 && min >= 5)); - -const normalizeFilter = filter => { - if (filter === undefined) return; - if (typeof filter === 'function') return filter; - - if (typeof filter === 'string') { - const glob = picomatch$1(filter.trim()); - return entry => glob(entry.basename); - } - - if (Array.isArray(filter)) { - const positive = []; - const negative = []; - for (const item of filter) { - const trimmed = item.trim(); - if (trimmed.charAt(0) === BANG$2) { - negative.push(picomatch$1(trimmed.slice(1))); - } else { - positive.push(picomatch$1(trimmed)); - } - } - - if (negative.length > 0) { - if (positive.length > 0) { - return entry => - positive.some(f => f(entry.basename)) && !negative.some(f => f(entry.basename)); - } - return entry => !negative.some(f => f(entry.basename)); - } - return entry => positive.some(f => f(entry.basename)); - } +/** @type {Construct} */ +const characterEscape = { + name: 'characterEscape', + tokenize: tokenizeCharacterEscape }; +/** @type {Tokenizer} */ -class ReaddirpStream extends Readable { - static get defaultOptions() { - return { - root: '.', - /* eslint-disable no-unused-vars */ - fileFilter: (path) => true, - directoryFilter: (path) => true, - /* eslint-enable no-unused-vars */ - type: FILE_TYPE, - lstat: false, - depth: 2147483648, - alwaysStat: false - }; - } - - constructor(options = {}) { - super({ - objectMode: true, - autoDestroy: true, - highWaterMark: options.highWaterMark || 4096 - }); - const opts = { ...ReaddirpStream.defaultOptions, ...options }; - const { root, type } = opts; - - this._fileFilter = normalizeFilter(opts.fileFilter); - this._directoryFilter = normalizeFilter(opts.directoryFilter); - - const statMethod = opts.lstat ? lstat$2 : stat$3; - // Use bigint stats if it's windows and stat() supports options (node 10+). - if (wantBigintFsStats) { - this._stat = path => statMethod(path, { bigint: true }); - } else { - this._stat = statMethod; - } - - this._maxDepth = opts.depth; - this._wantsDir = [DIR_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE].includes(type); - this._wantsFile = [FILE_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE].includes(type); - this._wantsEverything = type === EVERYTHING_TYPE; - this._root = sysPath$3.resolve(root); - this._isDirent = ('Dirent' in fs$9) && !opts.alwaysStat; - this._statsProp = this._isDirent ? 'dirent' : 'stats'; - this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent }; - - // Launch stream with one parent, the root dir. - this.parents = [this._exploreDir(root, 1)]; - this.reading = false; - this.parent = undefined; - } - - async _read(batch) { - if (this.reading) return; - this.reading = true; - - try { - while (!this.destroyed && batch > 0) { - const { path, depth, files = [] } = this.parent || {}; - - if (files.length > 0) { - const slice = files.splice(0, batch).map(dirent => this._formatEntry(dirent, path)); - for (const entry of await Promise.all(slice)) { - if (this.destroyed) return; - - const entryType = await this._getEntryType(entry); - if (entryType === 'directory' && this._directoryFilter(entry)) { - if (depth <= this._maxDepth) { - this.parents.push(this._exploreDir(entry.fullPath, depth + 1)); - } - - if (this._wantsDir) { - this.push(entry); - batch--; - } - } else if ((entryType === 'file' || this._includeAsFile(entry)) && this._fileFilter(entry)) { - if (this._wantsFile) { - this.push(entry); - batch--; - } - } - } - } else { - const parent = this.parents.pop(); - if (!parent) { - this.push(null); - break; - } - this.parent = await parent; - if (this.destroyed) return; - } - } - } catch (error) { - this.destroy(error); - } finally { - this.reading = false; - } - } - - async _exploreDir(path, depth) { - let files; - try { - files = await readdir$1(path, this._rdOptions); - } catch (error) { - this._onError(error); - } - return { files, depth, path }; - } - - async _formatEntry(dirent, path) { - let entry; - try { - const basename = this._isDirent ? dirent.name : dirent; - const fullPath = sysPath$3.resolve(sysPath$3.join(path, basename)); - entry = { path: sysPath$3.relative(this._root, fullPath), fullPath, basename }; - entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath); - } catch (err) { - this._onError(err); - } - return entry; - } +function tokenizeCharacterEscape(effects, ok, nok) { + return start + /** @type {State} */ - _onError(err) { - if (isNormalFlowError(err) && !this.destroyed) { - this.emit('warn', err); - } else { - this.destroy(err); - } + function start(code) { + effects.enter('characterEscape'); + effects.enter('escapeMarker'); + effects.consume(code); + effects.exit('escapeMarker'); + return open } + /** @type {State} */ - async _getEntryType(entry) { - // entry may be undefined, because a warning or an error were emitted - // and the statsProp is undefined - const stats = entry && entry[this._statsProp]; - if (!stats) { - return; - } - if (stats.isFile()) { - return 'file'; - } - if (stats.isDirectory()) { - return 'directory'; - } - if (stats && stats.isSymbolicLink()) { - const full = entry.fullPath; - try { - const entryRealPath = await realpath$2(full); - const entryRealPathStats = await lstat$2(entryRealPath); - if (entryRealPathStats.isFile()) { - return 'file'; - } - if (entryRealPathStats.isDirectory()) { - const len = entryRealPath.length; - if (full.startsWith(entryRealPath) && full.substr(len, 1) === sysPath$3.sep) { - const recursiveError = new Error( - `Circular symlink detected: "${full}" points to "${entryRealPath}"` - ); - recursiveError.code = RECURSIVE_ERROR_CODE; - return this._onError(recursiveError); - } - return 'directory'; - } - } catch (error) { - this._onError(error); - } + function open(code) { + if (asciiPunctuation(code)) { + effects.enter('characterEscapeValue'); + effects.consume(code); + effects.exit('characterEscapeValue'); + effects.exit('characterEscape'); + return ok } - } - _includeAsFile(entry) { - const stats = entry && entry[this._statsProp]; - - return stats && this._wantsEverything && !stats.isDirectory(); - } -} - -/** - * @typedef {Object} ReaddirpArguments - * @property {Function=} fileFilter - * @property {Function=} directoryFilter - * @property {String=} type - * @property {Number=} depth - * @property {String=} root - * @property {Boolean=} lstat - * @property {Boolean=} bigint - */ - -/** - * Main function which ends up calling readdirRec and reads all files and directories in given root recursively. - * @param {String} root Root directory - * @param {ReaddirpArguments=} options Options to specify root (start directory), filters and recursion depth - */ -const readdirp$1 = (root, options = {}) => { - let type = options.entryType || options.type; - if (type === 'both') type = FILE_DIR_TYPE; // backwards-compatibility - if (type) options.type = type; - if (!root) { - throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)'); - } else if (typeof root !== 'string') { - throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)'); - } else if (type && !ALL_TYPES.includes(type)) { - throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`); - } - - options.root = root; - return new ReaddirpStream(options); -}; - -const readdirpPromise = (root, options = {}) => { - return new Promise((resolve, reject) => { - const files = []; - readdirp$1(root, options) - .on('data', entry => files.push(entry)) - .on('end', () => resolve(files)) - .on('error', error => reject(error)); - }); -}; - -readdirp$1.promise = readdirpPromise; -readdirp$1.ReaddirpStream = ReaddirpStream; -readdirp$1.default = readdirp$1; - -var readdirp_1 = readdirp$1; - -var anymatch$2 = {exports: {}}; - -/*! - * normalize-path - * - * Copyright (c) 2014-2018, Jon Schlinkert. - * Released under the MIT License. - */ - -var normalizePath$2 = function(path, stripTrailing) { - if (typeof path !== 'string') { - throw new TypeError('expected path to be a string'); - } - - if (path === '\\' || path === '/') return '/'; - - var len = path.length; - if (len <= 1) return path; - - // ensure that win32 namespaces has two leading slashes, so that the path is - // handled properly by the win32 version of path.parse() after being normalized - // https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces - var prefix = ''; - if (len > 4 && path[3] === '\\') { - var ch = path[2]; - if ((ch === '?' || ch === '.') && path.slice(0, 2) === '\\\\') { - path = path.slice(2); - prefix = '//'; - } - } - - var segs = path.split(/[/\\]+/); - if (stripTrailing !== false && segs[segs.length - 1] === '') { - segs.pop(); - } - return prefix + segs.join('/'); -}; - -Object.defineProperty(anymatch$2.exports, "__esModule", { value: true }); - -const picomatch = picomatch$2; -const normalizePath$1 = normalizePath$2; - -/** - * @typedef {(testString: string) => boolean} AnymatchFn - * @typedef {string|RegExp|AnymatchFn} AnymatchPattern - * @typedef {AnymatchPattern|AnymatchPattern[]} AnymatchMatcher - */ -const BANG$1 = '!'; -const DEFAULT_OPTIONS = {returnIndex: false}; -const arrify$1 = (item) => Array.isArray(item) ? item : [item]; - -/** - * @param {AnymatchPattern} matcher - * @param {object} options - * @returns {AnymatchFn} - */ -const createPattern = (matcher, options) => { - if (typeof matcher === 'function') { - return matcher; - } - if (typeof matcher === 'string') { - const glob = picomatch(matcher, options); - return (string) => matcher === string || glob(string); - } - if (matcher instanceof RegExp) { - return (string) => matcher.test(string); - } - return (string) => false; -}; - -/** - * @param {Array} patterns - * @param {Array} negPatterns - * @param {String|Array} args - * @param {Boolean} returnIndex - * @returns {boolean|number} - */ -const matchPatterns = (patterns, negPatterns, args, returnIndex) => { - const isList = Array.isArray(args); - const _path = isList ? args[0] : args; - if (!isList && typeof _path !== 'string') { - throw new TypeError('anymatch: second argument must be a string: got ' + - Object.prototype.toString.call(_path)) - } - const path = normalizePath$1(_path); - - for (let index = 0; index < negPatterns.length; index++) { - const nglob = negPatterns[index]; - if (nglob(path)) { - return returnIndex ? -1 : false; - } - } - - const applied = isList && [path].concat(args.slice(1)); - for (let index = 0; index < patterns.length; index++) { - const pattern = patterns[index]; - if (isList ? pattern(...applied) : pattern(path)) { - return returnIndex ? index : true; - } - } - - return returnIndex ? -1 : false; -}; - -/** - * @param {AnymatchMatcher} matchers - * @param {Array|string} testString - * @param {object} options - * @returns {boolean|number|Function} - */ -const anymatch$1 = (matchers, testString, options = DEFAULT_OPTIONS) => { - if (matchers == null) { - throw new TypeError('anymatch: specify first argument'); - } - const opts = typeof options === 'boolean' ? {returnIndex: options} : options; - const returnIndex = opts.returnIndex || false; - - // Early cache for matchers. - const mtchers = arrify$1(matchers); - const negatedGlobs = mtchers - .filter(item => typeof item === 'string' && item.charAt(0) === BANG$1) - .map(item => item.slice(1)) - .map(item => picomatch(item, opts)); - const patterns = mtchers - .filter(item => typeof item !== 'string' || (typeof item === 'string' && item.charAt(0) !== BANG$1)) - .map(matcher => createPattern(matcher, opts)); - - if (testString == null) { - return (testString, ri = false) => { - const returnIndex = typeof ri === 'boolean' ? ri : false; - return matchPatterns(patterns, negatedGlobs, testString, returnIndex); - } - } - - return matchPatterns(patterns, negatedGlobs, testString, returnIndex); -}; - -anymatch$1.default = anymatch$1; -anymatch$2.exports = anymatch$1; - -/*! - * 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 - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ - -var isExtglob = isExtglob$1; -var chars$1 = { '{': '}', '(': ')', '[': ']'}; -var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; -var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; - -var isGlob$2 = function isGlob(str, options) { - if (typeof str !== 'string' || str === '') { - return false; - } - - if (isExtglob(str)) { - return true; - } - - var regex = strictRegex; - var match; - - // optionally relax regex - if (options && options.strict === false) { - regex = relaxedRegex; - } - - while ((match = regex.exec(str))) { - if (match[2]) return true; - var idx = match.index + match[0].length; - - // if an open bracket/brace/paren is escaped, - // set the index to the next closing character - var open = match[1]; - var close = open ? chars$1[open] : null; - if (open && close) { - var n = str.indexOf(close, idx); - if (n !== -1) { - idx = n + 1; - } - } - - str = str.slice(idx); - } - return false; -}; - -var isGlob$1 = isGlob$2; -var pathPosixDirname = path$b.posix.dirname; -var isWin32 = require$$0$2.platform() === 'win32'; - -var slash = '/'; -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) < 0) { - str = str.replace(backslash, slash); - } - - // special case for strings ending in enclosure containing path separator - if (enclosure.test(str)) { - str += slash; - } - - // preserves full path in case of trailing path separator - str += 'a'; - - // remove path parts that are globby - do { - str = pathPosixDirname(str); - } while (isGlob$1(str) || globby.test(str)); - - // remove escape chars and return result - return str.replace(escaped, '$1'); -}; - -var utils$3 = {}; - -(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$3)); - -const utils$2 = utils$3; - -var stringify$6 = (ast, options = {}) => { - let stringify = (node, parent = {}) => { - let invalidBlock = options.escapeInvalid && utils$2.isInvalidBrace(parent); - let invalidNode = node.invalid === true && options.escapeInvalid === true; - let output = ''; - - if (node.value) { - if ((invalidBlock || invalidNode) && utils$2.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 - * - * 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 - * - * 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$c); - 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$c(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 - * - * Copyright (c) 2014-present, Jon Schlinkert. - * Licensed under the MIT License. - */ - -const util$3 = require$$0$4; -const toRegexRange = toRegexRange_1; - -const isObject$2 = val => val !== null && typeof val === 'object' && !Array.isArray(val); - -const transform$3 = 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$5 = (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$3.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$5(start, end, options) === false; - let format = options.transform || transform$3(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$2(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$2(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$1 = utils$3; - -const compile$1 = (ast, options = {}) => { - let walk = (node, parent = {}) => { - let invalidBlock = utils$1.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$1.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$1; - -const fill = fillRange; -const stringify$4 = stringify$6; -const utils = utils$3; - -const append = (queue = '', stash = '', enclose = false) => { - let result = []; - - queue = [].concat(queue); - stash = [].concat(stash); - - if (!stash.length) return queue; - if (!queue.length) { - return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash; - } - - for (let item of queue) { - if (Array.isArray(item)) { - for (let value of item) { - result.push(append(value, stash, enclose)); - } - } else { - for (let ele of stash) { - if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; - result.push(Array.isArray(ele) ? append(item, ele, enclose) : (item + ele)); - } - } - } - return utils.flatten(result); -}; - -const expand$4 = (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(q.pop(), stringify$4(node, options))); - return; - } - - if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { - q.push(append(q.pop(), ['{}'])); - return; - } - - if (node.nodes && node.ranges > 0) { - let args = utils.reduce(node.nodes); - - if (utils.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$4(node, options); - } - - q.push(append(q.pop(), range)); - node.nodes = []; - return; - } - - let enclose = utils.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(q.pop(), queue, enclose)); - continue; - } - - if (child.value && child.type !== 'open') { - queue.push(append(queue.pop(), child.value)); - continue; - } - - if (child.nodes) { - walk(child, node); - } - } - - return queue; - }; - - return utils.flatten(walk(ast)); -}; - -var expand_1 = expand$4; - -var constants$2 = { - 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$3 = stringify$6; - -/** - * Constants - */ - -const { - MAX_LENGTH: MAX_LENGTH$3, - CHAR_BACKSLASH, /* \ */ - CHAR_BACKTICK, /* ` */ - CHAR_COMMA: CHAR_COMMA$1, /* , */ - CHAR_DOT, /* . */ - CHAR_LEFT_PARENTHESES, /* ( */ - CHAR_RIGHT_PARENTHESES, /* ) */ - CHAR_LEFT_CURLY_BRACE, /* { */ - CHAR_RIGHT_CURLY_BRACE, /* } */ - CHAR_LEFT_SQUARE_BRACKET: CHAR_LEFT_SQUARE_BRACKET$1, /* [ */ - CHAR_RIGHT_SQUARE_BRACKET: CHAR_RIGHT_SQUARE_BRACKET$1, /* ] */ - CHAR_DOUBLE_QUOTE: CHAR_DOUBLE_QUOTE$1, /* " */ - CHAR_SINGLE_QUOTE: CHAR_SINGLE_QUOTE$1, /* ' */ - CHAR_NO_BREAK_SPACE, - CHAR_ZERO_WIDTH_NOBREAK_SPACE -} = constants$2; - -/** - * 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$3, opts.maxLength) : MAX_LENGTH$3; - 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$1) { - push({ type: 'text', value: '\\' + value }); - continue; - } - - /** - * Left square bracket: '[' - */ - - if (value === CHAR_LEFT_SQUARE_BRACKET$1) { - brackets++; - let next; - - while (index < length && (next = advance())) { - value += next; - - if (next === CHAR_LEFT_SQUARE_BRACKET$1) { - brackets++; - continue; - } - - if (next === CHAR_BACKSLASH) { - value += advance(); - continue; - } - - if (next === CHAR_RIGHT_SQUARE_BRACKET$1) { - brackets--; - - if (brackets === 0) { - break; - } - } - } - - push({ type: 'text', value }); - continue; - } - - /** - * Parentheses - */ - - if (value === CHAR_LEFT_PARENTHESES) { - block = push({ type: 'paren', nodes: [] }); - stack.push(block); - push({ type: 'text', value }); - continue; - } - - if (value === CHAR_RIGHT_PARENTHESES) { - 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) { - 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) { - 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$1 && depth > 0) { - if (block.ranges > 0) { - block.ranges = 0; - let open = block.nodes.shift(); - block.nodes = [open, { type: 'text', value: stringify$3(block) }]; - } - - push({ type: 'comma', value }); - block.commas++; - continue; - } - - /** - * Dot: '.' - */ - - if (value === CHAR_DOT && 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$1 = parse$c; - -const stringify$2 = stringify$6; -const compile = compile_1; -const expand$3 = expand_1; -const parse$b = parse_1$1; - -/** - * 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$2(braces$1.parse(input, options), options); - } - return stringify$2(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(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$3(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 require$$0$1 = [ - "3dm", - "3ds", - "3g2", - "3gp", - "7z", - "a", - "aac", - "adp", - "ai", - "aif", - "aiff", - "alz", - "ape", - "apk", - "appimage", - "ar", - "arj", - "asf", - "au", - "avi", - "bak", - "baml", - "bh", - "bin", - "bk", - "bmp", - "btif", - "bz2", - "bzip2", - "cab", - "caf", - "cgm", - "class", - "cmx", - "cpio", - "cr2", - "cur", - "dat", - "dcm", - "deb", - "dex", - "djvu", - "dll", - "dmg", - "dng", - "doc", - "docm", - "docx", - "dot", - "dotm", - "dra", - "DS_Store", - "dsk", - "dts", - "dtshd", - "dvb", - "dwg", - "dxf", - "ecelp4800", - "ecelp7470", - "ecelp9600", - "egg", - "eol", - "eot", - "epub", - "exe", - "f4v", - "fbs", - "fh", - "fla", - "flac", - "flatpak", - "fli", - "flv", - "fpx", - "fst", - "fvt", - "g3", - "gh", - "gif", - "graffle", - "gz", - "gzip", - "h261", - "h263", - "h264", - "icns", - "ico", - "ief", - "img", - "ipa", - "iso", - "jar", - "jpeg", - "jpg", - "jpgv", - "jpm", - "jxr", - "key", - "ktx", - "lha", - "lib", - "lvp", - "lz", - "lzh", - "lzma", - "lzo", - "m3u", - "m4a", - "m4v", - "mar", - "mdi", - "mht", - "mid", - "midi", - "mj2", - "mka", - "mkv", - "mmr", - "mng", - "mobi", - "mov", - "movie", - "mp3", - "mp4", - "mp4a", - "mpeg", - "mpg", - "mpga", - "mxu", - "nef", - "npx", - "numbers", - "nupkg", - "o", - "odp", - "ods", - "odt", - "oga", - "ogg", - "ogv", - "otf", - "ott", - "pages", - "pbm", - "pcx", - "pdb", - "pdf", - "pea", - "pgm", - "pic", - "png", - "pnm", - "pot", - "potm", - "potx", - "ppa", - "ppam", - "ppm", - "pps", - "ppsm", - "ppsx", - "ppt", - "pptm", - "pptx", - "psd", - "pya", - "pyc", - "pyo", - "pyv", - "qt", - "rar", - "ras", - "raw", - "resources", - "rgb", - "rip", - "rlc", - "rmf", - "rmvb", - "rpm", - "rtf", - "rz", - "s3m", - "s7z", - "scpt", - "sgi", - "shar", - "snap", - "sil", - "sketch", - "slk", - "smv", - "snk", - "so", - "stl", - "suo", - "sub", - "swf", - "tar", - "tbz", - "tbz2", - "tga", - "tgz", - "thmx", - "tif", - "tiff", - "tlz", - "ttc", - "ttf", - "txz", - "udf", - "uvh", - "uvi", - "uvm", - "uvp", - "uvs", - "uvu", - "viv", - "vob", - "war", - "wav", - "wax", - "wbmp", - "wdp", - "weba", - "webm", - "webp", - "whl", - "wim", - "wm", - "wma", - "wmv", - "wmx", - "woff", - "woff2", - "wrm", - "wvx", - "xbm", - "xif", - "xla", - "xlam", - "xls", - "xlsb", - "xlsm", - "xlsx", - "xlt", - "xltm", - "xltx", - "xm", - "xmind", - "xpi", - "xpm", - "xwd", - "xz", - "z", - "zip", - "zipx" -]; - -var binaryExtensions$1 = require$$0$1; - -const path$8 = path$b; -const binaryExtensions = binaryExtensions$1; - -const extensions = new Set(binaryExtensions); - -var isBinaryPath$1 = filePath => extensions.has(path$8.extname(filePath).slice(1).toLowerCase()); - -var constants$1 = {}; - -(function (exports) { - -const {sep} = path$b; -const {platform} = process; -const os = require$$0$2; - -exports.EV_ALL = 'all'; -exports.EV_READY = 'ready'; -exports.EV_ADD = 'add'; -exports.EV_CHANGE = 'change'; -exports.EV_ADD_DIR = 'addDir'; -exports.EV_UNLINK = 'unlink'; -exports.EV_UNLINK_DIR = 'unlinkDir'; -exports.EV_RAW = 'raw'; -exports.EV_ERROR = 'error'; - -exports.STR_DATA = 'data'; -exports.STR_END = 'end'; -exports.STR_CLOSE = 'close'; - -exports.FSEVENT_CREATED = 'created'; -exports.FSEVENT_MODIFIED = 'modified'; -exports.FSEVENT_DELETED = 'deleted'; -exports.FSEVENT_MOVED = 'moved'; -exports.FSEVENT_CLONED = 'cloned'; -exports.FSEVENT_UNKNOWN = 'unknown'; -exports.FSEVENT_TYPE_FILE = 'file'; -exports.FSEVENT_TYPE_DIRECTORY = 'directory'; -exports.FSEVENT_TYPE_SYMLINK = 'symlink'; - -exports.KEY_LISTENERS = 'listeners'; -exports.KEY_ERR = 'errHandlers'; -exports.KEY_RAW = 'rawEmitters'; -exports.HANDLER_KEYS = [exports.KEY_LISTENERS, exports.KEY_ERR, exports.KEY_RAW]; - -exports.DOT_SLASH = `.${sep}`; - -exports.BACK_SLASH_RE = /\\/g; -exports.DOUBLE_SLASH_RE = /\/\//; -exports.SLASH_OR_BACK_SLASH_RE = /[/\\]/; -exports.DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/; -exports.REPLACER_RE = /^\.[/\\]/; - -exports.SLASH = '/'; -exports.SLASH_SLASH = '//'; -exports.BRACE_START = '{'; -exports.BANG = '!'; -exports.ONE_DOT = '.'; -exports.TWO_DOTS = '..'; -exports.STAR = '*'; -exports.GLOBSTAR = '**'; -exports.ROOT_GLOBSTAR = '/**/*'; -exports.SLASH_GLOBSTAR = '/**'; -exports.DIR_SUFFIX = 'Dir'; -exports.ANYMATCH_OPTS = {dot: true}; -exports.STRING_TYPE = 'string'; -exports.FUNCTION_TYPE = 'function'; -exports.EMPTY_STR = ''; -exports.EMPTY_FN = () => {}; -exports.IDENTITY_FN = val => val; - -exports.isWindows = platform === 'win32'; -exports.isMacos = platform === 'darwin'; -exports.isLinux = platform === 'linux'; -exports.isIBMi = os.type() === 'OS400'; -}(constants$1)); - -const fs$8 = require$$0$3; -const sysPath$2 = path$b; -const { promisify: promisify$2 } = require$$0$4; -const isBinaryPath = isBinaryPath$1; -const { - isWindows: isWindows$3, - isLinux, - EMPTY_FN: EMPTY_FN$2, - EMPTY_STR: EMPTY_STR$1, - KEY_LISTENERS, - KEY_ERR, - KEY_RAW, - HANDLER_KEYS, - EV_CHANGE: EV_CHANGE$2, - EV_ADD: EV_ADD$2, - EV_ADD_DIR: EV_ADD_DIR$2, - EV_ERROR: EV_ERROR$2, - STR_DATA: STR_DATA$1, - STR_END: STR_END$2, - BRACE_START: BRACE_START$1, - STAR -} = constants$1; - -const THROTTLE_MODE_WATCH = 'watch'; - -const open = promisify$2(fs$8.open); -const stat$2 = promisify$2(fs$8.stat); -const lstat$1 = promisify$2(fs$8.lstat); -const close = promisify$2(fs$8.close); -const fsrealpath = promisify$2(fs$8.realpath); - -const statMethods$1 = { lstat: lstat$1, stat: stat$2 }; - -// TODO: emit errors properly. Example: EMFILE on Macos. -const foreach = (val, fn) => { - if (val instanceof Set) { - val.forEach(fn); - } else { - fn(val); - } -}; - -const addAndConvert = (main, prop, item) => { - let container = main[prop]; - if (!(container instanceof Set)) { - main[prop] = container = new Set([container]); - } - container.add(item); -}; - -const clearItem = cont => key => { - const set = cont[key]; - if (set instanceof Set) { - set.clear(); - } else { - delete cont[key]; - } -}; - -const delFromSet = (main, prop, item) => { - const container = main[prop]; - if (container instanceof Set) { - container.delete(item); - } else if (container === item) { - delete main[prop]; - } -}; - -const isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val; - -/** - * @typedef {String} Path - */ - -// fs_watch helpers - -// object to hold per-process fs_watch instances -// (may be shared across chokidar FSWatcher instances) - -/** - * @typedef {Object} FsWatchContainer - * @property {Set} listeners - * @property {Set} errHandlers - * @property {Set} rawEmitters - * @property {fs.FSWatcher=} watcher - * @property {Boolean=} watcherUnusable - */ - -/** - * @type {Map} - */ -const FsWatchInstances = new Map(); - -/** - * Instantiates the fs_watch interface - * @param {String} path to be watched - * @param {Object} options to be passed to fs_watch - * @param {Function} listener main event handler - * @param {Function} errHandler emits info about errors - * @param {Function} emitRaw emits raw event data - * @returns {fs.FSWatcher} new fsevents instance - */ -function createFsWatchInstance(path, options, listener, errHandler, emitRaw) { - const handleEvent = (rawEvent, evPath) => { - listener(path); - emitRaw(rawEvent, evPath, {watchedPath: path}); - - // emit based on events occurring for files from a directory's watcher in - // case the file's watcher misses it (and rely on throttling to de-dupe) - if (evPath && path !== evPath) { - fsWatchBroadcast( - sysPath$2.resolve(path, evPath), KEY_LISTENERS, sysPath$2.join(path, evPath) - ); - } - }; - try { - return fs$8.watch(path, options, handleEvent); - } catch (error) { - errHandler(error); - } -} - -/** - * Helper for passing fs_watch event data to a collection of listeners - * @param {Path} fullPath absolute path bound to fs_watch instance - * @param {String} type listener type - * @param {*=} val1 arguments to be passed to listeners - * @param {*=} val2 - * @param {*=} val3 - */ -const fsWatchBroadcast = (fullPath, type, val1, val2, val3) => { - const cont = FsWatchInstances.get(fullPath); - if (!cont) return; - foreach(cont[type], (listener) => { - listener(val1, val2, val3); - }); -}; - -/** - * Instantiates the fs_watch interface or binds listeners - * to an existing one covering the same file system entry - * @param {String} path - * @param {String} fullPath absolute path - * @param {Object} options to be passed to fs_watch - * @param {Object} handlers container for event listener functions - */ -const setFsWatchListener = (path, fullPath, options, handlers) => { - const {listener, errHandler, rawEmitter} = handlers; - let cont = FsWatchInstances.get(fullPath); - - /** @type {fs.FSWatcher=} */ - let watcher; - if (!options.persistent) { - watcher = createFsWatchInstance( - path, options, listener, errHandler, rawEmitter - ); - return watcher.close.bind(watcher); - } - if (cont) { - addAndConvert(cont, KEY_LISTENERS, listener); - addAndConvert(cont, KEY_ERR, errHandler); - addAndConvert(cont, KEY_RAW, rawEmitter); - } else { - watcher = createFsWatchInstance( - path, - options, - fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), - errHandler, // no need to use broadcast here - fsWatchBroadcast.bind(null, fullPath, KEY_RAW) - ); - if (!watcher) return; - watcher.on(EV_ERROR$2, async (error) => { - const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR); - cont.watcherUnusable = true; // documented since Node 10.4.1 - // Workaround for https://github.com/joyent/node/issues/4337 - if (isWindows$3 && error.code === 'EPERM') { - try { - const fd = await open(path, 'r'); - await close(fd); - broadcastErr(error); - } catch (err) {} - } else { - broadcastErr(error); - } - }); - cont = { - listeners: listener, - errHandlers: errHandler, - rawEmitters: rawEmitter, - watcher - }; - FsWatchInstances.set(fullPath, cont); - } - // const index = cont.listeners.indexOf(listener); - - // removes this instance's listeners and closes the underlying fs_watch - // instance if there are no more listeners left - return () => { - delFromSet(cont, KEY_LISTENERS, listener); - delFromSet(cont, KEY_ERR, errHandler); - delFromSet(cont, KEY_RAW, rawEmitter); - if (isEmptySet(cont.listeners)) { - // Check to protect against issue gh-730. - // if (cont.watcherUnusable) { - cont.watcher.close(); - // } - FsWatchInstances.delete(fullPath); - HANDLER_KEYS.forEach(clearItem(cont)); - cont.watcher = undefined; - Object.freeze(cont); - } - }; -}; - -// fs_watchFile helpers - -// object to hold per-process fs_watchFile instances -// (may be shared across chokidar FSWatcher instances) -const FsWatchFileInstances = new Map(); - -/** - * Instantiates the fs_watchFile interface or binds listeners - * to an existing one covering the same file system entry - * @param {String} path to be watched - * @param {String} fullPath absolute path - * @param {Object} options options to be passed to fs_watchFile - * @param {Object} handlers container for event listener functions - * @returns {Function} closer - */ -const setFsWatchFileListener = (path, fullPath, options, handlers) => { - const {listener, rawEmitter} = handlers; - let cont = FsWatchFileInstances.get(fullPath); - - const copts = cont && cont.options; - if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) { - fs$8.unwatchFile(fullPath); - cont = undefined; - } - - /* eslint-enable no-unused-vars, prefer-destructuring */ - - if (cont) { - addAndConvert(cont, KEY_LISTENERS, listener); - addAndConvert(cont, KEY_RAW, rawEmitter); - } else { - // TODO - // listeners.add(listener); - // rawEmitters.add(rawEmitter); - cont = { - listeners: listener, - rawEmitters: rawEmitter, - options, - watcher: fs$8.watchFile(fullPath, options, (curr, prev) => { - foreach(cont.rawEmitters, (rawEmitter) => { - rawEmitter(EV_CHANGE$2, fullPath, {curr, prev}); - }); - const currmtime = curr.mtimeMs; - if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) { - foreach(cont.listeners, (listener) => listener(path, curr)); - } - }) - }; - FsWatchFileInstances.set(fullPath, cont); - } - // const index = cont.listeners.indexOf(listener); - - // Removes this instance's listeners and closes the underlying fs_watchFile - // instance if there are no more listeners left. - return () => { - delFromSet(cont, KEY_LISTENERS, listener); - delFromSet(cont, KEY_RAW, rawEmitter); - if (isEmptySet(cont.listeners)) { - FsWatchFileInstances.delete(fullPath); - fs$8.unwatchFile(fullPath); - cont.options = cont.watcher = undefined; - Object.freeze(cont); - } - }; -}; - -/** - * @mixin - */ -class NodeFsHandler$1 { - -/** - * @param {import("../index").FSWatcher} fsW - */ -constructor(fsW) { - this.fsw = fsW; - this._boundHandleError = (error) => fsW._handleError(error); -} - -/** - * Watch file for changes with fs_watchFile or fs_watch. - * @param {String} path to file or dir - * @param {Function} listener on fs change - * @returns {Function} closer for the watcher instance - */ -_watchWithNodeFs(path, listener) { - const opts = this.fsw.options; - const directory = sysPath$2.dirname(path); - const basename = sysPath$2.basename(path); - const parent = this.fsw._getWatchedDir(directory); - parent.add(basename); - const absolutePath = sysPath$2.resolve(path); - const options = {persistent: opts.persistent}; - if (!listener) listener = EMPTY_FN$2; - - let closer; - if (opts.usePolling) { - options.interval = opts.enableBinaryInterval && isBinaryPath(basename) ? - opts.binaryInterval : opts.interval; - closer = setFsWatchFileListener(path, absolutePath, options, { - listener, - rawEmitter: this.fsw._emitRaw - }); - } else { - closer = setFsWatchListener(path, absolutePath, options, { - listener, - errHandler: this._boundHandleError, - rawEmitter: this.fsw._emitRaw - }); - } - return closer; -} - -/** - * Watch a file and emit add event if warranted. - * @param {Path} file Path - * @param {fs.Stats} stats result of fs_stat - * @param {Boolean} initialAdd was the file added at watch instantiation? - * @returns {Function} closer for the watcher instance - */ -_handleFile(file, stats, initialAdd) { - if (this.fsw.closed) { - return; - } - const dirname = sysPath$2.dirname(file); - const basename = sysPath$2.basename(file); - const parent = this.fsw._getWatchedDir(dirname); - // stats is always present - let prevStats = stats; - - // if the file is already being watched, do nothing - if (parent.has(basename)) return; - - const listener = async (path, newStats) => { - if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5)) return; - if (!newStats || newStats.mtimeMs === 0) { - try { - const newStats = await stat$2(file); - if (this.fsw.closed) return; - // Check that change event was not fired because of changed only accessTime. - const at = newStats.atimeMs; - const mt = newStats.mtimeMs; - if (!at || at <= mt || mt !== prevStats.mtimeMs) { - this.fsw._emit(EV_CHANGE$2, file, newStats); - } - if (isLinux && prevStats.ino !== newStats.ino) { - this.fsw._closeFile(path); - prevStats = newStats; - this.fsw._addPathCloser(path, this._watchWithNodeFs(file, listener)); - } else { - prevStats = newStats; - } - } catch (error) { - // Fix issues where mtime is null but file is still present - this.fsw._remove(dirname, basename); - } - // add is about to be emitted if file not already tracked in parent - } else if (parent.has(basename)) { - // Check that change event was not fired because of changed only accessTime. - const at = newStats.atimeMs; - const mt = newStats.mtimeMs; - if (!at || at <= mt || mt !== prevStats.mtimeMs) { - this.fsw._emit(EV_CHANGE$2, file, newStats); - } - prevStats = newStats; - } - }; - // kick off the watcher - const closer = this._watchWithNodeFs(file, listener); - - // emit an add event if we're supposed to - if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) { - if (!this.fsw._throttle(EV_ADD$2, file, 0)) return; - this.fsw._emit(EV_ADD$2, file, stats); - } - - return closer; -} - -/** - * Handle symlinks encountered while reading a dir. - * @param {Object} entry returned by readdirp - * @param {String} directory path of dir being read - * @param {String} path of this item - * @param {String} item basename of this item - * @returns {Promise} true if no more processing is needed for this entry. - */ -async _handleSymlink(entry, directory, path, item) { - if (this.fsw.closed) { - return; - } - const full = entry.fullPath; - const dir = this.fsw._getWatchedDir(directory); - - if (!this.fsw.options.followSymlinks) { - // watch symlink directly (don't follow) and detect changes - this.fsw._incrReadyCount(); - const linkPath = await fsrealpath(path); - if (this.fsw.closed) return; - if (dir.has(item)) { - if (this.fsw._symlinkPaths.get(full) !== linkPath) { - this.fsw._symlinkPaths.set(full, linkPath); - this.fsw._emit(EV_CHANGE$2, path, entry.stats); - } - } else { - dir.add(item); - this.fsw._symlinkPaths.set(full, linkPath); - this.fsw._emit(EV_ADD$2, path, entry.stats); - } - this.fsw._emitReady(); - return true; - } - - // don't follow the same symlink more than once - if (this.fsw._symlinkPaths.has(full)) { - return true; - } - - this.fsw._symlinkPaths.set(full, true); -} - -_handleRead(directory, initialAdd, wh, target, dir, depth, throttler) { - // Normalize the directory name on Windows - directory = sysPath$2.join(directory, EMPTY_STR$1); - - if (!wh.hasGlob) { - throttler = this.fsw._throttle('readdir', directory, 1000); - if (!throttler) return; - } - - const previous = this.fsw._getWatchedDir(wh.path); - const current = new Set(); - - let stream = this.fsw._readdirp(directory, { - fileFilter: entry => wh.filterPath(entry), - directoryFilter: entry => wh.filterDir(entry), - depth: 0 - }).on(STR_DATA$1, async (entry) => { - if (this.fsw.closed) { - stream = undefined; - return; - } - const item = entry.path; - let path = sysPath$2.join(directory, item); - current.add(item); - - if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path, item)) { - return; - } - - if (this.fsw.closed) { - stream = undefined; - return; - } - // Files that present in current directory snapshot - // but absent in previous are added to watch list and - // emit `add` event. - if (item === target || !target && !previous.has(item)) { - this.fsw._incrReadyCount(); - - // ensure relativeness of path is preserved in case of watcher reuse - path = sysPath$2.join(dir, sysPath$2.relative(dir, path)); - - this._addToNodeFs(path, initialAdd, wh, depth + 1); - } - }).on(EV_ERROR$2, this._boundHandleError); - - return new Promise(resolve => - stream.once(STR_END$2, () => { - if (this.fsw.closed) { - stream = undefined; - return; - } - const wasThrottled = throttler ? throttler.clear() : false; - - resolve(); - - // Files that absent in current directory snapshot - // but present in previous emit `remove` event - // and are removed from @watched[directory]. - previous.getChildren().filter((item) => { - return item !== directory && - !current.has(item) && - // in case of intersecting globs; - // a path may have been filtered out of this readdir, but - // shouldn't be removed because it matches a different glob - (!wh.hasGlob || wh.filterPath({ - fullPath: sysPath$2.resolve(directory, item) - })); - }).forEach((item) => { - this.fsw._remove(directory, item); - }); - - stream = undefined; - - // one more time for any missed in case changes came in extremely quickly - if (wasThrottled) this._handleRead(directory, false, wh, target, dir, depth, throttler); - }) - ); -} - -/** - * Read directory to add / remove files from `@watched` list and re-read it on change. - * @param {String} dir fs path - * @param {fs.Stats} stats - * @param {Boolean} initialAdd - * @param {Number} depth relative to user-supplied path - * @param {String} target child path targeted for watch - * @param {Object} wh Common watch helpers for this path - * @param {String} realpath - * @returns {Promise} closer for the watcher instance. - */ -async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) { - const parentDir = this.fsw._getWatchedDir(sysPath$2.dirname(dir)); - const tracked = parentDir.has(sysPath$2.basename(dir)); - if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) { - if (!wh.hasGlob || wh.globFilter(dir)) this.fsw._emit(EV_ADD_DIR$2, dir, stats); - } - - // ensure dir is tracked (harmless if redundant) - parentDir.add(sysPath$2.basename(dir)); - this.fsw._getWatchedDir(dir); - let throttler; - let closer; - - const oDepth = this.fsw.options.depth; - if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) { - if (!target) { - await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler); - if (this.fsw.closed) return; - } - - closer = this._watchWithNodeFs(dir, (dirPath, stats) => { - // if current directory is removed, do nothing - if (stats && stats.mtimeMs === 0) return; - - this._handleRead(dirPath, false, wh, target, dir, depth, throttler); - }); - } - return closer; -} - -/** - * Handle added file, directory, or glob pattern. - * Delegates call to _handleFile / _handleDir after checks. - * @param {String} path to file or ir - * @param {Boolean} initialAdd was the file added at watch instantiation? - * @param {Object} priorWh depth relative to user-supplied path - * @param {Number} depth Child path actually targeted for watch - * @param {String=} target Child path actually targeted for watch - * @returns {Promise} - */ -async _addToNodeFs(path, initialAdd, priorWh, depth, target) { - const ready = this.fsw._emitReady; - if (this.fsw._isIgnored(path) || this.fsw.closed) { - ready(); - return false; - } - - const wh = this.fsw._getWatchHelpers(path, depth); - if (!wh.hasGlob && priorWh) { - wh.hasGlob = priorWh.hasGlob; - wh.globFilter = priorWh.globFilter; - wh.filterPath = entry => priorWh.filterPath(entry); - wh.filterDir = entry => priorWh.filterDir(entry); - } - - // evaluate what is at the path we're being asked to watch - try { - const stats = await statMethods$1[wh.statMethod](wh.watchPath); - if (this.fsw.closed) return; - if (this.fsw._isIgnored(wh.watchPath, stats)) { - ready(); - return false; - } - - const follow = this.fsw.options.followSymlinks && !path.includes(STAR) && !path.includes(BRACE_START$1); - let closer; - if (stats.isDirectory()) { - const absPath = sysPath$2.resolve(path); - const targetPath = follow ? await fsrealpath(path) : path; - if (this.fsw.closed) return; - closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath); - if (this.fsw.closed) return; - // preserve this symlink's target path - if (absPath !== targetPath && targetPath !== undefined) { - this.fsw._symlinkPaths.set(absPath, targetPath); - } - } else if (stats.isSymbolicLink()) { - const targetPath = follow ? await fsrealpath(path) : path; - if (this.fsw.closed) return; - const parent = sysPath$2.dirname(wh.watchPath); - this.fsw._getWatchedDir(parent).add(wh.watchPath); - this.fsw._emit(EV_ADD$2, wh.watchPath, stats); - closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath); - if (this.fsw.closed) return; - - // preserve this symlink's target path - if (targetPath !== undefined) { - this.fsw._symlinkPaths.set(sysPath$2.resolve(path), targetPath); - } - } else { - closer = this._handleFile(wh.watchPath, stats, initialAdd); - } - ready(); - - this.fsw._addPathCloser(path, closer); - return false; - - } catch (error) { - if (this.fsw._handleError(error)) { - ready(); - return path; - } - } -} - -} - -var nodefsHandler = NodeFsHandler$1; - -var fseventsHandler = {exports: {}}; - -const fs$7 = require$$0$3; -const sysPath$1 = path$b; -const { promisify: promisify$1 } = require$$0$4; - -let fsevents; -try { - fsevents = undefined; -} catch (error) { - if (process.env.CHOKIDAR_PRINT_FSEVENTS_REQUIRE_ERROR) console.error(error); -} - -if (fsevents) { - // TODO: real check - const mtch = process.version.match(/v(\d+)\.(\d+)/); - if (mtch && mtch[1] && mtch[2]) { - const maj = Number.parseInt(mtch[1], 10); - const min = Number.parseInt(mtch[2], 10); - if (maj === 8 && min < 16) { - fsevents = undefined; - } - } -} - -const { - EV_ADD: EV_ADD$1, - EV_CHANGE: EV_CHANGE$1, - EV_ADD_DIR: EV_ADD_DIR$1, - EV_UNLINK: EV_UNLINK$1, - EV_ERROR: EV_ERROR$1, - STR_DATA, - STR_END: STR_END$1, - FSEVENT_CREATED, - FSEVENT_MODIFIED, - FSEVENT_DELETED, - FSEVENT_MOVED, - // FSEVENT_CLONED, - FSEVENT_UNKNOWN, - FSEVENT_TYPE_FILE, - FSEVENT_TYPE_DIRECTORY, - FSEVENT_TYPE_SYMLINK, - - ROOT_GLOBSTAR, - DIR_SUFFIX, - DOT_SLASH, - FUNCTION_TYPE: FUNCTION_TYPE$1, - EMPTY_FN: EMPTY_FN$1, - IDENTITY_FN -} = constants$1; - -const Depth = (value) => isNaN(value) ? {} : {depth: value}; - -const stat$1 = promisify$1(fs$7.stat); -const lstat = promisify$1(fs$7.lstat); -const realpath$1 = promisify$1(fs$7.realpath); - -const statMethods = { stat: stat$1, lstat }; - -/** - * @typedef {String} Path - */ - -/** - * @typedef {Object} FsEventsWatchContainer - * @property {Set} listeners - * @property {Function} rawEmitter - * @property {{stop: Function}} watcher - */ - -// fsevents instance helper functions -/** - * Object to hold per-process fsevents instances (may be shared across chokidar FSWatcher instances) - * @type {Map} - */ -const FSEventsWatchers = new Map(); - -// Threshold of duplicate path prefixes at which to start -// consolidating going forward -const consolidateThreshhold = 10; - -const wrongEventFlags = new Set([ - 69888, 70400, 71424, 72704, 73472, 131328, 131840, 262912 -]); - -/** - * Instantiates the fsevents interface - * @param {Path} path path to be watched - * @param {Function} callback called when fsevents is bound and ready - * @returns {{stop: Function}} new fsevents instance - */ -const createFSEventsInstance = (path, callback) => { - const stop = fsevents.watch(path, callback); - return {stop}; -}; - -/** - * Instantiates the fsevents interface or binds listeners to an existing one covering - * the same file tree. - * @param {Path} path - to be watched - * @param {Path} realPath - real path for symlinks - * @param {Function} listener - called when fsevents emits events - * @param {Function} rawEmitter - passes data to listeners of the 'raw' event - * @returns {Function} closer - */ -function setFSEventsListener(path, realPath, listener, rawEmitter) { - let watchPath = sysPath$1.extname(realPath) ? sysPath$1.dirname(realPath) : realPath; - - const parentPath = sysPath$1.dirname(watchPath); - let cont = FSEventsWatchers.get(watchPath); - - // If we've accumulated a substantial number of paths that - // could have been consolidated by watching one directory - // above the current one, create a watcher on the parent - // path instead, so that we do consolidate going forward. - if (couldConsolidate(parentPath)) { - watchPath = parentPath; - } - - const resolvedPath = sysPath$1.resolve(path); - const hasSymlink = resolvedPath !== realPath; - - const filteredListener = (fullPath, flags, info) => { - if (hasSymlink) fullPath = fullPath.replace(realPath, resolvedPath); - if ( - fullPath === resolvedPath || - !fullPath.indexOf(resolvedPath + sysPath$1.sep) - ) listener(fullPath, flags, info); - }; - - // check if there is already a watcher on a parent path - // modifies `watchPath` to the parent path when it finds a match - let watchedParent = false; - for (const watchedPath of FSEventsWatchers.keys()) { - if (realPath.indexOf(sysPath$1.resolve(watchedPath) + sysPath$1.sep) === 0) { - watchPath = watchedPath; - cont = FSEventsWatchers.get(watchPath); - watchedParent = true; - break; - } - } - - if (cont || watchedParent) { - cont.listeners.add(filteredListener); - } else { - cont = { - listeners: new Set([filteredListener]), - rawEmitter, - watcher: createFSEventsInstance(watchPath, (fullPath, flags) => { - if (!cont.listeners.size) return; - const info = fsevents.getInfo(fullPath, flags); - cont.listeners.forEach(list => { - list(fullPath, flags, info); - }); - - cont.rawEmitter(info.event, fullPath, info); - }) - }; - FSEventsWatchers.set(watchPath, cont); - } - - // removes this instance's listeners and closes the underlying fsevents - // instance if there are no more listeners left - return () => { - const lst = cont.listeners; - - lst.delete(filteredListener); - if (!lst.size) { - FSEventsWatchers.delete(watchPath); - if (cont.watcher) return cont.watcher.stop().then(() => { - cont.rawEmitter = cont.watcher = undefined; - Object.freeze(cont); - }); - } - }; -} - -// Decide whether or not we should start a new higher-level -// parent watcher -const couldConsolidate = (path) => { - let count = 0; - for (const watchPath of FSEventsWatchers.keys()) { - if (watchPath.indexOf(path) === 0) { - count++; - if (count >= consolidateThreshhold) { - return true; - } - } - } - - return false; -}; - -// returns boolean indicating whether fsevents can be used -const canUse = () => fsevents && FSEventsWatchers.size < 128; - -// determines subdirectory traversal levels from root to path -const calcDepth = (path, root) => { - let i = 0; - while (!path.indexOf(root) && (path = sysPath$1.dirname(path)) !== root) i++; - return i; -}; - -// returns boolean indicating whether the fsevents' event info has the same type -// as the one returned by fs.stat -const sameTypes = (info, stats) => ( - info.type === FSEVENT_TYPE_DIRECTORY && stats.isDirectory() || - info.type === FSEVENT_TYPE_SYMLINK && stats.isSymbolicLink() || - info.type === FSEVENT_TYPE_FILE && stats.isFile() -); - -/** - * @mixin - */ -class FsEventsHandler$1 { - -/** - * @param {import('../index').FSWatcher} fsw - */ -constructor(fsw) { - this.fsw = fsw; -} -checkIgnored(path, stats) { - const ipaths = this.fsw._ignoredPaths; - if (this.fsw._isIgnored(path, stats)) { - ipaths.add(path); - if (stats && stats.isDirectory()) { - ipaths.add(path + ROOT_GLOBSTAR); - } - return true; - } - - ipaths.delete(path); - ipaths.delete(path + ROOT_GLOBSTAR); -} - -addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts) { - const event = watchedDir.has(item) ? EV_CHANGE$1 : EV_ADD$1; - this.handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts); -} - -async checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts) { - try { - const stats = await stat$1(path); - if (this.fsw.closed) return; - if (sameTypes(info, stats)) { - this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); - } else { - this.handleEvent(EV_UNLINK$1, path, fullPath, realPath, parent, watchedDir, item, info, opts); - } - } catch (error) { - if (error.code === 'EACCES') { - this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); - } else { - this.handleEvent(EV_UNLINK$1, path, fullPath, realPath, parent, watchedDir, item, info, opts); - } - } -} - -handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts) { - if (this.fsw.closed || this.checkIgnored(path)) return; - - if (event === EV_UNLINK$1) { - const isDirectory = info.type === FSEVENT_TYPE_DIRECTORY; - // suppress unlink events on never before seen files - if (isDirectory || watchedDir.has(item)) { - this.fsw._remove(parent, item, isDirectory); - } - } else { - if (event === EV_ADD$1) { - // track new directories - if (info.type === FSEVENT_TYPE_DIRECTORY) this.fsw._getWatchedDir(path); - - if (info.type === FSEVENT_TYPE_SYMLINK && opts.followSymlinks) { - // push symlinks back to the top of the stack to get handled - const curDepth = opts.depth === undefined ? - undefined : calcDepth(fullPath, realPath) + 1; - return this._addToFsEvents(path, false, true, curDepth); - } - - // track new paths - // (other than symlinks being followed, which will be tracked soon) - this.fsw._getWatchedDir(parent).add(item); - } - /** - * @type {'add'|'addDir'|'unlink'|'unlinkDir'} - */ - const eventName = info.type === FSEVENT_TYPE_DIRECTORY ? event + DIR_SUFFIX : event; - this.fsw._emit(eventName, path); - if (eventName === EV_ADD_DIR$1) this._addToFsEvents(path, false, true); - } -} - -/** - * Handle symlinks encountered during directory scan - * @param {String} watchPath - file/dir path to be watched with fsevents - * @param {String} realPath - real path (in case of symlinks) - * @param {Function} transform - path transformer - * @param {Function} globFilter - path filter in case a glob pattern was provided - * @returns {Function} closer for the watcher instance -*/ -_watchWithFsEvents(watchPath, realPath, transform, globFilter) { - if (this.fsw.closed || this.fsw._isIgnored(watchPath)) return; - const opts = this.fsw.options; - const watchCallback = async (fullPath, flags, info) => { - if (this.fsw.closed) return; - if ( - opts.depth !== undefined && - calcDepth(fullPath, realPath) > opts.depth - ) return; - const path = transform(sysPath$1.join( - watchPath, sysPath$1.relative(watchPath, fullPath) - )); - if (globFilter && !globFilter(path)) return; - // ensure directories are tracked - const parent = sysPath$1.dirname(path); - const item = sysPath$1.basename(path); - const watchedDir = this.fsw._getWatchedDir( - info.type === FSEVENT_TYPE_DIRECTORY ? path : parent - ); - - // correct for wrong events emitted - if (wrongEventFlags.has(flags) || info.event === FSEVENT_UNKNOWN) { - if (typeof opts.ignored === FUNCTION_TYPE$1) { - let stats; - try { - stats = await stat$1(path); - } catch (error) {} - if (this.fsw.closed) return; - if (this.checkIgnored(path, stats)) return; - if (sameTypes(info, stats)) { - this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); - } else { - this.handleEvent(EV_UNLINK$1, path, fullPath, realPath, parent, watchedDir, item, info, opts); - } - } else { - this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts); - } - } else { - switch (info.event) { - case FSEVENT_CREATED: - case FSEVENT_MODIFIED: - return this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); - case FSEVENT_DELETED: - case FSEVENT_MOVED: - return this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts); - } - } - }; - - const closer = setFSEventsListener( - watchPath, - realPath, - watchCallback, - this.fsw._emitRaw - ); - - this.fsw._emitReady(); - return closer; -} - -/** - * Handle symlinks encountered during directory scan - * @param {String} linkPath path to symlink - * @param {String} fullPath absolute path to the symlink - * @param {Function} transform pre-existing path transformer - * @param {Number} curDepth level of subdirectories traversed to where symlink is - * @returns {Promise} - */ -async _handleFsEventsSymlink(linkPath, fullPath, transform, curDepth) { - // don't follow the same symlink more than once - if (this.fsw.closed || this.fsw._symlinkPaths.has(fullPath)) return; - - this.fsw._symlinkPaths.set(fullPath, true); - this.fsw._incrReadyCount(); - - try { - const linkTarget = await realpath$1(linkPath); - if (this.fsw.closed) return; - if (this.fsw._isIgnored(linkTarget)) { - return this.fsw._emitReady(); - } - - this.fsw._incrReadyCount(); - - // add the linkTarget for watching with a wrapper for transform - // that causes emitted paths to incorporate the link's path - this._addToFsEvents(linkTarget || linkPath, (path) => { - let aliasedPath = linkPath; - if (linkTarget && linkTarget !== DOT_SLASH) { - aliasedPath = path.replace(linkTarget, linkPath); - } else if (path !== DOT_SLASH) { - aliasedPath = sysPath$1.join(linkPath, path); - } - return transform(aliasedPath); - }, false, curDepth); - } catch(error) { - if (this.fsw._handleError(error)) { - return this.fsw._emitReady(); - } - } -} - -/** - * - * @param {Path} newPath - * @param {fs.Stats} stats - */ -emitAdd(newPath, stats, processPath, opts, forceAdd) { - const pp = processPath(newPath); - const isDir = stats.isDirectory(); - const dirObj = this.fsw._getWatchedDir(sysPath$1.dirname(pp)); - const base = sysPath$1.basename(pp); - - // ensure empty dirs get tracked - if (isDir) this.fsw._getWatchedDir(pp); - if (dirObj.has(base)) return; - dirObj.add(base); - - if (!opts.ignoreInitial || forceAdd === true) { - this.fsw._emit(isDir ? EV_ADD_DIR$1 : EV_ADD$1, pp, stats); - } -} - -initWatch(realPath, path, wh, processPath) { - if (this.fsw.closed) return; - const closer = this._watchWithFsEvents( - wh.watchPath, - sysPath$1.resolve(realPath || wh.watchPath), - processPath, - wh.globFilter - ); - this.fsw._addPathCloser(path, closer); -} - -/** - * Handle added path with fsevents - * @param {String} path file/dir path or glob pattern - * @param {Function|Boolean=} transform converts working path to what the user expects - * @param {Boolean=} forceAdd ensure add is emitted - * @param {Number=} priorDepth Level of subdirectories already traversed. - * @returns {Promise} - */ -async _addToFsEvents(path, transform, forceAdd, priorDepth) { - if (this.fsw.closed) { - return; - } - const opts = this.fsw.options; - const processPath = typeof transform === FUNCTION_TYPE$1 ? transform : IDENTITY_FN; - - const wh = this.fsw._getWatchHelpers(path); - - // evaluate what is at the path we're being asked to watch - try { - const stats = await statMethods[wh.statMethod](wh.watchPath); - if (this.fsw.closed) return; - if (this.fsw._isIgnored(wh.watchPath, stats)) { - throw null; - } - if (stats.isDirectory()) { - // emit addDir unless this is a glob parent - if (!wh.globFilter) this.emitAdd(processPath(path), stats, processPath, opts, forceAdd); - - // don't recurse further if it would exceed depth setting - if (priorDepth && priorDepth > opts.depth) return; - - // scan the contents of the dir - this.fsw._readdirp(wh.watchPath, { - fileFilter: entry => wh.filterPath(entry), - directoryFilter: entry => wh.filterDir(entry), - ...Depth(opts.depth - (priorDepth || 0)) - }).on(STR_DATA, (entry) => { - // need to check filterPath on dirs b/c filterDir is less restrictive - if (this.fsw.closed) { - return; - } - if (entry.stats.isDirectory() && !wh.filterPath(entry)) return; - - const joinedPath = sysPath$1.join(wh.watchPath, entry.path); - const {fullPath} = entry; - - if (wh.followSymlinks && entry.stats.isSymbolicLink()) { - // preserve the current depth here since it can't be derived from - // real paths past the symlink - const curDepth = opts.depth === undefined ? - undefined : calcDepth(joinedPath, sysPath$1.resolve(wh.watchPath)) + 1; - - this._handleFsEventsSymlink(joinedPath, fullPath, processPath, curDepth); - } else { - this.emitAdd(joinedPath, entry.stats, processPath, opts, forceAdd); - } - }).on(EV_ERROR$1, EMPTY_FN$1).on(STR_END$1, () => { - this.fsw._emitReady(); - }); - } else { - this.emitAdd(wh.watchPath, stats, processPath, opts, forceAdd); - this.fsw._emitReady(); - } - } catch (error) { - if (!error || this.fsw._handleError(error)) { - // TODO: Strange thing: "should not choke on an ignored watch path" will be failed without 2 ready calls -__- - this.fsw._emitReady(); - this.fsw._emitReady(); - } - } - - if (opts.persistent && forceAdd !== true) { - if (typeof transform === FUNCTION_TYPE$1) { - // realpath has already been resolved - this.initWatch(undefined, path, wh, processPath); - } else { - let realPath; - try { - realPath = await realpath$1(wh.watchPath); - } catch (e) {} - this.initWatch(realPath, path, wh, processPath); - } - } -} - -} - -fseventsHandler.exports = FsEventsHandler$1; -fseventsHandler.exports.canUse = canUse; - -const { EventEmitter } = require$$0$5; -const fs$6 = require$$0$3; -const sysPath = path$b; -const { promisify } = require$$0$4; -const readdirp = readdirp_1; -const anymatch = anymatch$2.exports.default; -const globParent = globParent$1; -const isGlob = isGlob$2; -const braces = braces_1; -const normalizePath = normalizePath$2; - -const NodeFsHandler = nodefsHandler; -const FsEventsHandler = fseventsHandler.exports; -const { - EV_ALL, - EV_READY, - EV_ADD, - EV_CHANGE, - EV_UNLINK, - EV_ADD_DIR, - EV_UNLINK_DIR, - EV_RAW, - EV_ERROR, - - STR_CLOSE, - STR_END, - - BACK_SLASH_RE, - DOUBLE_SLASH_RE, - SLASH_OR_BACK_SLASH_RE, - DOT_RE, - REPLACER_RE, - - SLASH: SLASH$1, - SLASH_SLASH, - BRACE_START, - BANG, - ONE_DOT, - TWO_DOTS, - GLOBSTAR: GLOBSTAR$1, - SLASH_GLOBSTAR, - ANYMATCH_OPTS, - STRING_TYPE, - FUNCTION_TYPE, - EMPTY_STR, - EMPTY_FN, - - isWindows: isWindows$2, - isMacos, - isIBMi -} = constants$1; - -const stat = promisify(fs$6.stat); -const readdir = promisify(fs$6.readdir); - -/** - * @typedef {String} Path - * @typedef {'all'|'add'|'addDir'|'change'|'unlink'|'unlinkDir'|'raw'|'error'|'ready'} EventName - * @typedef {'readdir'|'watch'|'add'|'remove'|'change'} ThrottleType - */ - -/** - * - * @typedef {Object} WatchHelpers - * @property {Boolean} followSymlinks - * @property {'stat'|'lstat'} statMethod - * @property {Path} path - * @property {Path} watchPath - * @property {Function} entryPath - * @property {Boolean} hasGlob - * @property {Object} globFilter - * @property {Function} filterPath - * @property {Function} filterDir - */ - -const arrify = (value = []) => Array.isArray(value) ? value : [value]; -const flatten$1 = (list, result = []) => { - list.forEach(item => { - if (Array.isArray(item)) { - flatten$1(item, result); - } else { - result.push(item); - } - }); - return result; -}; - -const unifyPaths = (paths_) => { - /** - * @type {Array} - */ - const paths = flatten$1(arrify(paths_)); - if (!paths.every(p => typeof p === STRING_TYPE)) { - throw new TypeError(`Non-string provided as watch path: ${paths}`); - } - return paths.map(normalizePathToUnix); -}; - -// If SLASH_SLASH occurs at the beginning of path, it is not replaced -// because "//StoragePC/DrivePool/Movies" is a valid network path -const toUnix = (string) => { - let str = string.replace(BACK_SLASH_RE, SLASH$1); - let prepend = false; - if (str.startsWith(SLASH_SLASH)) { - prepend = true; - } - while (str.match(DOUBLE_SLASH_RE)) { - str = str.replace(DOUBLE_SLASH_RE, SLASH$1); - } - if (prepend) { - str = SLASH$1 + str; - } - return str; -}; - -// Our version of upath.normalize -// TODO: this is not equal to path-normalize module - investigate why -const normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path))); - -const normalizeIgnored = (cwd = EMPTY_STR) => (path) => { - if (typeof path !== STRING_TYPE) return path; - return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path)); -}; - -const getAbsolutePath = (path, cwd) => { - if (sysPath.isAbsolute(path)) { - return path; - } - if (path.startsWith(BANG)) { - return BANG + sysPath.join(cwd, path.slice(1)); - } - return sysPath.join(cwd, path); -}; - -const undef = (opts, key) => opts[key] === undefined; - -/** - * Directory entry. - * @property {Path} path - * @property {Set} items - */ -class DirEntry { - /** - * @param {Path} dir - * @param {Function} removeWatcher - */ - constructor(dir, removeWatcher) { - this.path = dir; - this._removeWatcher = removeWatcher; - /** @type {Set} */ - this.items = new Set(); - } - - add(item) { - const {items} = this; - if (!items) return; - if (item !== ONE_DOT && item !== TWO_DOTS) items.add(item); - } - - async remove(item) { - const {items} = this; - if (!items) return; - items.delete(item); - if (items.size > 0) return; - - const dir = this.path; - try { - await readdir(dir); - } catch (err) { - if (this._removeWatcher) { - this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir)); - } - } - } - - has(item) { - const {items} = this; - if (!items) return; - return items.has(item); - } - - /** - * @returns {Array} - */ - getChildren() { - const {items} = this; - if (!items) return; - return [...items.values()]; - } - - dispose() { - this.items.clear(); - delete this.path; - delete this._removeWatcher; - delete this.items; - Object.freeze(this); - } -} - -const STAT_METHOD_F = 'stat'; -const STAT_METHOD_L = 'lstat'; -class WatchHelper { - constructor(path, watchPath, follow, fsw) { - this.fsw = fsw; - this.path = path = path.replace(REPLACER_RE, EMPTY_STR); - this.watchPath = watchPath; - this.fullWatchPath = sysPath.resolve(watchPath); - this.hasGlob = watchPath !== path; - /** @type {object|boolean} */ - if (path === EMPTY_STR) this.hasGlob = false; - this.globSymlink = this.hasGlob && follow ? undefined : false; - this.globFilter = this.hasGlob ? anymatch(path, undefined, ANYMATCH_OPTS) : false; - this.dirParts = this.getDirParts(path); - this.dirParts.forEach((parts) => { - if (parts.length > 1) parts.pop(); - }); - this.followSymlinks = follow; - this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L; - } - - checkGlobSymlink(entry) { - // only need to resolve once - // first entry should always have entry.parentDir === EMPTY_STR - if (this.globSymlink === undefined) { - this.globSymlink = entry.fullParentDir === this.fullWatchPath ? - false : {realPath: entry.fullParentDir, linkPath: this.fullWatchPath}; - } - - if (this.globSymlink) { - return entry.fullPath.replace(this.globSymlink.realPath, this.globSymlink.linkPath); - } - - return entry.fullPath; - } - - entryPath(entry) { - return sysPath.join(this.watchPath, - sysPath.relative(this.watchPath, this.checkGlobSymlink(entry)) - ); - } - - filterPath(entry) { - const {stats} = entry; - if (stats && stats.isSymbolicLink()) return this.filterDir(entry); - const resolvedPath = this.entryPath(entry); - const matchesGlob = this.hasGlob && typeof this.globFilter === FUNCTION_TYPE ? - this.globFilter(resolvedPath) : true; - return matchesGlob && - this.fsw._isntIgnored(resolvedPath, stats) && - this.fsw._hasReadPermissions(stats); - } - - getDirParts(path) { - if (!this.hasGlob) return []; - const parts = []; - const expandedPath = path.includes(BRACE_START) ? braces.expand(path) : [path]; - expandedPath.forEach((path) => { - parts.push(sysPath.relative(this.watchPath, path).split(SLASH_OR_BACK_SLASH_RE)); - }); - return parts; - } - - filterDir(entry) { - if (this.hasGlob) { - const entryParts = this.getDirParts(this.checkGlobSymlink(entry)); - let globstar = false; - this.unmatchedGlob = !this.dirParts.some((parts) => { - return parts.every((part, i) => { - if (part === GLOBSTAR$1) globstar = true; - return globstar || !entryParts[0][i] || anymatch(part, entryParts[0][i], ANYMATCH_OPTS); - }); - }); - } - return !this.unmatchedGlob && this.fsw._isntIgnored(this.entryPath(entry), entry.stats); - } -} - -/** - * Watches files & directories for changes. Emitted events: - * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error` - * - * new FSWatcher() - * .add(directories) - * .on('add', path => log('File', path, 'was added')) - */ -class FSWatcher extends EventEmitter { -// Not indenting methods for history sake; for now. -constructor(_opts) { - super(); - - const opts = {}; - if (_opts) Object.assign(opts, _opts); // for frozen objects - - /** @type {Map} */ - this._watched = new Map(); - /** @type {Map} */ - this._closers = new Map(); - /** @type {Set} */ - this._ignoredPaths = new Set(); - - /** @type {Map} */ - this._throttled = new Map(); - - /** @type {Map} */ - this._symlinkPaths = new Map(); - - this._streams = new Set(); - this.closed = false; - - // Set up default options. - if (undef(opts, 'persistent')) opts.persistent = true; - if (undef(opts, 'ignoreInitial')) opts.ignoreInitial = false; - if (undef(opts, 'ignorePermissionErrors')) opts.ignorePermissionErrors = false; - if (undef(opts, 'interval')) opts.interval = 100; - if (undef(opts, 'binaryInterval')) opts.binaryInterval = 300; - if (undef(opts, 'disableGlobbing')) opts.disableGlobbing = false; - opts.enableBinaryInterval = opts.binaryInterval !== opts.interval; - - // Enable fsevents on OS X when polling isn't explicitly enabled. - if (undef(opts, 'useFsEvents')) opts.useFsEvents = !opts.usePolling; - - // If we can't use fsevents, ensure the options reflect it's disabled. - const canUseFsEvents = FsEventsHandler.canUse(); - if (!canUseFsEvents) opts.useFsEvents = false; - - // Use polling on Mac if not using fsevents. - // Other platforms use non-polling fs_watch. - if (undef(opts, 'usePolling') && !opts.useFsEvents) { - opts.usePolling = isMacos; - } - - // Always default to polling on IBM i because fs.watch() is not available on IBM i. - if(isIBMi) { - opts.usePolling = true; - } - - // Global override (useful for end-developers that need to force polling for all - // instances of chokidar, regardless of usage/dependency depth) - const envPoll = process.env.CHOKIDAR_USEPOLLING; - if (envPoll !== undefined) { - const envLower = envPoll.toLowerCase(); - - if (envLower === 'false' || envLower === '0') { - opts.usePolling = false; - } else if (envLower === 'true' || envLower === '1') { - opts.usePolling = true; - } else { - opts.usePolling = !!envLower; - } - } - const envInterval = process.env.CHOKIDAR_INTERVAL; - if (envInterval) { - opts.interval = Number.parseInt(envInterval, 10); - } - - // Editor atomic write normalization enabled by default with fs.watch - if (undef(opts, 'atomic')) opts.atomic = !opts.usePolling && !opts.useFsEvents; - if (opts.atomic) this._pendingUnlinks = new Map(); - - if (undef(opts, 'followSymlinks')) opts.followSymlinks = true; - - if (undef(opts, 'awaitWriteFinish')) opts.awaitWriteFinish = false; - if (opts.awaitWriteFinish === true) opts.awaitWriteFinish = {}; - const awf = opts.awaitWriteFinish; - if (awf) { - if (!awf.stabilityThreshold) awf.stabilityThreshold = 2000; - if (!awf.pollInterval) awf.pollInterval = 100; - this._pendingWrites = new Map(); - } - if (opts.ignored) opts.ignored = arrify(opts.ignored); - - let readyCalls = 0; - this._emitReady = () => { - readyCalls++; - if (readyCalls >= this._readyCount) { - this._emitReady = EMPTY_FN; - this._readyEmitted = true; - // use process.nextTick to allow time for listener to be bound - process.nextTick(() => this.emit(EV_READY)); - } - }; - this._emitRaw = (...args) => this.emit(EV_RAW, ...args); - this._readyEmitted = false; - this.options = opts; - - // Initialize with proper watcher. - if (opts.useFsEvents) { - this._fsEventsHandler = new FsEventsHandler(this); - } else { - this._nodeFsHandler = new NodeFsHandler(this); - } - - // You’re frozen when your heart’s not open. - Object.freeze(opts); -} - -// Public methods - -/** - * Adds paths to be watched on an existing FSWatcher instance - * @param {Path|Array} paths_ - * @param {String=} _origAdd private; for handling non-existent paths to be watched - * @param {Boolean=} _internal private; indicates a non-user add - * @returns {FSWatcher} for chaining - */ -add(paths_, _origAdd, _internal) { - const {cwd, disableGlobbing} = this.options; - this.closed = false; - let paths = unifyPaths(paths_); - if (cwd) { - paths = paths.map((path) => { - const absPath = getAbsolutePath(path, cwd); - - // Check `path` instead of `absPath` because the cwd portion can't be a glob - if (disableGlobbing || !isGlob(path)) { - return absPath; - } - return normalizePath(absPath); - }); - } - - // set aside negated glob strings - paths = paths.filter((path) => { - if (path.startsWith(BANG)) { - this._ignoredPaths.add(path.slice(1)); - return false; - } - - // if a path is being added that was previously ignored, stop ignoring it - this._ignoredPaths.delete(path); - this._ignoredPaths.delete(path + SLASH_GLOBSTAR); - - // reset the cached userIgnored anymatch fn - // to make ignoredPaths changes effective - this._userIgnored = undefined; - - return true; - }); - - if (this.options.useFsEvents && this._fsEventsHandler) { - if (!this._readyCount) this._readyCount = paths.length; - if (this.options.persistent) this._readyCount *= 2; - paths.forEach((path) => this._fsEventsHandler._addToFsEvents(path)); - } else { - if (!this._readyCount) this._readyCount = 0; - this._readyCount += paths.length; - Promise.all( - paths.map(async path => { - const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, 0, 0, _origAdd); - if (res) this._emitReady(); - return res; - }) - ).then(results => { - if (this.closed) return; - results.filter(item => item).forEach(item => { - this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item)); - }); - }); - } - - return this; -} - -/** - * Close watchers or start ignoring events from specified paths. - * @param {Path|Array} paths_ - string or array of strings, file/directory paths and/or globs - * @returns {FSWatcher} for chaining -*/ -unwatch(paths_) { - if (this.closed) return this; - const paths = unifyPaths(paths_); - const {cwd} = this.options; - - paths.forEach((path) => { - // convert to absolute path unless relative path already matches - if (!sysPath.isAbsolute(path) && !this._closers.has(path)) { - if (cwd) path = sysPath.join(cwd, path); - path = sysPath.resolve(path); - } - - this._closePath(path); - - this._ignoredPaths.add(path); - if (this._watched.has(path)) { - this._ignoredPaths.add(path + SLASH_GLOBSTAR); - } - - // reset the cached userIgnored anymatch fn - // to make ignoredPaths changes effective - this._userIgnored = undefined; - }); - - return this; -} - -/** - * Close watchers and remove all listeners from watched paths. - * @returns {Promise}. -*/ -close() { - if (this.closed) return this._closePromise; - this.closed = true; - - // Memory management. - this.removeAllListeners(); - const closers = []; - this._closers.forEach(closerList => closerList.forEach(closer => { - const promise = closer(); - if (promise instanceof Promise) closers.push(promise); - })); - this._streams.forEach(stream => stream.destroy()); - this._userIgnored = undefined; - this._readyCount = 0; - this._readyEmitted = false; - this._watched.forEach(dirent => dirent.dispose()); - ['closers', 'watched', 'streams', 'symlinkPaths', 'throttled'].forEach(key => { - this[`_${key}`].clear(); - }); - - this._closePromise = closers.length ? Promise.all(closers).then(() => undefined) : Promise.resolve(); - return this._closePromise; -} - -/** - * Expose list of watched paths - * @returns {Object} for chaining -*/ -getWatched() { - const watchList = {}; - this._watched.forEach((entry, dir) => { - const key = this.options.cwd ? sysPath.relative(this.options.cwd, dir) : dir; - watchList[key || ONE_DOT] = entry.getChildren().sort(); - }); - return watchList; -} - -emitWithAll(event, args) { - this.emit(...args); - if (event !== EV_ERROR) this.emit(EV_ALL, ...args); -} - -// Common helpers -// -------------- - -/** - * Normalize and emit events. - * Calling _emit DOES NOT MEAN emit() would be called! - * @param {EventName} event Type of event - * @param {Path} path File or directory path - * @param {*=} val1 arguments to be passed with event - * @param {*=} val2 - * @param {*=} val3 - * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag - */ -async _emit(event, path, val1, val2, val3) { - if (this.closed) return; - - const opts = this.options; - if (isWindows$2) path = sysPath.normalize(path); - if (opts.cwd) path = sysPath.relative(opts.cwd, path); - /** @type Array */ - const args = [event, path]; - if (val3 !== undefined) args.push(val1, val2, val3); - else if (val2 !== undefined) args.push(val1, val2); - else if (val1 !== undefined) args.push(val1); - - const awf = opts.awaitWriteFinish; - let pw; - if (awf && (pw = this._pendingWrites.get(path))) { - pw.lastChange = new Date(); - return this; - } - - if (opts.atomic) { - if (event === EV_UNLINK) { - this._pendingUnlinks.set(path, args); - setTimeout(() => { - this._pendingUnlinks.forEach((entry, path) => { - this.emit(...entry); - this.emit(EV_ALL, ...entry); - this._pendingUnlinks.delete(path); - }); - }, typeof opts.atomic === 'number' ? opts.atomic : 100); - return this; - } - if (event === EV_ADD && this._pendingUnlinks.has(path)) { - event = args[0] = EV_CHANGE; - this._pendingUnlinks.delete(path); - } - } - - if (awf && (event === EV_ADD || event === EV_CHANGE) && this._readyEmitted) { - const awfEmit = (err, stats) => { - if (err) { - event = args[0] = EV_ERROR; - args[1] = err; - this.emitWithAll(event, args); - } else if (stats) { - // if stats doesn't exist the file must have been deleted - if (args.length > 2) { - args[2] = stats; - } else { - args.push(stats); - } - this.emitWithAll(event, args); - } - }; - - this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit); - return this; - } - - if (event === EV_CHANGE) { - const isThrottled = !this._throttle(EV_CHANGE, path, 50); - if (isThrottled) return this; - } - - if (opts.alwaysStat && val1 === undefined && - (event === EV_ADD || event === EV_ADD_DIR || event === EV_CHANGE) - ) { - const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path; - let stats; - try { - stats = await stat(fullPath); - } catch (err) {} - // Suppress event when fs_stat fails, to avoid sending undefined 'stat' - if (!stats || this.closed) return; - args.push(stats); - } - this.emitWithAll(event, args); - - return this; -} - -/** - * Common handler for errors - * @param {Error} error - * @returns {Error|Boolean} The error if defined, otherwise the value of the FSWatcher instance's `closed` flag - */ -_handleError(error) { - const code = error && error.code; - if (error && code !== 'ENOENT' && code !== 'ENOTDIR' && - (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES')) - ) { - this.emit(EV_ERROR, error); - } - return error || this.closed; -} - -/** - * Helper utility for throttling - * @param {ThrottleType} actionType type being throttled - * @param {Path} path being acted upon - * @param {Number} timeout duration of time to suppress duplicate actions - * @returns {Object|false} tracking object or false if action should be suppressed - */ -_throttle(actionType, path, timeout) { - if (!this._throttled.has(actionType)) { - this._throttled.set(actionType, new Map()); - } - - /** @type {Map} */ - const action = this._throttled.get(actionType); - /** @type {Object} */ - const actionPath = action.get(path); - - if (actionPath) { - actionPath.count++; - return false; - } - - let timeoutObject; - const clear = () => { - const item = action.get(path); - const count = item ? item.count : 0; - action.delete(path); - clearTimeout(timeoutObject); - if (item) clearTimeout(item.timeoutObject); - return count; - }; - timeoutObject = setTimeout(clear, timeout); - const thr = {timeoutObject, clear, count: 0}; - action.set(path, thr); - return thr; -} - -_incrReadyCount() { - return this._readyCount++; -} - -/** - * Awaits write operation to finish. - * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback. - * @param {Path} path being acted upon - * @param {Number} threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished - * @param {EventName} event - * @param {Function} awfEmit Callback to be called when ready for event to be emitted. - */ -_awaitWriteFinish(path, threshold, event, awfEmit) { - let timeoutHandler; - - let fullPath = path; - if (this.options.cwd && !sysPath.isAbsolute(path)) { - fullPath = sysPath.join(this.options.cwd, path); - } - - const now = new Date(); - - const awaitWriteFinish = (prevStat) => { - fs$6.stat(fullPath, (err, curStat) => { - if (err || !this._pendingWrites.has(path)) { - if (err && err.code !== 'ENOENT') awfEmit(err); - return; - } - - const now = Number(new Date()); - - if (prevStat && curStat.size !== prevStat.size) { - this._pendingWrites.get(path).lastChange = now; - } - const pw = this._pendingWrites.get(path); - const df = now - pw.lastChange; - - if (df >= threshold) { - this._pendingWrites.delete(path); - awfEmit(undefined, curStat); - } else { - timeoutHandler = setTimeout( - awaitWriteFinish, - this.options.awaitWriteFinish.pollInterval, - curStat - ); - } - }); - }; - - if (!this._pendingWrites.has(path)) { - this._pendingWrites.set(path, { - lastChange: now, - cancelWait: () => { - this._pendingWrites.delete(path); - clearTimeout(timeoutHandler); - return event; - } - }); - timeoutHandler = setTimeout( - awaitWriteFinish, - this.options.awaitWriteFinish.pollInterval - ); - } -} - -_getGlobIgnored() { - return [...this._ignoredPaths.values()]; -} - -/** - * Determines whether user has asked to ignore this path. - * @param {Path} path filepath or dir - * @param {fs.Stats=} stats result of fs.stat - * @returns {Boolean} - */ -_isIgnored(path, stats) { - if (this.options.atomic && DOT_RE.test(path)) return true; - if (!this._userIgnored) { - const {cwd} = this.options; - const ign = this.options.ignored; - - const ignored = ign && ign.map(normalizeIgnored(cwd)); - const paths = arrify(ignored) - .filter((path) => typeof path === STRING_TYPE && !isGlob(path)) - .map((path) => path + SLASH_GLOBSTAR); - const list = this._getGlobIgnored().map(normalizeIgnored(cwd)).concat(ignored, paths); - this._userIgnored = anymatch(list, undefined, ANYMATCH_OPTS); - } - - return this._userIgnored([path, stats]); -} - -_isntIgnored(path, stat) { - return !this._isIgnored(path, stat); -} - -/** - * Provides a set of common helpers and properties relating to symlink and glob handling. - * @param {Path} path file, directory, or glob pattern being watched - * @param {Number=} depth at any depth > 0, this isn't a glob - * @returns {WatchHelper} object containing helpers for this path - */ -_getWatchHelpers(path, depth) { - const watchPath = depth || this.options.disableGlobbing || !isGlob(path) ? path : globParent(path); - const follow = this.options.followSymlinks; - - return new WatchHelper(path, watchPath, follow, this); -} - -// Directory helpers -// ----------------- - -/** - * Provides directory tracking objects - * @param {String} directory path of the directory - * @returns {DirEntry} the directory's tracking object - */ -_getWatchedDir(directory) { - if (!this._boundRemove) this._boundRemove = this._remove.bind(this); - const dir = sysPath.resolve(directory); - if (!this._watched.has(dir)) this._watched.set(dir, new DirEntry(dir, this._boundRemove)); - return this._watched.get(dir); -} - -// File helpers -// ------------ - -/** - * Check for read permissions. - * Based on this answer on SO: https://stackoverflow.com/a/11781404/1358405 - * @param {fs.Stats} stats - object, result of fs_stat - * @returns {Boolean} indicates whether the file can be read -*/ -_hasReadPermissions(stats) { - if (this.options.ignorePermissionErrors) return true; - - // stats.mode may be bigint - const md = stats && Number.parseInt(stats.mode, 10); - const st = md & 0o777; - const it = Number.parseInt(st.toString(8)[0], 10); - return Boolean(4 & it); -} - -/** - * Handles emitting unlink events for - * files and directories, and via recursion, for - * files and directories within directories that are unlinked - * @param {String} directory within which the following item is located - * @param {String} item base path of item/directory - * @returns {void} -*/ -_remove(directory, item, isDirectory) { - // if what is being deleted is a directory, get that directory's paths - // for recursive deleting and cleaning of watched object - // if it is not a directory, nestedDirectoryChildren will be empty array - const path = sysPath.join(directory, item); - const fullPath = sysPath.resolve(path); - isDirectory = isDirectory != null - ? isDirectory - : this._watched.has(path) || this._watched.has(fullPath); - - // prevent duplicate handling in case of arriving here nearly simultaneously - // via multiple paths (such as _handleFile and _handleDir) - if (!this._throttle('remove', path, 100)) return; - - // if the only watched file is removed, watch for its return - if (!isDirectory && !this.options.useFsEvents && this._watched.size === 1) { - this.add(directory, item, true); - } - - // This will create a new entry in the watched object in either case - // so we got to do the directory check beforehand - const wp = this._getWatchedDir(path); - const nestedDirectoryChildren = wp.getChildren(); - - // Recursively remove children directories / files. - nestedDirectoryChildren.forEach(nested => this._remove(path, nested)); - - // Check if item was on the watched list and remove it - const parent = this._getWatchedDir(directory); - const wasTracked = parent.has(item); - parent.remove(item); - - // Fixes issue #1042 -> Relative paths were detected and added as symlinks - // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612), - // but never removed from the map in case the path was deleted. - // This leads to an incorrect state if the path was recreated: - // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553 - if (this._symlinkPaths.has(fullPath)) { - this._symlinkPaths.delete(fullPath); - } - - // If we wait for this file to be fully written, cancel the wait. - let relPath = path; - if (this.options.cwd) relPath = sysPath.relative(this.options.cwd, path); - if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) { - const event = this._pendingWrites.get(relPath).cancelWait(); - if (event === EV_ADD) return; - } - - // The Entry will either be a directory that just got removed - // or a bogus entry to a file, in either case we have to remove it - this._watched.delete(path); - this._watched.delete(fullPath); - const eventName = isDirectory ? EV_UNLINK_DIR : EV_UNLINK; - if (wasTracked && !this._isIgnored(path)) this._emit(eventName, path); - - // Avoid conflicts if we later create another file with the same name - if (!this.options.useFsEvents) { - this._closePath(path); - } -} - -/** - * Closes all watchers for a path - * @param {Path} path - */ -_closePath(path) { - this._closeFile(path); - const dir = sysPath.dirname(path); - this._getWatchedDir(dir).remove(sysPath.basename(path)); -} - -/** - * Closes only file-specific watchers - * @param {Path} path - */ -_closeFile(path) { - const closers = this._closers.get(path); - if (!closers) return; - closers.forEach(closer => closer()); - this._closers.delete(path); -} - -/** - * - * @param {Path} path - * @param {Function} closer - */ -_addPathCloser(path, closer) { - if (!closer) return; - let list = this._closers.get(path); - if (!list) { - list = []; - this._closers.set(path, list); - } - list.push(closer); -} - -_readdirp(root, opts) { - if (this.closed) return; - const options = {type: EV_ALL, alwaysStat: true, lstat: true, ...opts}; - let stream = readdirp(root, options); - this._streams.add(stream); - stream.once(STR_CLOSE, () => { - stream = undefined; - }); - stream.once(STR_END, () => { - if (stream) { - this._streams.delete(stream); - stream = undefined; - } - }); - return stream; -} - -} - -// Export FSWatcher class -chokidar.FSWatcher = FSWatcher; - -/** - * Instantiates watcher with paths to be tracked. - * @param {String|Array} paths file/directory paths and/or globs - * @param {Object=} options chokidar opts - * @returns an instance of FSWatcher for chaining. - */ -const watch = (paths, options) => { - const watcher = new FSWatcher(options); - watcher.add(paths); - return watcher; -}; - -chokidar.watch = watch; - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('vfile-message').VFileMessage} VFileMessage - * - * @typedef Statistics - * @property {number} fatal Fatal errors (`fatal: true`) - * @property {number} warn warning errors (`fatal: false`) - * @property {number} info informational messages (`fatal: null|undefined`) - * @property {number} nonfatal warning + info - * @property {number} total nonfatal + fatal - */ - -/** - * Get stats for a file, list of files, or list of messages. - * - * @param {Array.|VFile|VFileMessage} [value] - * @returns {Statistics} - */ -function statistics(value) { - var result = {true: 0, false: 0, null: 0}; - - if (value) { - if (Array.isArray(value)) { - list(value); - } else { - one(value); - } - } - - return { - fatal: result.true, - nonfatal: result.false + result.null, - warn: result.false, - info: result.null, - total: result.true + result.false + result.null - } - - /** - * @param {Array.} value - * @returns {void} - */ - function list(value) { - var index = -1; - - while (++index < value.length) { - one(value[index]); - } - } - - /** - * @param {VFile|VFileMessage} value - * @returns {void} - */ - function one(value) { - if ('messages' in value) return list(value.messages) - - result[ - value.fatal === undefined || value.fatal === null - ? null - : Boolean(value.fatal) - ]++; - } -} - -/** - * @typedef {(error?: Error|null|undefined, ...output: any[]) => void} Callback - * @typedef {(...input: any[]) => any} Middleware - * - * @typedef {(...input: any[]) => void} Run Call all middleware. - * @typedef {(fn: Middleware) => Pipeline} Use Add `fn` (middleware) to the list. - * @typedef {{run: Run, use: Use}} Pipeline - */ - -/** - * Create new middleware. - * - * @returns {Pipeline} - */ -function trough() { - /** @type {Middleware[]} */ - const fns = []; - /** @type {Pipeline} */ - const pipeline = {run, use}; - - return pipeline - - /** @type {Run} */ - function run(...values) { - let middlewareIndex = -1; - /** @type {Callback} */ - const callback = values.pop(); - - if (typeof callback !== 'function') { - throw new TypeError('Expected function as last argument, not ' + callback) - } - - next(null, ...values); - - /** - * Run the next `fn`, or we’re done. - * - * @param {Error|null|undefined} error - * @param {any[]} output - */ - function next(error, ...output) { - const fn = fns[++middlewareIndex]; - let index = -1; - - if (error) { - callback(error); - return - } - - // Copy non-nullish input into values. - while (++index < values.length) { - if (output[index] === null || output[index] === undefined) { - output[index] = values[index]; - } - } - - // Save the newly created `output` for the next call. - values = output; - - // Next or done. - if (fn) { - wrap(fn, next)(...output); - } else { - callback(null, ...output); - } - } - } - - /** @type {Use} */ - function use(middelware) { - if (typeof middelware !== 'function') { - throw new TypeError( - 'Expected `middelware` to be a function, not ' + middelware - ) - } - - fns.push(middelware); - return pipeline - } -} - -/** - * Wrap `middleware`. - * Can be sync or async; return a promise, receive a callback, or return new - * values and errors. - * - * @param {Middleware} middleware - * @param {Callback} callback - */ -function wrap(middleware, callback) { - /** @type {boolean} */ - let called; - - return wrapped - - /** - * Call `middleware`. - * @param {any[]} parameters - * @returns {void} - */ - function wrapped(...parameters) { - const fnExpectsCallback = middleware.length > parameters.length; - /** @type {any} */ - let result; - - if (fnExpectsCallback) { - parameters.push(done); - } - - try { - result = middleware(...parameters); - } catch (error) { - /** @type {Error} */ - const exception = error; - - // Well, this is quite the pickle. - // `middleware` received a callback and called it synchronously, but that - // threw an error. - // The only thing left to do is to throw the thing instead. - if (fnExpectsCallback && called) { - throw exception - } - - return done(exception) - } - - if (!fnExpectsCallback) { - if (result instanceof Promise) { - result.then(then, done); - } else if (result instanceof Error) { - done(result); - } else { - then(result); - } - } - } - - /** - * Call `callback`, only once. - * @type {Callback} - */ - function done(error, ...output) { - if (!called) { - called = true; - callback(error, ...output); - } - } - - /** - * Call `done` with one value. - * - * @param {any} [value] - */ - function then(value) { - done(null, value); - } -} - -/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */ -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$2(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); -} - - -var isNothing_1 = isNothing; -var isObject_1 = isObject$1; -var toArray_1 = toArray; -var repeat_1 = repeat; -var isNegativeZero_1 = isNegativeZero; -var extend_1 = extend$2; - -var common$4 = { - isNothing: isNothing_1, - isObject: isObject_1, - toArray: toArray_1, - repeat: repeat_1, - isNegativeZero: isNegativeZero_1, - extend: extend_1 -}; - -// YAML error class. http://stackoverflow.com/questions/8458984 - - -function formatError(exception, compact) { - var where = '', message = exception.reason || '(unknown reason)'; - - if (!exception.mark) return message; - - if (exception.mark.name) { - where += 'in "' + exception.mark.name + '" '; - } - - where += '(' + (exception.mark.line + 1) + ':' + (exception.mark.column + 1) + ')'; - - if (!compact && exception.mark.snippet) { - where += '\n\n' + exception.mark.snippet; - } - - return message + ' ' + where; -} - - -function YAMLException$1(reason, mark) { - // Super constructor - Error.call(this); - - this.name = 'YAMLException'; - this.reason = reason; - this.mark = mark; - this.message = formatError(this, false); - - // 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$1.prototype = Object.create(Error.prototype); -YAMLException$1.prototype.constructor = YAMLException$1; - - -YAMLException$1.prototype.toString = function toString(compact) { - return this.name + ': ' + formatError(this, compact); -}; - - -var exception = YAMLException$1; - -// get snippet for a single line, respecting maxLength -function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { - var head = ''; - var tail = ''; - var maxHalfLength = Math.floor(maxLineLength / 2) - 1; - - if (position - lineStart > maxHalfLength) { - head = ' ... '; - lineStart = position - maxHalfLength + head.length; - } - - if (lineEnd - position > maxHalfLength) { - tail = ' ...'; - lineEnd = position + maxHalfLength - tail.length; - } - - return { - str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, '→') + tail, - pos: position - lineStart + head.length // relative position - }; -} - - -function padStart(string, max) { - return common$4.repeat(' ', max - string.length) + string; -} - - -function makeSnippet(mark, options) { - options = Object.create(options || null); - - if (!mark.buffer) return null; - - if (!options.maxLength) options.maxLength = 79; - if (typeof options.indent !== 'number') options.indent = 1; - if (typeof options.linesBefore !== 'number') options.linesBefore = 3; - if (typeof options.linesAfter !== 'number') options.linesAfter = 2; - - var re = /\r?\n|\r|\0/g; - var lineStarts = [ 0 ]; - var lineEnds = []; - var match; - var foundLineNo = -1; - - while ((match = re.exec(mark.buffer))) { - lineEnds.push(match.index); - lineStarts.push(match.index + match[0].length); - - if (mark.position <= match.index && foundLineNo < 0) { - foundLineNo = lineStarts.length - 2; - } - } - - if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; - - var result = '', i, line; - var lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length; - var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3); - - for (i = 1; i <= options.linesBefore; i++) { - if (foundLineNo - i < 0) break; - line = getLine( - mark.buffer, - lineStarts[foundLineNo - i], - lineEnds[foundLineNo - i], - mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), - maxLineLength - ); - result = common$4.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) + - ' | ' + line.str + '\n' + result; - } - - line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); - result += common$4.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) + - ' | ' + line.str + '\n'; - result += common$4.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\n'; - - for (i = 1; i <= options.linesAfter; i++) { - if (foundLineNo + i >= lineEnds.length) break; - line = getLine( - mark.buffer, - lineStarts[foundLineNo + i], - lineEnds[foundLineNo + i], - mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), - maxLineLength - ); - result += common$4.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) + - ' | ' + line.str + '\n'; - } - - return result.replace(/\n$/, ''); -} - - -var snippet = makeSnippet; - -var TYPE_CONSTRUCTOR_OPTIONS = [ - 'kind', - 'multi', - 'resolve', - 'construct', - 'instanceOf', - 'predicate', - 'represent', - 'representName', - '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$1(tag, options) { - options = options || {}; - - Object.keys(options).forEach(function (name) { - if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) { - throw new exception('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.'); - } - }); - - // TODO: Add tag format check. - this.options = options; // keep original options in case user wants to extend this type later - 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.representName = options['representName'] || null; - this.defaultStyle = options['defaultStyle'] || null; - this.multi = options['multi'] || false; - this.styleAliases = compileStyleAliases(options['styleAliases'] || null); - - if (YAML_NODE_KINDS.indexOf(this.kind) === -1) { - throw new exception('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.'); - } -} - -var type$1 = Type$1; - -/*eslint-disable max-len*/ - - - - - -function compileList(schema, name) { - var result = []; - - schema[name].forEach(function (currentType) { - var newIndex = result.length; - - result.forEach(function (previousType, previousIndex) { - if (previousType.tag === currentType.tag && - previousType.kind === currentType.kind && - previousType.multi === currentType.multi) { - - newIndex = previousIndex; - } - }); - - result[newIndex] = currentType; - }); - - return result; -} - - -function compileMap(/* lists... */) { - var result = { - scalar: {}, - sequence: {}, - mapping: {}, - fallback: {}, - multi: { - scalar: [], - sequence: [], - mapping: [], - fallback: [] - } - }, index, length; - - function collectType(type) { - if (type.multi) { - result.multi[type.kind].push(type); - result.multi['fallback'].push(type); - } else { - 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$1(definition) { - return this.extend(definition); -} - - -Schema$1.prototype.extend = function extend(definition) { - var implicit = []; - var explicit = []; - - if (definition instanceof type$1) { - // Schema.extend(type) - explicit.push(definition); - - } else if (Array.isArray(definition)) { - // Schema.extend([ type1, type2, ... ]) - explicit = explicit.concat(definition); - - } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) { - // Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] }) - if (definition.implicit) implicit = implicit.concat(definition.implicit); - if (definition.explicit) explicit = explicit.concat(definition.explicit); - - } else { - throw new exception('Schema.extend argument should be a Type, [ Type ], ' + - 'or a schema definition ({ implicit: [...], explicit: [...] })'); - } - - implicit.forEach(function (type$1$1) { - if (!(type$1$1 instanceof type$1)) { - throw new exception('Specified list of YAML types (or a single Type object) contains a non-Type object.'); - } - - if (type$1$1.loadKind && type$1$1.loadKind !== 'scalar') { - throw new exception('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.'); - } - - if (type$1$1.multi) { - throw new exception('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.'); - } - }); - - explicit.forEach(function (type$1$1) { - if (!(type$1$1 instanceof type$1)) { - throw new exception('Specified list of YAML types (or a single Type object) contains a non-Type object.'); - } - }); - - var result = Object.create(Schema$1.prototype); - - result.implicit = (this.implicit || []).concat(implicit); - result.explicit = (this.explicit || []).concat(explicit); - - result.compiledImplicit = compileList(result, 'implicit'); - result.compiledExplicit = compileList(result, 'explicit'); - result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit); - - return result; -}; - - -var schema$1 = Schema$1; - -var str = new type$1('tag:yaml.org,2002:str', { - kind: 'scalar', - construct: function (data) { return data !== null ? data : ''; } -}); - -var seq = new type$1('tag:yaml.org,2002:seq', { - kind: 'sequence', - construct: function (data) { return data !== null ? data : []; } -}); - -var map$3 = new type$1('tag:yaml.org,2002:map', { - kind: 'mapping', - construct: function (data) { return data !== null ? data : {}; } -}); - -var failsafe = new schema$1({ - explicit: [ - str, - seq, - map$3 - ] -}); - -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$1('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'; }, - empty: function () { return ''; } - }, - defaultStyle: 'lowercase' -}); - -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$1('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' -}); - -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 !== '_'; - } - - - if (ch === 'o') { - // base 8 - index++; - - 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) - - // value should not start with `_`; - if (ch === '_') return false; - - for (; index < max; index++) { - ch = data[index]; - if (ch === '_') continue; - if (!isDecCode(data.charCodeAt(index))) { - return false; - } - hasDigits = true; - } - - // Should have digits and should not end with `_` - if (!hasDigits || ch === '_') return false; - - return true; -} - -function constructYamlInteger(data) { - var value = data, sign = 1, ch; - - 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.slice(2), 16); - if (value[1] === 'o') return sign * parseInt(value.slice(2), 8); - } - - return sign * parseInt(value, 10); -} - -function isInteger(object) { - return (Object.prototype.toString.call(object)) === '[object Number]' && - (object % 1 === 0 && !common$4.isNegativeZero(object)); -} - -var int = new type$1('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 ? '0o' + obj.toString(8) : '-0o' + 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 YAML_FLOAT_PATTERN = new RegExp( - // 2.5e4, 2.5 and integers - '^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?' + - // .2e4, .2 - // special case, seems not from spec - '|\\.[0-9_]+(?:[eE][-+]?[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; - - value = data.replace(/_/g, '').toLowerCase(); - sign = value[0] === '-' ? -1 : 1; - - 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; - } - 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$4.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$4.isNegativeZero(object)); -} - -var float = new type$1('tag:yaml.org,2002:float', { - kind: 'scalar', - resolve: resolveYamlFloat, - construct: constructYamlFloat, - predicate: isFloat, - represent: representYamlFloat, - defaultStyle: 'lowercase' -}); - -var json = failsafe.extend({ - implicit: [ - _null, - bool, - int, - float - ] -}); - -var core = json; - -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$1('tag:yaml.org,2002:timestamp', { - kind: 'scalar', - resolve: resolveYamlTimestamp, - construct: constructYamlTimestamp, - instanceOf: Date, - represent: representYamlTimestamp -}); - -function resolveYamlMerge(data) { - return data === '<<' || data === null; -} - -var merge$1 = new type$1('tag:yaml.org,2002:merge', { - kind: 'scalar', - resolve: resolveYamlMerge -}); - -/*eslint-disable no-bitwise*/ - - - - - -// [ 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); - } - - return new Uint8Array(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(obj) { - return Object.prototype.toString.call(obj) === '[object Uint8Array]'; -} - -var binary = new type$1('tag:yaml.org,2002:binary', { - kind: 'scalar', - resolve: resolveYamlBinary, - construct: constructYamlBinary, - predicate: isBinary, - represent: representYamlBinary -}); - -var _hasOwnProperty$3 = 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$3.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$1('tag:yaml.org,2002:omap', { - kind: 'sequence', - resolve: resolveYamlOmap, - construct: constructYamlOmap -}); - -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$1('tag:yaml.org,2002:pairs', { - kind: 'sequence', - resolve: resolveYamlPairs, - construct: constructYamlPairs -}); - -var _hasOwnProperty$2 = Object.prototype.hasOwnProperty; - -function resolveYamlSet(data) { - if (data === null) return true; - - var key, object = data; - - for (key in object) { - if (_hasOwnProperty$2.call(object, key)) { - if (object[key] !== null) return false; - } - } - - return true; -} - -function constructYamlSet(data) { - return data !== null ? data : {}; -} - -var set = new type$1('tag:yaml.org,2002:set', { - kind: 'mapping', - resolve: resolveYamlSet, - construct: constructYamlSet -}); - -var _default$1 = core.extend({ - implicit: [ - timestamp, - merge$1 - ], - explicit: [ - binary, - omap, - pairs, - set - ] -}); - -/*eslint-disable max-len,no-use-before-define*/ - - - - - - - -var _hasOwnProperty$1 = 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(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 = 0; i < 256; i++) { - simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; - simpleEscapeMap[i] = simpleEscapeSequence(i); -} - - -function State$1(input, options) { - this.input = input; - - this.filename = options['filename'] || null; - this.schema = options['schema'] || _default$1; - this.onWarning = options['onWarning'] || null; - // (Hidden) Remove? makes the loader to expect YAML 1.1 documents - // if such documents have no explicit %YAML directive - 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; - - // position of first leading tab in the current line, - // used to make sure there are no tabs in the indentation - this.firstTabInLine = -1; - - this.documents = []; - - /* - this.version; - this.checkLineBreaks; - this.tagMap; - this.anchorMap; - this.tag; - this.anchor; - this.kind; - this.result;*/ - -} - - -function generateError(state, message) { - var mark = { - name: state.filename, - buffer: state.input.slice(0, -1), // omit trailing \0 - position: state.position, - line: state.line, - column: state.position - state.lineStart - }; - - mark.snippet = snippet(mark); - - return new exception(message, mark); -} - -function throwError$1(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$1(state, 'duplication of %YAML directive'); - } - - if (args.length !== 1) { - throwError$1(state, 'YAML directive accepts exactly one argument'); - } - - match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); - - if (match === null) { - throwError$1(state, 'ill-formed argument of the YAML directive'); - } - - major = parseInt(match[1], 10); - minor = parseInt(match[2], 10); - - if (major !== 1) { - throwError$1(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$1(state, 'TAG directive accepts exactly two arguments'); - } - - handle = args[0]; - prefix = args[1]; - - if (!PATTERN_TAG_HANDLE.test(handle)) { - throwError$1(state, 'ill-formed tag handle (first argument) of the TAG directive'); - } - - if (_hasOwnProperty$1.call(state.tagMap, handle)) { - throwError$1(state, 'there is a previously declared suffix for "' + handle + '" tag handle'); - } - - if (!PATTERN_TAG_URI.test(prefix)) { - throwError$1(state, 'ill-formed tag prefix (second argument) of the TAG directive'); - } - - try { - prefix = decodeURIComponent(prefix); - } catch (err) { - throwError$1(state, 'tag prefix is malformed: ' + prefix); - } - - 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$1(state, 'expected valid JSON character'); - } - } - } else if (PATTERN_NON_PRINTABLE.test(_result)) { - throwError$1(state, 'the stream contains non-printable characters'); - } - - state.result += _result; - } -} - -function mergeMappings(state, destination, source, overridableKeys) { - var sourceKeys, key, index, quantity; - - if (!common$4.isObject(source)) { - throwError$1(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$1.call(destination, key)) { - destination[key] = source[key]; - overridableKeys[key] = true; - } - } -} - -function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, - startLine, startLineStart, 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$1(state, 'nested arrays are not supported inside keys'); - } - - if (typeof keyNode === 'object' && _class(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(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$1.call(overridableKeys, keyNode) && - _hasOwnProperty$1.call(_result, keyNode)) { - state.line = startLine || state.line; - state.lineStart = startLineStart || state.lineStart; - state.position = startPos || state.position; - throwError$1(state, 'duplicated mapping key'); - } - - // used for this specific key only because Object.defineProperty is slow - if (keyNode === '__proto__') { - Object.defineProperty(_result, keyNode, { - configurable: true, - enumerable: true, - writable: true, - value: valueNode - }); - } else { - _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$1(state, 'a line break is expected'); - } - - state.line += 1; - state.lineStart = state.position; - state.firstTabInLine = -1; -} - -function skipSeparationSpace(state, allowComments, checkIndent) { - var lineBreaks = 0, - ch = state.input.charCodeAt(state.position); - - while (ch !== 0) { - while (is_WHITE_SPACE(ch)) { - if (ch === 0x09/* Tab */ && state.firstTabInLine === -1) { - state.firstTabInLine = state.position; - } - 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$4.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$1(state, 'unexpected end of the document within a single quoted scalar'); - - } else { - state.position++; - captureEnd = state.position; - } - } - - throwError$1(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$1(state, 'expected hexadecimal character'); - } - } - - state.result += charFromCodepoint(hexResult); - - state.position++; - - } else { - throwError$1(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$1(state, 'unexpected end of the document within a double quoted scalar'); - - } else { - state.position++; - captureEnd = state.position; - } - } - - throwError$1(state, 'unexpected end of the stream within a double quoted scalar'); -} - -function readFlowCollection(state, nodeIndent) { - var readNext = true, - _line, - _lineStart, - _pos, - _tag = state.tag, - _result, - _anchor = state.anchor, - following, - terminator, - isPair, - isExplicitPair, - isMapping, - overridableKeys = Object.create(null), - 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$1(state, 'missed comma between flow collection entries'); - } else if (ch === 0x2C/* , */) { - // "flow collection entries can never be completely empty", as per YAML 1.2, section 7.4 - throwError$1(state, "expected the node content, but found ','"); - } - - 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; // Save the current line. - _lineStart = state.lineStart; - _pos = state.position; - 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, _line, _lineStart, _pos); - } else if (isPair) { - _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos)); - } 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$1(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$1(state, 'repeat of a chomping mode identifier'); - } - - } else if ((tmp = fromDecimalCode(ch)) >= 0) { - if (tmp === 0) { - throwError$1(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$1(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$4.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$4.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines); - - // End of more-indented block. - } else if (atMoreIndented) { - atMoreIndented = false; - state.result += common$4.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$4.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$4.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; - - // there is a leading tab before this token, so it can't be a block sequence/mapping; - // it can still be flow sequence/mapping or a scalar - if (state.firstTabInLine !== -1) return false; - - if (state.anchor !== null) { - state.anchorMap[state.anchor] = _result; - } - - ch = state.input.charCodeAt(state.position); - - while (ch !== 0) { - if (state.firstTabInLine !== -1) { - state.position = state.firstTabInLine; - throwError$1(state, 'tab characters must not be used in indentation'); - } - - 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$1(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, - _keyLine, - _keyLineStart, - _keyPos, - _tag = state.tag, - _anchor = state.anchor, - _result = {}, - overridableKeys = Object.create(null), - keyTag = null, - keyNode = null, - valueNode = null, - atExplicitKey = false, - detected = false, - ch; - - // there is a leading tab before this token, so it can't be a block sequence/mapping; - // it can still be flow sequence/mapping or a scalar - if (state.firstTabInLine !== -1) return false; - - if (state.anchor !== null) { - state.anchorMap[state.anchor] = _result; - } - - ch = state.input.charCodeAt(state.position); - - while (ch !== 0) { - if (!atExplicitKey && state.firstTabInLine !== -1) { - state.position = state.firstTabInLine; - throwError$1(state, 'tab characters must not be used in indentation'); - } - - following = state.input.charCodeAt(state.position + 1); - _line = state.line; // Save the current line. - - // - // 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, _keyLine, _keyLineStart, _keyPos); - 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$1(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 { - _keyLine = state.line; - _keyLineStart = state.lineStart; - _keyPos = state.position; - - if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) { - // Neither implicit nor explicit notation. - // Reading is done. Go to the epilogue. - break; - } - - 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$1(state, 'a whitespace character is expected after the key-value separator within a block mapping'); - } - - if (atExplicitKey) { - storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos); - keyTag = keyNode = valueNode = null; - } - - detected = true; - atExplicitKey = false; - allowCompact = false; - keyTag = state.tag; - keyNode = state.result; - - } else if (detected) { - throwError$1(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$1(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`. - } - } - - // - // Common reading code for both explicit and implicit notations. - // - if (state.line === _line || state.lineIndent > nodeIndent) { - if (atExplicitKey) { - _keyLine = state.line; - _keyLineStart = state.lineStart; - _keyPos = state.position; - } - - 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, _keyLine, _keyLineStart, _keyPos); - keyTag = keyNode = valueNode = null; - } - - skipSeparationSpace(state, true, -1); - ch = state.input.charCodeAt(state.position); - } - - if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) { - throwError$1(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, _keyLine, _keyLineStart, _keyPos); - } - - // 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$1(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$1(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$1(state, 'named tag handle cannot contain such characters'); - } - - isNamed = true; - _position = state.position + 1; - } else { - throwError$1(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$1(state, 'tag suffix cannot contain flow indicator characters'); - } - } - - if (tagName && !PATTERN_TAG_URI.test(tagName)) { - throwError$1(state, 'tag name cannot contain such characters: ' + tagName); - } - - try { - tagName = decodeURIComponent(tagName); - } catch (err) { - throwError$1(state, 'tag name is malformed: ' + tagName); - } - - if (isVerbatim) { - state.tag = tagName; - - } else if (_hasOwnProperty$1.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$1(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$1(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$1(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$1(state, 'name of an alias node must contain at least one character'); - } - - alias = state.input.slice(_position, state.position); - - if (!_hasOwnProperty$1.call(state.anchorMap, alias)) { - throwError$1(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 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$1(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) { - if (state.anchor !== null) { - state.anchorMap[state.anchor] = state.result; - } - - } else 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$1(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 (state.tag !== '!') { - if (_hasOwnProperty$1.call(state.typeMap[state.kind || 'fallback'], state.tag)) { - type = state.typeMap[state.kind || 'fallback'][state.tag]; - } else { - // looking for multi type - type = null; - typeList = state.typeMap.multi[state.kind || 'fallback']; - - for (typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) { - if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) { - type = typeList[typeIndex]; - break; - } - } - } - - if (!type) { - throwError$1(state, 'unknown tag !<' + state.tag + '>'); - } - - if (state.result !== null && type.kind !== state.kind) { - throwError$1(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be "' + type.kind + '", not "' + state.kind + '"'); - } - - if (!type.resolve(state.result, state.tag)) { // `state.result` updated in resolver if matched - throwError$1(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag'); - } else { - state.result = type.construct(state.result, state.tag); - if (state.anchor !== null) { - state.anchorMap[state.anchor] = state.result; - } - } - } - - 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 = Object.create(null); - state.anchorMap = Object.create(null); - - 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$1(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$1.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$1(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$1(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$1(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$1(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 exception('expected a single document in the stream, but found more'); -} - - -var loadAll_1 = loadAll$1; -var load_1 = load$1; - -var loader = { - loadAll: loadAll_1, - load: load_1 -}; - -/*eslint-disable no-use-before-define*/ - - - - - -var _toString = Object.prototype.toString; -var _hasOwnProperty = Object.prototype.hasOwnProperty; - -var CHAR_BOM = 0xFEFF; -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' -]; - -var DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/; - -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.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 exception('code point within a string may not be greater than 0xFFFFFFFF'); - } - - return '\\' + handle + common$4.repeat('0', length - string.length) + string; -} - - -var QUOTING_TYPE_SINGLE = 1, - QUOTING_TYPE_DOUBLE = 2; - -function State(options) { - this.schema = options['schema'] || _default$1; - this.indent = Math.max(1, (options['indent'] || 2)); - this.noArrayIndent = options['noArrayIndent'] || false; - this.skipInvalid = options['skipInvalid'] || false; - this.flowLevel = (common$4.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.quotingType = options['quotingType'] === '"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE; - this.forceQuotes = options['forceQuotes'] || false; - this.replacer = typeof options['replacer'] === 'function' ? options['replacer'] : null; - - 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$4.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$4.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 !== CHAR_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 -// Including s-white (for some reason, examples doesn't match specs in this aspect) -// ns-char ::= c-printable - b-line-feed - b-carriage-return - c-byte-order-mark -function isNsCharOrWhitespace(c) { - return isPrintable(c) - && c !== CHAR_BOM - // - b-char - && c !== CHAR_CARRIAGE_RETURN - && c !== CHAR_LINE_FEED; -} - -// [127] ns-plain-safe(c) ::= c = flow-out ⇒ ns-plain-safe-out -// c = flow-in ⇒ ns-plain-safe-in -// c = block-key ⇒ ns-plain-safe-out -// c = flow-key ⇒ ns-plain-safe-in -// [128] ns-plain-safe-out ::= ns-char -// [129] ns-plain-safe-in ::= ns-char - c-flow-indicator -// [130] ns-plain-char(c) ::= ( ns-plain-safe(c) - “:” - “#” ) -// | ( /* An ns-char preceding */ “#” ) -// | ( “:” /* Followed by an ns-plain-safe(c) */ ) -function isPlainSafe(c, prev, inblock) { - var cIsNsCharOrWhitespace = isNsCharOrWhitespace(c); - var cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c); - return ( - // ns-plain-safe - inblock ? // c = flow-in - cIsNsCharOrWhitespace - : cIsNsCharOrWhitespace - // - 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 - ) - // ns-plain-char - && c !== CHAR_SHARP // false on '#' - && !(prev === CHAR_COLON && !cIsNsChar) // false on ': ' - || (isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP) // change to true on '[^ ]#' - || (prev === CHAR_COLON && cIsNsChar); // change to true on ':[^ ]' -} - -// 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. - // No support of ( ( “?” | “:” | “-” ) /* Followed by an ns-plain-safe(c)) */ ) part - return isPrintable(c) && c !== CHAR_BOM - && !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; -} - -// Simplified test for values allowed as the last character in plain style. -function isPlainSafeLast(c) { - // just not whitespace or colon, it will be checked to be plain character later - return !isWhitespace(c) && c !== CHAR_COLON; -} - -// Same as 'string'.codePointAt(pos), but works in older browsers. -function codePointAt(string, pos) { - var first = string.charCodeAt(pos), second; - if (first >= 0xD800 && first <= 0xDBFF && pos + 1 < string.length) { - second = string.charCodeAt(pos + 1); - if (second >= 0xDC00 && second <= 0xDFFF) { - // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae - return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; - } - } - return first; -} - -// 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, quotingType, forceQuotes, inblock) { - - var i; - var char = 0; - var prevChar = null; - 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(codePointAt(string, 0)) - && isPlainSafeLast(codePointAt(string, string.length - 1)); - - if (singleLineOnly || forceQuotes) { - // Case: no block styles. - // Check for disallowed characters to rule out plain and single. - for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) { - char = codePointAt(string, i); - if (!isPrintable(char)) { - return STYLE_DOUBLE; - } - plain = plain && isPlainSafe(char, prevChar, inblock); - prevChar = char; - } - } else { - // Case: block styles permitted. - for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) { - char = codePointAt(string, 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; - } - plain = plain && isPlainSafe(char, prevChar, inblock); - prevChar = 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. - if (plain && !forceQuotes && !testAmbiguousType(string)) { - return STYLE_PLAIN; - } - return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : 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. - if (!forceQuotes) { - return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL; - } - return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE; -} - -// 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, inblock) { - state.dump = (function () { - if (string.length === 0) { - return state.quotingType === QUOTING_TYPE_DOUBLE ? '""' : "''"; - } - if (!state.noCompatMode) { - if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) { - return state.quotingType === QUOTING_TYPE_DOUBLE ? ('"' + string + '"') : ("'" + 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, state.quotingType, state.forceQuotes && !iskey, inblock)) { - - 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 exception('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 = 0; - var escapeSeq; - - for (var i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) { - char = codePointAt(string, i); - escapeSeq = ESCAPE_SEQUENCES[char]; - - if (!escapeSeq && isPrintable(char)) { - result += string[i]; - if (char >= 0x10000) result += string[i + 1]; - } else { - result += escapeSeq || encodeHex(char); - } - } - - return result; -} - -function writeFlowSequence(state, level, object) { - var _result = '', - _tag = state.tag, - index, - length, - value; - - for (index = 0, length = object.length; index < length; index += 1) { - value = object[index]; - - if (state.replacer) { - value = state.replacer.call(object, String(index), value); - } - - // Write only valid elements, put null instead of invalid elements. - if (writeNode(state, level, value, false, false) || - (typeof value === 'undefined' && - writeNode(state, level, null, false, false))) { - - if (_result !== '') _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, - value; - - for (index = 0, length = object.length; index < length; index += 1) { - value = object[index]; - - if (state.replacer) { - value = state.replacer.call(object, String(index), value); - } - - // Write only valid elements, put null instead of invalid elements. - if (writeNode(state, level + 1, value, true, true, false, true) || - (typeof value === 'undefined' && - writeNode(state, level + 1, null, true, true, false, true))) { - - if (!compact || _result !== '') { - _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 (_result !== '') pairBuffer += ', '; - - if (state.condenseFlow) pairBuffer += '"'; - - objectKey = objectKeyList[index]; - objectValue = object[objectKey]; - - if (state.replacer) { - objectValue = state.replacer.call(object, objectKey, objectValue); - } - - 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 exception('sortKeys must be a boolean or a function'); - } - - for (index = 0, length = objectKeyList.length; index < length; index += 1) { - pairBuffer = ''; - - if (!compact || _result !== '') { - pairBuffer += generateNextLine(state, level); - } - - objectKey = objectKeyList[index]; - objectValue = object[objectKey]; - - if (state.replacer) { - objectValue = state.replacer.call(object, objectKey, objectValue); - } - - 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))) { - - if (explicit) { - if (type.multi && type.representName) { - state.tag = type.representName(object); - } else { - state.tag = type.tag; - } - } else { - state.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.call(type.represent, style)) { - _result = type.represent[style](object, style); - } else { - throw new exception('!<' + 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, isblockseq) { - state.tag = null; - state.dump = object; - - if (!detectType(state, object, false)) { - detectType(state, object, true); - } - - var type = _toString.call(state.dump); - var inblock = block; - var tagStr; - - 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]') { - if (block && (state.dump.length !== 0)) { - if (state.noArrayIndent && !isblockseq && level > 0) { - writeBlockSequence(state, level - 1, state.dump, compact); - } else { - writeBlockSequence(state, level, state.dump, compact); - } - if (duplicate) { - state.dump = '&ref_' + duplicateIndex + state.dump; - } - } else { - writeFlowSequence(state, level, state.dump); - if (duplicate) { - state.dump = '&ref_' + duplicateIndex + ' ' + state.dump; - } - } - } else if (type === '[object String]') { - if (state.tag !== '?') { - writeScalar(state, state.dump, level, iskey, inblock); - } - } else if (type === '[object Undefined]') { - return false; - } else { - if (state.skipInvalid) return false; - throw new exception('unacceptable kind of an object to dump ' + type); - } - - if (state.tag !== null && state.tag !== '?') { - // Need to encode all characters except those allowed by the spec: - // - // [35] ns-dec-digit ::= [#x30-#x39] /* 0-9 */ - // [36] ns-hex-digit ::= ns-dec-digit - // | [#x41-#x46] /* A-F */ | [#x61-#x66] /* a-f */ - // [37] ns-ascii-letter ::= [#x41-#x5A] /* A-Z */ | [#x61-#x7A] /* a-z */ - // [38] ns-word-char ::= ns-dec-digit | ns-ascii-letter | “-” - // [39] ns-uri-char ::= “%” ns-hex-digit ns-hex-digit | ns-word-char | “#” - // | “;” | “/” | “?” | “:” | “@” | “&” | “=” | “+” | “$” | “,” - // | “_” | “.” | “!” | “~” | “*” | “'” | “(” | “)” | “[” | “]” - // - // Also need to encode '!' because it has special meaning (end of tag prefix). - // - tagStr = encodeURI( - state.tag[0] === '!' ? state.tag.slice(1) : state.tag - ).replace(/!/g, '%21'); - - if (state.tag[0] === '!') { - tagStr = '!' + tagStr; - } else if (tagStr.slice(0, 18) === 'tag:yaml.org,2002:') { - tagStr = '!!' + tagStr.slice(18); - } else { - tagStr = '!<' + tagStr + '>'; - } - - state.dump = tagStr + ' ' + 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$1(input, options) { - options = options || {}; - - var state = new State(options); - - if (!state.noRefs) getDuplicateReferences(input, state); - - var value = input; - - if (state.replacer) { - value = state.replacer.call({ '': value }, '', value); - } - - if (writeNode(state, 0, value, true, true)) return state.dump + '\n'; - - return ''; -} - -var dump_1 = dump$1; - -var dumper = { - dump: dump_1 -}; - -function renamed(from, to) { - return function () { - throw new Error('Function yaml.' + from + ' is removed in js-yaml 4. ' + - 'Use yaml.' + to + ' instead, which is now safe by default.'); - }; -} - - -var Type = type$1; -var Schema = schema$1; -var FAILSAFE_SCHEMA = failsafe; -var JSON_SCHEMA = json; -var CORE_SCHEMA = core; -var DEFAULT_SCHEMA = _default$1; -var load = loader.load; -var loadAll = loader.loadAll; -var dump = dumper.dump; -var YAMLException = exception; - -// Re-export all types in case user wants to create custom schema -var types$1 = { - binary: binary, - float: float, - map: map$3, - null: _null, - pairs: pairs, - set: set, - timestamp: timestamp, - bool: bool, - int: int, - merge: merge$1, - omap: omap, - seq: seq, - str: str -}; - -// Removed functions from JS-YAML 3.0.x -var safeLoad = renamed('safeLoad', 'load'); -var safeLoadAll = renamed('safeLoadAll', 'loadAll'); -var safeDump = renamed('safeDump', 'dump'); - -var jsYaml = { - Type: Type, - Schema: Schema, - FAILSAFE_SCHEMA: FAILSAFE_SCHEMA, - JSON_SCHEMA: JSON_SCHEMA, - CORE_SCHEMA: CORE_SCHEMA, - DEFAULT_SCHEMA: DEFAULT_SCHEMA, - load: load, - loadAll: loadAll, - dump: dump, - YAMLException: YAMLException, - types: types$1, - safeLoad: safeLoad, - safeLoadAll: safeLoadAll, - safeDump: safeDump -}; - -var isArrayish$2 = function isArrayish(obj) { - if (!obj) { - return false; - } - - return obj instanceof Array || Array.isArray(obj) || - (obj.length >= 0 && obj.splice instanceof Function); -}; - -var util$2 = require$$0$4; -var isArrayish$1 = isArrayish$2; - -var errorEx$1 = function errorEx(name, properties) { - if (!name || name.constructor !== String) { - properties = name || {}; - name = Error.name; - } - - var errorExError = function ErrorEXError(message) { - if (!this) { - return new ErrorEXError(message); - } - - message = message instanceof Error - ? message.message - : (message || this.message); - - Error.call(this, message); - Error.captureStackTrace(this, errorExError); - - this.name = name; - - Object.defineProperty(this, 'message', { - configurable: true, - enumerable: false, - get: function () { - var newMessage = message.split(/\r?\n/g); - - for (var key in properties) { - if (!properties.hasOwnProperty(key)) { - continue; - } - - var modifier = properties[key]; - - if ('message' in modifier) { - newMessage = modifier.message(this[key], newMessage) || newMessage; - if (!isArrayish$1(newMessage)) { - newMessage = [newMessage]; - } - } - } - - return newMessage.join('\n'); - }, - set: function (v) { - message = v; - } - }); - - var overwrittenStack = null; - - var stackDescriptor = Object.getOwnPropertyDescriptor(this, 'stack'); - var stackGetter = stackDescriptor.get; - var stackValue = stackDescriptor.value; - delete stackDescriptor.value; - delete stackDescriptor.writable; - - stackDescriptor.set = function (newstack) { - overwrittenStack = newstack; - }; - - stackDescriptor.get = function () { - var stack = (overwrittenStack || ((stackGetter) - ? stackGetter.call(this) - : stackValue)).split(/\r?\n+/g); - - // starting in Node 7, the stack builder caches the message. - // just replace it. - if (!overwrittenStack) { - stack[0] = this.name + ': ' + this.message; - } - - var lineCount = 1; - for (var key in properties) { - if (!properties.hasOwnProperty(key)) { - continue; - } - - var modifier = properties[key]; - - if ('line' in modifier) { - var line = modifier.line(this[key]); - if (line) { - stack.splice(lineCount++, 0, ' ' + line); - } - } - - if ('stack' in modifier) { - modifier.stack(this[key], stack); - } - } - - return stack.join('\n'); - }; - - Object.defineProperty(this, 'stack', stackDescriptor); - }; - - if (Object.setPrototypeOf) { - Object.setPrototypeOf(errorExError.prototype, Error.prototype); - Object.setPrototypeOf(errorExError, Error); - } else { - util$2.inherits(errorExError, Error); - } - - return errorExError; -}; - -errorEx$1.append = function (str, def) { - return { - message: function (v, message) { - v = v || def; - - if (v) { - message[0] += ' ' + str.replace('%s', v.toString()); - } - - return message; - } - }; -}; - -errorEx$1.line = function (str, def) { - return { - line: function (v) { - v = v || def; - - if (v) { - return str.replace('%s', v.toString()); - } - - return null; - } - }; -}; - -var errorEx_1 = errorEx$1; - -const hexify = char => { - const h = char.charCodeAt(0).toString(16).toUpperCase(); - return '0x' + (h.length % 2 ? '0' : '') + h -}; - -const parseError = (e, txt, context) => { - if (!txt) { - return { - message: e.message + ' while parsing empty string', - position: 0, - } - } - const badToken = e.message.match(/^Unexpected token (.) .*position\s+(\d+)/i); - const errIdx = badToken ? +badToken[2] - : e.message.match(/^Unexpected end of JSON.*/i) ? txt.length - 1 - : null; - - const msg = badToken ? e.message.replace(/^Unexpected token ./, `Unexpected token ${ - JSON.stringify(badToken[1]) - } (${hexify(badToken[1])})`) - : e.message; - - if (errIdx !== null && errIdx !== undefined) { - const start = errIdx <= context ? 0 - : errIdx - context; - - const end = errIdx + context >= txt.length ? txt.length - : errIdx + context; - - const slice = (start === 0 ? '' : '...') + - txt.slice(start, end) + - (end === txt.length ? '' : '...'); - - const near = txt === slice ? '' : 'near '; - - return { - message: msg + ` while parsing ${near}${JSON.stringify(slice)}`, - position: errIdx, - } - } else { - return { - message: msg + ` while parsing '${txt.slice(0, context * 2)}'`, - position: 0, - } - } -}; - -class JSONParseError extends SyntaxError { - constructor (er, txt, context, caller) { - context = context || 20; - const metadata = parseError(er, txt, context); - super(metadata.message); - Object.assign(this, metadata); - this.code = 'EJSONPARSE'; - this.systemError = er; - Error.captureStackTrace(this, caller || this.constructor); - } - get name () { return this.constructor.name } - set name (n) {} - get [Symbol.toStringTag] () { return this.constructor.name } -} - -const kIndent = Symbol.for('indent'); -const kNewline = Symbol.for('newline'); -// only respect indentation if we got a line break, otherwise squash it -// things other than objects and arrays aren't indented, so ignore those -// Important: in both of these regexps, the $1 capture group is the newline -// or undefined, and the $2 capture group is the indent, or undefined. -const formatRE = /^\s*[{\[]((?:\r?\n)+)([\s\t]*)/; -const emptyRE = /^(?:\{\}|\[\])((?:\r?\n)+)?$/; - -const parseJson$1 = (txt, reviver, context) => { - const parseText = stripBOM(txt); - context = context || 20; - try { - // get the indentation so that we can save it back nicely - // if the file starts with {" then we have an indent of '', ie, none - // otherwise, pick the indentation of the next line after the first \n - // If the pattern doesn't match, then it means no indentation. - // JSON.stringify ignores symbols, so this is reasonably safe. - // if the string is '{}' or '[]', then use the default 2-space indent. - const [, newline = '\n', indent = ' '] = parseText.match(emptyRE) || - parseText.match(formatRE) || - [, '', '']; - - const result = JSON.parse(parseText, reviver); - if (result && typeof result === 'object') { - result[kNewline] = newline; - result[kIndent] = indent; - } - return result - } catch (e) { - if (typeof txt !== 'string' && !Buffer.isBuffer(txt)) { - const isEmptyArray = Array.isArray(txt) && txt.length === 0; - throw Object.assign(new TypeError( - `Cannot parse ${isEmptyArray ? 'an empty array' : String(txt)}` - ), { - code: 'EJSONPARSE', - systemError: e, - }) - } - - throw new JSONParseError(e, parseText, context, parseJson$1) - } -}; - -// Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) -// because the buffer-to-string conversion in `fs.readFileSync()` -// translates it to FEFF, the UTF-16 BOM. -const stripBOM = txt => String(txt).replace(/^\uFEFF/, ''); - -var jsonParseEvenBetterErrors = parseJson$1; -parseJson$1.JSONParseError = JSONParseError; - -parseJson$1.noExceptions = (txt, reviver) => { - try { - return JSON.parse(stripBOM(txt), reviver) - } catch (e) {} -}; - -var LF = '\n'; -var CR = '\r'; -var LinesAndColumns$1 = (function () { - function LinesAndColumns(string) { - this.string = string; - var offsets = [0]; - for (var offset = 0; offset < string.length;) { - switch (string[offset]) { - case LF: - offset += LF.length; - offsets.push(offset); - break; - case CR: - offset += CR.length; - if (string[offset] === LF) { - offset += LF.length; - } - offsets.push(offset); - break; - default: - offset++; - break; - } - } - this.offsets = offsets; - } - LinesAndColumns.prototype.locationForIndex = function (index) { - if (index < 0 || index > this.string.length) { - return null; - } - var line = 0; - var offsets = this.offsets; - while (offsets[line + 1] <= index) { - line++; - } - var column = index - offsets[line]; - return { line: line, column: column }; - }; - LinesAndColumns.prototype.indexForLocation = function (location) { - var line = location.line, column = location.column; - if (line < 0 || line >= this.offsets.length) { - return null; - } - if (column < 0 || column > this.lengthOfLine(line)) { - return null; - } - return this.offsets[line] + column; - }; - LinesAndColumns.prototype.lengthOfLine = function (line) { - var offset = this.offsets[line]; - var nextOffset = line === this.offsets.length - 1 ? this.string.length : this.offsets[line + 1]; - return nextOffset - offset; - }; - return LinesAndColumns; -}()); - -var dist = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': LinesAndColumns$1 -}); - -var require$$2 = /*@__PURE__*/getAugmentedNamespace(dist); - -var lib$4 = {}; - -var lib$3 = {}; - -var jsTokens = {}; - -// Copyright 2014, 2015, 2016, 2017, 2018 Simon Lydell -// License: MIT. (See LICENSE.) - -Object.defineProperty(jsTokens, "__esModule", { - value: true -}); - -// This regex comes from regex.coffee, and is inserted here by generate-index.js -// (run `npm run build`). -jsTokens.default = /((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyus]{1,6}\b(?![\u0080-\uFFFF$\\]|\s*(?:[+\-*%&|^<>!=?({]|\/(?![\/*])))))|(0[xX][\da-fA-F]+|0[oO][0-7]+|0[bB][01]+|(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)|((?!\d)(?:(?!\s)[$\w\u0080-\uFFFF]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+)|(--|\+\+|&&|\|\||=>|\.{3}|(?:[+\-\/%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2})=?|[?~.,:;[\](){}])|(\s+)|(^$|[\s\S])/g; - -jsTokens.matchToToken = function(match) { - var token = {type: "invalid", value: match[0], closed: undefined}; - if (match[ 1]) token.type = "string" , token.closed = !!(match[3] || match[4]); - else if (match[ 5]) token.type = "comment"; - else if (match[ 6]) token.type = "comment", token.closed = !!match[7]; - else if (match[ 8]) token.type = "regex"; - else if (match[ 9]) token.type = "number"; - else if (match[10]) token.type = "name"; - else if (match[11]) token.type = "punctuator"; - else if (match[12]) token.type = "whitespace"; - return token -}; - -var lib$2 = {}; - -var identifier = {}; - -Object.defineProperty(identifier, "__esModule", { - value: true -}); -identifier.isIdentifierStart = isIdentifierStart; -identifier.isIdentifierChar = isIdentifierChar; -identifier.isIdentifierName = isIdentifierName; -let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ca\ua7d0\ua7d1\ua7d3\ua7d5-\ua7d9\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; -let nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0898-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; -const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); -const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); -nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; -const astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 68, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 190, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1070, 4050, 582, 8634, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8936, 3, 2, 6, 2, 1, 2, 290, 46, 2, 18, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 482, 44, 11, 6, 17, 0, 322, 29, 19, 43, 1269, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4152, 8, 221, 3, 5761, 15, 7472, 3104, 541, 1507, 4938]; -const astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 154, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 19306, 9, 87, 9, 39, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4706, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 262, 6, 10, 9, 357, 0, 62, 13, 1495, 6, 110, 6, 6, 9, 4759, 9, 787719, 239]; - -function isInAstralSet(code, set) { - let pos = 0x10000; - - for (let i = 0, length = set.length; i < length; i += 2) { - pos += set[i]; - if (pos > code) return false; - pos += set[i + 1]; - if (pos >= code) return true; - } - - return false; -} - -function isIdentifierStart(code) { - if (code < 65) return code === 36; - if (code <= 90) return true; - if (code < 97) return code === 95; - if (code <= 122) return true; - - if (code <= 0xffff) { - return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); - } - - return isInAstralSet(code, astralIdentifierStartCodes); -} - -function isIdentifierChar(code) { - if (code < 48) return code === 36; - if (code < 58) return true; - if (code < 65) return false; - if (code <= 90) return true; - if (code < 97) return code === 95; - if (code <= 122) return true; - - if (code <= 0xffff) { - return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); - } - - return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes); -} - -function isIdentifierName(name) { - let isFirst = true; - - for (let i = 0; i < name.length; i++) { - let cp = name.charCodeAt(i); - - if ((cp & 0xfc00) === 0xd800 && i + 1 < name.length) { - const trail = name.charCodeAt(++i); - - if ((trail & 0xfc00) === 0xdc00) { - cp = 0x10000 + ((cp & 0x3ff) << 10) + (trail & 0x3ff); - } - } - - if (isFirst) { - isFirst = false; - - if (!isIdentifierStart(cp)) { - return false; - } - } else if (!isIdentifierChar(cp)) { - return false; - } - } - - return !isFirst; -} - -var keyword = {}; - -Object.defineProperty(keyword, "__esModule", { - value: true -}); -keyword.isReservedWord = isReservedWord; -keyword.isStrictReservedWord = isStrictReservedWord; -keyword.isStrictBindOnlyReservedWord = isStrictBindOnlyReservedWord; -keyword.isStrictBindReservedWord = isStrictBindReservedWord; -keyword.isKeyword = isKeyword; -const reservedWords = { - keyword: ["break", "case", "catch", "continue", "debugger", "default", "do", "else", "finally", "for", "function", "if", "return", "switch", "throw", "try", "var", "const", "while", "with", "new", "this", "super", "class", "extends", "export", "import", "null", "true", "false", "in", "instanceof", "typeof", "void", "delete"], - strict: ["implements", "interface", "let", "package", "private", "protected", "public", "static", "yield"], - strictBind: ["eval", "arguments"] -}; -const keywords$1 = new Set(reservedWords.keyword); -const reservedWordsStrictSet = new Set(reservedWords.strict); -const reservedWordsStrictBindSet = new Set(reservedWords.strictBind); - -function isReservedWord(word, inModule) { - return inModule && word === "await" || word === "enum"; -} - -function isStrictReservedWord(word, inModule) { - return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word); -} - -function isStrictBindOnlyReservedWord(word) { - return reservedWordsStrictBindSet.has(word); -} - -function isStrictBindReservedWord(word, inModule) { - return isStrictReservedWord(word, inModule) || isStrictBindOnlyReservedWord(word); -} - -function isKeyword(word) { - return keywords$1.has(word); -} - -(function (exports) { - -Object.defineProperty(exports, "__esModule", { - value: true -}); -Object.defineProperty(exports, "isIdentifierName", { - enumerable: true, - get: function () { - return _identifier.isIdentifierName; - } -}); -Object.defineProperty(exports, "isIdentifierChar", { - enumerable: true, - get: function () { - return _identifier.isIdentifierChar; - } -}); -Object.defineProperty(exports, "isIdentifierStart", { - enumerable: true, - get: function () { - return _identifier.isIdentifierStart; - } -}); -Object.defineProperty(exports, "isReservedWord", { - enumerable: true, - get: function () { - return _keyword.isReservedWord; - } -}); -Object.defineProperty(exports, "isStrictBindOnlyReservedWord", { - enumerable: true, - get: function () { - return _keyword.isStrictBindOnlyReservedWord; - } -}); -Object.defineProperty(exports, "isStrictBindReservedWord", { - enumerable: true, - get: function () { - return _keyword.isStrictBindReservedWord; - } -}); -Object.defineProperty(exports, "isStrictReservedWord", { - enumerable: true, - get: function () { - return _keyword.isStrictReservedWord; - } -}); -Object.defineProperty(exports, "isKeyword", { - enumerable: true, - get: function () { - return _keyword.isKeyword; - } -}); - -var _identifier = identifier; - -var _keyword = keyword; -}(lib$2)); - -var chalk = {exports: {}}; - -var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; - -var escapeStringRegexp$1 = function (str) { - if (typeof str !== 'string') { - throw new TypeError('Expected a string'); - } - - return str.replace(matchOperatorsRe, '\\$&'); -}; - -var ansiStyles = {exports: {}}; - -var conversions$2 = {exports: {}}; - -var colorName = { - "aliceblue": [240, 248, 255], - "antiquewhite": [250, 235, 215], - "aqua": [0, 255, 255], - "aquamarine": [127, 255, 212], - "azure": [240, 255, 255], - "beige": [245, 245, 220], - "bisque": [255, 228, 196], - "black": [0, 0, 0], - "blanchedalmond": [255, 235, 205], - "blue": [0, 0, 255], - "blueviolet": [138, 43, 226], - "brown": [165, 42, 42], - "burlywood": [222, 184, 135], - "cadetblue": [95, 158, 160], - "chartreuse": [127, 255, 0], - "chocolate": [210, 105, 30], - "coral": [255, 127, 80], - "cornflowerblue": [100, 149, 237], - "cornsilk": [255, 248, 220], - "crimson": [220, 20, 60], - "cyan": [0, 255, 255], - "darkblue": [0, 0, 139], - "darkcyan": [0, 139, 139], - "darkgoldenrod": [184, 134, 11], - "darkgray": [169, 169, 169], - "darkgreen": [0, 100, 0], - "darkgrey": [169, 169, 169], - "darkkhaki": [189, 183, 107], - "darkmagenta": [139, 0, 139], - "darkolivegreen": [85, 107, 47], - "darkorange": [255, 140, 0], - "darkorchid": [153, 50, 204], - "darkred": [139, 0, 0], - "darksalmon": [233, 150, 122], - "darkseagreen": [143, 188, 143], - "darkslateblue": [72, 61, 139], - "darkslategray": [47, 79, 79], - "darkslategrey": [47, 79, 79], - "darkturquoise": [0, 206, 209], - "darkviolet": [148, 0, 211], - "deeppink": [255, 20, 147], - "deepskyblue": [0, 191, 255], - "dimgray": [105, 105, 105], - "dimgrey": [105, 105, 105], - "dodgerblue": [30, 144, 255], - "firebrick": [178, 34, 34], - "floralwhite": [255, 250, 240], - "forestgreen": [34, 139, 34], - "fuchsia": [255, 0, 255], - "gainsboro": [220, 220, 220], - "ghostwhite": [248, 248, 255], - "gold": [255, 215, 0], - "goldenrod": [218, 165, 32], - "gray": [128, 128, 128], - "green": [0, 128, 0], - "greenyellow": [173, 255, 47], - "grey": [128, 128, 128], - "honeydew": [240, 255, 240], - "hotpink": [255, 105, 180], - "indianred": [205, 92, 92], - "indigo": [75, 0, 130], - "ivory": [255, 255, 240], - "khaki": [240, 230, 140], - "lavender": [230, 230, 250], - "lavenderblush": [255, 240, 245], - "lawngreen": [124, 252, 0], - "lemonchiffon": [255, 250, 205], - "lightblue": [173, 216, 230], - "lightcoral": [240, 128, 128], - "lightcyan": [224, 255, 255], - "lightgoldenrodyellow": [250, 250, 210], - "lightgray": [211, 211, 211], - "lightgreen": [144, 238, 144], - "lightgrey": [211, 211, 211], - "lightpink": [255, 182, 193], - "lightsalmon": [255, 160, 122], - "lightseagreen": [32, 178, 170], - "lightskyblue": [135, 206, 250], - "lightslategray": [119, 136, 153], - "lightslategrey": [119, 136, 153], - "lightsteelblue": [176, 196, 222], - "lightyellow": [255, 255, 224], - "lime": [0, 255, 0], - "limegreen": [50, 205, 50], - "linen": [250, 240, 230], - "magenta": [255, 0, 255], - "maroon": [128, 0, 0], - "mediumaquamarine": [102, 205, 170], - "mediumblue": [0, 0, 205], - "mediumorchid": [186, 85, 211], - "mediumpurple": [147, 112, 219], - "mediumseagreen": [60, 179, 113], - "mediumslateblue": [123, 104, 238], - "mediumspringgreen": [0, 250, 154], - "mediumturquoise": [72, 209, 204], - "mediumvioletred": [199, 21, 133], - "midnightblue": [25, 25, 112], - "mintcream": [245, 255, 250], - "mistyrose": [255, 228, 225], - "moccasin": [255, 228, 181], - "navajowhite": [255, 222, 173], - "navy": [0, 0, 128], - "oldlace": [253, 245, 230], - "olive": [128, 128, 0], - "olivedrab": [107, 142, 35], - "orange": [255, 165, 0], - "orangered": [255, 69, 0], - "orchid": [218, 112, 214], - "palegoldenrod": [238, 232, 170], - "palegreen": [152, 251, 152], - "paleturquoise": [175, 238, 238], - "palevioletred": [219, 112, 147], - "papayawhip": [255, 239, 213], - "peachpuff": [255, 218, 185], - "peru": [205, 133, 63], - "pink": [255, 192, 203], - "plum": [221, 160, 221], - "powderblue": [176, 224, 230], - "purple": [128, 0, 128], - "rebeccapurple": [102, 51, 153], - "red": [255, 0, 0], - "rosybrown": [188, 143, 143], - "royalblue": [65, 105, 225], - "saddlebrown": [139, 69, 19], - "salmon": [250, 128, 114], - "sandybrown": [244, 164, 96], - "seagreen": [46, 139, 87], - "seashell": [255, 245, 238], - "sienna": [160, 82, 45], - "silver": [192, 192, 192], - "skyblue": [135, 206, 235], - "slateblue": [106, 90, 205], - "slategray": [112, 128, 144], - "slategrey": [112, 128, 144], - "snow": [255, 250, 250], - "springgreen": [0, 255, 127], - "steelblue": [70, 130, 180], - "tan": [210, 180, 140], - "teal": [0, 128, 128], - "thistle": [216, 191, 216], - "tomato": [255, 99, 71], - "turquoise": [64, 224, 208], - "violet": [238, 130, 238], - "wheat": [245, 222, 179], - "white": [255, 255, 255], - "whitesmoke": [245, 245, 245], - "yellow": [255, 255, 0], - "yellowgreen": [154, 205, 50] -}; - -/* MIT license */ - -var cssKeywords = colorName; - -// NOTE: conversions should only return primitive values (i.e. arrays, or -// values that give correct `typeof` results). -// do not use box values types (i.e. Number(), String(), etc.) - -var reverseKeywords = {}; -for (var key$1 in cssKeywords) { - if (cssKeywords.hasOwnProperty(key$1)) { - reverseKeywords[cssKeywords[key$1]] = key$1; - } -} - -var convert$2 = conversions$2.exports = { - rgb: {channels: 3, labels: 'rgb'}, - hsl: {channels: 3, labels: 'hsl'}, - hsv: {channels: 3, labels: 'hsv'}, - hwb: {channels: 3, labels: 'hwb'}, - cmyk: {channels: 4, labels: 'cmyk'}, - xyz: {channels: 3, labels: 'xyz'}, - lab: {channels: 3, labels: 'lab'}, - lch: {channels: 3, labels: 'lch'}, - hex: {channels: 1, labels: ['hex']}, - keyword: {channels: 1, labels: ['keyword']}, - ansi16: {channels: 1, labels: ['ansi16']}, - ansi256: {channels: 1, labels: ['ansi256']}, - hcg: {channels: 3, labels: ['h', 'c', 'g']}, - apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, - gray: {channels: 1, labels: ['gray']} -}; - -// hide .channels and .labels properties -for (var model in convert$2) { - if (convert$2.hasOwnProperty(model)) { - if (!('channels' in convert$2[model])) { - throw new Error('missing channels property: ' + model); - } - - if (!('labels' in convert$2[model])) { - throw new Error('missing channel labels property: ' + model); - } - - if (convert$2[model].labels.length !== convert$2[model].channels) { - throw new Error('channel and label counts mismatch: ' + model); - } - - var channels = convert$2[model].channels; - var labels$1 = convert$2[model].labels; - delete convert$2[model].channels; - delete convert$2[model].labels; - Object.defineProperty(convert$2[model], 'channels', {value: channels}); - Object.defineProperty(convert$2[model], 'labels', {value: labels$1}); - } -} - -convert$2.rgb.hsl = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var min = Math.min(r, g, b); - var max = Math.max(r, g, b); - var delta = max - min; - var h; - var s; - var l; - - if (max === min) { - h = 0; - } else if (r === max) { - h = (g - b) / delta; - } else if (g === max) { - h = 2 + (b - r) / delta; - } else if (b === max) { - h = 4 + (r - g) / delta; - } - - h = Math.min(h * 60, 360); - - if (h < 0) { - h += 360; - } - - l = (min + max) / 2; - - if (max === min) { - s = 0; - } else if (l <= 0.5) { - s = delta / (max + min); - } else { - s = delta / (2 - max - min); - } - - return [h, s * 100, l * 100]; -}; - -convert$2.rgb.hsv = function (rgb) { - var rdif; - var gdif; - var bdif; - var h; - var s; - - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var v = Math.max(r, g, b); - var diff = v - Math.min(r, g, b); - var diffc = function (c) { - return (v - c) / 6 / diff + 1 / 2; - }; - - if (diff === 0) { - h = s = 0; - } else { - s = diff / v; - rdif = diffc(r); - gdif = diffc(g); - bdif = diffc(b); - - if (r === v) { - h = bdif - gdif; - } else if (g === v) { - h = (1 / 3) + rdif - bdif; - } else if (b === v) { - h = (2 / 3) + gdif - rdif; - } - if (h < 0) { - h += 1; - } else if (h > 1) { - h -= 1; - } - } - - return [ - h * 360, - s * 100, - v * 100 - ]; -}; - -convert$2.rgb.hwb = function (rgb) { - var r = rgb[0]; - var g = rgb[1]; - var b = rgb[2]; - var h = convert$2.rgb.hsl(rgb)[0]; - var w = 1 / 255 * Math.min(r, Math.min(g, b)); - - b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); - - return [h, w * 100, b * 100]; -}; - -convert$2.rgb.cmyk = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var c; - var m; - var y; - var k; - - k = Math.min(1 - r, 1 - g, 1 - b); - c = (1 - r - k) / (1 - k) || 0; - m = (1 - g - k) / (1 - k) || 0; - y = (1 - b - k) / (1 - k) || 0; - - return [c * 100, m * 100, y * 100, k * 100]; -}; - -/** - * See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance - * */ -function comparativeDistance(x, y) { - return ( - Math.pow(x[0] - y[0], 2) + - Math.pow(x[1] - y[1], 2) + - Math.pow(x[2] - y[2], 2) - ); -} - -convert$2.rgb.keyword = function (rgb) { - var reversed = reverseKeywords[rgb]; - if (reversed) { - return reversed; - } - - var currentClosestDistance = Infinity; - var currentClosestKeyword; - - for (var keyword in cssKeywords) { - if (cssKeywords.hasOwnProperty(keyword)) { - var value = cssKeywords[keyword]; - - // Compute comparative distance - var distance = comparativeDistance(rgb, value); - - // Check if its less, if so set as closest - if (distance < currentClosestDistance) { - currentClosestDistance = distance; - currentClosestKeyword = keyword; - } - } - } - - return currentClosestKeyword; -}; - -convert$2.keyword.rgb = function (keyword) { - return cssKeywords[keyword]; -}; - -convert$2.rgb.xyz = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - - // assume sRGB - r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92); - g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92); - b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92); - - var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); - var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); - var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); - - return [x * 100, y * 100, z * 100]; -}; - -convert$2.rgb.lab = function (rgb) { - var xyz = convert$2.rgb.xyz(rgb); - var x = xyz[0]; - var y = xyz[1]; - var z = xyz[2]; - var l; - var a; - var b; - - x /= 95.047; - y /= 100; - z /= 108.883; - - x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); - - l = (116 * y) - 16; - a = 500 * (x - y); - b = 200 * (y - z); - - return [l, a, b]; -}; - -convert$2.hsl.rgb = function (hsl) { - var h = hsl[0] / 360; - var s = hsl[1] / 100; - var l = hsl[2] / 100; - var t1; - var t2; - var t3; - var rgb; - var val; - - if (s === 0) { - val = l * 255; - return [val, val, val]; - } - - if (l < 0.5) { - t2 = l * (1 + s); - } else { - t2 = l + s - l * s; - } - - t1 = 2 * l - t2; - - rgb = [0, 0, 0]; - for (var i = 0; i < 3; i++) { - t3 = h + 1 / 3 * -(i - 1); - if (t3 < 0) { - t3++; - } - if (t3 > 1) { - t3--; - } - - if (6 * t3 < 1) { - val = t1 + (t2 - t1) * 6 * t3; - } else if (2 * t3 < 1) { - val = t2; - } else if (3 * t3 < 2) { - val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; - } else { - val = t1; - } - - rgb[i] = val * 255; - } - - return rgb; -}; - -convert$2.hsl.hsv = function (hsl) { - var h = hsl[0]; - var s = hsl[1] / 100; - var l = hsl[2] / 100; - var smin = s; - var lmin = Math.max(l, 0.01); - var sv; - var v; - - l *= 2; - s *= (l <= 1) ? l : 2 - l; - smin *= lmin <= 1 ? lmin : 2 - lmin; - v = (l + s) / 2; - sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); - - return [h, sv * 100, v * 100]; -}; - -convert$2.hsv.rgb = function (hsv) { - var h = hsv[0] / 60; - var s = hsv[1] / 100; - var v = hsv[2] / 100; - var hi = Math.floor(h) % 6; - - var f = h - Math.floor(h); - var p = 255 * v * (1 - s); - var q = 255 * v * (1 - (s * f)); - var t = 255 * v * (1 - (s * (1 - f))); - v *= 255; - - switch (hi) { - case 0: - return [v, t, p]; - case 1: - return [q, v, p]; - case 2: - return [p, v, t]; - case 3: - return [p, q, v]; - case 4: - return [t, p, v]; - case 5: - return [v, p, q]; - } -}; - -convert$2.hsv.hsl = function (hsv) { - var h = hsv[0]; - var s = hsv[1] / 100; - var v = hsv[2] / 100; - var vmin = Math.max(v, 0.01); - var lmin; - var sl; - var l; - - l = (2 - s) * v; - lmin = (2 - s) * vmin; - sl = s * vmin; - sl /= (lmin <= 1) ? lmin : 2 - lmin; - sl = sl || 0; - l /= 2; - - return [h, sl * 100, l * 100]; -}; - -// http://dev.w3.org/csswg/css-color/#hwb-to-rgb -convert$2.hwb.rgb = function (hwb) { - var h = hwb[0] / 360; - var wh = hwb[1] / 100; - var bl = hwb[2] / 100; - var ratio = wh + bl; - var i; - var v; - var f; - var n; - - // wh + bl cant be > 1 - if (ratio > 1) { - wh /= ratio; - bl /= ratio; - } - - i = Math.floor(6 * h); - v = 1 - bl; - f = 6 * h - i; - - if ((i & 0x01) !== 0) { - f = 1 - f; - } - - n = wh + f * (v - wh); // linear interpolation - - var r; - var g; - var b; - switch (i) { - default: - case 6: - case 0: r = v; g = n; b = wh; break; - case 1: r = n; g = v; b = wh; break; - case 2: r = wh; g = v; b = n; break; - case 3: r = wh; g = n; b = v; break; - case 4: r = n; g = wh; b = v; break; - case 5: r = v; g = wh; b = n; break; - } - - return [r * 255, g * 255, b * 255]; -}; - -convert$2.cmyk.rgb = function (cmyk) { - var c = cmyk[0] / 100; - var m = cmyk[1] / 100; - var y = cmyk[2] / 100; - var k = cmyk[3] / 100; - var r; - var g; - var b; - - r = 1 - Math.min(1, c * (1 - k) + k); - g = 1 - Math.min(1, m * (1 - k) + k); - b = 1 - Math.min(1, y * (1 - k) + k); - - return [r * 255, g * 255, b * 255]; -}; - -convert$2.xyz.rgb = function (xyz) { - var x = xyz[0] / 100; - var y = xyz[1] / 100; - var z = xyz[2] / 100; - var r; - var g; - var b; - - r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); - g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); - b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); - - // assume sRGB - r = r > 0.0031308 - ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055) - : r * 12.92; - - g = g > 0.0031308 - ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055) - : g * 12.92; - - b = b > 0.0031308 - ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055) - : b * 12.92; - - r = Math.min(Math.max(0, r), 1); - g = Math.min(Math.max(0, g), 1); - b = Math.min(Math.max(0, b), 1); - - return [r * 255, g * 255, b * 255]; -}; - -convert$2.xyz.lab = function (xyz) { - var x = xyz[0]; - var y = xyz[1]; - var z = xyz[2]; - var l; - var a; - var b; - - x /= 95.047; - y /= 100; - z /= 108.883; - - x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); - - l = (116 * y) - 16; - a = 500 * (x - y); - b = 200 * (y - z); - - return [l, a, b]; -}; - -convert$2.lab.xyz = function (lab) { - var l = lab[0]; - var a = lab[1]; - var b = lab[2]; - var x; - var y; - var z; - - y = (l + 16) / 116; - x = a / 500 + y; - z = y - b / 200; - - var y2 = Math.pow(y, 3); - var x2 = Math.pow(x, 3); - var z2 = Math.pow(z, 3); - y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787; - x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787; - z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787; - - x *= 95.047; - y *= 100; - z *= 108.883; - - return [x, y, z]; -}; - -convert$2.lab.lch = function (lab) { - var l = lab[0]; - var a = lab[1]; - var b = lab[2]; - var hr; - var h; - var c; - - hr = Math.atan2(b, a); - h = hr * 360 / 2 / Math.PI; - - if (h < 0) { - h += 360; - } - - c = Math.sqrt(a * a + b * b); - - return [l, c, h]; -}; - -convert$2.lch.lab = function (lch) { - var l = lch[0]; - var c = lch[1]; - var h = lch[2]; - var a; - var b; - var hr; - - hr = h / 360 * 2 * Math.PI; - a = c * Math.cos(hr); - b = c * Math.sin(hr); - - return [l, a, b]; -}; - -convert$2.rgb.ansi16 = function (args) { - var r = args[0]; - var g = args[1]; - var b = args[2]; - var value = 1 in arguments ? arguments[1] : convert$2.rgb.hsv(args)[2]; // hsv -> ansi16 optimization - - value = Math.round(value / 50); - - if (value === 0) { - return 30; - } - - var ansi = 30 - + ((Math.round(b / 255) << 2) - | (Math.round(g / 255) << 1) - | Math.round(r / 255)); - - if (value === 2) { - ansi += 60; - } - - return ansi; -}; - -convert$2.hsv.ansi16 = function (args) { - // optimization here; we already know the value and don't need to get - // it converted for us. - return convert$2.rgb.ansi16(convert$2.hsv.rgb(args), args[2]); -}; - -convert$2.rgb.ansi256 = function (args) { - var r = args[0]; - var g = args[1]; - var b = args[2]; - - // we use the extended greyscale palette here, with the exception of - // black and white. normal palette only has 4 greyscale shades. - if (r === g && g === b) { - if (r < 8) { - return 16; - } - - if (r > 248) { - return 231; - } - - return Math.round(((r - 8) / 247) * 24) + 232; - } - - var ansi = 16 - + (36 * Math.round(r / 255 * 5)) - + (6 * Math.round(g / 255 * 5)) - + Math.round(b / 255 * 5); - - return ansi; -}; - -convert$2.ansi16.rgb = function (args) { - var color = args % 10; - - // handle greyscale - if (color === 0 || color === 7) { - if (args > 50) { - color += 3.5; - } - - color = color / 10.5 * 255; - - return [color, color, color]; - } - - var mult = (~~(args > 50) + 1) * 0.5; - var r = ((color & 1) * mult) * 255; - var g = (((color >> 1) & 1) * mult) * 255; - var b = (((color >> 2) & 1) * mult) * 255; - - return [r, g, b]; -}; - -convert$2.ansi256.rgb = function (args) { - // handle greyscale - if (args >= 232) { - var c = (args - 232) * 10 + 8; - return [c, c, c]; - } - - args -= 16; - - var rem; - var r = Math.floor(args / 36) / 5 * 255; - var g = Math.floor((rem = args % 36) / 6) / 5 * 255; - var b = (rem % 6) / 5 * 255; - - return [r, g, b]; -}; - -convert$2.rgb.hex = function (args) { - var integer = ((Math.round(args[0]) & 0xFF) << 16) - + ((Math.round(args[1]) & 0xFF) << 8) - + (Math.round(args[2]) & 0xFF); - - var string = integer.toString(16).toUpperCase(); - return '000000'.substring(string.length) + string; -}; - -convert$2.hex.rgb = function (args) { - var match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); - if (!match) { - return [0, 0, 0]; - } - - var colorString = match[0]; - - if (match[0].length === 3) { - colorString = colorString.split('').map(function (char) { - return char + char; - }).join(''); - } - - var integer = parseInt(colorString, 16); - var r = (integer >> 16) & 0xFF; - var g = (integer >> 8) & 0xFF; - var b = integer & 0xFF; - - return [r, g, b]; -}; - -convert$2.rgb.hcg = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var max = Math.max(Math.max(r, g), b); - var min = Math.min(Math.min(r, g), b); - var chroma = (max - min); - var grayscale; - var hue; - - if (chroma < 1) { - grayscale = min / (1 - chroma); - } else { - grayscale = 0; - } - - if (chroma <= 0) { - hue = 0; - } else - if (max === r) { - hue = ((g - b) / chroma) % 6; - } else - if (max === g) { - hue = 2 + (b - r) / chroma; - } else { - hue = 4 + (r - g) / chroma + 4; - } - - hue /= 6; - hue %= 1; - - return [hue * 360, chroma * 100, grayscale * 100]; -}; - -convert$2.hsl.hcg = function (hsl) { - var s = hsl[1] / 100; - var l = hsl[2] / 100; - var c = 1; - var f = 0; - - if (l < 0.5) { - c = 2.0 * s * l; - } else { - c = 2.0 * s * (1.0 - l); - } - - if (c < 1.0) { - f = (l - 0.5 * c) / (1.0 - c); - } - - return [hsl[0], c * 100, f * 100]; -}; - -convert$2.hsv.hcg = function (hsv) { - var s = hsv[1] / 100; - var v = hsv[2] / 100; - - var c = s * v; - var f = 0; - - if (c < 1.0) { - f = (v - c) / (1 - c); - } - - return [hsv[0], c * 100, f * 100]; -}; - -convert$2.hcg.rgb = function (hcg) { - var h = hcg[0] / 360; - var c = hcg[1] / 100; - var g = hcg[2] / 100; - - if (c === 0.0) { - return [g * 255, g * 255, g * 255]; - } - - var pure = [0, 0, 0]; - var hi = (h % 1) * 6; - var v = hi % 1; - var w = 1 - v; - var mg = 0; - - switch (Math.floor(hi)) { - case 0: - pure[0] = 1; pure[1] = v; pure[2] = 0; break; - case 1: - pure[0] = w; pure[1] = 1; pure[2] = 0; break; - case 2: - pure[0] = 0; pure[1] = 1; pure[2] = v; break; - case 3: - pure[0] = 0; pure[1] = w; pure[2] = 1; break; - case 4: - pure[0] = v; pure[1] = 0; pure[2] = 1; break; - default: - pure[0] = 1; pure[1] = 0; pure[2] = w; - } - - mg = (1.0 - c) * g; - - return [ - (c * pure[0] + mg) * 255, - (c * pure[1] + mg) * 255, - (c * pure[2] + mg) * 255 - ]; -}; - -convert$2.hcg.hsv = function (hcg) { - var c = hcg[1] / 100; - var g = hcg[2] / 100; - - var v = c + g * (1.0 - c); - var f = 0; - - if (v > 0.0) { - f = c / v; - } - - return [hcg[0], f * 100, v * 100]; -}; - -convert$2.hcg.hsl = function (hcg) { - var c = hcg[1] / 100; - var g = hcg[2] / 100; - - var l = g * (1.0 - c) + 0.5 * c; - var s = 0; - - if (l > 0.0 && l < 0.5) { - s = c / (2 * l); - } else - if (l >= 0.5 && l < 1.0) { - s = c / (2 * (1 - l)); - } - - return [hcg[0], s * 100, l * 100]; -}; - -convert$2.hcg.hwb = function (hcg) { - var c = hcg[1] / 100; - var g = hcg[2] / 100; - var v = c + g * (1.0 - c); - return [hcg[0], (v - c) * 100, (1 - v) * 100]; -}; - -convert$2.hwb.hcg = function (hwb) { - var w = hwb[1] / 100; - var b = hwb[2] / 100; - var v = 1 - b; - var c = v - w; - var g = 0; - - if (c < 1) { - g = (v - c) / (1 - c); - } - - return [hwb[0], c * 100, g * 100]; -}; - -convert$2.apple.rgb = function (apple) { - return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255]; -}; - -convert$2.rgb.apple = function (rgb) { - return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535]; -}; - -convert$2.gray.rgb = function (args) { - return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; -}; - -convert$2.gray.hsl = convert$2.gray.hsv = function (args) { - return [0, 0, args[0]]; -}; - -convert$2.gray.hwb = function (gray) { - return [0, 100, gray[0]]; -}; - -convert$2.gray.cmyk = function (gray) { - return [0, 0, 0, gray[0]]; -}; - -convert$2.gray.lab = function (gray) { - return [gray[0], 0, 0]; -}; - -convert$2.gray.hex = function (gray) { - var val = Math.round(gray[0] / 100 * 255) & 0xFF; - var integer = (val << 16) + (val << 8) + val; - - var string = integer.toString(16).toUpperCase(); - return '000000'.substring(string.length) + string; -}; - -convert$2.rgb.gray = function (rgb) { - var val = (rgb[0] + rgb[1] + rgb[2]) / 3; - return [val / 255 * 100]; -}; - -var conversions$1 = conversions$2.exports; - -/* - this function routes a model to all other models. - - all functions that are routed have a property `.conversion` attached - to the returned synthetic function. This property is an array - of strings, each with the steps in between the 'from' and 'to' - color models (inclusive). - - conversions that are not possible simply are not included. -*/ - -function buildGraph() { - var graph = {}; - // https://jsperf.com/object-keys-vs-for-in-with-closure/3 - var models = Object.keys(conversions$1); - - for (var len = models.length, i = 0; i < len; i++) { - graph[models[i]] = { - // http://jsperf.com/1-vs-infinity - // micro-opt, but this is simple. - distance: -1, - parent: null - }; - } - - return graph; -} - -// https://en.wikipedia.org/wiki/Breadth-first_search -function deriveBFS(fromModel) { - var graph = buildGraph(); - var queue = [fromModel]; // unshift -> queue -> pop - - graph[fromModel].distance = 0; - - while (queue.length) { - var current = queue.pop(); - var adjacents = Object.keys(conversions$1[current]); - - for (var len = adjacents.length, i = 0; i < len; i++) { - var adjacent = adjacents[i]; - var node = graph[adjacent]; - - if (node.distance === -1) { - node.distance = graph[current].distance + 1; - node.parent = current; - queue.unshift(adjacent); - } - } - } - - return graph; -} - -function link$1(from, to) { - return function (args) { - return to(from(args)); - }; -} - -function wrapConversion(toModel, graph) { - var path = [graph[toModel].parent, toModel]; - var fn = conversions$1[graph[toModel].parent][toModel]; - - var cur = graph[toModel].parent; - while (graph[cur].parent) { - path.unshift(graph[cur].parent); - fn = link$1(conversions$1[graph[cur].parent][cur], fn); - cur = graph[cur].parent; - } - - fn.conversion = path; - return fn; -} - -var route$1 = function (fromModel) { - var graph = deriveBFS(fromModel); - var conversion = {}; - - var models = Object.keys(graph); - for (var len = models.length, i = 0; i < len; i++) { - var toModel = models[i]; - var node = graph[toModel]; - - if (node.parent === null) { - // no possible conversion, or this node is the source model. - continue; - } - - conversion[toModel] = wrapConversion(toModel, graph); - } - - return conversion; -}; - -var conversions = conversions$2.exports; -var route = route$1; - -var convert$1 = {}; - -var models = Object.keys(conversions); - -function wrapRaw(fn) { - var wrappedFn = function (args) { - if (args === undefined || args === null) { - return args; - } - - if (arguments.length > 1) { - args = Array.prototype.slice.call(arguments); - } - - return fn(args); - }; - - // preserve .conversion property if there is one - if ('conversion' in fn) { - wrappedFn.conversion = fn.conversion; - } - - return wrappedFn; -} - -function wrapRounded(fn) { - var wrappedFn = function (args) { - if (args === undefined || args === null) { - return args; - } - - if (arguments.length > 1) { - args = Array.prototype.slice.call(arguments); - } - - var result = fn(args); - - // we're assuming the result is an array here. - // see notice in conversions.js; don't use box types - // in conversion functions. - if (typeof result === 'object') { - for (var len = result.length, i = 0; i < len; i++) { - result[i] = Math.round(result[i]); - } - } - - return result; - }; - - // preserve .conversion property if there is one - if ('conversion' in fn) { - wrappedFn.conversion = fn.conversion; - } - - return wrappedFn; -} - -models.forEach(function (fromModel) { - convert$1[fromModel] = {}; - - Object.defineProperty(convert$1[fromModel], 'channels', {value: conversions[fromModel].channels}); - Object.defineProperty(convert$1[fromModel], 'labels', {value: conversions[fromModel].labels}); - - var routes = route(fromModel); - var routeModels = Object.keys(routes); - - routeModels.forEach(function (toModel) { - var fn = routes[toModel]; - - convert$1[fromModel][toModel] = wrapRounded(fn); - convert$1[fromModel][toModel].raw = wrapRaw(fn); - }); -}); - -var colorConvert = convert$1; - -(function (module) { -const colorConvert$1 = colorConvert; - -const wrapAnsi16 = (fn, offset) => function () { - const code = fn.apply(colorConvert$1, arguments); - return `\u001B[${code + offset}m`; -}; - -const wrapAnsi256 = (fn, offset) => function () { - const code = fn.apply(colorConvert$1, arguments); - return `\u001B[${38 + offset};5;${code}m`; -}; - -const wrapAnsi16m = (fn, offset) => function () { - const rgb = fn.apply(colorConvert$1, arguments); - return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`; -}; - -function assembleStyles() { - const codes = new Map(); - const styles = { - 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], - 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], - gray: [90, 39], - - // Bright color - 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], - bgRedBright: [101, 49], - bgGreenBright: [102, 49], - bgYellowBright: [103, 49], - bgBlueBright: [104, 49], - bgMagentaBright: [105, 49], - bgCyanBright: [106, 49], - bgWhiteBright: [107, 49] - } - }; - - // Fix humans - styles.color.grey = styles.color.gray; - - for (const groupName of Object.keys(styles)) { - const group = styles[groupName]; - - for (const styleName of Object.keys(group)) { - const style = group[styleName]; - - styles[styleName] = { - open: `\u001B[${style[0]}m`, - close: `\u001B[${style[1]}m` - }; - - group[styleName] = styles[styleName]; - - codes.set(style[0], style[1]); - } - - Object.defineProperty(styles, groupName, { - value: group, - enumerable: false - }); - - Object.defineProperty(styles, 'codes', { - value: codes, - enumerable: false - }); - } - - const ansi2ansi = n => n; - const rgb2rgb = (r, g, b) => [r, g, b]; - - styles.color.close = '\u001B[39m'; - styles.bgColor.close = '\u001B[49m'; - - styles.color.ansi = { - ansi: wrapAnsi16(ansi2ansi, 0) - }; - styles.color.ansi256 = { - ansi256: wrapAnsi256(ansi2ansi, 0) - }; - styles.color.ansi16m = { - rgb: wrapAnsi16m(rgb2rgb, 0) - }; - - styles.bgColor.ansi = { - ansi: wrapAnsi16(ansi2ansi, 10) - }; - styles.bgColor.ansi256 = { - ansi256: wrapAnsi256(ansi2ansi, 10) - }; - styles.bgColor.ansi16m = { - rgb: wrapAnsi16m(rgb2rgb, 10) - }; - - for (let key of Object.keys(colorConvert$1)) { - if (typeof colorConvert$1[key] !== 'object') { - continue; - } - - const suite = colorConvert$1[key]; - - if (key === 'ansi16') { - key = 'ansi'; - } - - if ('ansi16' in suite) { - styles.color.ansi[key] = wrapAnsi16(suite.ansi16, 0); - styles.bgColor.ansi[key] = wrapAnsi16(suite.ansi16, 10); - } - - if ('ansi256' in suite) { - styles.color.ansi256[key] = wrapAnsi256(suite.ansi256, 0); - styles.bgColor.ansi256[key] = wrapAnsi256(suite.ansi256, 10); - } - - if ('rgb' in suite) { - styles.color.ansi16m[key] = wrapAnsi16m(suite.rgb, 0); - styles.bgColor.ansi16m[key] = wrapAnsi16m(suite.rgb, 10); - } - } - - return styles; -} - -// Make the export immutable -Object.defineProperty(module, 'exports', { - enumerable: true, - get: assembleStyles -}); -}(ansiStyles)); - -var hasFlag$2 = (flag, argv) => { - argv = argv || process.argv; - const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--'); - const pos = argv.indexOf(prefix + flag); - const terminatorPos = argv.indexOf('--'); - return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos); -}; - -const os$1 = require$$0$2; -const hasFlag$1 = hasFlag$2; - -const env$1 = process.env; - -let forceColor; -if (hasFlag$1('no-color') || - hasFlag$1('no-colors') || - hasFlag$1('color=false')) { - forceColor = false; -} else if (hasFlag$1('color') || - hasFlag$1('colors') || - hasFlag$1('color=true') || - hasFlag$1('color=always')) { - forceColor = true; -} -if ('FORCE_COLOR' in env$1) { - forceColor = env$1.FORCE_COLOR.length === 0 || parseInt(env$1.FORCE_COLOR, 10) !== 0; -} - -function translateLevel$1(level) { - if (level === 0) { - return false; - } - - return { - level, - hasBasic: true, - has256: level >= 2, - has16m: level >= 3 - }; -} - -function supportsColor$1(stream) { - if (forceColor === false) { - return 0; - } - - if (hasFlag$1('color=16m') || - hasFlag$1('color=full') || - hasFlag$1('color=truecolor')) { - return 3; - } - - if (hasFlag$1('color=256')) { - return 2; - } - - if (stream && !stream.isTTY && forceColor !== true) { - return 0; - } - - const min = forceColor ? 1 : 0; - - if (process.platform === 'win32') { - // Node.js 7.5.0 is the first version of Node.js to include a patch to - // libuv that enables 256 color output on Windows. Anything earlier and it - // won't work. However, here we target Node.js 8 at minimum as it is an LTS - // release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows - // release that supports 256 colors. Windows 10 build 14931 is the first release - // that supports 16m/TrueColor. - const osRelease = os$1.release().split('.'); - if ( - Number(process.versions.node.split('.')[0]) >= 8 && - Number(osRelease[0]) >= 10 && - Number(osRelease[2]) >= 10586 - ) { - return Number(osRelease[2]) >= 14931 ? 3 : 2; - } - - return 1; - } - - if ('CI' in env$1) { - if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env$1) || env$1.CI_NAME === 'codeship') { - return 1; - } - - return min; - } - - if ('TEAMCITY_VERSION' in env$1) { - return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env$1.TEAMCITY_VERSION) ? 1 : 0; - } - - if (env$1.COLORTERM === 'truecolor') { - return 3; - } - - if ('TERM_PROGRAM' in env$1) { - const version = parseInt((env$1.TERM_PROGRAM_VERSION || '').split('.')[0], 10); - - switch (env$1.TERM_PROGRAM) { - case 'iTerm.app': - return version >= 3 ? 3 : 2; - case 'Apple_Terminal': - return 2; - // No default - } - } - - if (/-256(color)?$/i.test(env$1.TERM)) { - return 2; - } - - if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env$1.TERM)) { - return 1; - } - - if ('COLORTERM' in env$1) { - return 1; - } - - if (env$1.TERM === 'dumb') { - return min; - } - - return min; -} - -function getSupportLevel(stream) { - const level = supportsColor$1(stream); - return translateLevel$1(level); -} - -var supportsColor_1 = { - supportsColor: getSupportLevel, - stdout: getSupportLevel(process.stdout), - stderr: getSupportLevel(process.stderr) -}; - -const TEMPLATE_REGEX = /(?:\\(u[a-f\d]{4}|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi; -const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g; -const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/; -const ESCAPE_REGEX = /\\(u[a-f\d]{4}|x[a-f\d]{2}|.)|([^\\])/gi; - -const ESCAPES = new Map([ - ['n', '\n'], - ['r', '\r'], - ['t', '\t'], - ['b', '\b'], - ['f', '\f'], - ['v', '\v'], - ['0', '\0'], - ['\\', '\\'], - ['e', '\u001B'], - ['a', '\u0007'] -]); - -function unescape(c) { - if ((c[0] === 'u' && c.length === 5) || (c[0] === 'x' && c.length === 3)) { - return String.fromCharCode(parseInt(c.slice(1), 16)); - } - - return ESCAPES.get(c) || c; -} - -function parseArguments(name, args) { - const results = []; - const chunks = args.trim().split(/\s*,\s*/g); - let matches; - - for (const chunk of chunks) { - if (!isNaN(chunk)) { - results.push(Number(chunk)); - } else if ((matches = chunk.match(STRING_REGEX))) { - results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, chr) => escape ? unescape(escape) : chr)); - } else { - throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`); - } - } - - return results; -} - -function parseStyle(style) { - STYLE_REGEX.lastIndex = 0; - - const results = []; - let matches; - - while ((matches = STYLE_REGEX.exec(style)) !== null) { - const name = matches[1]; - - if (matches[2]) { - const args = parseArguments(name, matches[2]); - results.push([name].concat(args)); - } else { - results.push([name]); - } - } - - return results; -} - -function buildStyle(chalk, styles) { - const enabled = {}; - - for (const layer of styles) { - for (const style of layer.styles) { - enabled[style[0]] = layer.inverse ? null : style.slice(1); - } - } - - let current = chalk; - for (const styleName of Object.keys(enabled)) { - if (Array.isArray(enabled[styleName])) { - if (!(styleName in current)) { - throw new Error(`Unknown Chalk style: ${styleName}`); - } - - if (enabled[styleName].length > 0) { - current = current[styleName].apply(current, enabled[styleName]); - } else { - current = current[styleName]; - } - } - } - - return current; -} - -var templates = (chalk, tmp) => { - const styles = []; - const chunks = []; - let chunk = []; - - // eslint-disable-next-line max-params - tmp.replace(TEMPLATE_REGEX, (m, escapeChar, inverse, style, close, chr) => { - if (escapeChar) { - chunk.push(unescape(escapeChar)); - } else if (style) { - const str = chunk.join(''); - chunk = []; - chunks.push(styles.length === 0 ? str : buildStyle(chalk, styles)(str)); - styles.push({inverse, styles: parseStyle(style)}); - } else if (close) { - if (styles.length === 0) { - throw new Error('Found extraneous } in Chalk template literal'); - } - - chunks.push(buildStyle(chalk, styles)(chunk.join(''))); - chunk = []; - styles.pop(); - } else { - chunk.push(chr); - } - }); - - chunks.push(chunk.join('')); - - if (styles.length > 0) { - const errMsg = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`; - throw new Error(errMsg); - } - - return chunks.join(''); -}; - -(function (module) { -const escapeStringRegexp = escapeStringRegexp$1; -const ansiStyles$1 = ansiStyles.exports; -const stdoutColor = supportsColor_1.stdout; - -const template = templates; - -const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); - -// `supportsColor.level` → `ansiStyles.color[name]` mapping -const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m']; - -// `color-convert` models to exclude from the Chalk API due to conflicts and such -const skipModels = new Set(['gray']); - -const styles = Object.create(null); - -function applyOptions(obj, options) { - options = options || {}; - - // Detect level if not set manually - const scLevel = stdoutColor ? stdoutColor.level : 0; - obj.level = options.level === undefined ? scLevel : options.level; - obj.enabled = 'enabled' in options ? options.enabled : obj.level > 0; -} - -function Chalk(options) { - // We check for this.template here since calling `chalk.constructor()` - // by itself will have a `this` of a previously constructed chalk object - if (!this || !(this instanceof Chalk) || this.template) { - const chalk = {}; - applyOptions(chalk, options); - - chalk.template = function () { - const args = [].slice.call(arguments); - return chalkTag.apply(null, [chalk.template].concat(args)); - }; - - Object.setPrototypeOf(chalk, Chalk.prototype); - Object.setPrototypeOf(chalk.template, chalk); - - chalk.template.constructor = Chalk; - - return chalk.template; - } - - applyOptions(this, options); -} - -// Use bright blue on Windows as the normal blue color is illegible -if (isSimpleWindowsTerm) { - ansiStyles$1.blue.open = '\u001B[94m'; -} - -for (const key of Object.keys(ansiStyles$1)) { - ansiStyles$1[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles$1[key].close), 'g'); - - styles[key] = { - get() { - const codes = ansiStyles$1[key]; - return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key); - } - }; -} - -styles.visible = { - get() { - return build.call(this, this._styles || [], true, 'visible'); - } -}; - -ansiStyles$1.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles$1.color.close), 'g'); -for (const model of Object.keys(ansiStyles$1.color.ansi)) { - if (skipModels.has(model)) { - continue; - } - - styles[model] = { - get() { - const level = this.level; - return function () { - const open = ansiStyles$1.color[levelMapping[level]][model].apply(null, arguments); - const codes = { - open, - close: ansiStyles$1.color.close, - closeRe: ansiStyles$1.color.closeRe - }; - return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); - }; - } - }; -} - -ansiStyles$1.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles$1.bgColor.close), 'g'); -for (const model of Object.keys(ansiStyles$1.bgColor.ansi)) { - if (skipModels.has(model)) { - continue; - } - - const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1); - styles[bgModel] = { - get() { - const level = this.level; - return function () { - const open = ansiStyles$1.bgColor[levelMapping[level]][model].apply(null, arguments); - const codes = { - open, - close: ansiStyles$1.bgColor.close, - closeRe: ansiStyles$1.bgColor.closeRe - }; - return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); - }; - } - }; -} - -const proto = Object.defineProperties(() => {}, styles); - -function build(_styles, _empty, key) { - const builder = function () { - return applyStyle.apply(builder, arguments); - }; - - builder._styles = _styles; - builder._empty = _empty; - - const self = this; - - Object.defineProperty(builder, 'level', { - enumerable: true, - get() { - return self.level; - }, - set(level) { - self.level = level; - } - }); - - Object.defineProperty(builder, 'enabled', { - enumerable: true, - get() { - return self.enabled; - }, - set(enabled) { - self.enabled = enabled; - } - }); - - // See below for fix regarding invisible grey/dim combination on Windows - builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey'; - - // `__proto__` is used because we must return a function, but there is - // no way to create a function with a different prototype - builder.__proto__ = proto; // eslint-disable-line no-proto - - return builder; -} - -function applyStyle() { - // Support varags, but simply cast to string in case there's only one arg - const args = arguments; - const argsLen = args.length; - let str = String(arguments[0]); - - if (argsLen === 0) { - return ''; - } - - if (argsLen > 1) { - // Don't slice `arguments`, it prevents V8 optimizations - for (let a = 1; a < argsLen; a++) { - str += ' ' + args[a]; - } - } - - if (!this.enabled || this.level <= 0 || !str) { - return this._empty ? '' : str; - } - - // Turns out that on Windows dimmed gray text becomes invisible in cmd.exe, - // see https://github.com/chalk/chalk/issues/58 - // If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop. - const originalDim = ansiStyles$1.dim.open; - if (isSimpleWindowsTerm && this.hasGrey) { - ansiStyles$1.dim.open = ''; - } - - for (const code of this._styles.slice().reverse()) { - // 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'. - str = code.open + str.replace(code.closeRe, code.open) + code.close; - - // 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 - str = str.replace(/\r?\n/g, `${code.close}$&${code.open}`); - } - - // Reset the original `dim` if we changed it to work around the Windows dimmed gray issue - ansiStyles$1.dim.open = originalDim; - - return str; -} - -function chalkTag(chalk, strings) { - if (!Array.isArray(strings)) { - // If chalk() was called by itself or with a string, - // return the string itself as a string. - return [].slice.call(arguments, 1).join(' '); - } - - const args = [].slice.call(arguments, 2); - const parts = [strings.raw[0]]; - - for (let i = 1; i < strings.length; i++) { - parts.push(String(args[i - 1]).replace(/[{}\\]/g, '\\$&')); - parts.push(String(strings.raw[i])); - } - - return template(chalk, parts.join('')); -} - -Object.defineProperties(Chalk.prototype, styles); - -module.exports = Chalk(); // eslint-disable-line new-cap -module.exports.supportsColor = stdoutColor; -module.exports.default = module.exports; // For TypeScript -}(chalk)); - -Object.defineProperty(lib$3, "__esModule", { - value: true -}); -lib$3.shouldHighlight = shouldHighlight; -lib$3.getChalk = getChalk; -lib$3.default = highlight; - -var _jsTokens = jsTokens; - -var _helperValidatorIdentifier = lib$2; - -var _chalk = chalk.exports; - -const sometimesKeywords = new Set(["as", "async", "from", "get", "of", "set"]); - -function getDefs$1(chalk) { - return { - keyword: chalk.cyan, - capitalized: chalk.yellow, - jsxIdentifier: chalk.yellow, - punctuator: chalk.yellow, - number: chalk.magenta, - string: chalk.green, - regex: chalk.magenta, - comment: chalk.grey, - invalid: chalk.white.bgRed.bold - }; -} - -const NEWLINE$1 = /\r\n|[\n\r\u2028\u2029]/; -const BRACKET = /^[()[\]{}]$/; -let tokenize; -{ - const JSX_TAG = /^[a-z][\w-]*$/i; - - const getTokenType = function (token, offset, text) { - if (token.type === "name") { - if ((0, _helperValidatorIdentifier.isKeyword)(token.value) || (0, _helperValidatorIdentifier.isStrictReservedWord)(token.value, true) || sometimesKeywords.has(token.value)) { - return "keyword"; - } - - if (JSX_TAG.test(token.value) && (text[offset - 1] === "<" || text.substr(offset - 2, 2) == " colorize(str)).join("\n"); - } else { - highlighted += value; - } - } - - return highlighted; -} - -function shouldHighlight(options) { - return !!_chalk.supportsColor || options.forceColor; -} - -function getChalk(options) { - return options.forceColor ? new _chalk.constructor({ - enabled: true, - level: 1 - }) : _chalk; -} - -function highlight(code, options = {}) { - if (shouldHighlight(options)) { - const chalk = getChalk(options); - const defs = getDefs$1(chalk); - return highlightTokens(defs, code); - } else { - return code; - } -} - -Object.defineProperty(lib$4, "__esModule", { - value: true -}); -lib$4.codeFrameColumns = codeFrameColumns$1; -lib$4.default = _default; - -var _highlight = lib$3; - -let deprecationWarningShown = false; - -function getDefs(chalk) { - return { - gutter: chalk.grey, - marker: chalk.red.bold, - message: chalk.red.bold - }; -} - -const NEWLINE = /\r\n|[\n\r\u2028\u2029]/; - -function getMarkerLines(loc, source, opts) { - const startLoc = Object.assign({ - column: 0, - line: -1 - }, loc.start); - const endLoc = Object.assign({}, startLoc, loc.end); - const { - linesAbove = 2, - linesBelow = 3 - } = opts || {}; - const startLine = startLoc.line; - const startColumn = startLoc.column; - const endLine = endLoc.line; - const endColumn = endLoc.column; - let start = Math.max(startLine - (linesAbove + 1), 0); - let end = Math.min(source.length, endLine + linesBelow); - - if (startLine === -1) { - start = 0; - } - - if (endLine === -1) { - end = source.length; - } - - const lineDiff = endLine - startLine; - const markerLines = {}; - - if (lineDiff) { - for (let i = 0; i <= lineDiff; i++) { - const lineNumber = i + startLine; - - if (!startColumn) { - markerLines[lineNumber] = true; - } else if (i === 0) { - const sourceLength = source[lineNumber - 1].length; - markerLines[lineNumber] = [startColumn, sourceLength - startColumn + 1]; - } else if (i === lineDiff) { - markerLines[lineNumber] = [0, endColumn]; - } else { - const sourceLength = source[lineNumber - i].length; - markerLines[lineNumber] = [0, sourceLength]; - } - } - } else { - if (startColumn === endColumn) { - if (startColumn) { - markerLines[startLine] = [startColumn, 0]; - } else { - markerLines[startLine] = true; - } - } else { - markerLines[startLine] = [startColumn, endColumn - startColumn]; - } - } - - return { - start, - end, - markerLines - }; -} - -function codeFrameColumns$1(rawLines, loc, opts = {}) { - const highlighted = (opts.highlightCode || opts.forceColor) && (0, _highlight.shouldHighlight)(opts); - const chalk = (0, _highlight.getChalk)(opts); - const defs = getDefs(chalk); - - const maybeHighlight = (chalkFn, string) => { - return highlighted ? chalkFn(string) : string; - }; - - const lines = rawLines.split(NEWLINE); - const { - start, - end, - markerLines - } = getMarkerLines(loc, lines, opts); - const hasColumns = loc.start && typeof loc.start.column === "number"; - const numberMaxWidth = String(end).length; - const highlightedLines = highlighted ? (0, _highlight.default)(rawLines, opts) : rawLines; - let frame = highlightedLines.split(NEWLINE).slice(start, end).map((line, index) => { - const number = start + 1 + index; - const paddedNumber = ` ${number}`.slice(-numberMaxWidth); - const gutter = ` ${paddedNumber} |`; - const hasMarker = markerLines[number]; - const lastMarkerLine = !markerLines[number + 1]; - - if (hasMarker) { - let markerLine = ""; - - if (Array.isArray(hasMarker)) { - const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replace(/[^\t]/g, " "); - const numberOfMarkers = hasMarker[1] || 1; - markerLine = ["\n ", maybeHighlight(defs.gutter, gutter.replace(/\d/g, " ")), " ", markerSpacing, maybeHighlight(defs.marker, "^").repeat(numberOfMarkers)].join(""); - - if (lastMarkerLine && opts.message) { - markerLine += " " + maybeHighlight(defs.message, opts.message); - } - } - - return [maybeHighlight(defs.marker, ">"), maybeHighlight(defs.gutter, gutter), line.length > 0 ? ` ${line}` : "", markerLine].join(""); - } else { - return ` ${maybeHighlight(defs.gutter, gutter)}${line.length > 0 ? ` ${line}` : ""}`; - } - }).join("\n"); - - if (opts.message && !hasColumns) { - frame = `${" ".repeat(numberMaxWidth + 1)}${opts.message}\n${frame}`; - } - - if (highlighted) { - return chalk.reset(frame); - } else { - return frame; - } -} - -function _default(rawLines, lineNumber, colNumber, opts = {}) { - if (!deprecationWarningShown) { - deprecationWarningShown = true; - const message = "Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`."; - - if (process.emitWarning) { - process.emitWarning(message, "DeprecationWarning"); - } else { - const deprecationError = new Error(message); - deprecationError.name = "DeprecationWarning"; - console.warn(new Error(message)); - } - } - - colNumber = Math.max(colNumber, 0); - const location = { - start: { - column: colNumber, - line: lineNumber - } - }; - return codeFrameColumns$1(rawLines, location, opts); -} - -const errorEx = errorEx_1; -const fallback = jsonParseEvenBetterErrors; -const {default: LinesAndColumns} = require$$2; -const {codeFrameColumns} = lib$4; - -const JSONError = errorEx('JSONError', { - fileName: errorEx.append('in %s'), - codeFrame: errorEx.append('\n\n%s\n') -}); - -const parseJson = (string, reviver, filename) => { - if (typeof reviver === 'string') { - filename = reviver; - reviver = null; - } - - try { - try { - return JSON.parse(string, reviver); - } catch (error) { - fallback(string, reviver); - throw error; - } - } catch (error) { - error.message = error.message.replace(/\n/g, ''); - const indexMatch = error.message.match(/in JSON at position (\d+) while parsing/); - - const jsonError = new JSONError(error); - if (filename) { - jsonError.fileName = filename; - } - - if (indexMatch && indexMatch.length > 0) { - const lines = new LinesAndColumns(string); - const index = Number(indexMatch[1]); - const location = lines.locationForIndex(index); - - const codeFrame = codeFrameColumns( - string, - {start: {line: location.line + 1, column: location.column + 1}}, - {highlightCode: true} - ); - - jsonError.codeFrame = codeFrame; - } - - throw jsonError; - } -}; - -parseJson.JSONError = JSONError; - -var parseJson_1 = parseJson; - -var src = {exports: {}}; - -var browser = {exports: {}}; - -/** - * Helpers. - */ - -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 - */ - -var ms = function(val, options) { - options = options || {}; - var type = typeof val; - if (type === 'string' && val.length > 0) { - return parse$a(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$a(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$1(ms, msAbs, d, 'day'); - } - if (msAbs >= h) { - return plural$1(ms, msAbs, h, 'hour'); - } - if (msAbs >= m) { - return plural$1(ms, msAbs, m, 'minute'); - } - if (msAbs >= s) { - return plural$1(ms, msAbs, s, 'second'); - } - return ms + ' ms'; -} - -/** - * Pluralization helper. - */ - -function plural$1(ms, msAbs, n, name) { - var isPlural = msAbs >= n * 1.5; - return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); -} - -/** - * 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 = ms; - 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 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.substr(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; -} - -var common$3 = setup; - -/* eslint-env browser */ - -(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' && navigator.userAgent && 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' && navigator.userAgent && 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' && navigator.userAgent && 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 = common$3(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, browser.exports)); - -var node = {exports: {}}; - -/** - * Module dependencies. - */ - -(function (module, exports) { -const tty = tty$1; -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 = supportsColor_1$1; - - 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 = common$3(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, node.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.exports = browser.exports; -} else { - src.exports = node.exports; -} - -var createDebug = src.exports; - -var re$6 = {exports: {}}; - -// Note: this is the semver.org version of the spec that it implements -// Not necessarily the package version of this code. -const SEMVER_SPEC_VERSION = '2.0.0'; - -const MAX_LENGTH$2 = 256; -const MAX_SAFE_INTEGER$1 = Number.MAX_SAFE_INTEGER || - /* istanbul ignore next */ 9007199254740991; - -// Max safe segment length for coercion. -const MAX_SAFE_COMPONENT_LENGTH = 16; - -var constants = { - SEMVER_SPEC_VERSION, - MAX_LENGTH: MAX_LENGTH$2, - MAX_SAFE_INTEGER: MAX_SAFE_INTEGER$1, - MAX_SAFE_COMPONENT_LENGTH -}; - -const debug$f = ( - typeof process === 'object' && - process.env && - process.env.NODE_DEBUG && - /\bsemver\b/i.test(process.env.NODE_DEBUG) -) ? (...args) => console.error('SEMVER', ...args) - : () => {}; - -var debug_1 = debug$f; - -(function (module, exports) { -const { MAX_SAFE_COMPONENT_LENGTH } = constants; -const debug = debug_1; -exports = module.exports = {}; - -// The actual regexps go on exports.re -const re = exports.re = []; -const src = exports.src = []; -const t = exports.t = {}; -let R = 0; - -const createToken = (name, value, isGlobal) => { - const index = R++; - debug(index, value); - t[name] = index; - src[index] = value; - re[index] = new RegExp(value, isGlobal ? 'g' : undefined); -}; - -// The following Regular Expressions can be used for tokenizing, -// validating, and parsing SemVer version strings. - -// ## Numeric Identifier -// A single `0`, or a non-zero digit followed by zero or more digits. - -createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*'); -createToken('NUMERICIDENTIFIERLOOSE', '[0-9]+'); - -// ## Non-numeric Identifier -// Zero or more digits, followed by a letter or hyphen, and then zero or -// more letters, digits, or hyphens. - -createToken('NONNUMERICIDENTIFIER', '\\d*[a-zA-Z-][a-zA-Z0-9-]*'); - -// ## Main Version -// Three dot-separated numeric identifiers. - -createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` + - `(${src[t.NUMERICIDENTIFIER]})\\.` + - `(${src[t.NUMERICIDENTIFIER]})`); - -createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + - `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + - `(${src[t.NUMERICIDENTIFIERLOOSE]})`); - -// ## Pre-release Version Identifier -// A numeric identifier, or a non-numeric identifier. - -createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NUMERICIDENTIFIER] -}|${src[t.NONNUMERICIDENTIFIER]})`); - -createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NUMERICIDENTIFIERLOOSE] -}|${src[t.NONNUMERICIDENTIFIER]})`); - -// ## Pre-release Version -// Hyphen, followed by one or more dot-separated pre-release version -// identifiers. - -createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER] -}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`); - -createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE] -}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`); - -// ## Build Metadata Identifier -// Any combination of digits, letters, or hyphens. - -createToken('BUILDIDENTIFIER', '[0-9A-Za-z-]+'); - -// ## Build Metadata -// Plus sign, followed by one or more period-separated build metadata -// identifiers. - -createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER] -}(?:\\.${src[t.BUILDIDENTIFIER]})*))`); - -// ## Full Version String -// A main version, followed optionally by a pre-release version and -// build metadata. - -// Note that the only major, minor, patch, and pre-release sections of -// the version string are capturing groups. The build metadata is not a -// capturing group, because it should not ever be used in version -// comparison. - -createToken('FULLPLAIN', `v?${src[t.MAINVERSION] -}${src[t.PRERELEASE]}?${ - src[t.BUILD]}?`); - -createToken('FULL', `^${src[t.FULLPLAIN]}$`); - -// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. -// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty -// common in the npm registry. -createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE] -}${src[t.PRERELEASELOOSE]}?${ - src[t.BUILD]}?`); - -createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`); - -createToken('GTLT', '((?:<|>)?=?)'); - -// Something like "2.*" or "1.2.x". -// Note that "x.x" is a valid xRange identifer, meaning "any version" -// Only the first item is strictly required. -createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`); -createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`); - -createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` + - `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + - `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + - `(?:${src[t.PRERELEASE]})?${ - src[t.BUILD]}?` + - `)?)?`); - -createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` + - `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + - `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + - `(?:${src[t.PRERELEASELOOSE]})?${ - src[t.BUILD]}?` + - `)?)?`); - -createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`); -createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`); - -// Coercion. -// Extract anything that could conceivably be a part of a valid semver -createToken('COERCE', `${'(^|[^\\d])' + - '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` + - `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + - `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + - `(?:$|[^\\d])`); -createToken('COERCERTL', src[t.COERCE], true); - -// Tilde ranges. -// Meaning is "reasonably at or greater than" -createToken('LONETILDE', '(?:~>?)'); - -createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true); -exports.tildeTrimReplace = '$1~'; - -createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`); -createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`); - -// Caret ranges. -// Meaning is "at least and backwards compatible with" -createToken('LONECARET', '(?:\\^)'); - -createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true); -exports.caretTrimReplace = '$1^'; - -createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`); -createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`); - -// A simple gt/lt/eq thing, or just "" to indicate "any version" -createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`); -createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`); - -// An expression to strip any whitespace between the gtlt and the thing -// it modifies, so that `> 1.2.3` ==> `>1.2.3` -createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT] -}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true); -exports.comparatorTrimReplace = '$1$2$3'; - -// Something like `1.2.3 - 1.2.4` -// Note that these all use the loose form, because they'll be -// checked against either the strict or loose comparator form -// later. -createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` + - `\\s+-\\s+` + - `(${src[t.XRANGEPLAIN]})` + - `\\s*$`); - -createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` + - `\\s+-\\s+` + - `(${src[t.XRANGEPLAINLOOSE]})` + - `\\s*$`); - -// Star ranges basically just allow anything at all. -createToken('STAR', '(<|>)?=?\\s*\\*'); -// >=0.0.0 is like a star -createToken('GTE0', '^\\s*>=\\s*0\.0\.0\\s*$'); -createToken('GTE0PRE', '^\\s*>=\\s*0\.0\.0-0\\s*$'); -}(re$6, re$6.exports)); - -// parse out just the options we care about so we always get a consistent -// obj with keys in a consistent order. -const opts = ['includePrerelease', 'loose', 'rtl']; -const parseOptions$4 = options => - !options ? {} - : typeof options !== 'object' ? { loose: true } - : opts.filter(k => options[k]).reduce((options, k) => { - options[k] = true; - return options - }, {}); -var parseOptions_1 = parseOptions$4; - -const numeric$1 = /^[0-9]+$/; -const compareIdentifiers$1 = (a, b) => { - const anum = numeric$1.test(a); - const bnum = numeric$1.test(b); - - if (anum && bnum) { - a = +a; - b = +b; - } - - return a === b ? 0 - : (anum && !bnum) ? -1 - : (bnum && !anum) ? 1 - : a < b ? -1 - : 1 -}; - -const rcompareIdentifiers = (a, b) => compareIdentifiers$1(b, a); - -var identifiers = { - compareIdentifiers: compareIdentifiers$1, - rcompareIdentifiers -}; - -const debug$e = debug_1; -const { MAX_LENGTH: MAX_LENGTH$1, MAX_SAFE_INTEGER } = constants; -const { re: re$5, t: t$4 } = re$6.exports; - -const parseOptions$3 = parseOptions_1; -const { compareIdentifiers } = identifiers; -class SemVer$e { - constructor (version, options) { - options = parseOptions$3(options); - - if (version instanceof SemVer$e) { - if (version.loose === !!options.loose && - version.includePrerelease === !!options.includePrerelease) { - return version - } else { - version = version.version; - } - } else if (typeof version !== 'string') { - throw new TypeError(`Invalid Version: ${version}`) - } - - if (version.length > MAX_LENGTH$1) { - throw new TypeError( - `version is longer than ${MAX_LENGTH$1} characters` - ) - } - - debug$e('SemVer', version, options); - this.options = options; - this.loose = !!options.loose; - // this isn't actually relevant for versions, but keep it so that we - // don't run into trouble passing this.options around. - this.includePrerelease = !!options.includePrerelease; - - const m = version.trim().match(options.loose ? re$5[t$4.LOOSE] : re$5[t$4.FULL]); - - if (!m) { - throw new TypeError(`Invalid Version: ${version}`) - } - - this.raw = version; - - // these are actually numbers - this.major = +m[1]; - this.minor = +m[2]; - this.patch = +m[3]; - - if (this.major > MAX_SAFE_INTEGER || this.major < 0) { - throw new TypeError('Invalid major version') - } - - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { - throw new TypeError('Invalid minor version') - } - - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { - throw new TypeError('Invalid patch version') - } - - // numberify any prerelease numeric ids - if (!m[4]) { - this.prerelease = []; - } else { - this.prerelease = m[4].split('.').map((id) => { - if (/^[0-9]+$/.test(id)) { - const num = +id; - if (num >= 0 && num < MAX_SAFE_INTEGER) { - return num - } - } - return id - }); - } - - this.build = m[5] ? m[5].split('.') : []; - this.format(); - } - - format () { - this.version = `${this.major}.${this.minor}.${this.patch}`; - if (this.prerelease.length) { - this.version += `-${this.prerelease.join('.')}`; - } - return this.version - } - - toString () { - return this.version - } - - compare (other) { - debug$e('SemVer.compare', this.version, this.options, other); - if (!(other instanceof SemVer$e)) { - if (typeof other === 'string' && other === this.version) { - return 0 - } - other = new SemVer$e(other, this.options); - } - - if (other.version === this.version) { - return 0 - } - - return this.compareMain(other) || this.comparePre(other) - } - - compareMain (other) { - if (!(other instanceof SemVer$e)) { - other = new SemVer$e(other, this.options); - } - - return ( - compareIdentifiers(this.major, other.major) || - compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch) - ) - } - - comparePre (other) { - if (!(other instanceof SemVer$e)) { - other = new SemVer$e(other, this.options); - } - - // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) { - return -1 - } else if (!this.prerelease.length && other.prerelease.length) { - return 1 - } else if (!this.prerelease.length && !other.prerelease.length) { - return 0 - } - - let i = 0; - do { - const a = this.prerelease[i]; - const b = other.prerelease[i]; - debug$e('prerelease compare', i, a, b); - if (a === undefined && b === undefined) { - return 0 - } else if (b === undefined) { - return 1 - } else if (a === undefined) { - return -1 - } else if (a === b) { - continue - } else { - return compareIdentifiers(a, b) - } - } while (++i) - } - - compareBuild (other) { - if (!(other instanceof SemVer$e)) { - other = new SemVer$e(other, this.options); - } - - let i = 0; - do { - const a = this.build[i]; - const b = other.build[i]; - debug$e('prerelease compare', i, a, b); - if (a === undefined && b === undefined) { - return 0 - } else if (b === undefined) { - return 1 - } else if (a === undefined) { - return -1 - } else if (a === b) { - continue - } else { - return compareIdentifiers(a, b) - } - } while (++i) - } - - // preminor will bump the version up to the next minor release, and immediately - // down to pre-release. premajor and prepatch work the same way. - inc (release, identifier) { - switch (release) { - case 'premajor': - this.prerelease.length = 0; - this.patch = 0; - this.minor = 0; - this.major++; - this.inc('pre', identifier); - break - case 'preminor': - this.prerelease.length = 0; - this.patch = 0; - this.minor++; - this.inc('pre', identifier); - break - case 'prepatch': - // If this is already a prerelease, it will bump to the next version - // drop any prereleases that might already exist, since they are not - // relevant at this point. - this.prerelease.length = 0; - this.inc('patch', identifier); - this.inc('pre', identifier); - break - // If the input is a non-prerelease version, this acts the same as - // prepatch. - case 'prerelease': - if (this.prerelease.length === 0) { - this.inc('patch', identifier); - } - this.inc('pre', identifier); - break - - case 'major': - // If this is a pre-major version, bump up to the same major version. - // Otherwise increment major. - // 1.0.0-5 bumps to 1.0.0 - // 1.1.0 bumps to 2.0.0 - if ( - this.minor !== 0 || - this.patch !== 0 || - this.prerelease.length === 0 - ) { - this.major++; - } - this.minor = 0; - this.patch = 0; - this.prerelease = []; - break - case 'minor': - // If this is a pre-minor version, bump up to the same minor version. - // Otherwise increment minor. - // 1.2.0-5 bumps to 1.2.0 - // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) { - this.minor++; - } - this.patch = 0; - this.prerelease = []; - break - case 'patch': - // If this is not a pre-release version, it will increment the patch. - // If it is a pre-release it will bump up to the same patch version. - // 1.2.0-5 patches to 1.2.0 - // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) { - this.patch++; - } - this.prerelease = []; - break - // This probably shouldn't be used publicly. - // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. - case 'pre': - if (this.prerelease.length === 0) { - this.prerelease = [0]; - } else { - let i = this.prerelease.length; - while (--i >= 0) { - if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++; - i = -2; - } - } - if (i === -1) { - // didn't increment anything - this.prerelease.push(0); - } - } - if (identifier) { - // 1.2.0-beta.1 bumps to 1.2.0-beta.2, - // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 - if (this.prerelease[0] === identifier) { - if (isNaN(this.prerelease[1])) { - this.prerelease = [identifier, 0]; - } - } else { - this.prerelease = [identifier, 0]; - } - } - break - - default: - throw new Error(`invalid increment argument: ${release}`) - } - this.format(); - this.raw = this.version; - return this - } -} - -var semver$2 = SemVer$e; - -const {MAX_LENGTH} = constants; -const { re: re$4, t: t$3 } = re$6.exports; -const SemVer$d = semver$2; - -const parseOptions$2 = parseOptions_1; -const parse$9 = (version, options) => { - options = parseOptions$2(options); - - if (version instanceof SemVer$d) { - return version - } - - if (typeof version !== 'string') { - return null - } - - if (version.length > MAX_LENGTH) { - return null - } - - const r = options.loose ? re$4[t$3.LOOSE] : re$4[t$3.FULL]; - if (!r.test(version)) { - return null - } - - try { - return new SemVer$d(version, options) - } catch (er) { - return null - } -}; - -var parse_1 = parse$9; - -const parse$8 = parse_1; -const valid$1 = (version, options) => { - const v = parse$8(version, options); - return v ? v.version : null -}; -var valid_1 = valid$1; - -const parse$7 = parse_1; -const clean = (version, options) => { - const s = parse$7(version.trim().replace(/^[=v]+/, ''), options); - return s ? s.version : null -}; -var clean_1 = clean; - -const SemVer$c = semver$2; - -const inc = (version, release, options, identifier) => { - if (typeof (options) === 'string') { - identifier = options; - options = undefined; - } - - try { - return new SemVer$c(version, options).inc(release, identifier).version - } catch (er) { - return null - } -}; -var inc_1 = inc; - -const SemVer$b = semver$2; -const compare$b = (a, b, loose) => - new SemVer$b(a, loose).compare(new SemVer$b(b, loose)); - -var compare_1 = compare$b; - -const compare$a = compare_1; -const eq$2 = (a, b, loose) => compare$a(a, b, loose) === 0; -var eq_1 = eq$2; - -const parse$6 = parse_1; -const eq$1 = eq_1; - -const diff = (version1, version2) => { - if (eq$1(version1, version2)) { - return null - } else { - const v1 = parse$6(version1); - const v2 = parse$6(version2); - const hasPre = v1.prerelease.length || v2.prerelease.length; - const prefix = hasPre ? 'pre' : ''; - const defaultResult = hasPre ? 'prerelease' : ''; - for (const key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return prefix + key - } - } - } - return defaultResult // may be undefined - } -}; -var diff_1 = diff; - -const SemVer$a = semver$2; -const major = (a, loose) => new SemVer$a(a, loose).major; -var major_1 = major; - -const SemVer$9 = semver$2; -const minor = (a, loose) => new SemVer$9(a, loose).minor; -var minor_1 = minor; - -const SemVer$8 = semver$2; -const patch = (a, loose) => new SemVer$8(a, loose).patch; -var patch_1 = patch; - -const parse$5 = parse_1; -const prerelease = (version, options) => { - const parsed = parse$5(version, options); - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null -}; -var prerelease_1 = prerelease; - -const compare$9 = compare_1; -const rcompare = (a, b, loose) => compare$9(b, a, loose); -var rcompare_1 = rcompare; - -const compare$8 = compare_1; -const compareLoose = (a, b) => compare$8(a, b, true); -var compareLoose_1 = compareLoose; - -const SemVer$7 = semver$2; -const compareBuild$2 = (a, b, loose) => { - const versionA = new SemVer$7(a, loose); - const versionB = new SemVer$7(b, loose); - return versionA.compare(versionB) || versionA.compareBuild(versionB) -}; -var compareBuild_1 = compareBuild$2; - -const compareBuild$1 = compareBuild_1; -const sort$1 = (list, loose) => list.sort((a, b) => compareBuild$1(a, b, loose)); -var sort_1 = sort$1; - -const compareBuild = compareBuild_1; -const rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose)); -var rsort_1 = rsort; - -const compare$7 = compare_1; -const gt$3 = (a, b, loose) => compare$7(a, b, loose) > 0; -var gt_1 = gt$3; - -const compare$6 = compare_1; -const lt$2 = (a, b, loose) => compare$6(a, b, loose) < 0; -var lt_1 = lt$2; - -const compare$5 = compare_1; -const neq$1 = (a, b, loose) => compare$5(a, b, loose) !== 0; -var neq_1 = neq$1; - -const compare$4 = compare_1; -const gte$3 = (a, b, loose) => compare$4(a, b, loose) >= 0; -var gte_1 = gte$3; - -const compare$3 = compare_1; -const lte$3 = (a, b, loose) => compare$3(a, b, loose) <= 0; -var lte_1 = lte$3; - -const eq = eq_1; -const neq = neq_1; -const gt$2 = gt_1; -const gte$2 = gte_1; -const lt$1 = lt_1; -const lte$2 = lte_1; - -const cmp$1 = (a, op, b, loose) => { - switch (op) { - case '===': - if (typeof a === 'object') - a = a.version; - if (typeof b === 'object') - b = b.version; - return a === b - - case '!==': - if (typeof a === 'object') - a = a.version; - if (typeof b === 'object') - b = b.version; - return a !== b - - case '': - case '=': - case '==': - return eq(a, b, loose) - - case '!=': - return neq(a, b, loose) - - case '>': - return gt$2(a, b, loose) - - case '>=': - return gte$2(a, b, loose) - - case '<': - return lt$1(a, b, loose) - - case '<=': - return lte$2(a, b, loose) - - default: - throw new TypeError(`Invalid operator: ${op}`) - } -}; -var cmp_1 = cmp$1; - -const SemVer$6 = semver$2; -const parse$4 = parse_1; -const {re: re$3, t: t$2} = re$6.exports; - -const coerce$2 = (version, options) => { - if (version instanceof SemVer$6) { - return version - } - - if (typeof version === 'number') { - version = String(version); - } - - if (typeof version !== 'string') { - return null - } - - options = options || {}; - - let match = null; - if (!options.rtl) { - match = version.match(re$3[t$2.COERCE]); - } else { - // Find the right-most coercible string that does not share - // a terminus with a more left-ward coercible string. - // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4' - // - // Walk through the string checking with a /g regexp - // Manually set the index so as to pick up overlapping matches. - // Stop when we get a match that ends at the string end, since no - // coercible string can be more right-ward without the same terminus. - let next; - while ((next = re$3[t$2.COERCERTL].exec(version)) && - (!match || match.index + match[0].length !== version.length) - ) { - if (!match || - next.index + next[0].length !== match.index + match[0].length) { - match = next; - } - re$3[t$2.COERCERTL].lastIndex = next.index + next[1].length + next[2].length; - } - // leave it in a clean state - re$3[t$2.COERCERTL].lastIndex = -1; - } - - if (match === null) - return null - - return parse$4(`${match[2]}.${match[3] || '0'}.${match[4] || '0'}`, options) -}; -var coerce_1 = coerce$2; - -var iterator = function (Yallist) { - Yallist.prototype[Symbol.iterator] = function* () { - for (let walker = this.head; walker; walker = walker.next) { - yield walker.value; - } - }; -}; - -var yallist = Yallist$1; - -Yallist$1.Node = Node; -Yallist$1.create = Yallist$1; - -function Yallist$1 (list) { - var self = this; - if (!(self instanceof Yallist$1)) { - self = new Yallist$1(); - } - - self.tail = null; - self.head = null; - self.length = 0; - - if (list && typeof list.forEach === 'function') { - list.forEach(function (item) { - self.push(item); - }); - } else if (arguments.length > 0) { - for (var i = 0, l = arguments.length; i < l; i++) { - self.push(arguments[i]); - } - } - - return self -} - -Yallist$1.prototype.removeNode = function (node) { - if (node.list !== this) { - throw new Error('removing node which does not belong to this list') - } - - var next = node.next; - var prev = node.prev; - - if (next) { - next.prev = prev; - } - - if (prev) { - prev.next = next; - } - - if (node === this.head) { - this.head = next; - } - if (node === this.tail) { - this.tail = prev; - } - - node.list.length--; - node.next = null; - node.prev = null; - node.list = null; - - return next -}; - -Yallist$1.prototype.unshiftNode = function (node) { - if (node === this.head) { - return - } - - if (node.list) { - node.list.removeNode(node); - } - - var head = this.head; - node.list = this; - node.next = head; - if (head) { - head.prev = node; - } - - this.head = node; - if (!this.tail) { - this.tail = node; - } - this.length++; -}; - -Yallist$1.prototype.pushNode = function (node) { - if (node === this.tail) { - return - } - - if (node.list) { - node.list.removeNode(node); - } - - var tail = this.tail; - node.list = this; - node.prev = tail; - if (tail) { - tail.next = node; - } - - this.tail = node; - if (!this.head) { - this.head = node; - } - this.length++; -}; - -Yallist$1.prototype.push = function () { - for (var i = 0, l = arguments.length; i < l; i++) { - push$2(this, arguments[i]); - } - return this.length -}; - -Yallist$1.prototype.unshift = function () { - for (var i = 0, l = arguments.length; i < l; i++) { - unshift(this, arguments[i]); - } - return this.length -}; - -Yallist$1.prototype.pop = function () { - if (!this.tail) { - return undefined - } - - var res = this.tail.value; - this.tail = this.tail.prev; - if (this.tail) { - this.tail.next = null; - } else { - this.head = null; - } - this.length--; - return res -}; - -Yallist$1.prototype.shift = function () { - if (!this.head) { - return undefined - } - - var res = this.head.value; - this.head = this.head.next; - if (this.head) { - this.head.prev = null; - } else { - this.tail = null; - } - this.length--; - return res -}; - -Yallist$1.prototype.forEach = function (fn, thisp) { - thisp = thisp || this; - for (var walker = this.head, i = 0; walker !== null; i++) { - fn.call(thisp, walker.value, i, this); - walker = walker.next; - } -}; - -Yallist$1.prototype.forEachReverse = function (fn, thisp) { - thisp = thisp || this; - for (var walker = this.tail, i = this.length - 1; walker !== null; i--) { - fn.call(thisp, walker.value, i, this); - walker = walker.prev; - } -}; - -Yallist$1.prototype.get = function (n) { - for (var i = 0, walker = this.head; walker !== null && i < n; i++) { - // abort out of the list early if we hit a cycle - walker = walker.next; - } - if (i === n && walker !== null) { - return walker.value - } -}; - -Yallist$1.prototype.getReverse = function (n) { - for (var i = 0, walker = this.tail; walker !== null && i < n; i++) { - // abort out of the list early if we hit a cycle - walker = walker.prev; - } - if (i === n && walker !== null) { - return walker.value - } -}; - -Yallist$1.prototype.map = function (fn, thisp) { - thisp = thisp || this; - var res = new Yallist$1(); - for (var walker = this.head; walker !== null;) { - res.push(fn.call(thisp, walker.value, this)); - walker = walker.next; - } - return res -}; - -Yallist$1.prototype.mapReverse = function (fn, thisp) { - thisp = thisp || this; - var res = new Yallist$1(); - for (var walker = this.tail; walker !== null;) { - res.push(fn.call(thisp, walker.value, this)); - walker = walker.prev; - } - return res -}; - -Yallist$1.prototype.reduce = function (fn, initial) { - var acc; - var walker = this.head; - if (arguments.length > 1) { - acc = initial; - } else if (this.head) { - walker = this.head.next; - acc = this.head.value; - } else { - throw new TypeError('Reduce of empty list with no initial value') - } - - for (var i = 0; walker !== null; i++) { - acc = fn(acc, walker.value, i); - walker = walker.next; - } - - return acc -}; - -Yallist$1.prototype.reduceReverse = function (fn, initial) { - var acc; - var walker = this.tail; - if (arguments.length > 1) { - acc = initial; - } else if (this.tail) { - walker = this.tail.prev; - acc = this.tail.value; - } else { - throw new TypeError('Reduce of empty list with no initial value') - } - - for (var i = this.length - 1; walker !== null; i--) { - acc = fn(acc, walker.value, i); - walker = walker.prev; - } - - return acc -}; - -Yallist$1.prototype.toArray = function () { - var arr = new Array(this.length); - for (var i = 0, walker = this.head; walker !== null; i++) { - arr[i] = walker.value; - walker = walker.next; - } - return arr -}; - -Yallist$1.prototype.toArrayReverse = function () { - var arr = new Array(this.length); - for (var i = 0, walker = this.tail; walker !== null; i++) { - arr[i] = walker.value; - walker = walker.prev; - } - return arr -}; - -Yallist$1.prototype.slice = function (from, to) { - to = to || this.length; - if (to < 0) { - to += this.length; - } - from = from || 0; - if (from < 0) { - from += this.length; - } - var ret = new Yallist$1(); - if (to < from || to < 0) { - return ret - } - if (from < 0) { - from = 0; - } - if (to > this.length) { - to = this.length; - } - for (var i = 0, walker = this.head; walker !== null && i < from; i++) { - walker = walker.next; - } - for (; walker !== null && i < to; i++, walker = walker.next) { - ret.push(walker.value); - } - return ret -}; - -Yallist$1.prototype.sliceReverse = function (from, to) { - to = to || this.length; - if (to < 0) { - to += this.length; - } - from = from || 0; - if (from < 0) { - from += this.length; - } - var ret = new Yallist$1(); - if (to < from || to < 0) { - return ret - } - if (from < 0) { - from = 0; - } - if (to > this.length) { - to = this.length; - } - for (var i = this.length, walker = this.tail; walker !== null && i > to; i--) { - walker = walker.prev; - } - for (; walker !== null && i > from; i--, walker = walker.prev) { - ret.push(walker.value); - } - return ret -}; - -Yallist$1.prototype.splice = function (start, deleteCount, ...nodes) { - if (start > this.length) { - start = this.length - 1; - } - if (start < 0) { - start = this.length + start; - } - - for (var i = 0, walker = this.head; walker !== null && i < start; i++) { - walker = walker.next; - } - - var ret = []; - for (var i = 0; walker && i < deleteCount; i++) { - ret.push(walker.value); - walker = this.removeNode(walker); - } - if (walker === null) { - walker = this.tail; - } - - if (walker !== this.head && walker !== this.tail) { - walker = walker.prev; - } - - for (var i = 0; i < nodes.length; i++) { - walker = insert(this, walker, nodes[i]); - } - return ret; -}; - -Yallist$1.prototype.reverse = function () { - var head = this.head; - var tail = this.tail; - for (var walker = head; walker !== null; walker = walker.prev) { - var p = walker.prev; - walker.prev = walker.next; - walker.next = p; - } - this.head = tail; - this.tail = head; - return this -}; - -function insert (self, node, value) { - var inserted = node === self.head ? - new Node(value, null, node, self) : - new Node(value, node, node.next, self); - - if (inserted.next === null) { - self.tail = inserted; - } - if (inserted.prev === null) { - self.head = inserted; - } - - self.length++; - - return inserted -} - -function push$2 (self, item) { - self.tail = new Node(item, self.tail, null, self); - if (!self.head) { - self.head = self.tail; - } - self.length++; -} - -function unshift (self, item) { - self.head = new Node(item, null, self.head, self); - if (!self.tail) { - self.tail = self.head; - } - self.length++; -} - -function Node (value, prev, next, list) { - if (!(this instanceof Node)) { - return new Node(value, prev, next, list) - } - - this.list = list; - this.value = value; - - if (prev) { - prev.next = this; - this.prev = prev; - } else { - this.prev = null; - } - - if (next) { - next.prev = this; - this.next = next; - } else { - this.next = null; - } -} - -try { - // add if support for Symbol.iterator is present - iterator(Yallist$1); -} catch (er) {} - -// A linked list to keep track of recently-used-ness -const Yallist = yallist; - -const MAX = Symbol('max'); -const LENGTH = Symbol('length'); -const LENGTH_CALCULATOR = Symbol('lengthCalculator'); -const ALLOW_STALE = Symbol('allowStale'); -const MAX_AGE = Symbol('maxAge'); -const DISPOSE = Symbol('dispose'); -const NO_DISPOSE_ON_SET = Symbol('noDisposeOnSet'); -const LRU_LIST = Symbol('lruList'); -const CACHE = Symbol('cache'); -const UPDATE_AGE_ON_GET = Symbol('updateAgeOnGet'); - -const naiveLength = () => 1; - -// lruList is a yallist where the head is the youngest -// item, and the tail is the oldest. the list contains the Hit -// objects as the entries. -// Each Hit object has a reference to its Yallist.Node. This -// never changes. -// -// cache is a Map (or PseudoMap) that matches the keys to -// the Yallist.Node object. -class LRUCache { - constructor (options) { - if (typeof options === 'number') - options = { max: options }; - - if (!options) - options = {}; - - if (options.max && (typeof options.max !== 'number' || options.max < 0)) - throw new TypeError('max must be a non-negative number') - // Kind of weird to have a default max of Infinity, but oh well. - this[MAX] = options.max || Infinity; - - const lc = options.length || naiveLength; - this[LENGTH_CALCULATOR] = (typeof lc !== 'function') ? naiveLength : lc; - this[ALLOW_STALE] = options.stale || false; - if (options.maxAge && typeof options.maxAge !== 'number') - throw new TypeError('maxAge must be a number') - this[MAX_AGE] = options.maxAge || 0; - this[DISPOSE] = options.dispose; - this[NO_DISPOSE_ON_SET] = options.noDisposeOnSet || false; - this[UPDATE_AGE_ON_GET] = options.updateAgeOnGet || false; - this.reset(); - } - - // resize the cache when the max changes. - set max (mL) { - if (typeof mL !== 'number' || mL < 0) - throw new TypeError('max must be a non-negative number') - - this[MAX] = mL || Infinity; - trim(this); - } - get max () { - return this[MAX] - } - - set allowStale (allowStale) { - this[ALLOW_STALE] = !!allowStale; - } - get allowStale () { - return this[ALLOW_STALE] - } - - set maxAge (mA) { - if (typeof mA !== 'number') - throw new TypeError('maxAge must be a non-negative number') - - this[MAX_AGE] = mA; - trim(this); - } - get maxAge () { - return this[MAX_AGE] - } - - // resize the cache when the lengthCalculator changes. - set lengthCalculator (lC) { - if (typeof lC !== 'function') - lC = naiveLength; - - if (lC !== this[LENGTH_CALCULATOR]) { - this[LENGTH_CALCULATOR] = lC; - this[LENGTH] = 0; - this[LRU_LIST].forEach(hit => { - hit.length = this[LENGTH_CALCULATOR](hit.value, hit.key); - this[LENGTH] += hit.length; - }); - } - trim(this); - } - get lengthCalculator () { return this[LENGTH_CALCULATOR] } - - get length () { return this[LENGTH] } - get itemCount () { return this[LRU_LIST].length } - - rforEach (fn, thisp) { - thisp = thisp || this; - for (let walker = this[LRU_LIST].tail; walker !== null;) { - const prev = walker.prev; - forEachStep(this, fn, walker, thisp); - walker = prev; - } - } - - forEach (fn, thisp) { - thisp = thisp || this; - for (let walker = this[LRU_LIST].head; walker !== null;) { - const next = walker.next; - forEachStep(this, fn, walker, thisp); - walker = next; - } - } - - keys () { - return this[LRU_LIST].toArray().map(k => k.key) - } - - values () { - return this[LRU_LIST].toArray().map(k => k.value) - } - - reset () { - if (this[DISPOSE] && - this[LRU_LIST] && - this[LRU_LIST].length) { - this[LRU_LIST].forEach(hit => this[DISPOSE](hit.key, hit.value)); - } - - this[CACHE] = new Map(); // hash of items by key - this[LRU_LIST] = new Yallist(); // list of items in order of use recency - this[LENGTH] = 0; // length of items in the list - } - - dump () { - return this[LRU_LIST].map(hit => - isStale(this, hit) ? false : { - k: hit.key, - v: hit.value, - e: hit.now + (hit.maxAge || 0) - }).toArray().filter(h => h) - } - - dumpLru () { - return this[LRU_LIST] - } - - set (key, value, maxAge) { - maxAge = maxAge || this[MAX_AGE]; - - if (maxAge && typeof maxAge !== 'number') - throw new TypeError('maxAge must be a number') - - const now = maxAge ? Date.now() : 0; - const len = this[LENGTH_CALCULATOR](value, key); - - if (this[CACHE].has(key)) { - if (len > this[MAX]) { - del(this, this[CACHE].get(key)); - return false - } - - const node = this[CACHE].get(key); - const item = node.value; - - // dispose of the old one before overwriting - // split out into 2 ifs for better coverage tracking - if (this[DISPOSE]) { - if (!this[NO_DISPOSE_ON_SET]) - this[DISPOSE](key, item.value); - } - - item.now = now; - item.maxAge = maxAge; - item.value = value; - this[LENGTH] += len - item.length; - item.length = len; - this.get(key); - trim(this); - return true - } - - const hit = new Entry(key, value, len, now, maxAge); - - // oversized objects fall out of cache automatically. - if (hit.length > this[MAX]) { - if (this[DISPOSE]) - this[DISPOSE](key, value); - - return false - } - - this[LENGTH] += hit.length; - this[LRU_LIST].unshift(hit); - this[CACHE].set(key, this[LRU_LIST].head); - trim(this); - return true - } - - has (key) { - if (!this[CACHE].has(key)) return false - const hit = this[CACHE].get(key).value; - return !isStale(this, hit) - } - - get (key) { - return get(this, key, true) - } - - peek (key) { - return get(this, key, false) - } - - pop () { - const node = this[LRU_LIST].tail; - if (!node) - return null - - del(this, node); - return node.value - } - - del (key) { - del(this, this[CACHE].get(key)); - } - - load (arr) { - // reset the cache - this.reset(); - - const now = Date.now(); - // A previous serialized cache has the most recent items first - for (let l = arr.length - 1; l >= 0; l--) { - const hit = arr[l]; - const expiresAt = hit.e || 0; - if (expiresAt === 0) - // the item was created without expiration in a non aged cache - this.set(hit.k, hit.v); - else { - const maxAge = expiresAt - now; - // dont add already expired items - if (maxAge > 0) { - this.set(hit.k, hit.v, maxAge); - } - } - } - } - - prune () { - this[CACHE].forEach((value, key) => get(this, key, false)); - } -} - -const get = (self, key, doUse) => { - const node = self[CACHE].get(key); - if (node) { - const hit = node.value; - if (isStale(self, hit)) { - del(self, node); - if (!self[ALLOW_STALE]) - return undefined - } else { - if (doUse) { - if (self[UPDATE_AGE_ON_GET]) - node.value.now = Date.now(); - self[LRU_LIST].unshiftNode(node); - } - } - return hit.value - } -}; - -const isStale = (self, hit) => { - if (!hit || (!hit.maxAge && !self[MAX_AGE])) - return false - - const diff = Date.now() - hit.now; - return hit.maxAge ? diff > hit.maxAge - : self[MAX_AGE] && (diff > self[MAX_AGE]) -}; - -const trim = self => { - if (self[LENGTH] > self[MAX]) { - for (let walker = self[LRU_LIST].tail; - self[LENGTH] > self[MAX] && walker !== null;) { - // We know that we're about to delete this one, and also - // what the next least recently used key will be, so just - // go ahead and set it now. - const prev = walker.prev; - del(self, walker); - walker = prev; - } - } -}; - -const del = (self, node) => { - if (node) { - const hit = node.value; - if (self[DISPOSE]) - self[DISPOSE](hit.key, hit.value); - - self[LENGTH] -= hit.length; - self[CACHE].delete(hit.key); - self[LRU_LIST].removeNode(node); - } -}; - -class Entry { - constructor (key, value, length, now, maxAge) { - this.key = key; - this.value = value; - this.length = length; - this.now = now; - this.maxAge = maxAge || 0; - } -} - -const forEachStep = (self, fn, node, thisp) => { - let hit = node.value; - if (isStale(self, hit)) { - del(self, node); - if (!self[ALLOW_STALE]) - hit = undefined; - } - if (hit) - fn.call(thisp, hit.value, hit.key, self); -}; - -var lruCache = LRUCache; - -// hoisted class for cyclic dependency -class Range$a { - constructor (range, options) { - options = parseOptions$1(options); - - if (range instanceof Range$a) { - if ( - range.loose === !!options.loose && - range.includePrerelease === !!options.includePrerelease - ) { - return range - } else { - return new Range$a(range.raw, options) - } - } - - if (range instanceof Comparator$3) { - // just put it in the set and return - this.raw = range.value; - this.set = [[range]]; - this.format(); - return this - } - - this.options = options; - this.loose = !!options.loose; - this.includePrerelease = !!options.includePrerelease; - - // First, split based on boolean or || - this.raw = range; - this.set = range - .split(/\s*\|\|\s*/) - // map the range to a 2d array of comparators - .map(range => this.parseRange(range.trim())) - // throw out any comparator lists that are empty - // this generally means that it was not a valid range, which is allowed - // in loose mode, but will still throw if the WHOLE range is invalid. - .filter(c => c.length); - - if (!this.set.length) { - throw new TypeError(`Invalid SemVer Range: ${range}`) - } - - // if we have any that are not the null set, throw out null sets. - if (this.set.length > 1) { - // keep the first one, in case they're all null sets - const first = this.set[0]; - this.set = this.set.filter(c => !isNullSet(c[0])); - if (this.set.length === 0) - this.set = [first]; - else if (this.set.length > 1) { - // if we have any that are *, then the range is just * - for (const c of this.set) { - if (c.length === 1 && isAny(c[0])) { - this.set = [c]; - break - } - } - } - } - - this.format(); - } - - format () { - this.range = this.set - .map((comps) => { - return comps.join(' ').trim() - }) - .join('||') - .trim(); - return this.range - } - - toString () { - return this.range - } - - parseRange (range) { - range = range.trim(); - - // memoize range parsing for performance. - // this is a very hot path, and fully deterministic. - const memoOpts = Object.keys(this.options).join(','); - const memoKey = `parseRange:${memoOpts}:${range}`; - const cached = cache.get(memoKey); - if (cached) - return cached - - const loose = this.options.loose; - // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - const hr = loose ? re$2[t$1.HYPHENRANGELOOSE] : re$2[t$1.HYPHENRANGE]; - range = range.replace(hr, hyphenReplace(this.options.includePrerelease)); - debug$d('hyphen replace', range); - // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(re$2[t$1.COMPARATORTRIM], comparatorTrimReplace); - debug$d('comparator trim', range, re$2[t$1.COMPARATORTRIM]); - - // `~ 1.2.3` => `~1.2.3` - range = range.replace(re$2[t$1.TILDETRIM], tildeTrimReplace); - - // `^ 1.2.3` => `^1.2.3` - range = range.replace(re$2[t$1.CARETTRIM], caretTrimReplace); - - // normalize spaces - range = range.split(/\s+/).join(' '); - - // At this point, the range is completely trimmed and - // ready to be split into comparators. - - const compRe = loose ? re$2[t$1.COMPARATORLOOSE] : re$2[t$1.COMPARATOR]; - const rangeList = range - .split(' ') - .map(comp => parseComparator(comp, this.options)) - .join(' ') - .split(/\s+/) - // >=0.0.0 is equivalent to * - .map(comp => replaceGTE0(comp, this.options)) - // in loose mode, throw out any that are not valid comparators - .filter(this.options.loose ? comp => !!comp.match(compRe) : () => true) - .map(comp => new Comparator$3(comp, this.options)); - - // if any comparators are the null set, then replace with JUST null set - // if more than one comparator, remove any * comparators - // also, don't include the same comparator more than once - rangeList.length; - const rangeMap = new Map(); - for (const comp of rangeList) { - if (isNullSet(comp)) - return [comp] - rangeMap.set(comp.value, comp); - } - if (rangeMap.size > 1 && rangeMap.has('')) - rangeMap.delete(''); - - const result = [...rangeMap.values()]; - cache.set(memoKey, result); - return result - } - - intersects (range, options) { - if (!(range instanceof Range$a)) { - throw new TypeError('a Range is required') - } - - return this.set.some((thisComparators) => { - return ( - isSatisfiable(thisComparators, options) && - range.set.some((rangeComparators) => { - return ( - isSatisfiable(rangeComparators, options) && - thisComparators.every((thisComparator) => { - return rangeComparators.every((rangeComparator) => { - return thisComparator.intersects(rangeComparator, options) - }) - }) - ) - }) - ) - }) - } - - // if ANY of the sets match ALL of its comparators, then pass - test (version) { - if (!version) { - return false - } - - if (typeof version === 'string') { - try { - version = new SemVer$5(version, this.options); - } catch (er) { - return false - } - } - - for (let i = 0; i < this.set.length; i++) { - if (testSet(this.set[i], version, this.options)) { - return true - } - } - return false - } -} -var range$1 = Range$a; - -const LRU = lruCache; -const cache = new LRU({ max: 1000 }); - -const parseOptions$1 = parseOptions_1; -const Comparator$3 = comparator$1; -const debug$d = debug_1; -const SemVer$5 = semver$2; -const { - re: re$2, - t: t$1, - comparatorTrimReplace, - tildeTrimReplace, - caretTrimReplace -} = re$6.exports; - -const isNullSet = c => c.value === '<0.0.0-0'; -const isAny = c => c.value === ''; - -// take a set of comparators and determine whether there -// exists a version which can satisfy it -const isSatisfiable = (comparators, options) => { - let result = true; - const remainingComparators = comparators.slice(); - let testComparator = remainingComparators.pop(); - - while (result && remainingComparators.length) { - result = remainingComparators.every((otherComparator) => { - return testComparator.intersects(otherComparator, options) - }); - - testComparator = remainingComparators.pop(); - } - - return result -}; - -// comprised of xranges, tildes, stars, and gtlt's at this point. -// already replaced the hyphen ranges -// turn into a set of JUST comparators. -const parseComparator = (comp, options) => { - debug$d('comp', comp, options); - comp = replaceCarets(comp, options); - debug$d('caret', comp); - comp = replaceTildes(comp, options); - debug$d('tildes', comp); - comp = replaceXRanges(comp, options); - debug$d('xrange', comp); - comp = replaceStars(comp, options); - debug$d('stars', comp); - return comp -}; - -const isX = id => !id || id.toLowerCase() === 'x' || id === '*'; - -// ~, ~> --> * (any, kinda silly) -// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0-0 -// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0-0 -// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0-0 -// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0-0 -// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0-0 -const replaceTildes = (comp, options) => - comp.trim().split(/\s+/).map((comp) => { - return replaceTilde(comp, options) - }).join(' '); - -const replaceTilde = (comp, options) => { - const r = options.loose ? re$2[t$1.TILDELOOSE] : re$2[t$1.TILDE]; - return comp.replace(r, (_, M, m, p, pr) => { - debug$d('tilde', comp, _, M, m, p, pr); - let ret; - - if (isX(M)) { - ret = ''; - } else if (isX(m)) { - ret = `>=${M}.0.0 <${+M + 1}.0.0-0`; - } else if (isX(p)) { - // ~1.2 == >=1.2.0 <1.3.0-0 - ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`; - } else if (pr) { - debug$d('replaceTilde pr', pr); - ret = `>=${M}.${m}.${p}-${pr - } <${M}.${+m + 1}.0-0`; - } else { - // ~1.2.3 == >=1.2.3 <1.3.0-0 - ret = `>=${M}.${m}.${p - } <${M}.${+m + 1}.0-0`; - } - - debug$d('tilde return', ret); - return ret - }) -}; - -// ^ --> * (any, kinda silly) -// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0-0 -// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0-0 -// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0-0 -// ^1.2.3 --> >=1.2.3 <2.0.0-0 -// ^1.2.0 --> >=1.2.0 <2.0.0-0 -const replaceCarets = (comp, options) => - comp.trim().split(/\s+/).map((comp) => { - return replaceCaret(comp, options) - }).join(' '); - -const replaceCaret = (comp, options) => { - debug$d('caret', comp, options); - const r = options.loose ? re$2[t$1.CARETLOOSE] : re$2[t$1.CARET]; - const z = options.includePrerelease ? '-0' : ''; - return comp.replace(r, (_, M, m, p, pr) => { - debug$d('caret', comp, _, M, m, p, pr); - let ret; - - if (isX(M)) { - ret = ''; - } else if (isX(m)) { - ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; - } else if (isX(p)) { - if (M === '0') { - ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; - } else { - ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`; - } - } else if (pr) { - debug$d('replaceCaret pr', pr); - if (M === '0') { - if (m === '0') { - ret = `>=${M}.${m}.${p}-${pr - } <${M}.${m}.${+p + 1}-0`; - } else { - ret = `>=${M}.${m}.${p}-${pr - } <${M}.${+m + 1}.0-0`; - } - } else { - ret = `>=${M}.${m}.${p}-${pr - } <${+M + 1}.0.0-0`; - } - } else { - debug$d('no pr'); - if (M === '0') { - if (m === '0') { - ret = `>=${M}.${m}.${p - }${z} <${M}.${m}.${+p + 1}-0`; - } else { - ret = `>=${M}.${m}.${p - }${z} <${M}.${+m + 1}.0-0`; - } - } else { - ret = `>=${M}.${m}.${p - } <${+M + 1}.0.0-0`; - } - } - - debug$d('caret return', ret); - return ret - }) -}; - -const replaceXRanges = (comp, options) => { - debug$d('replaceXRanges', comp, options); - return comp.split(/\s+/).map((comp) => { - return replaceXRange(comp, options) - }).join(' ') -}; - -const replaceXRange = (comp, options) => { - comp = comp.trim(); - const r = options.loose ? re$2[t$1.XRANGELOOSE] : re$2[t$1.XRANGE]; - return comp.replace(r, (ret, gtlt, M, m, p, pr) => { - debug$d('xRange', comp, ret, gtlt, M, m, p, pr); - const xM = isX(M); - const xm = xM || isX(m); - const xp = xm || isX(p); - const anyX = xp; - - if (gtlt === '=' && anyX) { - gtlt = ''; - } - - // if we're including prereleases in the match, then we need - // to fix this to -0, the lowest possible prerelease value - pr = options.includePrerelease ? '-0' : ''; - - if (xM) { - if (gtlt === '>' || gtlt === '<') { - // nothing is allowed - ret = '<0.0.0-0'; - } else { - // nothing is forbidden - ret = '*'; - } - } else if (gtlt && anyX) { - // we know patch is an x, because we have any x at all. - // replace X with 0 - if (xm) { - m = 0; - } - p = 0; - - if (gtlt === '>') { - // >1 => >=2.0.0 - // >1.2 => >=1.3.0 - gtlt = '>='; - if (xm) { - M = +M + 1; - m = 0; - p = 0; - } else { - m = +m + 1; - p = 0; - } - } else if (gtlt === '<=') { - // <=0.7.x is actually <0.8.0, since any 0.7.x should - // pass. Similarly, <=7.x is actually <8.0.0, etc. - gtlt = '<'; - if (xm) { - M = +M + 1; - } else { - m = +m + 1; - } - } - - if (gtlt === '<') - pr = '-0'; - - ret = `${gtlt + M}.${m}.${p}${pr}`; - } else if (xm) { - ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`; - } else if (xp) { - ret = `>=${M}.${m}.0${pr - } <${M}.${+m + 1}.0-0`; - } - - debug$d('xRange return', ret); - - return ret - }) -}; - -// Because * is AND-ed with everything else in the comparator, -// and '' means "any version", just remove the *s entirely. -const replaceStars = (comp, options) => { - debug$d('replaceStars', comp, options); - // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(re$2[t$1.STAR], '') -}; - -const replaceGTE0 = (comp, options) => { - debug$d('replaceGTE0', comp, options); - return comp.trim() - .replace(re$2[options.includePrerelease ? t$1.GTE0PRE : t$1.GTE0], '') -}; - -// This function is passed to string.replace(re[t.HYPHENRANGE]) -// M, m, patch, prerelease, build -// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 -// 1.2.3 - 3.4 => >=1.2.0 <3.5.0-0 Any 3.4.x will do -// 1.2 - 3.4 => >=1.2.0 <3.5.0-0 -const hyphenReplace = incPr => ($0, - from, fM, fm, fp, fpr, fb, - to, tM, tm, tp, tpr, tb) => { - if (isX(fM)) { - from = ''; - } else if (isX(fm)) { - from = `>=${fM}.0.0${incPr ? '-0' : ''}`; - } else if (isX(fp)) { - from = `>=${fM}.${fm}.0${incPr ? '-0' : ''}`; - } else if (fpr) { - from = `>=${from}`; - } else { - from = `>=${from}${incPr ? '-0' : ''}`; - } - - if (isX(tM)) { - to = ''; - } else if (isX(tm)) { - to = `<${+tM + 1}.0.0-0`; - } else if (isX(tp)) { - to = `<${tM}.${+tm + 1}.0-0`; - } else if (tpr) { - to = `<=${tM}.${tm}.${tp}-${tpr}`; - } else if (incPr) { - to = `<${tM}.${tm}.${+tp + 1}-0`; - } else { - to = `<=${to}`; - } - - return (`${from} ${to}`).trim() -}; - -const testSet = (set, version, options) => { - for (let i = 0; i < set.length; i++) { - if (!set[i].test(version)) { - return false - } - } - - if (version.prerelease.length && !options.includePrerelease) { - // Find the set of versions that are allowed to have prereleases - // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 - // That should allow `1.2.3-pr.2` to pass. - // However, `1.2.4-alpha.notready` should NOT be allowed, - // even though it's within the range set by the comparators. - for (let i = 0; i < set.length; i++) { - debug$d(set[i].semver); - if (set[i].semver === Comparator$3.ANY) { - continue - } - - if (set[i].semver.prerelease.length > 0) { - const allowed = set[i].semver; - if (allowed.major === version.major && - allowed.minor === version.minor && - allowed.patch === version.patch) { - return true - } - } - } - - // Version has a -pre, but it's not one of the ones we like. - return false - } - - return true -}; - -const ANY$2 = Symbol('SemVer ANY'); -// hoisted class for cyclic dependency -class Comparator$2 { - static get ANY () { - return ANY$2 - } - constructor (comp, options) { - options = parseOptions(options); - - if (comp instanceof Comparator$2) { - if (comp.loose === !!options.loose) { - return comp - } else { - comp = comp.value; - } - } - - debug$c('comparator', comp, options); - this.options = options; - this.loose = !!options.loose; - this.parse(comp); - - if (this.semver === ANY$2) { - this.value = ''; - } else { - this.value = this.operator + this.semver.version; - } - - debug$c('comp', this); - } - - parse (comp) { - const r = this.options.loose ? re$1[t.COMPARATORLOOSE] : re$1[t.COMPARATOR]; - const m = comp.match(r); - - if (!m) { - throw new TypeError(`Invalid comparator: ${comp}`) - } - - this.operator = m[1] !== undefined ? m[1] : ''; - if (this.operator === '=') { - this.operator = ''; - } - - // if it literally is just '>' or '' then allow anything. - if (!m[2]) { - this.semver = ANY$2; - } else { - this.semver = new SemVer$4(m[2], this.options.loose); - } - } - - toString () { - return this.value - } - - test (version) { - debug$c('Comparator.test', version, this.options.loose); - - if (this.semver === ANY$2 || version === ANY$2) { - return true - } - - if (typeof version === 'string') { - try { - version = new SemVer$4(version, this.options); - } catch (er) { - return false - } - } - - return cmp(version, this.operator, this.semver, this.options) - } - - intersects (comp, options) { - if (!(comp instanceof Comparator$2)) { - throw new TypeError('a Comparator is required') - } - - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - }; - } - - if (this.operator === '') { - if (this.value === '') { - return true - } - return new Range$9(comp.value, options).test(this.value) - } else if (comp.operator === '') { - if (comp.value === '') { - return true - } - return new Range$9(this.value, options).test(comp.semver) - } - - const sameDirectionIncreasing = - (this.operator === '>=' || this.operator === '>') && - (comp.operator === '>=' || comp.operator === '>'); - const sameDirectionDecreasing = - (this.operator === '<=' || this.operator === '<') && - (comp.operator === '<=' || comp.operator === '<'); - const sameSemVer = this.semver.version === comp.semver.version; - const differentDirectionsInclusive = - (this.operator === '>=' || this.operator === '<=') && - (comp.operator === '>=' || comp.operator === '<='); - const oppositeDirectionsLessThan = - cmp(this.semver, '<', comp.semver, options) && - (this.operator === '>=' || this.operator === '>') && - (comp.operator === '<=' || comp.operator === '<'); - const oppositeDirectionsGreaterThan = - cmp(this.semver, '>', comp.semver, options) && - (this.operator === '<=' || this.operator === '<') && - (comp.operator === '>=' || comp.operator === '>'); - - return ( - sameDirectionIncreasing || - sameDirectionDecreasing || - (sameSemVer && differentDirectionsInclusive) || - oppositeDirectionsLessThan || - oppositeDirectionsGreaterThan - ) - } -} - -var comparator$1 = Comparator$2; - -const parseOptions = parseOptions_1; -const {re: re$1, t} = re$6.exports; -const cmp = cmp_1; -const debug$c = debug_1; -const SemVer$4 = semver$2; -const Range$9 = range$1; - -const Range$8 = range$1; -const satisfies$3 = (version, range, options) => { - try { - range = new Range$8(range, options); - } catch (er) { - return false - } - return range.test(version) -}; -var satisfies_1 = satisfies$3; - -const Range$7 = range$1; - -// Mostly just for testing and legacy API reasons -const toComparators = (range, options) => - new Range$7(range, options).set - .map(comp => comp.map(c => c.value).join(' ').trim().split(' ')); - -var toComparators_1 = toComparators; - -const SemVer$3 = semver$2; -const Range$6 = range$1; - -const maxSatisfying = (versions, range, options) => { - let max = null; - let maxSV = null; - let rangeObj = null; - try { - rangeObj = new Range$6(range, options); - } catch (er) { - return null - } - versions.forEach((v) => { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!max || maxSV.compare(v) === -1) { - // compare(max, v, true) - max = v; - maxSV = new SemVer$3(max, options); - } - } - }); - return max -}; -var maxSatisfying_1 = maxSatisfying; - -const SemVer$2 = semver$2; -const Range$5 = range$1; -const minSatisfying = (versions, range, options) => { - let min = null; - let minSV = null; - let rangeObj = null; - try { - rangeObj = new Range$5(range, options); - } catch (er) { - return null - } - versions.forEach((v) => { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!min || minSV.compare(v) === 1) { - // compare(min, v, true) - min = v; - minSV = new SemVer$2(min, options); - } - } - }); - return min -}; -var minSatisfying_1 = minSatisfying; - -const SemVer$1 = semver$2; -const Range$4 = range$1; -const gt$1 = gt_1; - -const minVersion = (range, loose) => { - range = new Range$4(range, loose); - - let minver = new SemVer$1('0.0.0'); - if (range.test(minver)) { - return minver - } - - minver = new SemVer$1('0.0.0-0'); - if (range.test(minver)) { - return minver - } - - minver = null; - for (let i = 0; i < range.set.length; ++i) { - const comparators = range.set[i]; - - let setMin = null; - comparators.forEach((comparator) => { - // Clone to avoid manipulating the comparator's semver object. - const compver = new SemVer$1(comparator.semver.version); - switch (comparator.operator) { - case '>': - if (compver.prerelease.length === 0) { - compver.patch++; - } else { - compver.prerelease.push(0); - } - compver.raw = compver.format(); - /* fallthrough */ - case '': - case '>=': - if (!setMin || gt$1(compver, setMin)) { - setMin = compver; - } - break - case '<': - case '<=': - /* Ignore maximum versions */ - break - /* istanbul ignore next */ - default: - throw new Error(`Unexpected operation: ${comparator.operator}`) - } - }); - if (setMin && (!minver || gt$1(minver, setMin))) - minver = setMin; - } - - if (minver && range.test(minver)) { - return minver - } - - return null -}; -var minVersion_1 = minVersion; - -const Range$3 = range$1; -const validRange = (range, options) => { - try { - // Return '*' instead of '' so that truthiness works. - // This will throw if it's invalid anyway - return new Range$3(range, options).range || '*' - } catch (er) { - return null - } -}; -var valid = validRange; - -const SemVer = semver$2; -const Comparator$1 = comparator$1; -const {ANY: ANY$1} = Comparator$1; -const Range$2 = range$1; -const satisfies$2 = satisfies_1; -const gt = gt_1; -const lt = lt_1; -const lte$1 = lte_1; -const gte$1 = gte_1; - -const outside$2 = (version, range, hilo, options) => { - version = new SemVer(version, options); - range = new Range$2(range, options); - - let gtfn, ltefn, ltfn, comp, ecomp; - switch (hilo) { - case '>': - gtfn = gt; - ltefn = lte$1; - ltfn = lt; - comp = '>'; - ecomp = '>='; - break - case '<': - gtfn = lt; - ltefn = gte$1; - ltfn = gt; - comp = '<'; - ecomp = '<='; - break - default: - throw new TypeError('Must provide a hilo val of "<" or ">"') - } - - // If it satisfies the range it is not outside - if (satisfies$2(version, range, options)) { - return false - } - - // From now on, variable terms are as if we're in "gtr" mode. - // but note that everything is flipped for the "ltr" function. - - for (let i = 0; i < range.set.length; ++i) { - const comparators = range.set[i]; - - let high = null; - let low = null; - - comparators.forEach((comparator) => { - if (comparator.semver === ANY$1) { - comparator = new Comparator$1('>=0.0.0'); - } - high = high || comparator; - low = low || comparator; - if (gtfn(comparator.semver, high.semver, options)) { - high = comparator; - } else if (ltfn(comparator.semver, low.semver, options)) { - low = comparator; - } - }); - - // If the edge version comparator has a operator then our version - // isn't outside it - if (high.operator === comp || high.operator === ecomp) { - return false - } - - // If the lowest version comparator has an operator and our version - // is less than it then it isn't higher than the range - if ((!low.operator || low.operator === comp) && - ltefn(version, low.semver)) { - return false - } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false - } - } - return true -}; - -var outside_1 = outside$2; - -// Determine if version is greater than all the versions possible in the range. -const outside$1 = outside_1; -const gtr = (version, range, options) => outside$1(version, range, '>', options); -var gtr_1 = gtr; - -const outside = outside_1; -// Determine if version is less than all the versions possible in the range -const ltr = (version, range, options) => outside(version, range, '<', options); -var ltr_1 = ltr; - -const Range$1 = range$1; -const intersects = (r1, r2, options) => { - r1 = new Range$1(r1, options); - r2 = new Range$1(r2, options); - return r1.intersects(r2) -}; -var intersects_1 = intersects; - -// given a set of versions and a range, create a "simplified" range -// that includes the same versions that the original range does -// If the original range is shorter than the simplified one, return that. -const satisfies$1 = satisfies_1; -const compare$2 = compare_1; -var simplify = (versions, range, options) => { - const set = []; - let min = null; - let prev = null; - const v = versions.sort((a, b) => compare$2(a, b, options)); - for (const version of v) { - const included = satisfies$1(version, range, options); - if (included) { - prev = version; - if (!min) - min = version; - } else { - if (prev) { - set.push([min, prev]); - } - prev = null; - min = null; - } - } - if (min) - set.push([min, null]); - - const ranges = []; - for (const [min, max] of set) { - if (min === max) - ranges.push(min); - else if (!max && min === v[0]) - ranges.push('*'); - else if (!max) - ranges.push(`>=${min}`); - else if (min === v[0]) - ranges.push(`<=${max}`); - else - ranges.push(`${min} - ${max}`); - } - const simplified = ranges.join(' || '); - const original = typeof range.raw === 'string' ? range.raw : String(range); - return simplified.length < original.length ? simplified : range -}; - -const Range = range$1; -const Comparator = comparator$1; -const { ANY } = Comparator; -const satisfies = satisfies_1; -const compare$1 = compare_1; - -// Complex range `r1 || r2 || ...` is a subset of `R1 || R2 || ...` iff: -// - Every simple range `r1, r2, ...` is a null set, OR -// - Every simple range `r1, r2, ...` which is not a null set is a subset of -// some `R1, R2, ...` -// -// Simple range `c1 c2 ...` is a subset of simple range `C1 C2 ...` iff: -// - If c is only the ANY comparator -// - If C is only the ANY comparator, return true -// - Else if in prerelease mode, return false -// - else replace c with `[>=0.0.0]` -// - If C is only the ANY comparator -// - if in prerelease mode, return true -// - else replace C with `[>=0.0.0]` -// - Let EQ be the set of = comparators in c -// - If EQ is more than one, return true (null set) -// - Let GT be the highest > or >= comparator in c -// - Let LT be the lowest < or <= comparator in c -// - If GT and LT, and GT.semver > LT.semver, return true (null set) -// - If any C is a = range, and GT or LT are set, return false -// - If EQ -// - If GT, and EQ does not satisfy GT, return true (null set) -// - If LT, and EQ does not satisfy LT, return true (null set) -// - If EQ satisfies every C, return true -// - Else return false -// - If GT -// - If GT.semver is lower than any > or >= comp in C, return false -// - If GT is >=, and GT.semver does not satisfy every C, return false -// - If GT.semver has a prerelease, and not in prerelease mode -// - If no C has a prerelease and the GT.semver tuple, return false -// - If LT -// - If LT.semver is greater than any < or <= comp in C, return false -// - If LT is <=, and LT.semver does not satisfy every C, return false -// - If GT.semver has a prerelease, and not in prerelease mode -// - If no C has a prerelease and the LT.semver tuple, return false -// - Else return true - -const subset = (sub, dom, options = {}) => { - if (sub === dom) - return true - - sub = new Range(sub, options); - dom = new Range(dom, options); - let sawNonNull = false; - - OUTER: for (const simpleSub of sub.set) { - for (const simpleDom of dom.set) { - const isSub = simpleSubset(simpleSub, simpleDom, options); - sawNonNull = sawNonNull || isSub !== null; - if (isSub) - continue OUTER - } - // the null set is a subset of everything, but null simple ranges in - // a complex range should be ignored. so if we saw a non-null range, - // then we know this isn't a subset, but if EVERY simple range was null, - // then it is a subset. - if (sawNonNull) - return false - } - return true -}; - -const simpleSubset = (sub, dom, options) => { - if (sub === dom) - return true - - if (sub.length === 1 && sub[0].semver === ANY) { - if (dom.length === 1 && dom[0].semver === ANY) - return true - else if (options.includePrerelease) - sub = [ new Comparator('>=0.0.0-0') ]; - else - sub = [ new Comparator('>=0.0.0') ]; - } - - if (dom.length === 1 && dom[0].semver === ANY) { - if (options.includePrerelease) - return true - else - dom = [ new Comparator('>=0.0.0') ]; - } - - const eqSet = new Set(); - let gt, lt; - for (const c of sub) { - if (c.operator === '>' || c.operator === '>=') - gt = higherGT(gt, c, options); - else if (c.operator === '<' || c.operator === '<=') - lt = lowerLT(lt, c, options); - else - eqSet.add(c.semver); - } - - if (eqSet.size > 1) - return null - - let gtltComp; - if (gt && lt) { - gtltComp = compare$1(gt.semver, lt.semver, options); - if (gtltComp > 0) - return null - else if (gtltComp === 0 && (gt.operator !== '>=' || lt.operator !== '<=')) - return null - } - - // will iterate one or zero times - for (const eq of eqSet) { - if (gt && !satisfies(eq, String(gt), options)) - return null - - if (lt && !satisfies(eq, String(lt), options)) - return null - - for (const c of dom) { - if (!satisfies(eq, String(c), options)) - return false - } - - return true - } - - let higher, lower; - let hasDomLT, hasDomGT; - // if the subset has a prerelease, we need a comparator in the superset - // with the same tuple and a prerelease, or it's not a subset - let needDomLTPre = lt && - !options.includePrerelease && - lt.semver.prerelease.length ? lt.semver : false; - let needDomGTPre = gt && - !options.includePrerelease && - gt.semver.prerelease.length ? gt.semver : false; - // exception: <1.2.3-0 is the same as <1.2.3 - if (needDomLTPre && needDomLTPre.prerelease.length === 1 && - lt.operator === '<' && needDomLTPre.prerelease[0] === 0) { - needDomLTPre = false; - } - - for (const c of dom) { - hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>='; - hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<='; - if (gt) { - if (needDomGTPre) { - if (c.semver.prerelease && c.semver.prerelease.length && - c.semver.major === needDomGTPre.major && - c.semver.minor === needDomGTPre.minor && - c.semver.patch === needDomGTPre.patch) { - needDomGTPre = false; - } - } - if (c.operator === '>' || c.operator === '>=') { - higher = higherGT(gt, c, options); - if (higher === c && higher !== gt) - return false - } else if (gt.operator === '>=' && !satisfies(gt.semver, String(c), options)) - return false - } - if (lt) { - if (needDomLTPre) { - if (c.semver.prerelease && c.semver.prerelease.length && - c.semver.major === needDomLTPre.major && - c.semver.minor === needDomLTPre.minor && - c.semver.patch === needDomLTPre.patch) { - needDomLTPre = false; - } - } - if (c.operator === '<' || c.operator === '<=') { - lower = lowerLT(lt, c, options); - if (lower === c && lower !== lt) - return false - } else if (lt.operator === '<=' && !satisfies(lt.semver, String(c), options)) - return false - } - if (!c.operator && (lt || gt) && gtltComp !== 0) - return false - } - - // if there was a < or >, and nothing in the dom, then must be false - // UNLESS it was limited by another range in the other direction. - // Eg, >1.0.0 <1.0.1 is still a subset of <2.0.0 - if (gt && hasDomLT && !lt && gtltComp !== 0) - return false - - if (lt && hasDomGT && !gt && gtltComp !== 0) - return false - - // we needed a prerelease range in a specific tuple, but didn't get one - // then this isn't a subset. eg >=1.2.3-pre is not a subset of >=1.0.0, - // because it includes prereleases in the 1.2.3 tuple - if (needDomGTPre || needDomLTPre) - return false - - return true -}; - -// >=1.2.3 is lower than >1.2.3 -const higherGT = (a, b, options) => { - if (!a) - return b - const comp = compare$1(a.semver, b.semver, options); - return comp > 0 ? a - : comp < 0 ? b - : b.operator === '>' && a.operator === '>=' ? b - : a -}; - -// <=1.2.3 is higher than <1.2.3 -const lowerLT = (a, b, options) => { - if (!a) - return b - const comp = compare$1(a.semver, b.semver, options); - return comp < 0 ? a - : comp > 0 ? b - : b.operator === '<' && a.operator === '<=' ? b - : a -}; - -var subset_1 = subset; - -// just pre-load all the stuff that index.js lazily exports -const internalRe = re$6.exports; -var semver$1 = { - re: internalRe.re, - src: internalRe.src, - tokens: internalRe.t, - SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION, - SemVer: semver$2, - compareIdentifiers: identifiers.compareIdentifiers, - rcompareIdentifiers: identifiers.rcompareIdentifiers, - parse: parse_1, - valid: valid_1, - clean: clean_1, - inc: inc_1, - diff: diff_1, - major: major_1, - minor: minor_1, - patch: patch_1, - prerelease: prerelease_1, - compare: compare_1, - rcompare: rcompare_1, - compareLoose: compareLoose_1, - compareBuild: compareBuild_1, - sort: sort_1, - rsort: rsort_1, - gt: gt_1, - lt: lt_1, - eq: eq_1, - neq: neq_1, - gte: gte_1, - lte: lte_1, - cmp: cmp_1, - coerce: coerce_1, - Comparator: comparator$1, - Range: range$1, - satisfies: satisfies_1, - toComparators: toComparators_1, - maxSatisfying: maxSatisfying_1, - minSatisfying: minSatisfying_1, - minVersion: minVersion_1, - validRange: valid, - outside: outside_1, - gtr: gtr_1, - ltr: ltr_1, - intersects: intersects_1, - simplifyRange: simplify, - subset: subset_1, -}; - -var semver = semver$1; - -var builtins = function ({ - version = process.version, - experimental = false -} = {}) { - var coreModules = [ - 'assert', - 'buffer', - 'child_process', - 'cluster', - 'console', - 'constants', - 'crypto', - 'dgram', - 'dns', - 'domain', - 'events', - 'fs', - 'http', - 'https', - 'module', - 'net', - 'os', - 'path', - 'punycode', - 'querystring', - 'readline', - 'repl', - 'stream', - 'string_decoder', - 'sys', - 'timers', - 'tls', - 'tty', - 'url', - 'util', - 'vm', - 'zlib' - ]; - - if (semver.lt(version, '6.0.0')) coreModules.push('freelist'); - if (semver.gte(version, '1.0.0')) coreModules.push('v8'); - if (semver.gte(version, '1.1.0')) coreModules.push('process'); - if (semver.gte(version, '8.0.0')) coreModules.push('inspector'); - if (semver.gte(version, '8.1.0')) coreModules.push('async_hooks'); - if (semver.gte(version, '8.4.0')) coreModules.push('http2'); - if (semver.gte(version, '8.5.0')) coreModules.push('perf_hooks'); - if (semver.gte(version, '10.0.0')) coreModules.push('trace_events'); - - if ( - semver.gte(version, '10.5.0') && - (experimental || semver.gte(version, '12.0.0')) - ) { - coreModules.push('worker_threads'); - } - if (semver.gte(version, '12.16.0') && experimental) { - coreModules.push('wasi'); - } - - return coreModules -}; - -// Manually “tree shaken” from: - -const reader = {read: read$3}; -var packageJsonReader = reader; - -/** - * @param {string} jsonPath - * @returns {{string: string}} - */ -function read$3(jsonPath) { - return find$1(path$b.dirname(jsonPath)) -} - -/** - * @param {string} dir - * @returns {{string: string}} - */ -function find$1(dir) { - try { - const string = require$$0$3.readFileSync( - path$b.toNamespacedPath(path$b.join(dir, 'package.json')), - 'utf8' - ); - return {string} - } catch (error) { - if (error.code === 'ENOENT') { - const parent = path$b.dirname(dir); - if (dir !== parent) return find$1(parent) - return {string: undefined} - // Throw all other errors. - /* c8 ignore next 4 */ - } - - throw error - } -} - -// Manually “tree shaken” from: - -const isWindows$1 = process.platform === 'win32'; - -const own$e = {}.hasOwnProperty; - -const codes = {}; - -/** - * @typedef {(...args: unknown[]) => string} MessageFunction - */ - -/** @type {Map} */ -const messages = new Map(); -const nodeInternalPrefix = '__node_internal_'; -/** @type {number} */ -let userStackTraceLimit; - -codes.ERR_INVALID_MODULE_SPECIFIER = createError( - 'ERR_INVALID_MODULE_SPECIFIER', - /** - * @param {string} request - * @param {string} reason - * @param {string} [base] - */ - (request, reason, base = undefined) => { - return `Invalid module "${request}" ${reason}${ - base ? ` imported from ${base}` : '' - }` - }, - TypeError -); - -codes.ERR_INVALID_PACKAGE_CONFIG = createError( - 'ERR_INVALID_PACKAGE_CONFIG', - /** - * @param {string} path - * @param {string} [base] - * @param {string} [message] - */ - (path, base, message) => { - return `Invalid package config ${path}${ - base ? ` while importing ${base}` : '' - }${message ? `. ${message}` : ''}` - }, - Error -); - -codes.ERR_INVALID_PACKAGE_TARGET = createError( - 'ERR_INVALID_PACKAGE_TARGET', - /** - * @param {string} pkgPath - * @param {string} key - * @param {unknown} target - * @param {boolean} [isImport=false] - * @param {string} [base] - */ - (pkgPath, key, target, isImport = false, base = undefined) => { - const relError = - typeof target === 'string' && - !isImport && - target.length > 0 && - !target.startsWith('./'); - if (key === '.') { - assert$2(isImport === false); - return ( - `Invalid "exports" main target ${JSON.stringify(target)} defined ` + - `in the package config ${pkgPath}package.json${ - base ? ` imported from ${base}` : '' - }${relError ? '; targets must start with "./"' : ''}` - ) - } - - return `Invalid "${ - isImport ? 'imports' : 'exports' - }" target ${JSON.stringify( - target - )} defined for '${key}' in the package config ${pkgPath}package.json${ - base ? ` imported from ${base}` : '' - }${relError ? '; targets must start with "./"' : ''}` - }, - Error -); - -codes.ERR_MODULE_NOT_FOUND = createError( - 'ERR_MODULE_NOT_FOUND', - /** - * @param {string} path - * @param {string} base - * @param {string} [type] - */ - (path, base, type = 'package') => { - return `Cannot find ${type} '${path}' imported from ${base}` - }, - Error -); - -codes.ERR_PACKAGE_IMPORT_NOT_DEFINED = createError( - 'ERR_PACKAGE_IMPORT_NOT_DEFINED', - /** - * @param {string} specifier - * @param {string} packagePath - * @param {string} base - */ - (specifier, packagePath, base) => { - return `Package import specifier "${specifier}" is not defined${ - packagePath ? ` in package ${packagePath}package.json` : '' - } imported from ${base}` - }, - TypeError -); - -codes.ERR_PACKAGE_PATH_NOT_EXPORTED = createError( - 'ERR_PACKAGE_PATH_NOT_EXPORTED', - /** - * @param {string} pkgPath - * @param {string} subpath - * @param {string} [base] - */ - (pkgPath, subpath, base = undefined) => { - if (subpath === '.') - return `No "exports" main defined in ${pkgPath}package.json${ - base ? ` imported from ${base}` : '' - }` - return `Package subpath '${subpath}' is not defined by "exports" in ${pkgPath}package.json${ - base ? ` imported from ${base}` : '' - }` - }, - Error -); - -codes.ERR_UNSUPPORTED_DIR_IMPORT = createError( - 'ERR_UNSUPPORTED_DIR_IMPORT', - "Directory import '%s' is not supported " + - 'resolving ES modules imported from %s', - Error -); - -codes.ERR_UNKNOWN_FILE_EXTENSION = createError( - 'ERR_UNKNOWN_FILE_EXTENSION', - 'Unknown file extension "%s" for %s', - TypeError -); - -codes.ERR_INVALID_ARG_VALUE = createError( - 'ERR_INVALID_ARG_VALUE', - /** - * @param {string} name - * @param {unknown} value - * @param {string} [reason='is invalid'] - */ - (name, value, reason = 'is invalid') => { - let inspected = inspect$1(value); - - if (inspected.length > 128) { - inspected = `${inspected.slice(0, 128)}...`; - } - - const type = name.includes('.') ? 'property' : 'argument'; - - return `The ${type} '${name}' ${reason}. Received ${inspected}` - }, - TypeError - // Note: extra classes have been shaken out. - // , RangeError -); - -codes.ERR_UNSUPPORTED_ESM_URL_SCHEME = createError( - 'ERR_UNSUPPORTED_ESM_URL_SCHEME', - /** - * @param {URL} url - */ - (url) => { - let message = - 'Only file and data URLs are supported by the default ESM loader'; - - if (isWindows$1 && url.protocol.length === 2) { - message += '. On Windows, absolute paths must be valid file:// URLs'; - } - - message += `. Received protocol '${url.protocol}'`; - return message - }, - Error -); - -/** - * Utility function for registering the error codes. Only used here. Exported - * *only* to allow for testing. - * @param {string} sym - * @param {MessageFunction|string} value - * @param {ErrorConstructor} def - * @returns {new (...args: unknown[]) => Error} - */ -function createError(sym, value, def) { - // Special case for SystemError that formats the error message differently - // The SystemErrors only have SystemError as their base classes. - messages.set(sym, value); - - return makeNodeErrorWithCode(def, sym) -} - -/** - * @param {ErrorConstructor} Base - * @param {string} key - * @returns {ErrorConstructor} - */ -function makeNodeErrorWithCode(Base, key) { - // @ts-expect-error It’s a Node error. - return NodeError - /** - * @param {unknown[]} args - */ - function NodeError(...args) { - const limit = Error.stackTraceLimit; - if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = 0; - const error = new Base(); - // Reset the limit and setting the name property. - if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = limit; - const message = getMessage(key, args, error); - Object.defineProperty(error, 'message', { - value: message, - enumerable: false, - writable: true, - configurable: true - }); - Object.defineProperty(error, 'toString', { - /** @this {Error} */ - value() { - return `${this.name} [${key}]: ${this.message}` - }, - enumerable: false, - writable: true, - configurable: true - }); - addCodeToName(error, Base.name, key); - // @ts-expect-error It’s a Node error. - error.code = key; - return error - } -} - -const addCodeToName = hideStackFrames( - /** - * @param {Error} error - * @param {string} name - * @param {string} code - * @returns {void} - */ - function (error, name, code) { - // Set the stack - error = captureLargerStackTrace(error); - // Add the error code to the name to include it in the stack trace. - error.name = `${name} [${code}]`; - // Access the stack to generate the error message including the error code - // from the name. - error.stack; // eslint-disable-line no-unused-expressions - // Reset the name to the actual name. - if (name === 'SystemError') { - Object.defineProperty(error, 'name', { - value: name, - enumerable: false, - writable: true, - configurable: true - }); - } else { - delete error.name; - } - } -); - -/** - * @returns {boolean} - */ -function isErrorStackTraceLimitWritable() { - const desc = Object.getOwnPropertyDescriptor(Error, 'stackTraceLimit'); - if (desc === undefined) { - return Object.isExtensible(Error) - } - - return own$e.call(desc, 'writable') ? desc.writable : desc.set !== undefined -} - -/** - * This function removes unnecessary frames from Node.js core errors. - * @template {(...args: unknown[]) => unknown} T - * @type {(fn: T) => T} - */ -function hideStackFrames(fn) { - // We rename the functions that will be hidden to cut off the stacktrace - // at the outermost one - const hidden = nodeInternalPrefix + fn.name; - Object.defineProperty(fn, 'name', {value: hidden}); - return fn -} - -const captureLargerStackTrace = hideStackFrames( - /** - * @param {Error} error - * @returns {Error} - */ - function (error) { - const stackTraceLimitIsWritable = isErrorStackTraceLimitWritable(); - if (stackTraceLimitIsWritable) { - userStackTraceLimit = Error.stackTraceLimit; - Error.stackTraceLimit = Number.POSITIVE_INFINITY; - } - - Error.captureStackTrace(error); - - // Reset the limit - if (stackTraceLimitIsWritable) Error.stackTraceLimit = userStackTraceLimit; - - return error - } -); - -/** - * @param {string} key - * @param {unknown[]} args - * @param {Error} self - * @returns {string} - */ -function getMessage(key, args, self) { - const message = messages.get(key); - - if (typeof message === 'function') { - assert$2( - message.length <= args.length, // Default options do not count. - `Code: ${key}; The provided arguments length (${args.length}) does not ` + - `match the required ones (${message.length}).` - ); - return Reflect.apply(message, self, args) - } - - const expectedLength = (message.match(/%[dfijoOs]/g) || []).length; - assert$2( - expectedLength === args.length, - `Code: ${key}; The provided arguments length (${args.length}) does not ` + - `match the required ones (${expectedLength}).` - ); - if (args.length === 0) return message - - args.unshift(message); - return Reflect.apply(format$2, null, args) -} - -// Manually “tree shaken” from: - -const {ERR_UNKNOWN_FILE_EXTENSION} = codes; - -const extensionFormatMap = { - __proto__: null, - '.cjs': 'commonjs', - '.js': 'module', - '.mjs': 'module' -}; - -/** - * @param {string} url - * @returns {{format: string|null}} - */ -function defaultGetFormat(url) { - if (url.startsWith('node:')) { - return {format: 'builtin'} - } - - const parsed = new URL$1(url); - - if (parsed.protocol === 'data:') { - const {1: mime} = /^([^/]+\/[^;,]+)[^,]*?(;base64)?,/.exec( - parsed.pathname - ) || [null, null]; - const format = mime === 'text/javascript' ? 'module' : null; - return {format} - } - - if (parsed.protocol === 'file:') { - const ext = path$b.extname(parsed.pathname); - /** @type {string} */ - let format; - if (ext === '.js') { - format = getPackageType(parsed.href) === 'module' ? 'module' : 'commonjs'; - } else { - format = extensionFormatMap[ext]; - } - - if (!format) { - throw new ERR_UNKNOWN_FILE_EXTENSION(ext, fileURLToPath(url)) - } - - return {format: format || null} - } - - return {format: null} -} - -// Manually “tree shaken” from: - -const listOfBuiltins = builtins(); - -const { - ERR_INVALID_MODULE_SPECIFIER, - ERR_INVALID_PACKAGE_CONFIG, - ERR_INVALID_PACKAGE_TARGET, - ERR_MODULE_NOT_FOUND, - ERR_PACKAGE_IMPORT_NOT_DEFINED, - ERR_PACKAGE_PATH_NOT_EXPORTED, - ERR_UNSUPPORTED_DIR_IMPORT, - ERR_UNSUPPORTED_ESM_URL_SCHEME, - ERR_INVALID_ARG_VALUE -} = codes; - -const own$d = {}.hasOwnProperty; - -const DEFAULT_CONDITIONS = Object.freeze(['node', 'import']); -const DEFAULT_CONDITIONS_SET = new Set(DEFAULT_CONDITIONS); - -const invalidSegmentRegEx = /(^|\\|\/)(\.\.?|node_modules)(\\|\/|$)/; -const patternRegEx = /\*/g; -const encodedSepRegEx = /%2f|%2c/i; -/** @type {Set} */ -const emittedPackageWarnings = new Set(); -/** @type {Map} */ -const packageJsonCache = new Map(); - -/** - * @param {string} match - * @param {URL} pjsonUrl - * @param {boolean} isExports - * @param {URL} base - * @returns {void} - */ -function emitFolderMapDeprecation(match, pjsonUrl, isExports, base) { - const pjsonPath = fileURLToPath(pjsonUrl); - - if (emittedPackageWarnings.has(pjsonPath + '|' + match)) return - emittedPackageWarnings.add(pjsonPath + '|' + match); - process.emitWarning( - `Use of deprecated folder mapping "${match}" in the ${ - isExports ? '"exports"' : '"imports"' - } field module resolution of the package at ${pjsonPath}${ - base ? ` imported from ${fileURLToPath(base)}` : '' - }.\n` + - `Update this package.json to use a subpath pattern like "${match}*".`, - 'DeprecationWarning', - 'DEP0148' - ); -} - -/** - * @param {URL} url - * @param {URL} packageJsonUrl - * @param {URL} base - * @param {unknown} [main] - * @returns {void} - */ -function emitLegacyIndexDeprecation(url, packageJsonUrl, base, main) { - const {format} = defaultGetFormat(url.href); - if (format !== 'module') return - const path = fileURLToPath(url.href); - const pkgPath = fileURLToPath(new URL$1('.', packageJsonUrl)); - const basePath = fileURLToPath(base); - if (main) - process.emitWarning( - `Package ${pkgPath} has a "main" field set to ${JSON.stringify(main)}, ` + - `excluding the full filename and extension to the resolved file at "${path.slice( - pkgPath.length - )}", imported from ${basePath}.\n Automatic extension resolution of the "main" field is` + - 'deprecated for ES modules.', - 'DeprecationWarning', - 'DEP0151' - ); - else - process.emitWarning( - `No "main" or "exports" field defined in the package.json for ${pkgPath} resolving the main entry point "${path.slice( - pkgPath.length - )}", imported from ${basePath}.\nDefault "index" lookups for the main are deprecated for ES modules.`, - 'DeprecationWarning', - 'DEP0151' - ); -} - -/** - * @param {string[]} [conditions] - * @returns {Set} - */ -function getConditionsSet(conditions) { - if (conditions !== undefined && conditions !== DEFAULT_CONDITIONS) { - if (!Array.isArray(conditions)) { - throw new ERR_INVALID_ARG_VALUE( - 'conditions', - conditions, - 'expected an array' - ) - } - - return new Set(conditions) - } - - return DEFAULT_CONDITIONS_SET -} - -/** - * @param {string} path - * @returns {Stats} - */ -function tryStatSync(path) { - // Note: from Node 15 onwards we can use `throwIfNoEntry: false` instead. - try { - return statSync(path) - } catch { - return new Stats() - } -} - -/** - * @param {string} path - * @param {string|URL} specifier Note: `specifier` is actually optional, not base. - * @param {URL} [base] - * @returns {PackageConfig} - */ -function getPackageConfig(path, specifier, base) { - const existing = packageJsonCache.get(path); - if (existing !== undefined) { - return existing - } - - const source = packageJsonReader.read(path).string; - - if (source === undefined) { - /** @type {PackageConfig} */ - const packageConfig = { - pjsonPath: path, - exists: false, - main: undefined, - name: undefined, - type: 'none', - exports: undefined, - imports: undefined - }; - packageJsonCache.set(path, packageConfig); - return packageConfig - } - - /** @type {Object.} */ - let packageJson; - try { - packageJson = JSON.parse(source); - } catch (error) { - throw new ERR_INVALID_PACKAGE_CONFIG( - path, - (base ? `"${specifier}" from ` : '') + fileURLToPath(base || specifier), - error.message - ) - } - - const {exports, imports, main, name, type} = packageJson; - - /** @type {PackageConfig} */ - const packageConfig = { - pjsonPath: path, - exists: true, - main: typeof main === 'string' ? main : undefined, - name: typeof name === 'string' ? name : undefined, - type: type === 'module' || type === 'commonjs' ? type : 'none', - // @ts-expect-error Assume `Object.`. - exports, - // @ts-expect-error Assume `Object.`. - imports: imports && typeof imports === 'object' ? imports : undefined - }; - packageJsonCache.set(path, packageConfig); - return packageConfig -} - -/** - * @param {URL|string} resolved - * @returns {PackageConfig} - */ -function getPackageScopeConfig(resolved) { - let packageJsonUrl = new URL$1('./package.json', resolved); - - while (true) { - const packageJsonPath = packageJsonUrl.pathname; - - if (packageJsonPath.endsWith('node_modules/package.json')) break - - const packageConfig = getPackageConfig( - fileURLToPath(packageJsonUrl), - resolved - ); - if (packageConfig.exists) return packageConfig - - const lastPackageJsonUrl = packageJsonUrl; - packageJsonUrl = new URL$1('../package.json', packageJsonUrl); - - // Terminates at root where ../package.json equals ../../package.json - // (can't just check "/package.json" for Windows support). - if (packageJsonUrl.pathname === lastPackageJsonUrl.pathname) break - } - - const packageJsonPath = fileURLToPath(packageJsonUrl); - /** @type {PackageConfig} */ - const packageConfig = { - pjsonPath: packageJsonPath, - exists: false, - main: undefined, - name: undefined, - type: 'none', - exports: undefined, - imports: undefined - }; - packageJsonCache.set(packageJsonPath, packageConfig); - return packageConfig -} - -/** - * Legacy CommonJS main resolution: - * 1. let M = pkg_url + (json main field) - * 2. TRY(M, M.js, M.json, M.node) - * 3. TRY(M/index.js, M/index.json, M/index.node) - * 4. TRY(pkg_url/index.js, pkg_url/index.json, pkg_url/index.node) - * 5. NOT_FOUND - * - * @param {URL} url - * @returns {boolean} - */ -function fileExists(url) { - return tryStatSync(fileURLToPath(url)).isFile() -} - -/** - * @param {URL} packageJsonUrl - * @param {PackageConfig} packageConfig - * @param {URL} base - * @returns {URL} - */ -function legacyMainResolve(packageJsonUrl, packageConfig, base) { - /** @type {URL} */ - let guess; - if (packageConfig.main !== undefined) { - guess = new URL$1(`./${packageConfig.main}`, packageJsonUrl); - // Note: fs check redundances will be handled by Descriptor cache here. - if (fileExists(guess)) return guess - - const tries = [ - `./${packageConfig.main}.js`, - `./${packageConfig.main}.json`, - `./${packageConfig.main}.node`, - `./${packageConfig.main}/index.js`, - `./${packageConfig.main}/index.json`, - `./${packageConfig.main}/index.node` - ]; - let i = -1; - - while (++i < tries.length) { - guess = new URL$1(tries[i], packageJsonUrl); - if (fileExists(guess)) break - guess = undefined; - } - - if (guess) { - emitLegacyIndexDeprecation( - guess, - packageJsonUrl, - base, - packageConfig.main - ); - return guess - } - // Fallthrough. - } - - const tries = ['./index.js', './index.json', './index.node']; - let i = -1; - - while (++i < tries.length) { - guess = new URL$1(tries[i], packageJsonUrl); - if (fileExists(guess)) break - guess = undefined; - } - - if (guess) { - emitLegacyIndexDeprecation(guess, packageJsonUrl, base, packageConfig.main); - return guess - } - - // Not found. - throw new ERR_MODULE_NOT_FOUND( - fileURLToPath(new URL$1('.', packageJsonUrl)), - fileURLToPath(base) - ) -} - -/** - * @param {URL} resolved - * @param {URL} base - * @returns {URL} - */ -function finalizeResolution(resolved, base) { - if (encodedSepRegEx.test(resolved.pathname)) - throw new ERR_INVALID_MODULE_SPECIFIER( - resolved.pathname, - 'must not include encoded "/" or "\\" characters', - fileURLToPath(base) - ) - - const path = fileURLToPath(resolved); - - const stats = tryStatSync(path.endsWith('/') ? path.slice(-1) : path); - - if (stats.isDirectory()) { - const error = new ERR_UNSUPPORTED_DIR_IMPORT(path, fileURLToPath(base)); - // @ts-expect-error Add this for `import.meta.resolve`. - error.url = String(resolved); - throw error - } - - if (!stats.isFile()) { - throw new ERR_MODULE_NOT_FOUND( - path || resolved.pathname, - base && fileURLToPath(base), - 'module' - ) - } - - return resolved -} - -/** - * @param {string} specifier - * @param {URL?} packageJsonUrl - * @param {URL} base - * @returns {never} - */ -function throwImportNotDefined(specifier, packageJsonUrl, base) { - throw new ERR_PACKAGE_IMPORT_NOT_DEFINED( - specifier, - packageJsonUrl && fileURLToPath(new URL$1('.', packageJsonUrl)), - fileURLToPath(base) - ) -} - -/** - * @param {string} subpath - * @param {URL} packageJsonUrl - * @param {URL} base - * @returns {never} - */ -function throwExportsNotFound(subpath, packageJsonUrl, base) { - throw new ERR_PACKAGE_PATH_NOT_EXPORTED( - fileURLToPath(new URL$1('.', packageJsonUrl)), - subpath, - base && fileURLToPath(base) - ) -} - -/** - * @param {string} subpath - * @param {URL} packageJsonUrl - * @param {boolean} internal - * @param {URL} [base] - * @returns {never} - */ -function throwInvalidSubpath(subpath, packageJsonUrl, internal, base) { - const reason = `request is not a valid subpath for the "${ - internal ? 'imports' : 'exports' - }" resolution of ${fileURLToPath(packageJsonUrl)}`; - - throw new ERR_INVALID_MODULE_SPECIFIER( - subpath, - reason, - base && fileURLToPath(base) - ) -} - -/** - * @param {string} subpath - * @param {unknown} target - * @param {URL} packageJsonUrl - * @param {boolean} internal - * @param {URL} [base] - * @returns {never} - */ -function throwInvalidPackageTarget( - subpath, - target, - packageJsonUrl, - internal, - base -) { - target = - typeof target === 'object' && target !== null - ? JSON.stringify(target, null, '') - : `${target}`; - - throw new ERR_INVALID_PACKAGE_TARGET( - fileURLToPath(new URL$1('.', packageJsonUrl)), - subpath, - target, - internal, - base && fileURLToPath(base) - ) -} - -/** - * @param {string} target - * @param {string} subpath - * @param {string} match - * @param {URL} packageJsonUrl - * @param {URL} base - * @param {boolean} pattern - * @param {boolean} internal - * @param {Set} conditions - * @returns {URL} - */ -function resolvePackageTargetString( - target, - subpath, - match, - packageJsonUrl, - base, - pattern, - internal, - conditions -) { - if (subpath !== '' && !pattern && target[target.length - 1] !== '/') - throwInvalidPackageTarget(match, target, packageJsonUrl, internal, base); - - if (!target.startsWith('./')) { - if (internal && !target.startsWith('../') && !target.startsWith('/')) { - let isURL = false; - - try { - new URL$1(target); - isURL = true; - } catch {} - - if (!isURL) { - const exportTarget = pattern - ? target.replace(patternRegEx, subpath) - : target + subpath; - - return packageResolve(exportTarget, packageJsonUrl, conditions) - } - } - - throwInvalidPackageTarget(match, target, packageJsonUrl, internal, base); - } - - if (invalidSegmentRegEx.test(target.slice(2))) - throwInvalidPackageTarget(match, target, packageJsonUrl, internal, base); - - const resolved = new URL$1(target, packageJsonUrl); - const resolvedPath = resolved.pathname; - const packagePath = new URL$1('.', packageJsonUrl).pathname; - - if (!resolvedPath.startsWith(packagePath)) - throwInvalidPackageTarget(match, target, packageJsonUrl, internal, base); - - if (subpath === '') return resolved - - if (invalidSegmentRegEx.test(subpath)) - throwInvalidSubpath(match + subpath, packageJsonUrl, internal, base); - - if (pattern) return new URL$1(resolved.href.replace(patternRegEx, subpath)) - return new URL$1(subpath, resolved) -} - -/** - * @param {string} key - * @returns {boolean} - */ -function isArrayIndex(key) { - const keyNumber = Number(key); - if (`${keyNumber}` !== key) return false - return keyNumber >= 0 && keyNumber < 0xffff_ffff -} - -/** - * @param {URL} packageJsonUrl - * @param {unknown} target - * @param {string} subpath - * @param {string} packageSubpath - * @param {URL} base - * @param {boolean} pattern - * @param {boolean} internal - * @param {Set} conditions - * @returns {URL} - */ -function resolvePackageTarget( - packageJsonUrl, - target, - subpath, - packageSubpath, - base, - pattern, - internal, - conditions -) { - if (typeof target === 'string') { - return resolvePackageTargetString( - target, - subpath, - packageSubpath, - packageJsonUrl, - base, - pattern, - internal, - conditions - ) - } - - if (Array.isArray(target)) { - /** @type {unknown[]} */ - const targetList = target; - if (targetList.length === 0) return null - - /** @type {Error} */ - let lastException; - let i = -1; - - while (++i < targetList.length) { - const targetItem = targetList[i]; - /** @type {URL} */ - let resolved; - try { - resolved = resolvePackageTarget( - packageJsonUrl, - targetItem, - subpath, - packageSubpath, - base, - pattern, - internal, - conditions - ); - } catch (error) { - lastException = error; - if (error.code === 'ERR_INVALID_PACKAGE_TARGET') continue - throw error - } - - if (resolved === undefined) continue - - if (resolved === null) { - lastException = null; - continue - } - - return resolved - } - - if (lastException === undefined || lastException === null) { - // @ts-expect-error The diff between `undefined` and `null` seems to be - // intentional - return lastException - } - - throw lastException - } - - if (typeof target === 'object' && target !== null) { - const keys = Object.getOwnPropertyNames(target); - let i = -1; - - while (++i < keys.length) { - const key = keys[i]; - if (isArrayIndex(key)) { - throw new ERR_INVALID_PACKAGE_CONFIG( - fileURLToPath(packageJsonUrl), - base, - '"exports" cannot contain numeric property keys.' - ) - } - } - - i = -1; - - while (++i < keys.length) { - const key = keys[i]; - if (key === 'default' || (conditions && conditions.has(key))) { - /** @type {unknown} */ - const conditionalTarget = target[key]; - const resolved = resolvePackageTarget( - packageJsonUrl, - conditionalTarget, - subpath, - packageSubpath, - base, - pattern, - internal, - conditions - ); - if (resolved === undefined) continue - return resolved - } - } - - return undefined - } - - if (target === null) { - return null - } - - throwInvalidPackageTarget( - packageSubpath, - target, - packageJsonUrl, - internal, - base - ); -} - -/** - * @param {unknown} exports - * @param {URL} packageJsonUrl - * @param {URL} base - * @returns {boolean} - */ -function isConditionalExportsMainSugar(exports, packageJsonUrl, base) { - if (typeof exports === 'string' || Array.isArray(exports)) return true - if (typeof exports !== 'object' || exports === null) return false - - const keys = Object.getOwnPropertyNames(exports); - let isConditionalSugar = false; - let i = 0; - let j = -1; - while (++j < keys.length) { - const key = keys[j]; - const curIsConditionalSugar = key === '' || key[0] !== '.'; - if (i++ === 0) { - isConditionalSugar = curIsConditionalSugar; - } else if (isConditionalSugar !== curIsConditionalSugar) { - throw new ERR_INVALID_PACKAGE_CONFIG( - fileURLToPath(packageJsonUrl), - base, - '"exports" cannot contain some keys starting with \'.\' and some not.' + - ' The exports object must either be an object of package subpath keys' + - ' or an object of main entry condition name keys only.' - ) - } - } - - return isConditionalSugar -} - -/** - * @param {URL} packageJsonUrl - * @param {string} packageSubpath - * @param {Object.} packageConfig - * @param {URL} base - * @param {Set} conditions - * @returns {ResolveObject} - */ -function packageExportsResolve( - packageJsonUrl, - packageSubpath, - packageConfig, - base, - conditions -) { - let exports = packageConfig.exports; - if (isConditionalExportsMainSugar(exports, packageJsonUrl, base)) - exports = {'.': exports}; - - if (own$d.call(exports, packageSubpath)) { - const target = exports[packageSubpath]; - const resolved = resolvePackageTarget( - packageJsonUrl, - target, - '', - packageSubpath, - base, - false, - false, - conditions - ); - if (resolved === null || resolved === undefined) - throwExportsNotFound(packageSubpath, packageJsonUrl, base); - return {resolved, exact: true} - } - - let bestMatch = ''; - const keys = Object.getOwnPropertyNames(exports); - let i = -1; - - while (++i < keys.length) { - const key = keys[i]; - if ( - key[key.length - 1] === '*' && - packageSubpath.startsWith(key.slice(0, -1)) && - packageSubpath.length >= key.length && - key.length > bestMatch.length - ) { - bestMatch = key; - } else if ( - key[key.length - 1] === '/' && - packageSubpath.startsWith(key) && - key.length > bestMatch.length - ) { - bestMatch = key; - } - } - - if (bestMatch) { - const target = exports[bestMatch]; - const pattern = bestMatch[bestMatch.length - 1] === '*'; - const subpath = packageSubpath.slice(bestMatch.length - (pattern ? 1 : 0)); - const resolved = resolvePackageTarget( - packageJsonUrl, - target, - subpath, - bestMatch, - base, - pattern, - false, - conditions - ); - if (resolved === null || resolved === undefined) - throwExportsNotFound(packageSubpath, packageJsonUrl, base); - if (!pattern) - emitFolderMapDeprecation(bestMatch, packageJsonUrl, true, base); - return {resolved, exact: pattern} - } - - throwExportsNotFound(packageSubpath, packageJsonUrl, base); -} - -/** - * @param {string} name - * @param {URL} base - * @param {Set} [conditions] - * @returns {ResolveObject} - */ -function packageImportsResolve(name, base, conditions) { - if (name === '#' || name.startsWith('#/')) { - const reason = 'is not a valid internal imports specifier name'; - throw new ERR_INVALID_MODULE_SPECIFIER(name, reason, fileURLToPath(base)) - } - - /** @type {URL} */ - let packageJsonUrl; - - const packageConfig = getPackageScopeConfig(base); - - if (packageConfig.exists) { - packageJsonUrl = pathToFileURL(packageConfig.pjsonPath); - const imports = packageConfig.imports; - if (imports) { - if (own$d.call(imports, name)) { - const resolved = resolvePackageTarget( - packageJsonUrl, - imports[name], - '', - name, - base, - false, - true, - conditions - ); - if (resolved !== null) return {resolved, exact: true} - } else { - let bestMatch = ''; - const keys = Object.getOwnPropertyNames(imports); - let i = -1; - - while (++i < keys.length) { - const key = keys[i]; - - if ( - key[key.length - 1] === '*' && - name.startsWith(key.slice(0, -1)) && - name.length >= key.length && - key.length > bestMatch.length - ) { - bestMatch = key; - } else if ( - key[key.length - 1] === '/' && - name.startsWith(key) && - key.length > bestMatch.length - ) { - bestMatch = key; - } - } - - if (bestMatch) { - const target = imports[bestMatch]; - const pattern = bestMatch[bestMatch.length - 1] === '*'; - const subpath = name.slice(bestMatch.length - (pattern ? 1 : 0)); - const resolved = resolvePackageTarget( - packageJsonUrl, - target, - subpath, - bestMatch, - base, - pattern, - true, - conditions - ); - if (resolved !== null) { - if (!pattern) - emitFolderMapDeprecation(bestMatch, packageJsonUrl, false, base); - return {resolved, exact: pattern} - } - } - } - } - } - - throwImportNotDefined(name, packageJsonUrl, base); -} - -/** - * @param {string} url - * @returns {PackageType} - */ -function getPackageType(url) { - const packageConfig = getPackageScopeConfig(url); - return packageConfig.type -} - -/** - * @param {string} specifier - * @param {URL} base - */ -function parsePackageName(specifier, base) { - let separatorIndex = specifier.indexOf('/'); - let validPackageName = true; - let isScoped = false; - if (specifier[0] === '@') { - isScoped = true; - if (separatorIndex === -1 || specifier.length === 0) { - validPackageName = false; - } else { - separatorIndex = specifier.indexOf('/', separatorIndex + 1); - } - } - - const packageName = - separatorIndex === -1 ? specifier : specifier.slice(0, separatorIndex); - - // Package name cannot have leading . and cannot have percent-encoding or - // separators. - let i = -1; - while (++i < packageName.length) { - if (packageName[i] === '%' || packageName[i] === '\\') { - validPackageName = false; - break - } - } - - if (!validPackageName) { - throw new ERR_INVALID_MODULE_SPECIFIER( - specifier, - 'is not a valid package name', - fileURLToPath(base) - ) - } - - const packageSubpath = - '.' + (separatorIndex === -1 ? '' : specifier.slice(separatorIndex)); - - return {packageName, packageSubpath, isScoped} -} - -/** - * @param {string} specifier - * @param {URL} base - * @param {Set} conditions - * @returns {URL} - */ -function packageResolve(specifier, base, conditions) { - const {packageName, packageSubpath, isScoped} = parsePackageName( - specifier, - base - ); - - // ResolveSelf - const packageConfig = getPackageScopeConfig(base); - - // Can’t test. - /* c8 ignore next 16 */ - if (packageConfig.exists) { - const packageJsonUrl = pathToFileURL(packageConfig.pjsonPath); - if ( - packageConfig.name === packageName && - packageConfig.exports !== undefined && - packageConfig.exports !== null - ) { - return packageExportsResolve( - packageJsonUrl, - packageSubpath, - packageConfig, - base, - conditions - ).resolved - } - } - - let packageJsonUrl = new URL$1( - './node_modules/' + packageName + '/package.json', - base - ); - let packageJsonPath = fileURLToPath(packageJsonUrl); - /** @type {string} */ - let lastPath; - do { - const stat = tryStatSync(packageJsonPath.slice(0, -13)); - if (!stat.isDirectory()) { - lastPath = packageJsonPath; - packageJsonUrl = new URL$1( - (isScoped ? '../../../../node_modules/' : '../../../node_modules/') + - packageName + - '/package.json', - packageJsonUrl - ); - packageJsonPath = fileURLToPath(packageJsonUrl); - continue - } - - // Package match. - const packageConfig = getPackageConfig(packageJsonPath, specifier, base); - if (packageConfig.exports !== undefined && packageConfig.exports !== null) - return packageExportsResolve( - packageJsonUrl, - packageSubpath, - packageConfig, - base, - conditions - ).resolved - if (packageSubpath === '.') - return legacyMainResolve(packageJsonUrl, packageConfig, base) - return new URL$1(packageSubpath, packageJsonUrl) - // Cross-platform root check. - } while (packageJsonPath.length !== lastPath.length) - - throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base)) -} - -/** - * @param {string} specifier - * @returns {boolean} - */ -function isRelativeSpecifier(specifier) { - if (specifier[0] === '.') { - if (specifier.length === 1 || specifier[1] === '/') return true - if ( - specifier[1] === '.' && - (specifier.length === 2 || specifier[2] === '/') - ) { - return true - } - } - - return false -} - -/** - * @param {string} specifier - * @returns {boolean} - */ -function shouldBeTreatedAsRelativeOrAbsolutePath(specifier) { - if (specifier === '') return false - if (specifier[0] === '/') return true - return isRelativeSpecifier(specifier) -} - -/** - * The “Resolver Algorithm Specification” as detailed in the Node docs (which is - * sync and slightly lower-level than `resolve`). - * - * - * - * @param {string} specifier - * @param {URL} base - * @param {Set} [conditions] - * @returns {URL} - */ -function moduleResolve(specifier, base, conditions) { - // Order swapped from spec for minor perf gain. - // Ok since relative URLs cannot parse as URLs. - /** @type {URL} */ - let resolved; - - if (shouldBeTreatedAsRelativeOrAbsolutePath(specifier)) { - resolved = new URL$1(specifier, base); - } else if (specifier[0] === '#') { -({resolved} = packageImportsResolve(specifier, base, conditions)); - } else { - try { - resolved = new URL$1(specifier); - } catch { - resolved = packageResolve(specifier, base, conditions); - } - } - - return finalizeResolution(resolved, base) -} - -/** - * @param {string} specifier - * @param {{parentURL?: string, conditions?: string[]}} context - * @returns {{url: string}} - */ -function defaultResolve(specifier, context = {}) { - const {parentURL} = context; - /** @type {URL} */ - let parsed; - - try { - parsed = new URL$1(specifier); - if (parsed.protocol === 'data:') { - return {url: specifier} - } - } catch {} - - if (parsed && parsed.protocol === 'node:') return {url: specifier} - if (parsed && parsed.protocol !== 'file:' && parsed.protocol !== 'data:') - throw new ERR_UNSUPPORTED_ESM_URL_SCHEME(parsed) - - if (listOfBuiltins.includes(specifier)) { - return {url: 'node:' + specifier} - } - - if (parentURL.startsWith('data:')) { - // This is gonna blow up, we want the error - new URL$1(specifier, parentURL); - } - - const conditions = getConditionsSet(context.conditions); - let url = moduleResolve(specifier, new URL$1(parentURL), conditions); - - const urlPath = fileURLToPath(url); - const real = realpathSync$1(urlPath); - const old = url; - url = pathToFileURL(real + (urlPath.endsWith(path$b.sep) ? '/' : '')); - url.search = old.search; - url.hash = old.hash; - - return {url: `${url}`} -} - -/** - * Provides a module-relative resolution function scoped to each module, - * returning the URL string. - * `import.meta.resolve` also accepts a second argument which is the parent - * module from which to resolve from. - * - * This function is asynchronous because the ES module resolver in Node.js is - * allowed to be asynchronous. - * - * @param {string} specifier The module specifier to resolve relative to parent. - * @param {string} parent The absolute parent module URL to resolve from. - * You should pass `import.meta.url` or something else - * @returns {Promise} - */ -async function resolve(specifier, parent) { - if (!parent) { - throw new Error( - 'Please pass `parent`: `import-meta-resolve` cannot ponyfill that' - ) - } - - try { - return defaultResolve(specifier, {parentURL: parent}).url - } catch (error) { - return error.code === 'ERR_UNSUPPORTED_DIR_IMPORT' - ? error.url - : Promise.reject(error) - } -} - -var libnpmconfig = {}; - -class FiggyPudding { - constructor (specs, opts, providers) { - this.__specs = specs || {}; - Object.keys(this.__specs).forEach(alias => { - if (typeof this.__specs[alias] === 'string') { - const key = this.__specs[alias]; - const realSpec = this.__specs[key]; - if (realSpec) { - const aliasArr = realSpec.aliases || []; - aliasArr.push(alias, key); - realSpec.aliases = [...(new Set(aliasArr))]; - this.__specs[alias] = realSpec; - } else { - throw new Error(`Alias refers to invalid key: ${key} -> ${alias}`) - } - } - }); - this.__opts = opts || {}; - this.__providers = reverse((providers).filter( - x => x != null && typeof x === 'object' - )); - this.__isFiggyPudding = true; - } - get (key) { - return pudGet(this, key, true) - } - get [Symbol.toStringTag] () { return 'FiggyPudding' } - forEach (fn, thisArg = this) { - for (let [key, value] of this.entries()) { - fn.call(thisArg, value, key, this); - } - } - toJSON () { - const obj = {}; - this.forEach((val, key) => { - obj[key] = val; - }); - return obj - } - * entries (_matcher) { - for (let key of Object.keys(this.__specs)) { - yield [key, this.get(key)]; - } - const matcher = _matcher || this.__opts.other; - if (matcher) { - const seen = new Set(); - for (let p of this.__providers) { - const iter = p.entries ? p.entries(matcher) : entries(p); - for (let [key, val] of iter) { - if (matcher(key) && !seen.has(key)) { - seen.add(key); - yield [key, val]; - } - } - } - } - } - * [Symbol.iterator] () { - for (let [key, value] of this.entries()) { - yield [key, value]; - } - } - * keys () { - for (let [key] of this.entries()) { - yield key; - } - } - * values () { - for (let [, value] of this.entries()) { - yield value; - } - } - concat (...moreConfig) { - return new Proxy(new FiggyPudding( - this.__specs, - this.__opts, - reverse(this.__providers).concat(moreConfig) - ), proxyHandler) - } -} -try { - const util = require$$0$4; - FiggyPudding.prototype[util.inspect.custom] = function (depth, opts) { - return ( - this[Symbol.toStringTag] + ' ' - ) + util.inspect(this.toJSON(), opts) - }; -} catch (e) {} - -function BadKeyError (key) { - throw Object.assign(new Error( - `invalid config key requested: ${key}` - ), {code: 'EBADKEY'}) -} - -function pudGet (pud, key, validate) { - let spec = pud.__specs[key]; - if (validate && !spec && (!pud.__opts.other || !pud.__opts.other(key))) { - BadKeyError(key); - } else { - if (!spec) { spec = {}; } - let ret; - for (let p of pud.__providers) { - ret = tryGet(key, p); - if (ret === undefined && spec.aliases && spec.aliases.length) { - for (let alias of spec.aliases) { - if (alias === key) { continue } - ret = tryGet(alias, p); - if (ret !== undefined) { - break - } - } - } - if (ret !== undefined) { - break - } - } - if (ret === undefined && spec.default !== undefined) { - if (typeof spec.default === 'function') { - return spec.default(pud) - } else { - return spec.default - } - } else { - return ret - } - } -} - -function tryGet (key, p) { - let ret; - if (p.__isFiggyPudding) { - ret = pudGet(p, key, false); - } else if (typeof p.get === 'function') { - ret = p.get(key); - } else { - ret = p[key]; - } - return ret -} - -const proxyHandler = { - has (obj, prop) { - return prop in obj.__specs && pudGet(obj, prop, false) !== undefined - }, - ownKeys (obj) { - return Object.keys(obj.__specs) - }, - get (obj, prop) { - if ( - typeof prop === 'symbol' || - prop.slice(0, 2) === '__' || - prop in FiggyPudding.prototype - ) { - return obj[prop] - } - return obj.get(prop) - }, - set (obj, prop, value) { - if ( - typeof prop === 'symbol' || - prop.slice(0, 2) === '__' - ) { - obj[prop] = value; - return true - } else { - throw new Error('figgyPudding options cannot be modified. Use .concat() instead.') - } - }, - deleteProperty () { - throw new Error('figgyPudding options cannot be deleted. Use .concat() and shadow them instead.') - } -}; - -var figgyPudding_1 = figgyPudding$1; -function figgyPudding$1 (specs, opts) { - function factory (...providers) { - return new Proxy(new FiggyPudding( - specs, - opts, - providers - ), proxyHandler) - } - return factory -} - -function reverse (arr) { - const ret = []; - arr.forEach(x => ret.unshift(x)); - return ret -} - -function entries (obj) { - return Object.keys(obj).map(k => [k, obj[k]]) -} - -var findUp$1 = {exports: {}}; - -var locatePath$1 = {exports: {}}; - -var pathExists$1 = {exports: {}}; - -const fs$5 = require$$0$3; - -pathExists$1.exports = fp => new Promise(resolve => { - fs$5.access(fp, err => { - resolve(!err); - }); -}); - -pathExists$1.exports.sync = fp => { - try { - fs$5.accessSync(fp); - return true; - } catch (err) { - return false; - } -}; - -var pLimit$2 = {exports: {}}; - -var pTry$2 = {exports: {}}; - -const pTry$1 = (fn, ...arguments_) => new Promise(resolve => { - resolve(fn(...arguments_)); -}); - -pTry$2.exports = pTry$1; -// TODO: remove this in the next major version -pTry$2.exports.default = pTry$1; - -const pTry = pTry$2.exports; - -const pLimit$1 = concurrency => { - if (!((Number.isInteger(concurrency) || concurrency === Infinity) && concurrency > 0)) { - return Promise.reject(new TypeError('Expected `concurrency` to be a number from 1 and up')); - } - - const queue = []; - let activeCount = 0; - - const next = () => { - activeCount--; - - if (queue.length > 0) { - queue.shift()(); - } - }; - - const run = (fn, resolve, ...args) => { - activeCount++; - - const result = pTry(fn, ...args); - - resolve(result); - - result.then(next, next); - }; - - const enqueue = (fn, resolve, ...args) => { - if (activeCount < concurrency) { - run(fn, resolve, ...args); - } else { - queue.push(run.bind(null, fn, resolve, ...args)); - } - }; - - const generator = (fn, ...args) => new Promise(resolve => enqueue(fn, resolve, ...args)); - Object.defineProperties(generator, { - activeCount: { - get: () => activeCount - }, - pendingCount: { - get: () => queue.length - }, - clearQueue: { - value: () => { - queue.length = 0; - } - } - }); - - return generator; -}; - -pLimit$2.exports = pLimit$1; -pLimit$2.exports.default = pLimit$1; - -const pLimit = pLimit$2.exports; - -class EndError extends Error { - constructor(value) { - super(); - this.value = value; - } -} - -// The input can also be a promise, so we `Promise.resolve()` it -const testElement = (el, tester) => Promise.resolve(el).then(tester); - -// The input can also be a promise, so we `Promise.all()` them both -const finder$1 = el => Promise.all(el).then(val => val[1] === true && Promise.reject(new EndError(val[0]))); - -var pLocate$1 = (iterable, tester, opts) => { - opts = Object.assign({ - concurrency: Infinity, - preserveOrder: true - }, opts); - - const limit = pLimit(opts.concurrency); - - // Start all the promises concurrently with optional limit - const items = [...iterable].map(el => [el, limit(testElement, el, tester)]); - - // Check the promises either serially or concurrently - const checkLimit = pLimit(opts.preserveOrder ? 1 : Infinity); - - return Promise.all(items.map(el => checkLimit(finder$1, el))) - .then(() => {}) - .catch(err => err instanceof EndError ? err.value : Promise.reject(err)); -}; - -const path$7 = path$b; -const pathExists = pathExists$1.exports; -const pLocate = pLocate$1; - -locatePath$1.exports = (iterable, options) => { - options = Object.assign({ - cwd: process.cwd() - }, options); - - return pLocate(iterable, el => pathExists(path$7.resolve(options.cwd, el)), options); -}; - -locatePath$1.exports.sync = (iterable, options) => { - options = Object.assign({ - cwd: process.cwd() - }, options); - - for (const el of iterable) { - if (pathExists.sync(path$7.resolve(options.cwd, el))) { - return el; - } - } -}; - -const path$6 = path$b; -const locatePath = locatePath$1.exports; - -findUp$1.exports = (filename, opts = {}) => { - const startDir = path$6.resolve(opts.cwd || ''); - const {root} = path$6.parse(startDir); - - const filenames = [].concat(filename); - - return new Promise(resolve => { - (function find(dir) { - locatePath(filenames, {cwd: dir}).then(file => { - if (file) { - resolve(path$6.join(dir, file)); - } else if (dir === root) { - resolve(null); - } else { - find(path$6.dirname(dir)); - } - }); - })(startDir); - }); -}; - -findUp$1.exports.sync = (filename, opts = {}) => { - let dir = path$6.resolve(opts.cwd || ''); - const {root} = path$6.parse(dir); - - const filenames = [].concat(filename); - - // eslint-disable-next-line no-constant-condition - while (true) { - const file = locatePath.sync(filenames, {cwd: dir}); - - if (file) { - return path$6.join(dir, file); - } - - if (dir === root) { - return null; - } - - dir = path$6.dirname(dir); - } -}; - -var ini$1 = {}; - -ini$1.parse = ini$1.decode = decode$1; - -ini$1.stringify = ini$1.encode = encode$1; - -ini$1.safe = safe$1; -ini$1.unsafe = unsafe$1; - -var eol$1 = typeof process !== 'undefined' && - process.platform === 'win32' ? '\r\n' : '\n'; - -function encode$1 (obj, opt) { - var children = []; - var out = ''; - - if (typeof opt === 'string') { - opt = { - section: opt, - whitespace: false, - }; - } else { - opt = opt || {}; - opt.whitespace = opt.whitespace === true; - } - - var separator = opt.whitespace ? ' = ' : '='; - - Object.keys(obj).forEach(function (k, _, __) { - var val = obj[k]; - if (val && Array.isArray(val)) { - val.forEach(function (item) { - out += safe$1(k + '[]') + separator + safe$1(item) + '\n'; - }); - } else if (val && typeof val === 'object') - children.push(k); - else - out += safe$1(k) + separator + safe$1(val) + eol$1; - }); - - if (opt.section && out.length) - out = '[' + safe$1(opt.section) + ']' + eol$1 + out; - - children.forEach(function (k, _, __) { - var nk = dotSplit(k).join('\\.'); - var section = (opt.section ? opt.section + '.' : '') + nk; - var child = encode$1(obj[k], { - section: section, - whitespace: opt.whitespace, - }); - if (out.length && child.length) - out += eol$1; - - out += child; - }); - - return out -} - -function dotSplit (str) { - return str.replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002') - .replace(/\\\./g, '\u0001') - .split(/\./).map(function (part) { - return part.replace(/\1/g, '\\.') - .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001') - }) -} - -function decode$1 (str) { - var out = {}; - var p = out; - var section = null; - // section |key = value - var re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i; - var lines = str.split(/[\r\n]+/g); - - lines.forEach(function (line, _, __) { - if (!line || line.match(/^\s*[;#]/)) - return - var match = line.match(re); - if (!match) - return - if (match[1] !== undefined) { - section = unsafe$1(match[1]); - if (section === '__proto__') { - // not allowed - // keep parsing the section, but don't attach it. - p = {}; - return - } - p = out[section] = out[section] || {}; - return - } - var key = unsafe$1(match[2]); - if (key === '__proto__') - return - var value = match[3] ? unsafe$1(match[4]) : true; - switch (value) { - case 'true': - case 'false': - case 'null': value = JSON.parse(value); - } - - // Convert keys with '[]' suffix to an array - if (key.length > 2 && key.slice(-2) === '[]') { - key = key.substring(0, key.length - 2); - if (key === '__proto__') - return - if (!p[key]) - p[key] = []; - else if (!Array.isArray(p[key])) - p[key] = [p[key]]; - } - - // safeguard against resetting a previously defined - // array by accidentally forgetting the brackets - if (Array.isArray(p[key])) - p[key].push(value); - else - p[key] = value; - }); - - // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}} - // use a filter to return the keys that have to be deleted. - Object.keys(out).filter(function (k, _, __) { - if (!out[k] || - typeof out[k] !== 'object' || - Array.isArray(out[k])) - return false - - // see if the parent section is also an object. - // if so, add it to that, and mark this one for deletion - var parts = dotSplit(k); - var p = out; - var l = parts.pop(); - var nl = l.replace(/\\\./g, '.'); - parts.forEach(function (part, _, __) { - if (part === '__proto__') - return - if (!p[part] || typeof p[part] !== 'object') - p[part] = {}; - p = p[part]; - }); - if (p === out && nl === l) - return false - - p[nl] = out[k]; - return true - }).forEach(function (del, _, __) { - delete out[del]; - }); - - return out -} - -function isQuoted (val) { - return (val.charAt(0) === '"' && val.slice(-1) === '"') || - (val.charAt(0) === "'" && val.slice(-1) === "'") -} - -function safe$1 (val) { - return (typeof val !== 'string' || - val.match(/[=\r\n]/) || - val.match(/^\[/) || - (val.length > 1 && - isQuoted(val)) || - val !== val.trim()) - ? JSON.stringify(val) - : val.replace(/;/g, '\\;').replace(/#/g, '\\#') -} - -function unsafe$1 (val, doUnesc) { - val = (val || '').trim(); - if (isQuoted(val)) { - // remove the single quotes before calling JSON.parse - if (val.charAt(0) === "'") - val = val.substr(1, val.length - 2); - - try { - val = JSON.parse(val); - } catch (_) {} - } else { - // walk the val to find the first not-escaped ; character - var esc = false; - var unesc = ''; - for (var i = 0, l = val.length; i < l; i++) { - var c = val.charAt(i); - if (esc) { - if ('\\;#'.indexOf(c) !== -1) - unesc += c; - else - unesc += '\\' + c; - - esc = false; - } else if (';#'.indexOf(c) !== -1) - break - else if (c === '\\') - esc = true; - else - unesc += c; - } - if (esc) - unesc += '\\'; - - return unesc.trim() - } - return val -} - -const fs$4 = require$$0$3; -const figgyPudding = figgyPudding_1; -const findUp = findUp$1.exports; -const ini = ini$1; -const os = require$$0$2; -const path$5 = path$b; - -const NpmConfig = figgyPudding({}, { - // Open up the pudding object. - other () { return true } -}); - -const ConfigOpts = figgyPudding({ - cache: { default: path$5.join(os.homedir(), '.npm') }, - configNames: { default: ['npmrc', '.npmrc'] }, - envPrefix: { default: /^npm_config_/i }, - cwd: { default: () => process.cwd() }, - globalconfig: { - default: () => path$5.join(getGlobalPrefix(), 'etc', 'npmrc') - }, - userconfig: { default: path$5.join(os.homedir(), '.npmrc') } -}); - -libnpmconfig.read = getNpmConfig; -function getNpmConfig (_opts, _builtin) { - const builtin = ConfigOpts(_builtin); - const env = {}; - for (let key of Object.keys(process.env)) { - if (!key.match(builtin.envPrefix)) continue - const newKey = key.toLowerCase() - .replace(builtin.envPrefix, '') - .replace(/(?!^)_/g, '-'); - env[newKey] = process.env[key]; - } - const cli = NpmConfig(_opts); - const userConfPath = ( - builtin.userconfig || - cli.userconfig || - env.userconfig - ); - const user = userConfPath && maybeReadIni(userConfPath); - const globalConfPath = ( - builtin.globalconfig || - cli.globalconfig || - env.globalconfig - ); - const global = globalConfPath && maybeReadIni(globalConfPath); - const projConfPath = findUp.sync(builtin.configNames, { cwd: builtin.cwd }); - let proj = {}; - if (projConfPath && projConfPath !== userConfPath) { - proj = maybeReadIni(projConfPath); - } - const newOpts = NpmConfig(builtin, global, user, proj, env, cli); - if (newOpts.cache) { - return newOpts.concat({ - cache: path$5.resolve( - ( - (cli.cache || env.cache) - ? builtin.cwd - : proj.cache - ? path$5.dirname(projConfPath) - : user.cache - ? path$5.dirname(userConfPath) - : global.cache - ? path$5.dirname(globalConfPath) - : path$5.dirname(userConfPath) - ), - newOpts.cache - ) - }) - } else { - return newOpts - } -} - -function maybeReadIni (f) { - let txt; - try { - txt = fs$4.readFileSync(f, 'utf8'); - } catch (err) { - if (err.code === 'ENOENT') { - return '' - } else { - throw err - } - } - return ini.parse(txt) -} - -function getGlobalPrefix () { - if (process.env.PREFIX) { - return process.env.PREFIX - } else if (process.platform === 'win32') { - // c:\node\node.exe --> prefix=c:\node\ - return path$5.dirname(process.execPath) - } else { - // /usr/local/bin/node --> prefix=/usr/local - let pref = path$5.dirname(path$5.dirname(process.execPath)); - // destdir only is respected on Unix - if (process.env.DESTDIR) { - pref = path$5.join(process.env.DESTDIR, pref); - } - return pref - } -} - -/** - * @typedef ResolveOptions - * @property {string} [prefix] - * @property {string|string[]} [cwd] - * @property {boolean} [global] - */ - -const electron = process.versions.electron !== undefined; -const windows = process.platform === 'win32'; - -const argv = process.argv[1] || /* c8 ignore next */ ''; -const nvm = process.env.NVM_BIN; -const appData = process.env.APPDATA; - -/* c8 ignore next */ -const globalsLibrary = windows ? '' : 'lib'; - -/** @type {{prefix?: string}} */ -let builtinNpmConfig; - -// The prefix config defaults to the location where node is installed. -// On Windows, this is in a place called `%AppData%`, which we have to -// pass to `libnpmconfig` explicitly: -/* c8 ignore next 4 */ -if (windows && appData) { - builtinNpmConfig = {prefix: path$b.join(appData, 'npm')}; -} - -/** - * Note: `libnpmconfig` uses `figgy-pudding` which is slated for archival. - * Either `libnpmconfig` will switch to an alternative or we’ll have to. - * @type {string} - */ -let npmPrefix = libnpmconfig.read(null, builtinNpmConfig).prefix; - -// If there is no prefix defined, use the defaults -// See: -/* c8 ignore next 5 */ -if (!npmPrefix) { - npmPrefix = windows - ? path$b.dirname(process.execPath) - : path$b.resolve(process.execPath, '../..'); -} - -const globalsDefault = electron || argv.indexOf(npmPrefix) === 0; -let globalDir = path$b.resolve(npmPrefix, globalsLibrary, 'node_modules'); - -// If we’re in Electron, we’re running in a modified Node that cannot really -// install global node modules. -// To find the actual modules, the user has to set `prefix` somewhere in an -// `.npmrc` (which is picked up by `libnpmconfig`). -// Most people don’t do that, and some use NVM instead to manage different -// versions of Node. -// Luckily NVM leaks some environment variables that we can pick up on to try -// and detect the actual modules. -/* c8 ignore next 3 */ -if (electron && nvm && !require$$0$3.existsSync(globalDir)) { - globalDir = path$b.resolve(nvm, '..', globalsLibrary, 'node_modules'); -} - -/** - * Load the plugin found using `resolvePlugin`. - * - * @param {string} name The name to import. - * @param {LoadOptions} [options] - * @returns {Promise} - */ -async function loadPlugin(name, options = {}) { - const {key = 'default', ...rest} = options; - const fp = await resolvePlugin(name, rest); - /** @type {Object.} */ - // Bug with coverage on Node@12. - /* c8 ignore next 3 */ - const mod = await import(pathToFileURL(fp).href); - return key === false ? mod : mod[key] -} - -/** - * Find a plugin. - * - * See also: - * * https://docs.npmjs.com/files/folders#node-modules - * * https://github.com/sindresorhus/resolve-from - * - * Uses the standard node module loading strategy to find `$name` in each given - * `cwd` (and optionally the global `node_modules` directory). - * - * If a prefix is given and `$name` is not a path, `$prefix-$name` is also - * searched (preferring these over non-prefixed modules). - * - * @param {string} name - * @param {ResolveOptions} [options] - * @returns {Promise.} - */ -async function resolvePlugin(name, options = {}) { - const prefix = options.prefix - ? options.prefix + - (options.prefix.charAt(options.prefix.length - 1) === '-' ? '' : '-') - : undefined; - const cwd = options.cwd; - const globals = - options.global === undefined || options.global === null - ? globalsDefault - : options.global; - const sources = Array.isArray(cwd) ? cwd.concat() : [cwd || process.cwd()]; - /** @type {string} */ - let plugin; - /** @type {Error} */ - let lastError; - - // Non-path. - if (name.charAt(0) !== '.') { - if (globals) { - sources.push(globalDir); - } - - let scope = ''; - - // Unprefix module. - if (prefix) { - // Scope? - if (name.charAt(0) === '@') { - const slash = name.indexOf('/'); - - // Let’s keep the algorithm simple. - // No need to care if this is a “valid” scope (I think?). - // But we do check for the slash. - if (slash !== -1) { - scope = name.slice(0, slash + 1); - name = name.slice(slash + 1); - } - } - - if (name.slice(0, prefix.length) !== prefix) { - plugin = scope + prefix + name; - } - - name = scope + name; - } - } - - let index = -1; - /** @type {string} */ - let fp; - - while (++index < sources.length) { - fp = plugin && (await attempt(sources[index], plugin)); - if (fp) return fp - - fp = await attempt(sources[index], name); - if (fp) return fp - } - - // There’s always an error. - // Bug with coverage on Node@12. - /* c8 ignore next 8 */ - throw lastError - - /** - * @param {string} base - * @param {string} name - * @returns {Promise} - */ - async function attempt(base, name) { - try { - // `import-meta-resolve` resolves from files, whereas `load-plugin` works - // on folders, which is why we add a `/` at the end. - return fileURLToPath( - await resolve(name, pathToFileURL(base).href + '/') - ) - // Bug with coverage on Node@12. - /* c8 ignore next 1 */ - } catch (error) { - lastError = error; - } - } -} - -function isPlainObject$1(value) { - if (Object.prototype.toString.call(value) !== '[object Object]') { - return false; - } - - const prototype = Object.getPrototypeOf(value); - return prototype === null || prototype === Object.prototype; -} - -var format$1 = {exports: {}}; - -(function (module) { -(function() { - - //// Export the API - var namespace; - - // CommonJS / Node module - { - namespace = module.exports = format; - } - - namespace.format = format; - namespace.vsprintf = vsprintf; - - if (typeof console !== 'undefined' && typeof console.log === 'function') { - namespace.printf = printf; - } - - function printf(/* ... */) { - console.log(format.apply(null, arguments)); - } - - function vsprintf(fmt, replacements) { - return format.apply(null, [fmt].concat(replacements)); - } - - function format(fmt) { - var argIndex = 1 // skip initial format argument - , args = [].slice.call(arguments) - , i = 0 - , n = fmt.length - , result = '' - , c - , escaped = false - , arg - , tmp - , leadingZero = false - , precision - , nextArg = function() { return args[argIndex++]; } - , slurpNumber = function() { - var digits = ''; - while (/\d/.test(fmt[i])) { - digits += fmt[i++]; - c = fmt[i]; - } - return digits.length > 0 ? parseInt(digits) : null; - } - ; - for (; i < n; ++i) { - c = fmt[i]; - if (escaped) { - escaped = false; - if (c == '.') { - leadingZero = false; - c = fmt[++i]; - } - else if (c == '0' && fmt[i + 1] == '.') { - leadingZero = true; - i += 2; - c = fmt[i]; - } - else { - leadingZero = true; - } - precision = slurpNumber(); - switch (c) { - case 'b': // number in binary - result += parseInt(nextArg(), 10).toString(2); - break; - case 'c': // character - arg = nextArg(); - if (typeof arg === 'string' || arg instanceof String) - result += arg; - else - result += String.fromCharCode(parseInt(arg, 10)); - break; - case 'd': // number in decimal - result += parseInt(nextArg(), 10); - break; - case 'f': // floating point number - tmp = String(parseFloat(nextArg()).toFixed(precision || 6)); - result += leadingZero ? tmp : tmp.replace(/^0/, ''); - break; - case 'j': // JSON - result += JSON.stringify(nextArg()); - break; - case 'o': // number in octal - result += '0' + parseInt(nextArg(), 10).toString(8); - break; - case 's': // string - result += nextArg(); - break; - case 'x': // lowercase hexadecimal - result += '0x' + parseInt(nextArg(), 10).toString(16); - break; - case 'X': // uppercase hexadecimal - result += '0x' + parseInt(nextArg(), 10).toString(16).toUpperCase(); - break; - default: - result += c; - break; - } - } else if (c === '%') { - escaped = true; - } else { - result += c; - } - } - return result; - } - -}()); -}(format$1)); - -var formatter = format$1.exports; - -// @ts-ignore - -var fault = Object.assign(create$1(Error), { - eval: create$1(EvalError), - range: create$1(RangeError), - reference: create$1(ReferenceError), - syntax: create$1(SyntaxError), - type: create$1(TypeError), - uri: create$1(URIError) -}); - -/** - * Create a new `EConstructor`, with the formatted `format` as a first argument. - * - * @template {Error} Fault - * @template {new (reason: string) => Fault} Class - * @param {Class} Constructor - */ -function create$1(Constructor) { - /** @type {string} */ - // @ts-ignore - FormattedError.displayName = Constructor.displayName || Constructor.name; - - return FormattedError - - /** - * @param {string} [format] - * @param {...unknown} values - * @returns {Fault} - */ - function FormattedError(format, ...values) { - /** @type {string} */ - var reason = format ? formatter(format, ...values) : format; - return new Constructor(reason) - } -} - -const debug$b = createDebug('unified-engine:find-up'); - -/** - * @template Value - */ -class FindUp { - /** - * @callback Create - * @param {Buffer} buf - * @param {string} filePath - * @returns {Promise|Value|undefined} - */ - - /** - * @callback Callback - * @param {Error|null} error - * @param {Value} [result] - * @returns {void} - */ - - /** - * @typedef Options - * @property {string} cwd - * @property {string|undefined} filePath - * @property {boolean|undefined} [detect] - * @property {string[]} names - * @property {Create} create - */ - - /** - * @param {Options} options - */ - constructor(options) { - /** @type {Record} */ - this.cache = {}; - /** @type {string} */ - this.cwd = options.cwd; - /** @type {boolean|undefined} */ - this.detect = options.detect; - /** @type {string[]} */ - this.names = options.names; - /** @type {Create} */ - this.create = options.create; - - /** @type {string|undefined} */ - this.givenFilePath = options.filePath - ? path$c.resolve(options.cwd, options.filePath) - : undefined; - - /* eslint-disable no-unused-expressions */ - /** @type {Error|Value|Callback[]|undefined} */ - this.givenFile; - /* eslint-enable no-unused-expressions */ - } - - /** - * @param {string} filePath - * @param {Callback} callback - */ - load(filePath, callback) { - const self = this; - const givenFile = this.givenFile; - const {givenFilePath} = this; - - if (givenFilePath) { - if (givenFile) { - apply(callback, givenFile); - } else { - const cbs = [callback]; - this.givenFile = cbs; - debug$b('Checking given file `%s`', givenFilePath); - fs$a.readFile(givenFilePath, (error, buf) => { - if (error) { - /** @type {NodeJS.ErrnoException} */ - const result = fault( - 'Cannot read given file `%s`\n%s', - path$c.relative(this.cwd, givenFilePath), - error.stack - ); - result.code = 'ENOENT'; - result.path = error.path; - result.syscall = error.syscall; - loaded(result); - } else { - wrap(this.create, (error, /** @type {Value} */ result) => { - if (error) { - debug$b(error.message); - loaded( - fault( - 'Cannot parse given file `%s`\n%s', - path$c.relative(this.cwd, givenFilePath), - error.stack - ) - ); - } else { - debug$b('Read given file `%s`', givenFilePath); - loaded(result); - } - })(buf, givenFilePath); - } - - /** @param {Error|Value} result */ - function loaded(result) { - self.givenFile = result; - applyAll(cbs, result); - } - }); - } - - return - } - - if (!this.detect) { - return callback(null) - } - - filePath = path$c.resolve(this.cwd, filePath); - const parent = path$c.dirname(filePath); - - if (parent in this.cache) { - apply(callback, this.cache[parent]); - } else { - this.cache[parent] = [callback]; - find(parent); - } - - /** - * @param {string} directory - */ - function find(directory) { - let index = -1; - - next(); - - function next() { - // Try to read the next file. - // We do not use `readdir` because on huge directories, that could be - // *very* slow. - if (++index < self.names.length) { - fs$a.readFile(path$c.join(directory, self.names[index]), done); - } else { - const parent = path$c.dirname(directory); - - if (directory === parent) { - debug$b('No files found for `%s`', filePath); - found(null); - } else if (parent in self.cache) { - apply(found, self.cache[parent]); - } else { - self.cache[parent] = [found]; - find(parent); - } - } - } - - /** - * @param {NodeJS.ErrnoException|null} error - * @param {Buffer} [buf] - * @returns {void} - */ - function done(error, buf) { - const fp = path$c.join(directory, self.names[index]); - - if (error) { - // Hard to test. - /* c8 ignore next 13 */ - if (error.code === 'ENOENT') { - return next() - } - - debug$b(error.message); - return found( - fault( - 'Cannot read file `%s`\n%s', - path$c.relative(self.cwd, fp), - error.message - ) - ) - } - - wrap(self.create, (error, /** @type {Value} */ result) => { - if (error) { - found( - fault( - 'Cannot parse file `%s`\n%s', - path$c.relative(self.cwd, fp), - error.message - ) - ); - } else if (result) { - debug$b('Read file `%s`', fp); - found(null, result); - } else { - next(); - } - })(buf, fp); - } - - /** - * @param {Error|null} error - * @param {Value} [result] - * @returns {void} - */ - function found(error, result) { - /** @type {Callback[]} */ - // @ts-expect-error: always a list if found. - const cbs = self.cache[directory]; - self.cache[directory] = error || result; - applyAll(cbs, error || result); - } - } - - /** - * @param {Callback[]} cbs - * @param {Value|Error|undefined} result - */ - function applyAll(cbs, result) { - let index = cbs.length; - - while (index--) { - apply(cbs[index], result); - } - } - - /** - * @param {Callback} cb - * @param {Value|Error|Callback[]|undefined} result - */ - function apply(cb, result) { - if (Array.isArray(result)) { - result.push(cb); - } else if (result instanceof Error) { - cb(result); - } else { - cb(null, result); - } - } - } -} - -/** - * @typedef {import('unified').Plugin} Plugin - * @typedef {import('unified').PluginTuple} PluginTuple - * @typedef {import('unified').PluggableList} PluggableList - * - * @typedef {Record} Settings - * - * @typedef {Record} PluginIdObject - * @typedef {Array} PluginIdList - * - * @typedef Preset - * @property {Settings} [settings] - * @property {PluggableList|PluginIdObject|PluginIdList|undefined} [plugins] - * - * @typedef Config - * @property {Settings} [settings] - * @property {Array} [plugins] - * - * @callback ConfigTransform - * @param {any} config - * @param {string} filePath - * @returns {Preset} - * - * @callback Loader - * @param {Buffer} buf - * @param {string} filePath - * @returns {Promise} - * - * @callback Callback - * @param {Error|null} error - * @param {Config} [result] - * @returns {void} - */ - -const debug$a = createDebug('unified-engine:configuration'); - -const own$c = {}.hasOwnProperty; - -/** @type {Record} */ -const loaders = { - '.json': loadJson, - '.cjs': loadScriptOrModule, - '.mjs': loadScriptOrModule, - '.js': loadScriptOrModule, - '.yaml': loadYaml, - '.yml': loadYaml -}; - -const defaultLoader = loadJson; - -/** - * @typedef Options - * @property {string} cwd - * @property {string} [packageField] - * @property {string} [pluginPrefix] - * @property {string} [rcName] - * @property {string} [rcPath] - * @property {boolean} [detectConfig] - * @property {ConfigTransform} [configTransform] - * @property {Preset} [defaultConfig] - * @property {Preset['settings']} [settings] - * @property {Preset['plugins']} [plugins] - */ - -class Configuration { - /** - * @param {Options} options - */ - constructor(options) { - /** @type {string[]} */ - const names = []; - - /** @type {string} */ - this.cwd = options.cwd; - /** @type {string|undefined} */ - this.packageField = options.packageField; - /** @type {string|undefined} */ - this.pluginPrefix = options.pluginPrefix; - /** @type {ConfigTransform|undefined} */ - this.configTransform = options.configTransform; - /** @type {Preset|undefined} */ - this.defaultConfig = options.defaultConfig; - - if (options.rcName) { - names.push( - options.rcName, - ...Object.keys(loaders).map((d) => options.rcName + d) - ); - debug$a('Looking for `%s` configuration files', names); - } - - if (options.packageField) { - names.push('package.json'); - debug$a( - 'Looking for `%s` fields in `package.json` files', - options.packageField - ); - } - - /** @type {Preset} */ - this.given = {settings: options.settings, plugins: options.plugins}; - this.create = this.create.bind(this); - - /** @type {FindUp} */ - this.findUp = new FindUp({ - cwd: options.cwd, - filePath: options.rcPath, - detect: options.detectConfig, - names, - create: this.create - }); - } - - /** - * @param {string} filePath - * @param {Callback} callback - * @returns {void} - */ - load(filePath, callback) { - this.findUp.load( - filePath || path$c.resolve(this.cwd, 'stdin.js'), - (error, file) => { - if (error || file) { - return callback(error, file) - } - - this.create(undefined, undefined).then((result) => { - callback(null, result); - }, callback); - } - ); - } - - /** - * @param {Buffer|undefined} buf - * @param {string|undefined} filePath - * @returns {Promise} - */ - async create(buf, filePath) { - const options = {prefix: this.pluginPrefix, cwd: this.cwd}; - const result = {settings: {}, plugins: []}; - const extname = filePath ? path$c.extname(filePath) : undefined; - const loader = - extname && extname in loaders ? loaders[extname] : defaultLoader; - /** @type {Preset|undefined} */ - let value; - - if (filePath && buf) { - value = await loader.call(this, buf, filePath); - - if (this.configTransform && value !== undefined) { - value = this.configTransform(value, filePath); - } - } - - // Exit if we did find a `package.json`, but it does not have configuration. - if ( - filePath && - value === undefined && - path$c.basename(filePath) === 'package.json' - ) { - return - } - - if (value === undefined) { - if (this.defaultConfig) { - await merge( - result, - this.defaultConfig, - Object.assign({}, options, {root: this.cwd}) - ); - } - } else { - await merge( - result, - value, - // @ts-expect-error: `value` can only exist if w/ `filePath`. - Object.assign({}, options, {root: path$c.dirname(filePath)}) - ); - } - - await merge( - result, - this.given, - Object.assign({}, options, {root: this.cwd}) - ); - - // C8 bug on Node@12 - /* c8 ignore next 2 */ - return result - } -} - -/** @type {Loader} */ -async function loadScriptOrModule(_, filePath) { - // C8 bug on Node@12 - /* c8 ignore next 4 */ - // @ts-expect-error: Assume it matches config. - // type-coverage:ignore-next-line - return loadFromAbsolutePath(filePath, this.cwd) -} - -/** @type {Loader} */ -async function loadYaml(buf, filePath) { - // C8 bug on Node@12 - /* c8 ignore next 4 */ - // @ts-expect-error: Assume it matches config. - return jsYaml.load(String(buf), {filename: path$c.basename(filePath)}) -} - -/** @type {Loader} */ -async function loadJson(buf, filePath) { - /** @type {Record} */ - const result = parseJson_1(String(buf), filePath); - - // C8 bug on Node@12 - /* c8 ignore next 8 */ - // @ts-expect-error: Assume it matches config. - return path$c.basename(filePath) === 'package.json' - ? // @ts-expect-error: `this` is the configuration context, TS doesn’t like - // `this` on callbacks. - // type-coverage:ignore-next-line - result[this.packageField] - : result -} - -/** - * @param {Required} target - * @param {Preset} raw - * @param {{root: string, prefix: string|undefined}} options - * @returns {Promise} - */ -async function merge(target, raw, options) { - if (typeof raw === 'object' && raw !== null) { - await addPreset(raw); - } else { - throw new Error('Expected preset, not `' + raw + '`') - } - - // C8 bug on Node@12 - /* c8 ignore next 6 */ - return target - - /** - * @param {Preset} result - */ - async function addPreset(result) { - const plugins = result.plugins; - - if (plugins === null || plugins === undefined) ; else if (typeof plugins === 'object' && plugins !== null) { - await (Array.isArray(plugins) ? addEach(plugins) : addIn(plugins)); - } else { - throw new Error( - 'Expected a list or object of plugins, not `' + plugins + '`' - ) - } - - target.settings = Object.assign({}, target.settings, result.settings); - // C8 bug on Node@12 - /* c8 ignore next 6 */ - } - - /** - * @param {PluginIdList|PluggableList} result - */ - async function addEach(result) { - let index = -1; - - while (++index < result.length) { - const value = result[index]; - - // Keep order sequential instead of parallel. - /* eslint-disable no-await-in-loop */ - // @ts-expect-error: Spreading is fine. - // type-coverage:ignore-next-line - await (Array.isArray(value) ? use(...value) : use(value, undefined)); - /* eslint-enable no-await-in-loop */ - } - // C8 bug on Node@12 - /* c8 ignore next 6 */ - } - - /** - * @param {PluginIdObject} result - */ - async function addIn(result) { - /** @type {string} */ - let key; - - for (key in result) { - if (own$c.call(result, key)) { - // Keep order sequential instead of parallel. - // eslint-disable-next-line no-await-in-loop - await use(key, result[key]); - } - } - // C8 bug on Node@12 - /* c8 ignore next 7 */ - } - - /** - * @param {string|Plugin|Preset} usable - * @param {Settings|null|undefined} value - */ - async function use(usable, value) { - if (typeof usable === 'string') { - await addModule(usable, value); - } else if (typeof usable === 'function') { - addPlugin(usable, value); - } else { - await merge(target, usable, options); - } - // C8 bug on Node@12 - /* c8 ignore next 7 */ - } - - /** - * @param {string} id - * @param {Settings|null|undefined} value - */ - async function addModule(id, value) { - /** @type {string} */ - let fp; - - try { - fp = await resolvePlugin(id, { - cwd: options.root, - prefix: options.prefix - }); - } catch (error) { - addPlugin(() => { - throw fault('Could not find module `%s`\n%s', id, error.stack) - }, value); - return - } - - const result = await loadFromAbsolutePath(fp, options.root); - - try { - if (typeof result === 'function') { - addPlugin(result, value); - } else { - await merge( - target, - result, - Object.assign({}, options, {root: path$c.dirname(fp)}) - ); - } - } catch { - throw fault( - 'Error: Expected preset or plugin, not %s, at `%s`', - result, - path$c.relative(options.root, fp) - ) - } - // C8 bug on Node@12 - /* c8 ignore next 8 */ - } - - /** - * @param {Plugin} plugin - * @param {Settings|null|undefined} value - * @returns {void} - */ - function addPlugin(plugin, value) { - const entry = find(target.plugins, plugin); - - if (value === null) { - value = undefined; - } - - if (entry) { - reconfigure(entry, value); - } else { - target.plugins.push([plugin, value]); - } - } -} - -/** - * @param {PluginTuple} entry - * @param {Settings|undefined} value - * @returns {void} - */ -function reconfigure(entry, value) { - if (isPlainObject$1(entry[1]) && isPlainObject$1(value)) { - value = Object.assign({}, entry[1], value); - } - - entry[1] = value; -} - -/** - * @param {Array} entries - * @param {Plugin} plugin - * @returns {PluginTuple|undefined} - */ -function find(entries, plugin) { - let index = -1; - - while (++index < entries.length) { - const entry = entries[index]; - if (entry[0] === plugin) { - return entry - } - } -} - -/** - * @param {string} fp - * @param {string} base - * @returns {Promise} - */ -async function loadFromAbsolutePath(fp, base) { - try { - /** @type {{default?: unknown}} */ - const result = await import(pathToFileURL$1(fp).href); - - if (!('default' in result)) { - throw new Error( - 'Expected a plugin or preset exported as the default export' - ) - } - - // @ts-expect-error: assume plugin/preset. - return result.default - // C8 bug on Node@12 - /* c8 ignore next 4 */ - } catch (error) { - throw fault('Cannot import `%s`\n%s', path$c.relative(base, fp), error.stack) - } -} - -/** - * @typedef {import('./index.js').Settings} Settings - */ - -/** - * @param {Context} context - * @param {Settings} settings - */ -function configure$3(context, settings) { - context.configuration = new Configuration(settings); -} - -// A simple implementation of make-array -function makeArray (subject) { - return Array.isArray(subject) - ? subject - : [subject] -} - -const EMPTY = ''; -const SPACE = ' '; -const ESCAPE = '\\'; -const REGEX_TEST_BLANK_LINE = /^\s+$/; -const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/; -const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/; -const REGEX_SPLITALL_CRLF = /\r?\n/g; -// /foo, -// ./foo, -// ../foo, -// . -// .. -const REGEX_TEST_INVALID_PATH = /^\.*\/|^\.+$/; - -const SLASH = '/'; -const KEY_IGNORE = typeof Symbol !== 'undefined' - ? Symbol.for('node-ignore') - /* istanbul ignore next */ - : 'node-ignore'; - -const define = (object, key, value) => - Object.defineProperty(object, key, {value}); - -const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g; - -// Sanitize the range of a regular expression -// The cases are complicated, see test cases for details -const sanitizeRange = range => range.replace( - REGEX_REGEXP_RANGE, - (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0) - ? match - // Invalid range (out of order) which is ok for gitignore rules but - // fatal for JavaScript regular expression, so eliminate it. - : EMPTY -); - -// See fixtures #59 -const cleanRangeBackSlash = slashes => { - const {length} = slashes; - return slashes.slice(0, length - length % 2) -}; - -// > If the pattern ends with a slash, -// > it is removed for the purpose of the following description, -// > but it would only find a match with a directory. -// > In other words, foo/ will match a directory foo and paths underneath it, -// > but will not match a regular file or a symbolic link foo -// > (this is consistent with the way how pathspec works in general in Git). -// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`' -// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call -// you could use option `mark: true` with `glob` - -// '`foo/`' should not continue with the '`..`' -const REPLACERS = [ - - // > Trailing spaces are ignored unless they are quoted with backslash ("\") - [ - // (a\ ) -> (a ) - // (a ) -> (a) - // (a \ ) -> (a ) - /\\?\s+$/, - match => match.indexOf('\\') === 0 - ? SPACE - : EMPTY - ], - - // replace (\ ) with ' ' - [ - /\\\s/g, - () => SPACE - ], - - // Escape metacharacters - // which is written down by users but means special for regular expressions. - - // > There are 12 characters with special meanings: - // > - the backslash \, - // > - the caret ^, - // > - the dollar sign $, - // > - the period or dot ., - // > - the vertical bar or pipe symbol |, - // > - the question mark ?, - // > - the asterisk or star *, - // > - the plus sign +, - // > - the opening parenthesis (, - // > - the closing parenthesis ), - // > - and the opening square bracket [, - // > - the opening curly brace {, - // > These special characters are often called "metacharacters". - [ - /[\\$.|*+(){^]/g, - match => `\\${match}` - ], - - [ - // > a question mark (?) matches a single character - /(?!\\)\?/g, - () => '[^/]' - ], - - // leading slash - [ - - // > A leading slash matches the beginning of the pathname. - // > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c". - // A leading slash matches the beginning of the pathname - /^\//, - () => '^' - ], - - // replace special metacharacter slash after the leading slash - [ - /\//g, - () => '\\/' - ], - - [ - // > A leading "**" followed by a slash means match in all directories. - // > For example, "**/foo" matches file or directory "foo" anywhere, - // > the same as pattern "foo". - // > "**/foo/bar" matches file or directory "bar" anywhere that is directly - // > under directory "foo". - // Notice that the '*'s have been replaced as '\\*' - /^\^*\\\*\\\*\\\//, - - // '**/foo' <-> 'foo' - () => '^(?:.*\\/)?' - ], - - // starting - [ - // there will be no leading '/' - // (which has been replaced by section "leading slash") - // If starts with '**', adding a '^' to the regular expression also works - /^(?=[^^])/, - function startingReplacer () { - // If has a slash `/` at the beginning or middle - return !/\/(?!$)/.test(this) - // > Prior to 2.22.1 - // > If the pattern does not contain a slash /, - // > Git treats it as a shell glob pattern - // Actually, if there is only a trailing slash, - // git also treats it as a shell glob pattern - - // After 2.22.1 (compatible but clearer) - // > If there is a separator at the beginning or middle (or both) - // > of the pattern, then the pattern is relative to the directory - // > level of the particular .gitignore file itself. - // > Otherwise the pattern may also match at any level below - // > the .gitignore level. - ? '(?:^|\\/)' - - // > Otherwise, Git treats the pattern as a shell glob suitable for - // > consumption by fnmatch(3) - : '^' - } - ], - - // two globstars - [ - // Use lookahead assertions so that we could match more than one `'/**'` - /\\\/\\\*\\\*(?=\\\/|$)/g, - - // Zero, one or several directories - // should not use '*', or it will be replaced by the next replacer - - // Check if it is not the last `'/**'` - (_, index, str) => index + 6 < str.length - - // case: /**/ - // > A slash followed by two consecutive asterisks then a slash matches - // > zero or more directories. - // > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on. - // '/**/' - ? '(?:\\/[^\\/]+)*' - - // case: /** - // > A trailing `"/**"` matches everything inside. - - // #21: everything inside but it should not include the current folder - : '\\/.+' - ], - - // intermediate wildcards - [ - // Never replace escaped '*' - // ignore rule '\*' will match the path '*' - - // 'abc.*/' -> go - // 'abc.*' -> skip this rule - /(^|[^\\]+)\\\*(?=.+)/g, - - // '*.js' matches '.js' - // '*.js' doesn't match 'abc' - (_, p1) => `${p1}[^\\/]*` - ], - - [ - // unescape, revert step 3 except for back slash - // For example, if a user escape a '\\*', - // after step 3, the result will be '\\\\\\*' - /\\\\\\(?=[$.|*+(){^])/g, - () => ESCAPE - ], - - [ - // '\\\\' -> '\\' - /\\\\/g, - () => ESCAPE - ], - - [ - // > The range notation, e.g. [a-zA-Z], - // > can be used to match one of the characters in a range. - - // `\` is escaped by step 3 - /(\\)?\[([^\]/]*?)(\\*)($|\])/g, - (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE - // '\\[bar]' -> '\\\\[bar\\]' - ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}` - : close === ']' - ? endEscape.length % 2 === 0 - // A normal case, and it is a range notation - // '[bar]' - // '[bar\\\\]' - ? `[${sanitizeRange(range)}${endEscape}]` - // Invalid range notaton - // '[bar\\]' -> '[bar\\\\]' - : '[]' - : '[]' - ], - - // ending - [ - // 'js' will not match 'js.' - // 'ab' will not match 'abc' - /(?:[^*])$/, - - // WTF! - // https://git-scm.com/docs/gitignore - // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1) - // which re-fixes #24, #38 - - // > If there is a separator at the end of the pattern then the pattern - // > will only match directories, otherwise the pattern can match both - // > files and directories. - - // 'js*' will not match 'a.js' - // 'js/' will not match 'a.js' - // 'js' will match 'a.js' and 'a.js/' - match => /\/$/.test(match) - // foo/ will not match 'foo' - ? `${match}$` - // foo matches 'foo' and 'foo/' - : `${match}(?=$|\\/$)` - ], - - // trailing wildcard - [ - /(\^|\\\/)?\\\*$/, - (_, p1) => { - const prefix = p1 - // '\^': - // '/*' does not match EMPTY - // '/*' does not match everything - - // '\\\/': - // 'abc/*' does not match 'abc/' - ? `${p1}[^/]+` - - // 'a*' matches 'a' - // 'a*' matches 'aa' - : '[^/]*'; - - return `${prefix}(?=$|\\/$)` - } - ], -]; - -// A simple cache, because an ignore rule only has only one certain meaning -const regexCache = Object.create(null); - -// @param {pattern} -const makeRegex = (pattern, negative, ignorecase) => { - const r = regexCache[pattern]; - if (r) { - return r - } - - // const replacers = negative - // ? NEGATIVE_REPLACERS - // : POSITIVE_REPLACERS - - const source = REPLACERS.reduce( - (prev, current) => prev.replace(current[0], current[1].bind(pattern)), - pattern - ); - - return regexCache[pattern] = ignorecase - ? new RegExp(source, 'i') - : new RegExp(source) -}; - -const isString = subject => typeof subject === 'string'; - -// > A blank line matches no files, so it can serve as a separator for readability. -const checkPattern = pattern => pattern - && isString(pattern) - && !REGEX_TEST_BLANK_LINE.test(pattern) - - // > A line starting with # serves as a comment. - && pattern.indexOf('#') !== 0; - -const splitPattern = pattern => pattern.split(REGEX_SPLITALL_CRLF); - -class IgnoreRule { - constructor ( - origin, - pattern, - negative, - regex - ) { - this.origin = origin; - this.pattern = pattern; - this.negative = negative; - this.regex = regex; - } -} - -const createRule = (pattern, ignorecase) => { - const origin = pattern; - let negative = false; - - // > An optional prefix "!" which negates the pattern; - if (pattern.indexOf('!') === 0) { - negative = true; - pattern = pattern.substr(1); - } - - pattern = pattern - // > Put a backslash ("\") in front of the first "!" for patterns that - // > begin with a literal "!", for example, `"\!important!.txt"`. - .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!') - // > Put a backslash ("\") in front of the first hash for patterns that - // > begin with a hash. - .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#'); - - const regex = makeRegex(pattern, negative, ignorecase); - - return new IgnoreRule( - origin, - pattern, - negative, - regex - ) -}; - -const throwError = (message, Ctor) => { - throw new Ctor(message) -}; - -const checkPath = (path, originalPath, doThrow) => { - if (!isString(path)) { - return doThrow( - `path must be a string, but got \`${originalPath}\``, - TypeError - ) - } - - // We don't know if we should ignore EMPTY, so throw - if (!path) { - return doThrow(`path must not be empty`, TypeError) - } - - // Check if it is a relative path - if (checkPath.isNotRelative(path)) { - const r = '`path.relative()`d'; - return doThrow( - `path should be a ${r} string, but got "${originalPath}"`, - RangeError - ) - } - - return true -}; - -const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path); - -checkPath.isNotRelative = isNotRelative; -checkPath.convert = p => p; - -class Ignore$1 { - constructor ({ - ignorecase = true - } = {}) { - this._rules = []; - this._ignorecase = ignorecase; - define(this, KEY_IGNORE, true); - this._initCache(); - } - - _initCache () { - this._ignoreCache = Object.create(null); - this._testCache = Object.create(null); - } - - _addPattern (pattern) { - // #32 - if (pattern && pattern[KEY_IGNORE]) { - this._rules = this._rules.concat(pattern._rules); - this._added = true; - return - } - - if (checkPattern(pattern)) { - const rule = createRule(pattern, this._ignorecase); - this._added = true; - this._rules.push(rule); - } - } - - // @param {Array | string | Ignore} pattern - add (pattern) { - this._added = false; - - makeArray( - isString(pattern) - ? splitPattern(pattern) - : pattern - ).forEach(this._addPattern, this); - - // Some rules have just added to the ignore, - // making the behavior changed. - if (this._added) { - this._initCache(); - } - - return this - } - - // legacy - addPattern (pattern) { - return this.add(pattern) - } - - // | ignored : unignored - // negative | 0:0 | 0:1 | 1:0 | 1:1 - // -------- | ------- | ------- | ------- | -------- - // 0 | TEST | TEST | SKIP | X - // 1 | TESTIF | SKIP | TEST | X - - // - SKIP: always skip - // - TEST: always test - // - TESTIF: only test if checkUnignored - // - X: that never happen - - // @param {boolean} whether should check if the path is unignored, - // setting `checkUnignored` to `false` could reduce additional - // path matching. - - // @returns {TestResult} true if a file is ignored - _testOne (path, checkUnignored) { - let ignored = false; - let unignored = false; - - this._rules.forEach(rule => { - const {negative} = rule; - if ( - unignored === negative && ignored !== unignored - || negative && !ignored && !unignored && !checkUnignored - ) { - return - } - - const matched = rule.regex.test(path); - - if (matched) { - ignored = !negative; - unignored = negative; - } - }); - - return { - ignored, - unignored - } - } - - // @returns {TestResult} - _test (originalPath, cache, checkUnignored, slices) { - const path = originalPath - // Supports nullable path - && checkPath.convert(originalPath); - - checkPath(path, originalPath, throwError); - - return this._t(path, cache, checkUnignored, slices) - } - - _t (path, cache, checkUnignored, slices) { - if (path in cache) { - return cache[path] - } - - if (!slices) { - // path/to/a.js - // ['path', 'to', 'a.js'] - slices = path.split(SLASH); - } - - slices.pop(); - - // If the path has no parent directory, just test it - if (!slices.length) { - return cache[path] = this._testOne(path, checkUnignored) - } - - const parent = this._t( - slices.join(SLASH) + SLASH, - cache, - checkUnignored, - slices - ); - - // If the path contains a parent directory, check the parent first - return cache[path] = parent.ignored - // > It is not possible to re-include a file if a parent directory of - // > that file is excluded. - ? parent - : this._testOne(path, checkUnignored) - } - - ignores (path) { - return this._test(path, this._ignoreCache, false).ignored - } - - createFilter () { - return path => !this.ignores(path) - } - - filter (paths) { - return makeArray(paths).filter(this.createFilter()) - } - - // @returns {TestResult} - test (path) { - return this._test(path, this._testCache, true) - } -} - -const factory$1 = options => new Ignore$1(options); - -const returnFalse = () => false; - -const isPathValid = path => - checkPath(path && checkPath.convert(path), path, returnFalse); - -factory$1.isPathValid = isPathValid; - -// Fixes typescript -factory$1.default = factory$1; - -var ignore = factory$1; - -// Windows -// -------------------------------------------------------------- -/* istanbul ignore if */ -if ( - // Detect `process` so that it can run in browsers. - typeof process !== 'undefined' - && ( - process.env && process.env.IGNORE_TEST_WIN32 - || process.platform === 'win32' - ) -) { - /* eslint no-control-regex: "off" */ - const makePosix = str => /^\\\\\?\\/.test(str) - || /["<>|\u0000-\u001F]+/u.test(str) - ? str - : str.replace(/\\/g, '/'); - - checkPath.convert = makePosix; - - // 'C:\\foo' <- 'C:\\foo' has been converted to 'C:/' - // 'd:\\foo' - const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i; - checkPath.isNotRelative = path => - REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path) - || isNotRelative(path); -} - -/** - * @typedef {import('ignore').Ignore & {filePath: string}} IgnoreConfig - * - * @typedef {'cwd'|'dir'} ResolveFrom - * - * @typedef Options - * @property {string} cwd - * @property {boolean|undefined} detectIgnore - * @property {string|undefined} ignoreName - * @property {string|undefined} ignorePath - * @property {ResolveFrom|undefined} ignorePathResolveFrom - * - * @callback Callback - * @param {Error|null} error - * @param {boolean|undefined} [result] - */ - -class Ignore { - /** - * @param {Options} options - */ - constructor(options) { - /** @type {string} */ - this.cwd = options.cwd; - /** @type {ResolveFrom|undefined} */ - this.ignorePathResolveFrom = options.ignorePathResolveFrom; - - /** @type {FindUp} */ - this.findUp = new FindUp({ - cwd: options.cwd, - filePath: options.ignorePath, - detect: options.detectIgnore, - names: options.ignoreName ? [options.ignoreName] : [], - create - }); - } - - /** - * @param {string} filePath - * @param {Callback} callback - */ - check(filePath, callback) { - this.findUp.load(filePath, (error, ignoreSet) => { - if (error) { - callback(error); - } else if (ignoreSet) { - const normal = path$c.relative( - path$c.resolve( - this.cwd, - this.ignorePathResolveFrom === 'cwd' ? '.' : ignoreSet.filePath - ), - path$c.resolve(this.cwd, filePath) - ); - - if ( - normal === '' || - normal === '..' || - normal.charAt(0) === path$c.sep || - normal.slice(0, 3) === '..' + path$c.sep - ) { - callback(null, false); - } else { - callback(null, ignoreSet.ignores(normal)); - } - } else { - callback(null, false); - } - }); - } -} - -/** - * @param {Buffer} buf - * @param {string} filePath - * @returns {IgnoreConfig} - */ -function create(buf, filePath) { - /** @type {IgnoreConfig} */ - return Object.assign(ignore().add(String(buf)), { - filePath: path$c.dirname(filePath) - }) -} - -var old$1 = {}; - -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var pathModule = path$b; -var isWindows = process.platform === 'win32'; -var fs$3 = require$$0$3; - -// JavaScript implementation of realpath, ported from node pre-v6 - -var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG); - -function rethrow() { - // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and - // is fairly slow to generate. - var callback; - if (DEBUG) { - var backtrace = new Error; - callback = debugCallback; - } else - callback = missingCallback; - - return callback; - - function debugCallback(err) { - if (err) { - backtrace.message = err.message; - err = backtrace; - missingCallback(err); - } - } - - function missingCallback(err) { - if (err) { - if (process.throwDeprecation) - throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs - else if (!process.noDeprecation) { - var msg = 'fs: missing callback ' + (err.stack || err.message); - if (process.traceDeprecation) - console.trace(msg); - else - console.error(msg); - } - } - } -} - -function maybeCallback(cb) { - return typeof cb === 'function' ? cb : rethrow(); -} - -pathModule.normalize; - -// Regexp that finds the next partion of a (partial) path -// result is [base_with_slash, base], e.g. ['somedir/', 'somedir'] -if (isWindows) { - var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; -} else { - var nextPartRe = /(.*?)(?:[\/]+|$)/g; -} - -// Regex to find the device root, including trailing slash. E.g. 'c:\\'. -if (isWindows) { - var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; -} else { - var splitRootRe = /^[\/]*/; -} - -old$1.realpathSync = function realpathSync(p, cache) { - // make p is absolute - p = pathModule.resolve(p); - - if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { - return cache[p]; - } - - var original = p, - seenLinks = {}, - knownHard = {}; - - // current character position in p - var pos; - // the partial path so far, including a trailing slash if any - var current; - // the partial path without a trailing slash (except when pointing at a root) - var base; - // the partial path scanned in the previous round, with slash - var previous; - - start(); - - function start() { - // Skip over roots - var m = splitRootRe.exec(p); - pos = m[0].length; - current = m[0]; - base = m[0]; - previous = ''; - - // On windows, check that the root exists. On unix there is no need. - if (isWindows && !knownHard[base]) { - fs$3.lstatSync(base); - knownHard[base] = true; - } - } - - // walk down the path, swapping out linked pathparts for their real - // values - // NB: p.length changes. - while (pos < p.length) { - // find the next part - nextPartRe.lastIndex = pos; - var result = nextPartRe.exec(p); - previous = current; - current += result[0]; - base = previous + result[1]; - pos = nextPartRe.lastIndex; - - // continue if not a symlink - if (knownHard[base] || (cache && cache[base] === base)) { - continue; - } - - var resolvedLink; - if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { - // some known symbolic link. no need to stat again. - resolvedLink = cache[base]; - } else { - var stat = fs$3.lstatSync(base); - if (!stat.isSymbolicLink()) { - knownHard[base] = true; - if (cache) cache[base] = base; - continue; - } - - // read the link if it wasn't read before - // dev/ino always return 0 on windows, so skip the check. - var linkTarget = null; - if (!isWindows) { - var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); - if (seenLinks.hasOwnProperty(id)) { - linkTarget = seenLinks[id]; - } - } - if (linkTarget === null) { - fs$3.statSync(base); - linkTarget = fs$3.readlinkSync(base); - } - resolvedLink = pathModule.resolve(previous, linkTarget); - // track this, if given a cache. - if (cache) cache[base] = resolvedLink; - if (!isWindows) seenLinks[id] = linkTarget; - } - - // resolve the link, then start over - p = pathModule.resolve(resolvedLink, p.slice(pos)); - start(); - } - - if (cache) cache[original] = p; - - return p; -}; - - -old$1.realpath = function realpath(p, cache, cb) { - if (typeof cb !== 'function') { - cb = maybeCallback(cache); - cache = null; - } - - // make p is absolute - p = pathModule.resolve(p); - - if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { - return process.nextTick(cb.bind(null, null, cache[p])); - } - - var original = p, - seenLinks = {}, - knownHard = {}; - - // current character position in p - var pos; - // the partial path so far, including a trailing slash if any - var current; - // the partial path without a trailing slash (except when pointing at a root) - var base; - // the partial path scanned in the previous round, with slash - var previous; - - start(); - - function start() { - // Skip over roots - var m = splitRootRe.exec(p); - pos = m[0].length; - current = m[0]; - base = m[0]; - previous = ''; - - // On windows, check that the root exists. On unix there is no need. - if (isWindows && !knownHard[base]) { - fs$3.lstat(base, function(err) { - if (err) return cb(err); - knownHard[base] = true; - LOOP(); - }); - } else { - process.nextTick(LOOP); - } - } - - // walk down the path, swapping out linked pathparts for their real - // values - function LOOP() { - // stop if scanned past end of path - if (pos >= p.length) { - if (cache) cache[original] = p; - return cb(null, p); - } - - // find the next part - nextPartRe.lastIndex = pos; - var result = nextPartRe.exec(p); - previous = current; - current += result[0]; - base = previous + result[1]; - pos = nextPartRe.lastIndex; - - // continue if not a symlink - if (knownHard[base] || (cache && cache[base] === base)) { - return process.nextTick(LOOP); - } - - if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { - // known symbolic link. no need to stat again. - return gotResolvedLink(cache[base]); - } - - return fs$3.lstat(base, gotStat); - } - - function gotStat(err, stat) { - if (err) return cb(err); - - // if not a symlink, skip to the next path part - if (!stat.isSymbolicLink()) { - knownHard[base] = true; - if (cache) cache[base] = base; - return process.nextTick(LOOP); - } - - // stat & read the link if not read before - // call gotTarget as soon as the link target is known - // dev/ino always return 0 on windows, so skip the check. - if (!isWindows) { - var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); - if (seenLinks.hasOwnProperty(id)) { - return gotTarget(null, seenLinks[id], base); - } - } - fs$3.stat(base, function(err) { - if (err) return cb(err); - - fs$3.readlink(base, function(err, target) { - if (!isWindows) seenLinks[id] = target; - gotTarget(err, target); - }); - }); - } - - function gotTarget(err, target, base) { - if (err) return cb(err); - - var resolvedLink = pathModule.resolve(previous, target); - if (cache) cache[base] = resolvedLink; - gotResolvedLink(resolvedLink); - } - - function gotResolvedLink(resolvedLink) { - // resolve the link, then start over - p = pathModule.resolve(resolvedLink, p.slice(pos)); - start(); - } -}; - -var fs_realpath = realpath; -realpath.realpath = realpath; -realpath.sync = realpathSync; -realpath.realpathSync = realpathSync; -realpath.monkeypatch = monkeypatch; -realpath.unmonkeypatch = unmonkeypatch; - -var fs$2 = require$$0$3; -var origRealpath = fs$2.realpath; -var origRealpathSync = fs$2.realpathSync; - -var version$2 = process.version; -var ok$1 = /^v[0-5]\./.test(version$2); -var old = old$1; - -function newError (er) { - return er && er.syscall === 'realpath' && ( - er.code === 'ELOOP' || - er.code === 'ENOMEM' || - er.code === 'ENAMETOOLONG' - ) -} - -function realpath (p, cache, cb) { - if (ok$1) { - return origRealpath(p, cache, cb) - } - - if (typeof cache === 'function') { - cb = cache; - cache = null; - } - origRealpath(p, cache, function (er, result) { - if (newError(er)) { - old.realpath(p, cache, cb); - } else { - cb(er, result); - } - }); -} - -function realpathSync (p, cache) { - if (ok$1) { - return origRealpathSync(p, cache) - } - - try { - return origRealpathSync(p, cache) - } catch (er) { - if (newError(er)) { - return old.realpathSync(p, cache) - } else { - throw er - } - } -} - -function monkeypatch () { - fs$2.realpath = realpath; - fs$2.realpathSync = realpathSync; -} - -function unmonkeypatch () { - fs$2.realpath = origRealpath; - fs$2.realpathSync = origRealpathSync; -} - -var concatMap$1 = function (xs, fn) { - var res = []; - for (var i = 0; i < xs.length; i++) { - var x = fn(xs[i], i); - if (isArray$1(x)) res.push.apply(res, x); - else res.push(x); - } - return res; -}; - -var isArray$1 = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - -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 concatMap = concatMap$1; -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 || /\$$/.test(m.pre)) return [str]; - - 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) { - var post = m.post.length - ? expand$2(m.post, false) - : ['']; - 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. - - // 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) - : ['']; - - 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 = concatMap(n, function(el) { return expand$2(el, 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 minimatch_1 = minimatch$3; -minimatch$3.Minimatch = Minimatch$1; - -var path$4 = { sep: '/' }; -try { - path$4 = path$b; -} catch (er) {} - -var GLOBSTAR = minimatch$3.GLOBSTAR = Minimatch$1.GLOBSTAR = {}; -var expand$1 = braceExpansion; - -var plTypes = { - '!': { open: '(?:(?!(?:', close: '))[^/]*?)'}, - '?': { open: '(?:', close: ')?' }, - '+': { open: '(?:', close: ')+' }, - '*': { open: '(?:', close: ')*' }, - '@': { open: '(?:', close: ')' } -}; - -// any single thing other than / -// don't need to escape / when using new RegExp() -var qmark = '[^/]'; - -// * => any number of characters -var star = 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. -var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'; - -// not a ^ or / followed by a dot, -// followed by anything, any number of times. -var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'; - -// characters that need to be escaped in RegExp. -var reSpecials = charSet('().*{}+?[]^$\\!'); - -// "abc" -> { a:true, b:true, c:true } -function charSet (s) { - return s.split('').reduce(function (set, c) { - set[c] = true; - return set - }, {}) -} - -// normalizes slashes. -var slashSplit = /\/+/; - -minimatch$3.filter = filter; -function filter (pattern, options) { - options = options || {}; - return function (p, i, list) { - return minimatch$3(p, pattern, options) - } -} - -function ext (a, b) { - a = a || {}; - b = b || {}; - var t = {}; - Object.keys(b).forEach(function (k) { - t[k] = b[k]; - }); - Object.keys(a).forEach(function (k) { - t[k] = a[k]; - }); - return t -} - -minimatch$3.defaults = function (def) { - if (!def || !Object.keys(def).length) return minimatch$3 - - var orig = minimatch$3; - - var m = function minimatch (p, pattern, options) { - return orig.minimatch(p, pattern, ext(def, options)) - }; - - m.Minimatch = function Minimatch (pattern, options) { - return new orig.Minimatch(pattern, ext(def, options)) - }; - - return m -}; - -Minimatch$1.defaults = function (def) { - if (!def || !Object.keys(def).length) return Minimatch$1 - return minimatch$3.defaults(def).Minimatch -}; - -function minimatch$3 (p, pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('glob pattern string required') - } - - if (!options) options = {}; - - // shortcut: comments match nothing. - if (!options.nocomment && pattern.charAt(0) === '#') { - return false - } - - // "" only matches "" - if (pattern.trim() === '') return p === '' - - return new Minimatch$1(pattern, options).match(p) -} - -function Minimatch$1 (pattern, options) { - if (!(this instanceof Minimatch$1)) { - return new Minimatch$1(pattern, options) - } - - if (typeof pattern !== 'string') { - throw new TypeError('glob pattern string required') - } - - if (!options) options = {}; - pattern = pattern.trim(); - - // windows support: need to use /, not \ - if (path$4.sep !== '/') { - pattern = pattern.split(path$4.sep).join('/'); - } - - this.options = options; - this.set = []; - this.pattern = pattern; - this.regexp = null; - this.negate = false; - this.comment = false; - this.empty = false; - - // make the set of regexps etc. - this.make(); -} - -Minimatch$1.prototype.debug = function () {}; - -Minimatch$1.prototype.make = make; -function make () { - // don't do it more than once. - if (this._made) return - - var pattern = this.pattern; - var 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 - var set = this.globSet = this.braceExpand(); - - if (options.debug) this.debug = console.error; - - this.debug(this.pattern, set); - - // 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 - set = this.globParts = set.map(function (s) { - return s.split(slashSplit) - }); - - this.debug(this.pattern, set); - - // glob --> regexps - set = set.map(function (s, si, set) { - return s.map(this.parse, this) - }, this); - - this.debug(this.pattern, set); - - // filter out everything that didn't compile properly. - set = set.filter(function (s) { - return s.indexOf(false) === -1 - }); - - this.debug(this.pattern, set); - - this.set = set; -} - -Minimatch$1.prototype.parseNegate = parseNegate; -function parseNegate () { - var pattern = this.pattern; - var negate = false; - var options = this.options; - var negateOffset = 0; - - if (options.nonegate) return - - for (var i = 0, l = pattern.length - ; i < l && pattern.charAt(i) === '!' - ; i++) { - negate = !negate; - negateOffset++; - } - - if (negateOffset) this.pattern = pattern.substr(negateOffset); - this.negate = negate; -} - -// 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 -minimatch$3.braceExpand = function (pattern, options) { - return braceExpand(pattern, options) -}; - -Minimatch$1.prototype.braceExpand = braceExpand; - -function braceExpand (pattern, options) { - if (!options) { - if (this instanceof Minimatch$1) { - options = this.options; - } else { - options = {}; - } - } - - pattern = typeof pattern === 'undefined' - ? this.pattern : pattern; - - if (typeof pattern === 'undefined') { - throw new TypeError('undefined pattern') - } - - if (options.nobrace || - !pattern.match(/\{.*\}/)) { - // shortcut. no need to expand. - return [pattern] - } - - return expand$1(pattern) -} - -// 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. -Minimatch$1.prototype.parse = parse$3; -var SUBPARSE = {}; -function parse$3 (pattern, isSub) { - if (pattern.length > 1024 * 64) { - throw new TypeError('pattern is too long') - } - - var options = this.options; - - // shortcuts - if (!options.noglobstar && pattern === '**') return GLOBSTAR - if (pattern === '') return '' - - var re = ''; - var hasMagic = !!options.nocase; - var escaping = false; - // ? => one single character - var patternListStack = []; - var negativeLists = []; - var stateChar; - var inClass = false; - var reClassStart = -1; - var classStart = -1; - // . and .. never match anything that doesn't start with ., - // even when options.dot is set. - var patternStart = pattern.charAt(0) === '.' ? '' // anything - // not (start or / followed by . or .. followed by / or end) - : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))' - : '(?!\\.)'; - var self = this; - - function clearStateChar () { - if (stateChar) { - // we had some state-tracking character - // that wasn't consumed by this pass. - switch (stateChar) { - case '*': - re += star; - hasMagic = true; - break - case '?': - re += qmark; - hasMagic = true; - break - default: - re += '\\' + stateChar; - break - } - self.debug('clearStateChar %j %j', stateChar, re); - stateChar = false; - } - } - - for (var i = 0, len = pattern.length, c - ; (i < len) && (c = pattern.charAt(i)) - ; i++) { - this.debug('%s\t%s %s %j', pattern, i, re, c); - - // skip over any that are escaped. - if (escaping && reSpecials[c]) { - re += '\\' + c; - escaping = false; - continue - } - - switch (c) { - case '/': - // completely not allowed, even escaped. - // Should already be path-split by now. - return false - - case '\\': - clearStateChar(); - escaping = true; - continue - - // the various stateChar values - // for the "extglob" stuff. - case '?': - case '*': - case '+': - case '@': - case '!': - this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c); - - // all of those are literals inside a class, except that - // the glob [!a] means [^a] in regexp - if (inClass) { - this.debug(' in class'); - if (c === '!' && i === classStart + 1) c = '^'; - re += c; - continue - } - - // if we already have a stateChar, then it means - // that there was something like ** or +? in there. - // Handle the stateChar, then proceed with this one. - self.debug('call clearStateChar %j', stateChar); - clearStateChar(); - stateChar = c; - // if extglob is disabled, then +(asdf|foo) isn't a thing. - // just clear the statechar *now*, rather than even diving into - // the patternList stuff. - if (options.noext) clearStateChar(); - continue - - case '(': - if (inClass) { - re += '('; - continue - } - - if (!stateChar) { - re += '\\('; - continue - } - - patternListStack.push({ - type: stateChar, - start: i - 1, - reStart: re.length, - open: plTypes[stateChar].open, - close: plTypes[stateChar].close - }); - // negation is (?:(?!js)[^/]*) - re += stateChar === '!' ? '(?:(?!(?:' : '(?:'; - this.debug('plType %j %j', stateChar, re); - stateChar = false; - continue - - case ')': - if (inClass || !patternListStack.length) { - re += '\\)'; - continue - } - - clearStateChar(); - hasMagic = true; - var pl = patternListStack.pop(); - // negation is (?:(?!js)[^/]*) - // The others are (?:) - re += pl.close; - if (pl.type === '!') { - negativeLists.push(pl); - } - pl.reEnd = re.length; - continue - - case '|': - if (inClass || !patternListStack.length || escaping) { - re += '\\|'; - escaping = false; - continue - } - - clearStateChar(); - re += '|'; - continue - - // these are mostly the same in regexp and glob - case '[': - // swallow any state-tracking char before the [ - clearStateChar(); - - if (inClass) { - re += '\\' + c; - continue - } - - inClass = true; - classStart = i; - reClassStart = re.length; - re += c; - continue - - case ']': - // a right bracket shall lose its special - // meaning and represent itself in - // a bracket expression if it occurs - // first in the list. -- POSIX.2 2.8.3.2 - if (i === classStart + 1 || !inClass) { - re += '\\' + c; - escaping = false; - continue - } - - // handle the case where we left a class open. - // "[z-a]" is valid, equivalent to "\[z-a\]" - if (inClass) { - // split where the last [ was, make sure we don't have - // an invalid re. if so, re-walk the contents of the - // would-be class to re-translate any characters that - // were passed through as-is - // TODO: It would probably be faster to determine this - // without a try/catch and a new RegExp, but it's tricky - // to do safely. For now, this is safe and works. - var cs = pattern.substring(classStart + 1, i); - try { - RegExp('[' + cs + ']'); - } catch (er) { - // not a valid class! - var sp = this.parse(cs, SUBPARSE); - re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'; - hasMagic = hasMagic || sp[1]; - inClass = false; - continue - } - } - - // finish up the class. - hasMagic = true; - inClass = false; - re += c; - continue - - default: - // swallow any state char that wasn't consumed - clearStateChar(); - - if (escaping) { - // no need - escaping = false; - } else if (reSpecials[c] - && !(c === '^' && inClass)) { - re += '\\'; - } - - re += c; - - } // switch - } // for - - // handle the case where we left a class open. - // "[abc" is valid, equivalent to "\[abc" - if (inClass) { - // split where the last [ was, and escape it - // this is a huge pita. We now have to re-walk - // the contents of the would-be class to re-translate - // any characters that were passed through as-is - cs = pattern.substr(classStart + 1); - sp = this.parse(cs, SUBPARSE); - re = re.substr(0, reClassStart) + '\\[' + sp[0]; - hasMagic = hasMagic || sp[1]; - } - - // handle the case where we had a +( thing at the *end* - // of the pattern. - // each pattern list stack adds 3 chars, and we need to go through - // and escape any | chars that were passed through as-is for the regexp. - // Go through and escape them, taking care not to double-escape any - // | chars that were already escaped. - for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) { - var tail = re.slice(pl.reStart + pl.open.length); - this.debug('setting tail', re, pl); - // maybe some even number of \, then maybe 1 \, followed by a | - tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) { - if (!$2) { - // the | isn't already escaped, so escape it. - $2 = '\\'; - } - - // need to escape all those slashes *again*, without escaping the - // one that we need for escaping the | character. As it works out, - // escaping an even number of slashes can be done by simply repeating - // it exactly after itself. That's why this trick works. - // - // I am sorry that you have to see this. - return $1 + $1 + $2 + '|' - }); - - this.debug('tail=%j\n %s', tail, tail, pl, re); - var t = pl.type === '*' ? star - : pl.type === '?' ? qmark - : '\\' + pl.type; - - hasMagic = true; - re = re.slice(0, pl.reStart) + t + '\\(' + tail; - } - - // handle trailing things that only matter at the very end. - clearStateChar(); - if (escaping) { - // trailing \\ - re += '\\\\'; - } - - // only need to apply the nodot start if the re starts with - // something that could conceivably capture a dot - var addPatternStart = false; - switch (re.charAt(0)) { - case '.': - case '[': - case '(': addPatternStart = true; - } - - // Hack to work around lack of negative lookbehind in JS - // A pattern like: *.!(x).!(y|z) needs to ensure that a name - // like 'a.xyz.yz' doesn't match. So, the first negative - // lookahead, has to look ALL the way ahead, to the end of - // the pattern. - for (var n = negativeLists.length - 1; n > -1; n--) { - var nl = negativeLists[n]; - - var nlBefore = re.slice(0, nl.reStart); - var nlFirst = re.slice(nl.reStart, nl.reEnd - 8); - var nlLast = re.slice(nl.reEnd - 8, nl.reEnd); - var nlAfter = re.slice(nl.reEnd); - - nlLast += nlAfter; - - // Handle nested stuff like *(*.js|!(*.json)), where open parens - // mean that we should *not* include the ) in the bit that is considered - // "after" the negated section. - var openParensBefore = nlBefore.split('(').length - 1; - var cleanAfter = nlAfter; - for (i = 0; i < openParensBefore; i++) { - cleanAfter = cleanAfter.replace(/\)[+*?]?/, ''); - } - nlAfter = cleanAfter; - - var dollar = ''; - if (nlAfter === '' && isSub !== SUBPARSE) { - dollar = '$'; - } - var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast; - re = newRe; - } - - // if the re is not "" at this point, then we need to make sure - // it doesn't match against an empty path part. - // Otherwise a/* will match a/, which it should not. - if (re !== '' && hasMagic) { - re = '(?=.)' + re; - } - - if (addPatternStart) { - re = patternStart + re; - } - - // parsing just a piece of a larger pattern. - if (isSub === SUBPARSE) { - return [re, hasMagic] - } - - // skip the regexp for non-magical patterns - // unescape anything in it, though, so that it'll be - // an exact match against a file etc. - if (!hasMagic) { - return globUnescape(pattern) - } - - var flags = options.nocase ? 'i' : ''; - try { - var regExp = new RegExp('^' + re + '$', flags); - } catch (er) { - // If it was an invalid regular expression, then it can't match - // anything. This trick looks for a character after the end of - // the string, which is of course impossible, except in multi-line - // mode, but it's not a /m regex. - return new RegExp('$.') - } - - regExp._glob = pattern; - regExp._src = re; - - return regExp -} - -minimatch$3.makeRe = function (pattern, options) { - return new Minimatch$1(pattern, options || {}).makeRe() -}; - -Minimatch$1.prototype.makeRe = makeRe; -function 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. - var set = this.set; - - if (!set.length) { - this.regexp = false; - return this.regexp - } - var options = this.options; - - var twoStar = options.noglobstar ? star - : options.dot ? twoStarDot - : twoStarNoDot; - var flags = options.nocase ? 'i' : ''; - - var re = set.map(function (pattern) { - return pattern.map(function (p) { - return (p === GLOBSTAR) ? twoStar - : (typeof p === 'string') ? regExpEscape(p) - : p._src - }).join('\\\/') - }).join('|'); - - // must match entire pattern - // ending in a * or ** will make it less strict. - re = '^(?:' + re + ')$'; - - // can match anything, as long as it's not this. - if (this.negate) re = '^(?!' + re + ').*$'; - - try { - this.regexp = new RegExp(re, flags); - } catch (ex) { - this.regexp = false; - } - return this.regexp -} - -minimatch$3.match = function (list, pattern, options) { - options = options || {}; - var mm = new Minimatch$1(pattern, options); - list = list.filter(function (f) { - return mm.match(f) - }); - if (mm.options.nonull && !list.length) { - list.push(pattern); - } - return list -}; - -Minimatch$1.prototype.match = match; -function match (f, 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 - - var options = this.options; - - // windows: need to use /, not \ - if (path$4.sep !== '/') { - f = f.split(path$4.sep).join('/'); - } - - // treat the test path as a set of pathparts. - f = f.split(slashSplit); - this.debug(this.pattern, 'split', f); - - // 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. - - var set = this.set; - this.debug(this.pattern, 'set', set); - - // Find the basename of the path by looking for the last non-empty segment - var filename; - var i; - for (i = f.length - 1; i >= 0; i--) { - filename = f[i]; - if (filename) break - } - - for (i = 0; i < set.length; i++) { - var pattern = set[i]; - var file = f; - if (options.matchBase && pattern.length === 1) { - file = [filename]; - } - var 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 -} - -// 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. -Minimatch$1.prototype.matchOne = function (file, pattern, partial) { - var options = this.options; - - this.debug('matchOne', - { 'this': this, file: file, pattern: 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. - if (p === false) return false - - if (p === GLOBSTAR) { - 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. - // If there's more *pattern* left, then - if (partial) { - // ran out of file - this.debug('\n>>> no match, partial?', file, fr, pattern, pr); - if (fr === fl) return true - } - return false - } - - // something other than ** - // non-magic patterns just have to match exactly - // patterns with magic have been turned into regexps. - var hit; - if (typeof p === 'string') { - if (options.nocase) { - hit = f.toLowerCase() === p.toLowerCase(); - } else { - hit = f === p; - } - this.debug('string match', p, f, hit); - } else { - hit = f.match(p); - 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/ - var emptyFileEnd = (fi === fl - 1) && (file[fi] === ''); - return emptyFileEnd - } - - // should be unreachable. - throw new Error('wtf?') -}; - -// replace stuff like \* with * -function globUnescape (s) { - return s.replace(/\\(.)/g, '$1') -} - -function regExpEscape (s) { - return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') -} - -var inherits$2 = {exports: {}}; - -var inherits_browser = {exports: {}}; - -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - inherits_browser.exports = function inherits(ctor, superCtor) { - if (superCtor) { - ctor.super_ = superCtor; - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - } - }; -} else { - // old school shim for old browsers - inherits_browser.exports = function inherits(ctor, superCtor) { - if (superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - } - }; -} - -try { - var util$1 = require$$0$4; - /* istanbul ignore next */ - if (typeof util$1.inherits !== 'function') throw ''; - inherits$2.exports = util$1.inherits; -} catch (e) { - /* istanbul ignore next */ - inherits$2.exports = inherits_browser.exports; -} - -var pathIsAbsolute = {exports: {}}; - -function posix(path) { - return path.charAt(0) === '/'; -} - -function win32(path) { - // https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56 - var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; - var result = splitDeviceRe.exec(path); - var device = result[1] || ''; - var isUnc = Boolean(device && device.charAt(1) !== ':'); - - // UNC paths are always absolute - return Boolean(result[2] || isUnc); -} - -pathIsAbsolute.exports = process.platform === 'win32' ? win32 : posix; -pathIsAbsolute.exports.posix = posix; -pathIsAbsolute.exports.win32 = win32; - -var common$2 = {}; - -common$2.setopts = setopts$2; -common$2.ownProp = ownProp$2; -common$2.makeAbs = makeAbs; -common$2.finish = finish; -common$2.mark = mark; -common$2.isIgnored = isIgnored$2; -common$2.childrenIgnored = childrenIgnored$2; - -function ownProp$2 (obj, field) { - return Object.prototype.hasOwnProperty.call(obj, field) -} - -var path$3 = path$b; -var minimatch$2 = minimatch_1; -var isAbsolute$2 = pathIsAbsolute.exports; -var Minimatch = minimatch$2.Minimatch; - -function alphasort (a, b) { - return a.localeCompare(b, 'en') -} - -function setupIgnores (self, options) { - self.ignore = options.ignore || []; - - if (!Array.isArray(self.ignore)) - self.ignore = [self.ignore]; - - if (self.ignore.length) { - self.ignore = self.ignore.map(ignoreMap); - } -} - -// ignore patterns are always in dot:true mode. -function ignoreMap (pattern) { - var gmatcher = null; - if (pattern.slice(-3) === '/**') { - var gpattern = pattern.replace(/(\/\*\*)+$/, ''); - gmatcher = new Minimatch(gpattern, { dot: true }); - } - - return { - matcher: new Minimatch(pattern, { dot: true }), - gmatcher: gmatcher - } -} - -function setopts$2 (self, pattern, options) { - if (!options) - options = {}; - - // base-matching: just use globstar for that. - if (options.matchBase && -1 === pattern.indexOf("/")) { - if (options.noglobstar) { - throw new Error("base matching requires globstar") - } - pattern = "**/" + pattern; - } - - self.silent = !!options.silent; - self.pattern = pattern; - self.strict = options.strict !== false; - self.realpath = !!options.realpath; - self.realpathCache = options.realpathCache || Object.create(null); - self.follow = !!options.follow; - self.dot = !!options.dot; - self.mark = !!options.mark; - self.nodir = !!options.nodir; - if (self.nodir) - self.mark = true; - self.sync = !!options.sync; - self.nounique = !!options.nounique; - self.nonull = !!options.nonull; - self.nosort = !!options.nosort; - self.nocase = !!options.nocase; - self.stat = !!options.stat; - self.noprocess = !!options.noprocess; - self.absolute = !!options.absolute; - - self.maxLength = options.maxLength || Infinity; - self.cache = options.cache || Object.create(null); - self.statCache = options.statCache || Object.create(null); - self.symlinks = options.symlinks || Object.create(null); - - setupIgnores(self, options); - - self.changedCwd = false; - var cwd = process.cwd(); - if (!ownProp$2(options, "cwd")) - self.cwd = cwd; - else { - self.cwd = path$3.resolve(options.cwd); - self.changedCwd = self.cwd !== cwd; - } - - self.root = options.root || path$3.resolve(self.cwd, "/"); - self.root = path$3.resolve(self.root); - if (process.platform === "win32") - self.root = self.root.replace(/\\/g, "/"); - - // TODO: is an absolute `cwd` supposed to be resolved against `root`? - // e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test') - self.cwdAbs = isAbsolute$2(self.cwd) ? self.cwd : makeAbs(self, self.cwd); - if (process.platform === "win32") - self.cwdAbs = self.cwdAbs.replace(/\\/g, "/"); - self.nomount = !!options.nomount; - - // disable comments and negation in Minimatch. - // Note that they are not supported in Glob itself anyway. - options.nonegate = true; - options.nocomment = true; - - self.minimatch = new Minimatch(pattern, options); - self.options = self.minimatch.options; -} - -function finish (self) { - var nou = self.nounique; - var all = nou ? [] : Object.create(null); - - for (var i = 0, l = self.matches.length; i < l; i ++) { - var matches = self.matches[i]; - if (!matches || Object.keys(matches).length === 0) { - if (self.nonull) { - // do like the shell, and spit out the literal glob - var literal = self.minimatch.globSet[i]; - if (nou) - all.push(literal); - else - all[literal] = true; - } - } else { - // had matches - var m = Object.keys(matches); - if (nou) - all.push.apply(all, m); - else - m.forEach(function (m) { - all[m] = true; - }); - } - } - - if (!nou) - all = Object.keys(all); - - if (!self.nosort) - all = all.sort(alphasort); - - // at *some* point we statted all of these - if (self.mark) { - for (var i = 0; i < all.length; i++) { - all[i] = self._mark(all[i]); - } - if (self.nodir) { - all = all.filter(function (e) { - var notDir = !(/\/$/.test(e)); - var c = self.cache[e] || self.cache[makeAbs(self, e)]; - if (notDir && c) - notDir = c !== 'DIR' && !Array.isArray(c); - return notDir - }); - } - } - - if (self.ignore.length) - all = all.filter(function(m) { - return !isIgnored$2(self, m) - }); - - self.found = all; -} - -function mark (self, p) { - var abs = makeAbs(self, p); - var c = self.cache[abs]; - var m = p; - if (c) { - var isDir = c === 'DIR' || Array.isArray(c); - var slash = p.slice(-1) === '/'; - - if (isDir && !slash) - m += '/'; - else if (!isDir && slash) - m = m.slice(0, -1); - - if (m !== p) { - var mabs = makeAbs(self, m); - self.statCache[mabs] = self.statCache[abs]; - self.cache[mabs] = self.cache[abs]; - } - } - - return m -} - -// lotta situps... -function makeAbs (self, f) { - var abs = f; - if (f.charAt(0) === '/') { - abs = path$3.join(self.root, f); - } else if (isAbsolute$2(f) || f === '') { - abs = f; - } else if (self.changedCwd) { - abs = path$3.resolve(self.cwd, f); - } else { - abs = path$3.resolve(f); - } - - if (process.platform === 'win32') - abs = abs.replace(/\\/g, '/'); - - return abs -} - - -// Return true, if pattern ends with globstar '**', for the accompanying parent directory. -// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents -function isIgnored$2 (self, path) { - if (!self.ignore.length) - return false - - return self.ignore.some(function(item) { - return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) - }) -} - -function childrenIgnored$2 (self, path) { - if (!self.ignore.length) - return false - - return self.ignore.some(function(item) { - return !!(item.gmatcher && item.gmatcher.match(path)) - }) -} - -var sync$1 = globSync$1; -globSync$1.GlobSync = GlobSync$1; - -var fs$1 = require$$0$3; -var rp$1 = fs_realpath; -var minimatch$1 = minimatch_1; -var path$2 = path$b; -var assert$1 = assert$2; -var isAbsolute$1 = pathIsAbsolute.exports; -var common$1 = common$2; -var setopts$1 = common$1.setopts; -var ownProp$1 = common$1.ownProp; -var childrenIgnored$1 = common$1.childrenIgnored; -var isIgnored$1 = common$1.isIgnored; - -function globSync$1 (pattern, options) { - if (typeof options === 'function' || arguments.length === 3) - throw new TypeError('callback provided to sync glob\n'+ - 'See: https://github.com/isaacs/node-glob/issues/167') - - return new GlobSync$1(pattern, options).found -} - -function GlobSync$1 (pattern, options) { - if (!pattern) - throw new Error('must provide pattern') - - if (typeof options === 'function' || arguments.length === 3) - throw new TypeError('callback provided to sync glob\n'+ - 'See: https://github.com/isaacs/node-glob/issues/167') - - if (!(this instanceof GlobSync$1)) - return new GlobSync$1(pattern, options) - - setopts$1(this, pattern, options); - - if (this.noprocess) - return this - - var n = this.minimatch.set.length; - this.matches = new Array(n); - for (var i = 0; i < n; i ++) { - this._process(this.minimatch.set[i], i, false); - } - this._finish(); -} - -GlobSync$1.prototype._finish = function () { - assert$1(this instanceof GlobSync$1); - if (this.realpath) { - var self = this; - this.matches.forEach(function (matchset, index) { - var set = self.matches[index] = Object.create(null); - for (var p in matchset) { - try { - p = self._makeAbs(p); - var real = rp$1.realpathSync(p, self.realpathCache); - set[real] = true; - } catch (er) { - if (er.syscall === 'stat') - set[self._makeAbs(p)] = true; - else - throw er - } - } - }); - } - common$1.finish(this); -}; - - -GlobSync$1.prototype._process = function (pattern, index, inGlobStar) { - assert$1(this instanceof GlobSync$1); - - // Get the first [n] parts of pattern that are all strings. - var n = 0; - while (typeof pattern[n] === 'string') { - n ++; - } - // now n is the index of the first one that is *not* a string. - - // See if there's anything else - var prefix; - switch (n) { - // if not, then this is rather simple - case pattern.length: - this._processSimple(pattern.join('/'), index); - return - - case 0: - // pattern *starts* with some non-trivial item. - // going to readdir(cwd), but not include the prefix in matches. - prefix = null; - break - - default: - // pattern has some string bits in the front. - // whatever it starts with, whether that's 'absolute' like /foo/bar, - // or 'relative' like '../baz' - prefix = pattern.slice(0, n).join('/'); - break - } - - var remain = pattern.slice(n); - - // get the list of entries. - var read; - if (prefix === null) - read = '.'; - else if (isAbsolute$1(prefix) || isAbsolute$1(pattern.join('/'))) { - if (!prefix || !isAbsolute$1(prefix)) - prefix = '/' + prefix; - read = prefix; - } else - read = prefix; - - var abs = this._makeAbs(read); - - //if ignored, skip processing - if (childrenIgnored$1(this, read)) - return - - var isGlobStar = remain[0] === minimatch$1.GLOBSTAR; - if (isGlobStar) - this._processGlobStar(prefix, read, abs, remain, index, inGlobStar); - else - this._processReaddir(prefix, read, abs, remain, index, inGlobStar); -}; - - -GlobSync$1.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) { - var entries = this._readdir(abs, inGlobStar); - - // if the abs isn't a dir, then nothing can match! - if (!entries) - return - - // It will only match dot entries if it starts with a dot, or if - // dot is set. Stuff like @(.foo|.bar) isn't allowed. - var pn = remain[0]; - var negate = !!this.minimatch.negate; - var rawGlob = pn._glob; - var dotOk = this.dot || rawGlob.charAt(0) === '.'; - - var matchedEntries = []; - for (var i = 0; i < entries.length; i++) { - var e = entries[i]; - if (e.charAt(0) !== '.' || dotOk) { - var m; - if (negate && !prefix) { - m = !e.match(pn); - } else { - m = e.match(pn); - } - if (m) - matchedEntries.push(e); - } - } - - var len = matchedEntries.length; - // If there are no matched entries, then nothing matches. - if (len === 0) - return - - // if this is the last remaining pattern bit, then no need for - // an additional stat *unless* the user has specified mark or - // stat explicitly. We know they exist, since readdir returned - // them. - - if (remain.length === 1 && !this.mark && !this.stat) { - if (!this.matches[index]) - this.matches[index] = Object.create(null); - - for (var i = 0; i < len; i ++) { - var e = matchedEntries[i]; - if (prefix) { - if (prefix.slice(-1) !== '/') - e = prefix + '/' + e; - else - e = prefix + e; - } - - if (e.charAt(0) === '/' && !this.nomount) { - e = path$2.join(this.root, e); - } - this._emitMatch(index, e); - } - // This was the last one, and no stats were needed - return - } - - // now test all matched entries as stand-ins for that part - // of the pattern. - remain.shift(); - for (var i = 0; i < len; i ++) { - var e = matchedEntries[i]; - var newPattern; - if (prefix) - newPattern = [prefix, e]; - else - newPattern = [e]; - this._process(newPattern.concat(remain), index, inGlobStar); - } -}; - - -GlobSync$1.prototype._emitMatch = function (index, e) { - if (isIgnored$1(this, e)) - return - - var abs = this._makeAbs(e); - - if (this.mark) - e = this._mark(e); - - if (this.absolute) { - e = abs; - } - - if (this.matches[index][e]) - return - - if (this.nodir) { - var c = this.cache[abs]; - if (c === 'DIR' || Array.isArray(c)) - return - } - - this.matches[index][e] = true; - - if (this.stat) - this._stat(e); -}; - - -GlobSync$1.prototype._readdirInGlobStar = function (abs) { - // follow all symlinked directories forever - // just proceed as if this is a non-globstar situation - if (this.follow) - return this._readdir(abs, false) - - var entries; - var lstat; - try { - lstat = fs$1.lstatSync(abs); - } catch (er) { - if (er.code === 'ENOENT') { - // lstat failed, doesn't exist - return null - } - } - - var isSym = lstat && lstat.isSymbolicLink(); - this.symlinks[abs] = isSym; - - // If it's not a symlink or a dir, then it's definitely a regular file. - // don't bother doing a readdir in that case. - if (!isSym && lstat && !lstat.isDirectory()) - this.cache[abs] = 'FILE'; - else - entries = this._readdir(abs, false); - - return entries -}; - -GlobSync$1.prototype._readdir = function (abs, inGlobStar) { - - if (inGlobStar && !ownProp$1(this.symlinks, abs)) - return this._readdirInGlobStar(abs) - - if (ownProp$1(this.cache, abs)) { - var c = this.cache[abs]; - if (!c || c === 'FILE') - return null - - if (Array.isArray(c)) - return c - } - - try { - return this._readdirEntries(abs, fs$1.readdirSync(abs)) - } catch (er) { - this._readdirError(abs, er); - return null - } -}; - -GlobSync$1.prototype._readdirEntries = function (abs, entries) { - // if we haven't asked to stat everything, then just - // assume that everything in there exists, so we can avoid - // having to stat it a second time. - if (!this.mark && !this.stat) { - for (var i = 0; i < entries.length; i ++) { - var e = entries[i]; - if (abs === '/') - e = abs + e; - else - e = abs + '/' + e; - this.cache[e] = true; - } - } - - this.cache[abs] = entries; - - // mark and cache dir-ness - return entries -}; - -GlobSync$1.prototype._readdirError = function (f, er) { - // handle errors, and cache the information - switch (er.code) { - case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 - case 'ENOTDIR': // totally normal. means it *does* exist. - var abs = this._makeAbs(f); - this.cache[abs] = 'FILE'; - if (abs === this.cwdAbs) { - var error = new Error(er.code + ' invalid cwd ' + this.cwd); - error.path = this.cwd; - error.code = er.code; - throw error - } - break - - case 'ENOENT': // not terribly unusual - case 'ELOOP': - case 'ENAMETOOLONG': - case 'UNKNOWN': - this.cache[this._makeAbs(f)] = false; - break - - default: // some unusual error. Treat as failure. - this.cache[this._makeAbs(f)] = false; - if (this.strict) - throw er - if (!this.silent) - console.error('glob error', er); - break - } -}; - -GlobSync$1.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) { - - var entries = this._readdir(abs, inGlobStar); - - // no entries means not a dir, so it can never have matches - // foo.txt/** doesn't match foo.txt - if (!entries) - return - - // test without the globstar, and with every child both below - // and replacing the globstar. - var remainWithoutGlobStar = remain.slice(1); - var gspref = prefix ? [ prefix ] : []; - var noGlobStar = gspref.concat(remainWithoutGlobStar); - - // the noGlobStar pattern exits the inGlobStar state - this._process(noGlobStar, index, false); - - var len = entries.length; - var isSym = this.symlinks[abs]; - - // If it's a symlink, and we're in a globstar, then stop - if (isSym && inGlobStar) - return - - for (var i = 0; i < len; i++) { - var e = entries[i]; - if (e.charAt(0) === '.' && !this.dot) - continue - - // these two cases enter the inGlobStar state - var instead = gspref.concat(entries[i], remainWithoutGlobStar); - this._process(instead, index, true); - - var below = gspref.concat(entries[i], remain); - this._process(below, index, true); - } -}; - -GlobSync$1.prototype._processSimple = function (prefix, index) { - // XXX review this. Shouldn't it be doing the mounting etc - // before doing stat? kinda weird? - var exists = this._stat(prefix); - - if (!this.matches[index]) - this.matches[index] = Object.create(null); - - // If it doesn't exist, then just mark the lack of results - if (!exists) - return - - if (prefix && isAbsolute$1(prefix) && !this.nomount) { - var trail = /[\/\\]$/.test(prefix); - if (prefix.charAt(0) === '/') { - prefix = path$2.join(this.root, prefix); - } else { - prefix = path$2.resolve(this.root, prefix); - if (trail) - prefix += '/'; - } - } - - if (process.platform === 'win32') - prefix = prefix.replace(/\\/g, '/'); - - // Mark this as a match - this._emitMatch(index, prefix); -}; - -// Returns either 'DIR', 'FILE', or false -GlobSync$1.prototype._stat = function (f) { - var abs = this._makeAbs(f); - var needDir = f.slice(-1) === '/'; - - if (f.length > this.maxLength) - return false - - if (!this.stat && ownProp$1(this.cache, abs)) { - var c = this.cache[abs]; - - if (Array.isArray(c)) - c = 'DIR'; - - // It exists, but maybe not how we need it - if (!needDir || c === 'DIR') - return c - - if (needDir && c === 'FILE') - return false - - // otherwise we have to stat, because maybe c=true - // if we know it exists, but not what it is. - } - var stat = this.statCache[abs]; - if (!stat) { - var lstat; - try { - lstat = fs$1.lstatSync(abs); - } catch (er) { - if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) { - this.statCache[abs] = false; - return false - } - } - - if (lstat && lstat.isSymbolicLink()) { - try { - stat = fs$1.statSync(abs); - } catch (er) { - stat = lstat; - } - } else { - stat = lstat; - } - } - - this.statCache[abs] = stat; - - var c = true; - if (stat) - c = stat.isDirectory() ? 'DIR' : 'FILE'; - - this.cache[abs] = this.cache[abs] || c; - - if (needDir && c === 'FILE') - return false - - return c -}; - -GlobSync$1.prototype._mark = function (p) { - return common$1.mark(this, p) -}; - -GlobSync$1.prototype._makeAbs = function (f) { - return common$1.makeAbs(this, f) -}; - -// Returns a wrapper function that returns a wrapped callback -// The wrapper function should do some stuff, and return a -// presumably different callback function. -// This makes sure that own properties are retained, so that -// decorations and such are not lost along the way. -var wrappy_1 = wrappy$2; -function wrappy$2 (fn, cb) { - if (fn && cb) return wrappy$2(fn)(cb) - - if (typeof fn !== 'function') - throw new TypeError('need wrapper function') - - Object.keys(fn).forEach(function (k) { - wrapper[k] = fn[k]; - }); - - return wrapper - - function wrapper() { - var args = new Array(arguments.length); - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i]; - } - var ret = fn.apply(this, args); - var cb = args[args.length-1]; - if (typeof ret === 'function' && ret !== cb) { - Object.keys(cb).forEach(function (k) { - ret[k] = cb[k]; - }); - } - return ret - } -} - -var once$3 = {exports: {}}; - -var wrappy$1 = wrappy_1; -once$3.exports = wrappy$1(once$2); -once$3.exports.strict = wrappy$1(onceStrict); - -once$2.proto = once$2(function () { - Object.defineProperty(Function.prototype, 'once', { - value: function () { - return once$2(this) - }, - configurable: true - }); - - Object.defineProperty(Function.prototype, 'onceStrict', { - value: function () { - return onceStrict(this) - }, - configurable: true - }); -}); - -function once$2 (fn) { - var f = function () { - if (f.called) return f.value - f.called = true; - return f.value = fn.apply(this, arguments) - }; - f.called = false; - return f -} - -function onceStrict (fn) { - var f = function () { - if (f.called) - throw new Error(f.onceError) - f.called = true; - return f.value = fn.apply(this, arguments) - }; - var name = fn.name || 'Function wrapped with `once`'; - f.onceError = name + " shouldn't be called more than once"; - f.called = false; - return f -} - -var wrappy = wrappy_1; -var reqs = Object.create(null); -var once$1 = once$3.exports; - -var inflight_1 = wrappy(inflight$1); - -function inflight$1 (key, cb) { - if (reqs[key]) { - reqs[key].push(cb); - return null - } else { - reqs[key] = [cb]; - return makeres(key) - } -} - -function makeres (key) { - return once$1(function RES () { - var cbs = reqs[key]; - var len = cbs.length; - var args = slice$1(arguments); - - // XXX It's somewhat ambiguous whether a new callback added in this - // pass should be queued for later execution if something in the - // list of callbacks throws, or if it should just be discarded. - // However, it's such an edge case that it hardly matters, and either - // choice is likely as surprising as the other. - // As it happens, we do go ahead and schedule it for later execution. - try { - for (var i = 0; i < len; i++) { - cbs[i].apply(null, args); - } - } finally { - if (cbs.length > len) { - // added more in the interim. - // de-zalgo, just in case, but don't call again. - cbs.splice(0, len); - process.nextTick(function () { - RES.apply(null, args); - }); - } else { - delete reqs[key]; - } - } - }) -} - -function slice$1 (args) { - var length = args.length; - var array = []; - - for (var i = 0; i < length; i++) array[i] = args[i]; - return array -} - -// Approach: -// -// 1. Get the minimatch set -// 2. For each pattern in the set, PROCESS(pattern, false) -// 3. Store matches per-set, then uniq them -// -// PROCESS(pattern, inGlobStar) -// Get the first [n] items from pattern that are all strings -// Join these together. This is PREFIX. -// If there is no more remaining, then stat(PREFIX) and -// add to matches if it succeeds. END. -// -// If inGlobStar and PREFIX is symlink and points to dir -// set ENTRIES = [] -// else readdir(PREFIX) as ENTRIES -// If fail, END -// -// with ENTRIES -// If pattern[n] is GLOBSTAR -// // handle the case where the globstar match is empty -// // by pruning it out, and testing the resulting pattern -// PROCESS(pattern[0..n] + pattern[n+1 .. $], false) -// // handle other cases. -// for ENTRY in ENTRIES (not dotfiles) -// // attach globstar + tail onto the entry -// // Mark that this entry is a globstar match -// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true) -// -// else // not globstar -// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot) -// Test ENTRY against pattern[n] -// If fails, continue -// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $]) -// -// Caveat: -// Cache all stats and readdirs results to minimize syscall. Since all -// we ever care about is existence and directory-ness, we can just keep -// `true` for files, and [children,...] for directories, or `false` for -// things that don't exist. - -var glob_1 = glob; - -var fs = require$$0$3; -var rp = fs_realpath; -var minimatch = minimatch_1; -var inherits$1 = inherits$2.exports; -var EE = require$$0$5.EventEmitter; -var path$1 = path$b; -var assert = assert$2; -var isAbsolute = pathIsAbsolute.exports; -var globSync = sync$1; -var common = common$2; -var setopts = common.setopts; -var ownProp = common.ownProp; -var inflight = inflight_1; -var childrenIgnored = common.childrenIgnored; -var isIgnored = common.isIgnored; - -var once = once$3.exports; - -function glob (pattern, options, cb) { - if (typeof options === 'function') cb = options, options = {}; - if (!options) options = {}; - - if (options.sync) { - if (cb) - throw new TypeError('callback provided to sync glob') - return globSync(pattern, options) - } - - return new Glob(pattern, options, cb) -} - -glob.sync = globSync; -var GlobSync = glob.GlobSync = globSync.GlobSync; - -// old api surface -glob.glob = glob; - -function extend$1 (origin, add) { - if (add === null || typeof add !== 'object') { - return origin - } - - var keys = Object.keys(add); - var i = keys.length; - while (i--) { - origin[keys[i]] = add[keys[i]]; - } - return origin -} - -glob.hasMagic = function (pattern, options_) { - var options = extend$1({}, options_); - options.noprocess = true; - - var g = new Glob(pattern, options); - var set = g.minimatch.set; - - if (!pattern) - return false - - if (set.length > 1) - return true - - for (var j = 0; j < set[0].length; j++) { - if (typeof set[0][j] !== 'string') - return true - } - - return false -}; - -glob.Glob = Glob; -inherits$1(Glob, EE); -function Glob (pattern, options, cb) { - if (typeof options === 'function') { - cb = options; - options = null; - } - - if (options && options.sync) { - if (cb) - throw new TypeError('callback provided to sync glob') - return new GlobSync(pattern, options) - } - - if (!(this instanceof Glob)) - return new Glob(pattern, options, cb) - - setopts(this, pattern, options); - this._didRealPath = false; - - // process each pattern in the minimatch set - var n = this.minimatch.set.length; - - // The matches are stored as {: true,...} so that - // duplicates are automagically pruned. - // Later, we do an Object.keys() on these. - // Keep them as a list so we can fill in when nonull is set. - this.matches = new Array(n); - - if (typeof cb === 'function') { - cb = once(cb); - this.on('error', cb); - this.on('end', function (matches) { - cb(null, matches); - }); - } - - var self = this; - this._processing = 0; - - this._emitQueue = []; - this._processQueue = []; - this.paused = false; - - if (this.noprocess) - return this - - if (n === 0) - return done() - - var sync = true; - for (var i = 0; i < n; i ++) { - this._process(this.minimatch.set[i], i, false, done); - } - sync = false; - - function done () { - --self._processing; - if (self._processing <= 0) { - if (sync) { - process.nextTick(function () { - self._finish(); - }); - } else { - self._finish(); - } - } - } -} - -Glob.prototype._finish = function () { - assert(this instanceof Glob); - if (this.aborted) - return - - if (this.realpath && !this._didRealpath) - return this._realpath() - - common.finish(this); - this.emit('end', this.found); -}; - -Glob.prototype._realpath = function () { - if (this._didRealpath) - return - - this._didRealpath = true; - - var n = this.matches.length; - if (n === 0) - return this._finish() - - var self = this; - for (var i = 0; i < this.matches.length; i++) - this._realpathSet(i, next); - - function next () { - if (--n === 0) - self._finish(); - } -}; - -Glob.prototype._realpathSet = function (index, cb) { - var matchset = this.matches[index]; - if (!matchset) - return cb() - - var found = Object.keys(matchset); - var self = this; - var n = found.length; - - if (n === 0) - return cb() - - var set = this.matches[index] = Object.create(null); - found.forEach(function (p, i) { - // If there's a problem with the stat, then it means that - // one or more of the links in the realpath couldn't be - // resolved. just return the abs value in that case. - p = self._makeAbs(p); - rp.realpath(p, self.realpathCache, function (er, real) { - if (!er) - set[real] = true; - else if (er.syscall === 'stat') - set[p] = true; - else - self.emit('error', er); // srsly wtf right here - - if (--n === 0) { - self.matches[index] = set; - cb(); - } - }); - }); -}; - -Glob.prototype._mark = function (p) { - return common.mark(this, p) -}; - -Glob.prototype._makeAbs = function (f) { - return common.makeAbs(this, f) -}; - -Glob.prototype.abort = function () { - this.aborted = true; - this.emit('abort'); -}; - -Glob.prototype.pause = function () { - if (!this.paused) { - this.paused = true; - this.emit('pause'); - } -}; - -Glob.prototype.resume = function () { - if (this.paused) { - this.emit('resume'); - this.paused = false; - if (this._emitQueue.length) { - var eq = this._emitQueue.slice(0); - this._emitQueue.length = 0; - for (var i = 0; i < eq.length; i ++) { - var e = eq[i]; - this._emitMatch(e[0], e[1]); - } - } - if (this._processQueue.length) { - var pq = this._processQueue.slice(0); - this._processQueue.length = 0; - for (var i = 0; i < pq.length; i ++) { - var p = pq[i]; - this._processing--; - this._process(p[0], p[1], p[2], p[3]); - } - } - } -}; - -Glob.prototype._process = function (pattern, index, inGlobStar, cb) { - assert(this instanceof Glob); - assert(typeof cb === 'function'); - - if (this.aborted) - return - - this._processing++; - if (this.paused) { - this._processQueue.push([pattern, index, inGlobStar, cb]); - return - } - - //console.error('PROCESS %d', this._processing, pattern) - - // Get the first [n] parts of pattern that are all strings. - var n = 0; - while (typeof pattern[n] === 'string') { - n ++; - } - // now n is the index of the first one that is *not* a string. - - // see if there's anything else - var prefix; - switch (n) { - // if not, then this is rather simple - case pattern.length: - this._processSimple(pattern.join('/'), index, cb); - return - - case 0: - // pattern *starts* with some non-trivial item. - // going to readdir(cwd), but not include the prefix in matches. - prefix = null; - break - - default: - // pattern has some string bits in the front. - // whatever it starts with, whether that's 'absolute' like /foo/bar, - // or 'relative' like '../baz' - prefix = pattern.slice(0, n).join('/'); - break - } - - var remain = pattern.slice(n); - - // get the list of entries. - var read; - if (prefix === null) - read = '.'; - else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { - if (!prefix || !isAbsolute(prefix)) - prefix = '/' + prefix; - read = prefix; - } else - read = prefix; - - var abs = this._makeAbs(read); - - //if ignored, skip _processing - if (childrenIgnored(this, read)) - return cb() - - var isGlobStar = remain[0] === minimatch.GLOBSTAR; - if (isGlobStar) - this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb); - else - this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb); -}; - -Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) { - var self = this; - this._readdir(abs, inGlobStar, function (er, entries) { - return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb) - }); -}; - -Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { - - // if the abs isn't a dir, then nothing can match! - if (!entries) - return cb() - - // It will only match dot entries if it starts with a dot, or if - // dot is set. Stuff like @(.foo|.bar) isn't allowed. - var pn = remain[0]; - var negate = !!this.minimatch.negate; - var rawGlob = pn._glob; - var dotOk = this.dot || rawGlob.charAt(0) === '.'; - - var matchedEntries = []; - for (var i = 0; i < entries.length; i++) { - var e = entries[i]; - if (e.charAt(0) !== '.' || dotOk) { - var m; - if (negate && !prefix) { - m = !e.match(pn); - } else { - m = e.match(pn); - } - if (m) - matchedEntries.push(e); - } - } - - //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries) - - var len = matchedEntries.length; - // If there are no matched entries, then nothing matches. - if (len === 0) - return cb() - - // if this is the last remaining pattern bit, then no need for - // an additional stat *unless* the user has specified mark or - // stat explicitly. We know they exist, since readdir returned - // them. - - if (remain.length === 1 && !this.mark && !this.stat) { - if (!this.matches[index]) - this.matches[index] = Object.create(null); - - for (var i = 0; i < len; i ++) { - var e = matchedEntries[i]; - if (prefix) { - if (prefix !== '/') - e = prefix + '/' + e; - else - e = prefix + e; - } - - if (e.charAt(0) === '/' && !this.nomount) { - e = path$1.join(this.root, e); - } - this._emitMatch(index, e); - } - // This was the last one, and no stats were needed - return cb() - } - - // now test all matched entries as stand-ins for that part - // of the pattern. - remain.shift(); - for (var i = 0; i < len; i ++) { - var e = matchedEntries[i]; - if (prefix) { - if (prefix !== '/') - e = prefix + '/' + e; - else - e = prefix + e; - } - this._process([e].concat(remain), index, inGlobStar, cb); - } - cb(); -}; - -Glob.prototype._emitMatch = function (index, e) { - if (this.aborted) - return - - if (isIgnored(this, e)) - return - - if (this.paused) { - this._emitQueue.push([index, e]); - return - } - - var abs = isAbsolute(e) ? e : this._makeAbs(e); - - if (this.mark) - e = this._mark(e); - - if (this.absolute) - e = abs; - - if (this.matches[index][e]) - return - - if (this.nodir) { - var c = this.cache[abs]; - if (c === 'DIR' || Array.isArray(c)) - return - } - - this.matches[index][e] = true; - - var st = this.statCache[abs]; - if (st) - this.emit('stat', e, st); - - this.emit('match', e); -}; - -Glob.prototype._readdirInGlobStar = function (abs, cb) { - if (this.aborted) - return - - // follow all symlinked directories forever - // just proceed as if this is a non-globstar situation - if (this.follow) - return this._readdir(abs, false, cb) - - var lstatkey = 'lstat\0' + abs; - var self = this; - var lstatcb = inflight(lstatkey, lstatcb_); - - if (lstatcb) - fs.lstat(abs, lstatcb); - - function lstatcb_ (er, lstat) { - if (er && er.code === 'ENOENT') - return cb() - - var isSym = lstat && lstat.isSymbolicLink(); - self.symlinks[abs] = isSym; - - // If it's not a symlink or a dir, then it's definitely a regular file. - // don't bother doing a readdir in that case. - if (!isSym && lstat && !lstat.isDirectory()) { - self.cache[abs] = 'FILE'; - cb(); - } else - self._readdir(abs, false, cb); - } -}; - -Glob.prototype._readdir = function (abs, inGlobStar, cb) { - if (this.aborted) - return - - cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb); - if (!cb) - return - - //console.error('RD %j %j', +inGlobStar, abs) - if (inGlobStar && !ownProp(this.symlinks, abs)) - return this._readdirInGlobStar(abs, cb) - - if (ownProp(this.cache, abs)) { - var c = this.cache[abs]; - if (!c || c === 'FILE') - return cb() - - if (Array.isArray(c)) - return cb(null, c) - } - fs.readdir(abs, readdirCb(this, abs, cb)); -}; - -function readdirCb (self, abs, cb) { - return function (er, entries) { - if (er) - self._readdirError(abs, er, cb); - else - self._readdirEntries(abs, entries, cb); - } -} - -Glob.prototype._readdirEntries = function (abs, entries, cb) { - if (this.aborted) - return - - // if we haven't asked to stat everything, then just - // assume that everything in there exists, so we can avoid - // having to stat it a second time. - if (!this.mark && !this.stat) { - for (var i = 0; i < entries.length; i ++) { - var e = entries[i]; - if (abs === '/') - e = abs + e; - else - e = abs + '/' + e; - this.cache[e] = true; - } - } - - this.cache[abs] = entries; - return cb(null, entries) -}; - -Glob.prototype._readdirError = function (f, er, cb) { - if (this.aborted) - return - - // handle errors, and cache the information - switch (er.code) { - case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 - case 'ENOTDIR': // totally normal. means it *does* exist. - var abs = this._makeAbs(f); - this.cache[abs] = 'FILE'; - if (abs === this.cwdAbs) { - var error = new Error(er.code + ' invalid cwd ' + this.cwd); - error.path = this.cwd; - error.code = er.code; - this.emit('error', error); - this.abort(); - } - break - - case 'ENOENT': // not terribly unusual - case 'ELOOP': - case 'ENAMETOOLONG': - case 'UNKNOWN': - this.cache[this._makeAbs(f)] = false; - break - - default: // some unusual error. Treat as failure. - this.cache[this._makeAbs(f)] = false; - if (this.strict) { - this.emit('error', er); - // If the error is handled, then we abort - // if not, we threw out of here - this.abort(); - } - if (!this.silent) - console.error('glob error', er); - break - } - - return cb() -}; - -Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) { - var self = this; - this._readdir(abs, inGlobStar, function (er, entries) { - self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb); - }); -}; - - -Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { - //console.error('pgs2', prefix, remain[0], entries) - - // no entries means not a dir, so it can never have matches - // foo.txt/** doesn't match foo.txt - if (!entries) - return cb() - - // test without the globstar, and with every child both below - // and replacing the globstar. - var remainWithoutGlobStar = remain.slice(1); - var gspref = prefix ? [ prefix ] : []; - var noGlobStar = gspref.concat(remainWithoutGlobStar); - - // the noGlobStar pattern exits the inGlobStar state - this._process(noGlobStar, index, false, cb); - - var isSym = this.symlinks[abs]; - var len = entries.length; - - // If it's a symlink, and we're in a globstar, then stop - if (isSym && inGlobStar) - return cb() - - for (var i = 0; i < len; i++) { - var e = entries[i]; - if (e.charAt(0) === '.' && !this.dot) - continue - - // these two cases enter the inGlobStar state - var instead = gspref.concat(entries[i], remainWithoutGlobStar); - this._process(instead, index, true, cb); - - var below = gspref.concat(entries[i], remain); - this._process(below, index, true, cb); - } - - cb(); -}; - -Glob.prototype._processSimple = function (prefix, index, cb) { - // XXX review this. Shouldn't it be doing the mounting etc - // before doing stat? kinda weird? - var self = this; - this._stat(prefix, function (er, exists) { - self._processSimple2(prefix, index, er, exists, cb); - }); -}; -Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) { - - //console.error('ps2', prefix, exists) - - if (!this.matches[index]) - this.matches[index] = Object.create(null); - - // If it doesn't exist, then just mark the lack of results - if (!exists) - return cb() - - if (prefix && isAbsolute(prefix) && !this.nomount) { - var trail = /[\/\\]$/.test(prefix); - if (prefix.charAt(0) === '/') { - prefix = path$1.join(this.root, prefix); - } else { - prefix = path$1.resolve(this.root, prefix); - if (trail) - prefix += '/'; - } - } - - if (process.platform === 'win32') - prefix = prefix.replace(/\\/g, '/'); - - // Mark this as a match - this._emitMatch(index, prefix); - cb(); -}; - -// Returns either 'DIR', 'FILE', or false -Glob.prototype._stat = function (f, cb) { - var abs = this._makeAbs(f); - var needDir = f.slice(-1) === '/'; - - if (f.length > this.maxLength) - return cb() - - if (!this.stat && ownProp(this.cache, abs)) { - var c = this.cache[abs]; - - if (Array.isArray(c)) - c = 'DIR'; - - // It exists, but maybe not how we need it - if (!needDir || c === 'DIR') - return cb(null, c) - - if (needDir && c === 'FILE') - return cb() - - // otherwise we have to stat, because maybe c=true - // if we know it exists, but not what it is. - } - var stat = this.statCache[abs]; - if (stat !== undefined) { - if (stat === false) - return cb(null, stat) - else { - var type = stat.isDirectory() ? 'DIR' : 'FILE'; - if (needDir && type === 'FILE') - return cb() - else - return cb(null, type, stat) - } - } - - var self = this; - var statcb = inflight('stat\0' + abs, lstatcb_); - if (statcb) - fs.lstat(abs, statcb); - - function lstatcb_ (er, lstat) { - if (lstat && lstat.isSymbolicLink()) { - // If it's a symlink, then treat it as the target, unless - // the target does not exist, then treat it as a file. - return fs.stat(abs, function (er, stat) { - if (er) - self._stat2(f, abs, null, lstat, cb); - else - self._stat2(f, abs, er, stat, cb); - }) - } else { - self._stat2(f, abs, er, lstat, cb); - } - } -}; - -Glob.prototype._stat2 = function (f, abs, er, stat, cb) { - if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) { - this.statCache[abs] = false; - return cb() - } - - var needDir = f.slice(-1) === '/'; - this.statCache[abs] = stat; - - if (abs.slice(-1) === '/' && stat && !stat.isDirectory()) - return cb(null, false, stat) - - var c = true; - if (stat) - c = stat.isDirectory() ? 'DIR' : 'FILE'; - this.cache[abs] = this.cache[abs] || c; - - if (needDir && c === 'FILE') - return cb() - - return cb(null, c, stat) -}; - -/*! - * Determine if an object is a Buffer - * - * @author Feross Aboukhadijeh - * @license MIT - */ - -var isBuffer = function isBuffer (obj) { - return obj != null && obj.constructor != null && - typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) -}; - -var own$b = {}.hasOwnProperty; - -/** - * @typedef {import('unist').Node} Node - * @typedef {import('unist').Position} Position - * @typedef {import('unist').Point} Point - */ - -/** - * Stringify one point, a position (start and end points), or a node’s - * positional information. - * - * @param {Node|Position|Point} [value] - * @returns {string} - */ -function stringifyPosition$1(value) { - // Nothing. - if (!value || typeof value !== 'object') { - return '' - } - - // Node. - if (own$b.call(value, 'position') || own$b.call(value, 'type')) { - // @ts-ignore looks like a node. - return position(value.position) - } - - // Position. - if (own$b.call(value, 'start') || own$b.call(value, 'end')) { - // @ts-ignore looks like a position. - return position(value) - } - - // Point. - if (own$b.call(value, 'line') || own$b.call(value, 'column')) { - // @ts-ignore looks like a point. - return point$1(value) - } - - // ? - return '' -} - -/** - * @param {Point} point - * @returns {string} - */ -function point$1(point) { - return index$1(point && point.line) + ':' + index$1(point && point.column) -} - -/** - * @param {Position} pos - * @returns {string} - */ -function position(pos) { - return point$1(pos && pos.start) + '-' + point$1(pos && pos.end) -} - -/** - * @param {number} value - * @returns {number} - */ -function index$1(value) { - return value && typeof value === 'number' ? value : 1 -} - -/** - * @typedef {import('unist').Node} Node - * @typedef {import('unist').Position} Position - * @typedef {import('unist').Point} Point - */ - -class VFileMessage extends Error { - /** - * Constructor of a message for `reason` at `place` from `origin`. - * When an error is passed in as `reason`, copies the `stack`. - * - * @param {string|Error} reason Reason for message (`string` or `Error`). Uses the stack and message of the error if given. - * @param {Node|Position|Point} [place] Place at which the message occurred in a file (`Node`, `Position`, or `Point`, optional). - * @param {string} [origin] Place in code the message originates from (`string`, optional). - */ - constructor(reason, place, origin) { - /** @type {[string?, string?]} */ - var parts = [null, null]; - /** @type {Position} */ - var position = { - start: {line: null, column: null}, - end: {line: null, column: null} - }; - /** @type {number} */ - var index; - - super(); - - if (typeof place === 'string') { - origin = place; - place = null; - } - - if (typeof origin === 'string') { - index = origin.indexOf(':'); - - if (index === -1) { - parts[1] = origin; - } else { - parts[0] = origin.slice(0, index); - parts[1] = origin.slice(index + 1); - } - } - - if (place) { - // Node. - if ('type' in place || 'position' in place) { - if (place.position) { - position = place.position; - } - } - // Position. - else if ('start' in place || 'end' in place) { - // @ts-ignore Looks like a position. - position = place; - } - // Point. - else if ('line' in place || 'column' in place) { - // @ts-ignore Looks like a point. - position.start = place; - } - } - - // Fields from `Error` - this.name = stringifyPosition$1(place) || '1:1'; - this.message = typeof reason === 'object' ? reason.message : reason; - this.stack = typeof reason === 'object' ? reason.stack : ''; - - /** - * Reason for message. - * @type {string} - */ - this.reason = this.message; - /** - * Starting line of error. - * @type {number?} - */ - this.line = position.start.line; - /** - * Starting column of error. - * @type {number?} - */ - this.column = position.start.column; - /** - * Namespace of warning. - * @type {string?} - */ - this.source = parts[0]; - /** - * Category of message. - * @type {string?} - */ - this.ruleId = parts[1]; - /** - * Full range information, when available. - * Has start and end properties, both set to an object with line and column, set to number?. - * @type {Position?} - */ - this.position = position; - - // The following fields are “well known”. - // Not standard. - // Feel free to add other non-standard fields to your messages. - - /* eslint-disable no-unused-expressions */ - /** - * You may add a file property with a path of a file (used throughout the VFile ecosystem). - * @type {string?} - */ - this.file; - /** - * If true, marks associated file as no longer processable. - * @type {boolean?} - */ - this.fatal; - /** - * You may add a url property with a link to documentation for the message. - * @type {string?} - */ - this.url; - /** - * You may add a note property with a long form description of the message (supported by vfile-reporter). - * @type {string?} - */ - this.note; - /* eslint-enable no-unused-expressions */ - } -} - -VFileMessage.prototype.file = ''; -VFileMessage.prototype.name = ''; -VFileMessage.prototype.reason = ''; -VFileMessage.prototype.message = ''; -VFileMessage.prototype.stack = ''; -VFileMessage.prototype.fatal = null; -VFileMessage.prototype.column = null; -VFileMessage.prototype.line = null; -VFileMessage.prototype.source = null; -VFileMessage.prototype.ruleId = null; -VFileMessage.prototype.position = null; - -const proc$1 = process$1; - -/** - * @typedef URL - * @property {string} hash - * @property {string} host - * @property {string} hostname - * @property {string} href - * @property {string} origin - * @property {string} password - * @property {string} pathname - * @property {string} port - * @property {string} protocol - * @property {string} search - * @property {any} searchParams - * @property {string} username - * @property {() => string} toString - * @property {() => string} toJSON - */ - -/** - * @param {unknown} fileURLOrPath - * @returns {fileURLOrPath is URL} - */ -// From: -function isUrl(fileURLOrPath) { - return ( - fileURLOrPath !== null && - typeof fileURLOrPath === 'object' && - // @ts-expect-error: indexable. - fileURLOrPath.href && - // @ts-expect-error: indexable. - fileURLOrPath.origin - ) -} - -/** - * @typedef {import('unist').Node} Node - * @typedef {import('unist').Position} Position - * @typedef {import('unist').Point} Point - * @typedef {import('./minurl.shared.js').URL} URL - * - * @typedef {'ascii'|'utf8'|'utf-8'|'utf16le'|'ucs2'|'ucs-2'|'base64'|'latin1'|'binary'|'hex'} BufferEncoding - * Encodings supported by the buffer class. - * This is a copy of the typing from Node, copied to prevent Node globals from - * being needed. - * Copied from: - * - * @typedef {string|Uint8Array} VFileValue - * Contents of the file. - * Can either be text, or a Buffer like structure. - * This does not directly use type `Buffer`, because it can also be used in a - * browser context. - * Instead this leverages `Uint8Array` which is the base type for `Buffer`, - * and a native JavaScript construct. - * - * @typedef {VFileValue|VFileOptions|VFile|URL} VFileCompatible - * Things that can be passed to the constructor. - * - * @typedef VFileCoreOptions - * @property {VFileValue} [value] - * @property {string} [cwd] - * @property {Array.} [history] - * @property {string|URL} [path] - * @property {string} [basename] - * @property {string} [stem] - * @property {string} [extname] - * @property {string} [dirname] - * @property {Object.} [data] - * - * @typedef {{[key: string]: unknown} & VFileCoreOptions} VFileOptions - * Configuration: a bunch of keys that will be shallow copied over to the new - * file. - * - * @typedef {Object.} VFileReporterSettings - * @typedef {(files: VFile[], options: T) => string} VFileReporter - */ - -// Order of setting (least specific to most), we need this because otherwise -// `{stem: 'a', path: '~/b.js'}` would throw, as a path is needed before a -// stem can be set. -const order = ['history', 'path', 'basename', 'stem', 'extname', 'dirname']; - -class VFile { - /** - * Create a new virtual file. - * - * If `options` is `string` or `Buffer`, treats it as `{value: options}`. - * If `options` is a `VFile`, shallow copies its data over to the new file. - * All other given fields are set on the newly created `VFile`. - * - * Path related properties are set in the following order (least specific to - * most specific): `history`, `path`, `basename`, `stem`, `extname`, - * `dirname`. - * - * It’s not possible to set either `dirname` or `extname` without setting - * either `history`, `path`, `basename`, or `stem` as well. - * - * @param {VFileCompatible} [value] - */ - constructor(value) { - /** @type {VFileOptions} */ - let options; - - if (!value) { - options = {}; - } else if (typeof value === 'string' || isBuffer(value)) { - // @ts-expect-error Looks like a buffer. - options = {value}; - } else if (isUrl(value)) { - options = {path: value}; - } else { - // @ts-expect-error Looks like file or options. - options = value; - } - - /** - * Place to store custom information. - * It’s OK to store custom data directly on the file, moving it to `data` - * gives a little more privacy. - * @type {Object.} - */ - this.data = {}; - - /** - * List of messages associated with the file. - * @type {Array.} - */ - this.messages = []; - - /** - * List of file paths the file moved between. - * @type {Array.} - */ - this.history = []; - - /** - * Base of `path`. - * Defaults to `process.cwd()` (`/` in browsers). - * @type {string} - */ - this.cwd = proc$1.cwd(); - - /* eslint-disable no-unused-expressions */ - /** - * Raw value. - * @type {VFileValue} - */ - this.value; - - // The below are non-standard, they are “well-known”. - // As in, used in several tools. - - /** - * Whether a file was saved to disk. - * This is used by vfile reporters. - * @type {boolean} - */ - this.stored; - - /** - * Sometimes files have a non-string representation. - * This can be stored in the `result` field. - * One example is when turning markdown into React nodes. - * This is used by unified to store non-string results. - * @type {unknown} - */ - this.result; - - /** - * Sometimes files have a source map associated with them. - * This can be stored in the `map` field. - * This should be a `RawSourceMap` type from the `source-map` module. - * @type {unknown} - */ - this.map; - /* eslint-enable no-unused-expressions */ - - // Set path related properties in the correct order. - let index = -1; - - while (++index < order.length) { - const prop = order[index]; - - // Note: we specifically use `in` instead of `hasOwnProperty` to accept - // `vfile`s too. - if (prop in options && options[prop] !== undefined) { - // @ts-expect-error: TS is confused by the different types for `history`. - this[prop] = prop === 'history' ? [...options[prop]] : options[prop]; - } - } - - /** @type {string} */ - let prop; - - // Set non-path related properties. - for (prop in options) { - // @ts-expect-error: fine to set other things. - if (!order.includes(prop)) this[prop] = options[prop]; - } - } - - /** - * Access full path (`~/index.min.js`). - * - * @returns {string} - */ - get path() { - return this.history[this.history.length - 1] - } - - /** - * Set full path (`~/index.min.js`). - * Cannot be nullified. - * - * @param {string|URL} path - */ - set path(path) { - if (isUrl(path)) { - path = fileURLToPath(path); - } - - assertNonEmpty(path, 'path'); - - if (this.path !== path) { - this.history.push(path); - } - } - - /** - * Access parent path (`~`). - */ - get dirname() { - return typeof this.path === 'string' ? path$b.dirname(this.path) : undefined - } - - /** - * Set parent path (`~`). - * Cannot be set if there's no `path` yet. - */ - set dirname(dirname) { - assertPath(this.basename, 'dirname'); - this.path = path$b.join(dirname || '', this.basename); - } - - /** - * Access basename (including extname) (`index.min.js`). - */ - get basename() { - return typeof this.path === 'string' ? path$b.basename(this.path) : undefined - } - - /** - * Set basename (`index.min.js`). - * Cannot contain path separators. - * Cannot be nullified either (use `file.path = file.dirname` instead). - */ - set basename(basename) { - assertNonEmpty(basename, 'basename'); - assertPart(basename, 'basename'); - this.path = path$b.join(this.dirname || '', basename); - } - - /** - * Access extname (including dot) (`.js`). - */ - get extname() { - return typeof this.path === 'string' ? path$b.extname(this.path) : undefined - } - - /** - * Set extname (including dot) (`.js`). - * Cannot be set if there's no `path` yet and cannot contain path separators. - */ - set extname(extname) { - assertPart(extname, 'extname'); - assertPath(this.dirname, 'extname'); - - if (extname) { - if (extname.charCodeAt(0) !== 46 /* `.` */) { - throw new Error('`extname` must start with `.`') - } - - if (extname.includes('.', 1)) { - throw new Error('`extname` cannot contain multiple dots') - } - } - - this.path = path$b.join(this.dirname, this.stem + (extname || '')); - } - - /** - * Access stem (w/o extname) (`index.min`). - */ - get stem() { - return typeof this.path === 'string' - ? path$b.basename(this.path, this.extname) - : undefined - } - - /** - * Set stem (w/o extname) (`index.min`). - * Cannot be nullified, and cannot contain path separators. - */ - set stem(stem) { - assertNonEmpty(stem, 'stem'); - assertPart(stem, 'stem'); - this.path = path$b.join(this.dirname || '', stem + (this.extname || '')); - } - - /** - * Serialize the file. - * - * @param {BufferEncoding} [encoding='utf8'] If `file.value` is a buffer, `encoding` is used to serialize buffers. - * @returns {string} - */ - toString(encoding) { - // @ts-expect-error string’s don’t accept the parameter, but buffers do. - return (this.value || '').toString(encoding) - } - - /** - * Create a message and associates it w/ the file. - * - * @param {string|Error} reason Reason for message (`string` or `Error`). Uses the stack and message of the error if given. - * @param {Node|Position|Point} [place] Place at which the message occurred in a file (`Node`, `Position`, or `Point`, optional). - * @param {string} [origin] Place in code the message originates from (`string`, optional). - * @returns {VFileMessage} - */ - message(reason, place, origin) { - const message = new VFileMessage(reason, place, origin); - - if (this.path) { - message.name = this.path + ':' + message.name; - message.file = this.path; - } - - message.fatal = false; - - this.messages.push(message); - - return message - } - - /** - * Info: create a message, associate it with the file, and mark the fatality - * as `null`. - * Calls `message()` internally. - * - * @param {string|Error} reason Reason for message (`string` or `Error`). Uses the stack and message of the error if given. - * @param {Node|Position|Point} [place] Place at which the message occurred in a file (`Node`, `Position`, or `Point`, optional). - * @param {string} [origin] Place in code the message originates from (`string`, optional). - * @returns {VFileMessage} - */ - info(reason, place, origin) { - const message = this.message(reason, place, origin); - - message.fatal = null; - - return message - } - - /** - * Fail: create a message, associate it with the file, mark the fatality as - * `true`. - * Note: fatal errors mean a file is no longer processable. - * Calls `message()` internally. - * - * @param {string|Error} reason Reason for message (`string` or `Error`). Uses the stack and message of the error if given. - * @param {Node|Position|Point} [place] Place at which the message occurred in a file (`Node`, `Position`, or `Point`, optional). - * @param {string} [origin] Place in code the message originates from (`string`, optional). - * @returns {never} - */ - fail(reason, place, origin) { - const message = this.message(reason, place, origin); - - message.fatal = true; - - throw message - } -} - -/** - * Assert that `part` is not a path (as in, does not contain `path.sep`). - * - * @param {string|undefined} part - * @param {string} name - * @returns {void} - */ -function assertPart(part, name) { - if (part && part.includes(path$b.sep)) { - throw new Error( - '`' + name + '` cannot be a path: did not expect `' + path$b.sep + '`' - ) - } -} - -/** - * Assert that `part` is not empty. - * - * @param {string|undefined} part - * @param {string} name - * @returns {asserts part is string} - */ -function assertNonEmpty(part, name) { - if (!part) { - throw new Error('`' + name + '` cannot be empty') - } -} - -/** - * Assert `path` exists. - * - * @param {string|undefined} path - * @param {string} name - * @returns {asserts path is string} - */ -function assertPath(path, name) { - if (!path) { - throw new Error('Setting `' + name + '` requires `path` to be set too') - } -} - -/** - * @typedef {import('vfile').VFileValue} Value - * @typedef {import('vfile').VFileOptions} Options - * @typedef {import('vfile').BufferEncoding} BufferEncoding - * - * @typedef {number|string} Mode - * @typedef {BufferEncoding|{encoding?: null|BufferEncoding, flag?: string}} ReadOptions - * @typedef {BufferEncoding|{encoding?: null|BufferEncoding, mode: Mode?, flag?: string}} WriteOptions - * - * @typedef {string|Uint8Array} Path Path of the file. - * @typedef {Path|URL|Options|VFile} Compatible Things that can be - * passed to the function. - */ - -/** - * Create a virtual file from a description. - * If `options` is a string or a buffer, it’s used as the path. - * If it’s a VFile itself, it’s returned instead. - * In all other cases, the options are passed through to `vfile()`. - * - * @param {Compatible} [options] - * @returns {VFile} - */ -function toVFile(options) { - if (typeof options === 'string' || options instanceof URL$1) { - options = {path: options}; - } else if (isBuffer(options)) { - options = {path: String(options)}; - } - - return looksLikeAVFile$1(options) ? options : new VFile(options) -} - -/** - * Create a virtual file and read it in, synchronously. - * - * @param {Compatible} description - * @param {ReadOptions} [options] - * @returns {VFile} - */ -function readSync(description, options) { - const file = toVFile(description); - file.value = require$$0$3.readFileSync(path$b.resolve(file.cwd, file.path), options); - return file -} - -/** - * Create a virtual file and write it in, synchronously. - * - * @param {Compatible} description - * @param {WriteOptions} [options] - * @returns {VFile} - */ -function writeSync(description, options) { - const file = toVFile(description); - require$$0$3.writeFileSync(path$b.resolve(file.cwd, file.path), file.value || '', options); - return file -} - -const read$2 = - /** - * @type {{ - * (description: Compatible, options: ReadOptions, callback: Callback): void - * (description: Compatible, callback: Callback): void - * (description: Compatible, options?: ReadOptions): Promise - * }} - */ - ( - /** - * Create a virtual file and read it in, asynchronously. - * - * @param {Compatible} description - * @param {ReadOptions} [options] - * @param {Callback} [callback] - */ - function (description, options, callback) { - const file = toVFile(description); - - if (!callback && typeof options === 'function') { - callback = options; - options = null; - } - - if (!callback) { - return new Promise(executor) - } - - executor(resolve, callback); - - /** - * @param {VFile} result - */ - function resolve(result) { - callback(null, result); - } - - /** - * @param {(x: VFile) => void} resolve - * @param {(x: Error, y?: VFile) => void} reject - */ - function executor(resolve, reject) { - /** @type {string} */ - let fp; - - try { - fp = path$b.resolve(file.cwd, file.path); - } catch (error) { - return reject(error) - } - - require$$0$3.readFile(fp, options, done); - - /** - * @param {Error} error - * @param {Value} result - */ - function done(error, result) { - if (error) { - reject(error); - } else { - file.value = result; - resolve(file); - } - } - } - } - ); - -const write = - /** - * @type {{ - * (description: Compatible, options: WriteOptions, callback: Callback): void - * (description: Compatible, callback: Callback): void - * (description: Compatible, options?: WriteOptions): Promise - * }} - */ - ( - /** - * Create a virtual file and write it in, asynchronously. - * - * @param {Compatible} description - * @param {WriteOptions} [options] - * @param {Callback} [callback] - */ - function (description, options, callback) { - const file = toVFile(description); - - // Weird, right? Otherwise `fs` doesn’t accept it. - if (!callback && typeof options === 'function') { - callback = options; - options = undefined; - } - - if (!callback) { - return new Promise(executor) - } - - executor(resolve, callback); - - /** - * @param {VFile} result - */ - function resolve(result) { - callback(null, result); - } - - /** - * @param {(x: VFile) => void} resolve - * @param {(x: Error, y?: VFile) => void} reject - */ - function executor(resolve, reject) { - /** @type {string} */ - let fp; - - try { - fp = path$b.resolve(file.cwd, file.path); - } catch (error) { - return reject(error) - } - - require$$0$3.writeFile(fp, file.value || '', options, done); - - /** - * @param {Error} error - */ - function done(error) { - if (error) { - reject(error); - } else { - resolve(file); - } - } - } - } - ); - -/** - * @param {Compatible} value - * @returns {value is VFile} - */ -function looksLikeAVFile$1(value) { - return ( - value && - typeof value === 'object' && - 'message' in value && - 'messages' in value - ) -} - -toVFile.readSync = readSync; -toVFile.writeSync = writeSync; -toVFile.read = read$2; -toVFile.write = write; - -/** - * @typedef {import('fs').Stats} Stats - * @typedef {import('vfile').VFile} VFile - * @typedef {import('./ignore.js').Ignore} Ignore - * @typedef {import('ignore').Ignore} GitIgnore - * - * @typedef Options - * @property {string} cwd - * @property {Array.} extensions - * @property {boolean|undefined} silentlyIgnore - * @property {Array.} ignorePatterns - * @property {Ignore} ignore - * - * @typedef SearchResults - * @property {fs.Stats|undefined} stats - * @property {boolean|undefined} ignored - * - * @typedef Result - * @property {Array.} input - * @property {VFile[]} output - * - * @typedef CleanResult - * @property {boolean} oneFileMode - * @property {VFile[]} files - * - * @callback Callback - * @param {Error|null} error - * @param {CleanResult} [result] - */ - -/** - * Search `patterns`, a mix of globs, paths, and files. - * - * @param {Array.} input - * @param {Options} options - * @param {Callback} callback - */ -function finder(input, options, callback) { - expand(input, options, (error, result) => { - // Glob errors are unusual. - // other errors are on the vfile results. - /* c8 ignore next 2 */ - if (error || !result) { - callback(error); - } else { - callback(null, {oneFileMode: oneFileMode(result), files: result.output}); - } - }); -} - -/** - * Expand the given glob patterns, search given and found directories, and map - * to vfiles. - * - * @param {Array.} input - * @param {Options} options - * @param {(error: Error|null, result?: Result) => void} next - */ -function expand(input, options, next) { - /** @type {Array.} */ - let paths = []; - let actual = 0; - let expected = 0; - let index = -1; - /** @type {boolean|undefined} */ - let failed; - - while (++index < input.length) { - let file = input[index]; - if (typeof file === 'string') { - if (glob_1.hasMagic(file)) { - expected++; - glob_1(file, {cwd: options.cwd}, (error, files) => { - // Glob errors are unusual. - /* c8 ignore next 3 */ - if (failed) { - return - } - - // Glob errors are unusual. - /* c8 ignore next 4 */ - if (error) { - failed = true; - done1(error); - } else { - actual++; - paths = paths.concat(files); - - if (actual === expected) { - search$1(paths, options, done1); - } - } - }); - } else { - // `relative` to make the paths canonical. - file = - path$c.relative(options.cwd, path$c.resolve(options.cwd, file)) || '.'; - paths.push(file); - } - } else { - const fp = file.path ? path$c.relative(options.cwd, file.path) : options.cwd; - file.cwd = options.cwd; - file.path = fp; - file.history = [fp]; - paths.push(file); - } - } - - if (!expected) { - search$1(paths, options, done1); - } - - /** - * @param {Error|null} error - * @param {Array} [files] - */ - function done1(error, files) { - // `search` currently does not give errors. - /* c8 ignore next 2 */ - if (error || !files) { - next(error); - } else { - next(null, {input: paths, output: files}); - } - } -} - -/** - * Search `paths`. - * - * @param {Array.} input - * @param {Options & {nested?: boolean}} options - * @param {(error: Error|null, files: Array.) => void} next - */ -function search$1(input, options, next) { - const extraIgnore = ignore().add(options.ignorePatterns); - let expected = 0; - let actual = 0; - let index = -1; - /** @type {Array.} */ - let files = []; - - while (++index < input.length) { - each(input[index]); - } - - if (!expected) { - next(null, files); - } - - /** - * @param {string|VFile} file - */ - function each(file) { - const ext = typeof file === 'string' ? path$c.extname(file) : file.extname; - - // Normalise globs. - if (typeof file === 'string') { - file = file.split('/').join(path$c.sep); - } - - const part = base$1(file); - - if ( - options.nested && - part && - (part.charAt(0) === '.' || part === 'node_modules') - ) { - return - } - - expected++; - - statAndIgnore( - file, - Object.assign({}, options, {extraIgnore}), - (error, result) => { - const ignored = result && result.ignored; - const dir = result && result.stats && result.stats.isDirectory(); - - if (ignored && (options.nested || options.silentlyIgnore)) { - return one(null, []) - } - - if (!ignored && dir) { - return fs$a.readdir( - path$c.resolve(options.cwd, filePath(file)), - (error, basenames) => { - // Should not happen often: the directory is `stat`ed first, which was ok, - // but reading it is not. - /* c8 ignore next 9 */ - if (error) { - const otherFile = toVFile(filePath(file)); - otherFile.cwd = options.cwd; - - try { - otherFile.fail('Cannot read directory'); - } catch {} - - one(null, [otherFile]); - } else { - search$1( - basenames.map((name) => path$c.join(filePath(file), name)), - Object.assign({}, options, {nested: true}), - one - ); - } - } - ) - } - - if ( - !dir && - options.nested && - options.extensions.length > 0 && - (!ext || !options.extensions.includes(ext)) - ) { - return one(null, []) - } - - file = toVFile(file); - file.cwd = options.cwd; - - if (ignored) { - try { - file.fail('Cannot process specified file: it’s ignored'); - // C8 bug on Node@12 - /* c8 ignore next 1 */ - } catch {} - } - - if (error && error.code === 'ENOENT') { - try { - file.fail( - error.syscall === 'stat' ? 'No such file or directory' : error - ); - // C8 bug on Node@12 - /* c8 ignore next 1 */ - } catch {} - } - - one(null, [file]); - } - ); - - /** - * Error is never given. Always given `results`. - * - * @param {Error|null} _ - * @param {Array.} results - */ - function one(_, results) { - /* istanbul ignore else - Always given. */ - if (results) { - files = files.concat(results); - } - - actual++; - - if (actual === expected) { - next(null, files); - } - } - } -} - -/** - * @param {VFile|string} file - * @param {Options & {extraIgnore: GitIgnore}} options - * @param {(error: NodeJS.ErrnoException|null, result?: SearchResults) => void} callback - */ -function statAndIgnore(file, options, callback) { - const fp = path$c.resolve(options.cwd, filePath(file)); - const normal = path$c.relative(options.cwd, fp); - let expected = 1; - let actual = 0; - /** @type {Stats|undefined} */ - let stats; - /** @type {boolean|undefined} */ - let ignored; - - if (typeof file === 'string' || !file.value) { - expected++; - fs$a.stat(fp, (error, value) => { - stats = value; - onStartOrCheck(error); - }); - } - - options.ignore.check(fp, (error, value) => { - ignored = value; - onStartOrCheck(error); - }); - - /** - * @param {Error|null} error - */ - function onStartOrCheck(error) { - actual++; - - if (error) { - callback(error); - actual = -1; - } else if (actual === expected) { - callback(null, { - stats, - ignored: - ignored || - (normal === '' || - normal === '..' || - normal.charAt(0) === path$c.sep || - normal.slice(0, 3) === '..' + path$c.sep - ? false - : options.extraIgnore.ignores(normal)) - }); - } - } -} - -/** - * @param {string|VFile} file - * @returns {string|undefined} - */ -function base$1(file) { - return typeof file === 'string' ? path$c.basename(file) : file.basename -} - -/** - * @param {string|VFile} file - * @returns {string} - */ -function filePath(file) { - return typeof file === 'string' ? file : file.path -} - -/** - * @param {Result} result - * @returns {boolean} - */ -function oneFileMode(result) { - return ( - result.output.length === 1 && - result.input.length === 1 && - result.output[0].path === result.input[0] - ) -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('trough').Callback} Callback - * @typedef {import('./index.js').Settings} Settings - * @typedef {import('./index.js').Configuration} Configuration - */ - -/** - * @param {Context} context - * @param {Settings} settings - * @param {Callback} next - */ -function fileSystem$1(context, settings, next) { - if (context.files.length === 0) { - next(); - } else { - finder( - context.files, - { - cwd: settings.cwd, - extensions: settings.extensions, - silentlyIgnore: settings.silentlyIgnore, - ignorePatterns: settings.ignorePatterns, - ignore: new Ignore({ - cwd: settings.cwd, - detectIgnore: settings.detectIgnore, - ignoreName: settings.ignoreName, - ignorePath: settings.ignorePath, - ignorePathResolveFrom: settings.ignorePathResolveFrom - }) - }, - (error, result) => { - // Glob errors typically don’t occur. - /* c8 ignore next 4 */ - if (!result) { - next(error); - return - } - - const output = result.files; - - // Sort alphabetically. - // Everything is unique so we do not care about cases where left and right - // are equal. - output.sort(sortAlphabetically); - - // Mark as given. - // This allows outputting files, which can be pretty dangerous, so it’s - // “hidden”. - let index = -1; - while (++index < output.length) { - output[index].data.unifiedEngineGiven = true; - } - - context.files = output; - - // If `out` was not set, detect it based on whether one file was given. - if (settings.out === null || settings.out === undefined) { - settings.out = result.oneFileMode; - } - - next(error); - } - ); - } - - /** - * @param {VFile} left - * @param {VFile} right - * @returns {number} - */ - function sortAlphabetically(left, right) { - return left.path < right.path ? -1 : 1 - } -} - -/* eslint-disable node/no-deprecated-api */ - -var toString$2 = Object.prototype.toString; - -var isModern = ( - typeof Buffer !== 'undefined' && - typeof Buffer.alloc === 'function' && - typeof Buffer.allocUnsafe === 'function' && - typeof Buffer.from === 'function' -); - -function isArrayBuffer (input) { - return toString$2.call(input).slice(8, -1) === 'ArrayBuffer' -} - -function fromArrayBuffer (obj, byteOffset, length) { - byteOffset >>>= 0; - - var maxLength = obj.byteLength - byteOffset; - - if (maxLength < 0) { - throw new RangeError("'offset' is out of bounds") - } - - if (length === undefined) { - length = maxLength; - } else { - length >>>= 0; - - if (length > maxLength) { - throw new RangeError("'length' is out of bounds") - } - } - - return isModern - ? Buffer.from(obj.slice(byteOffset, byteOffset + length)) - : new Buffer(new Uint8Array(obj.slice(byteOffset, byteOffset + length))) -} - -function fromString (string, encoding) { - if (typeof encoding !== 'string' || encoding === '') { - encoding = 'utf8'; - } - - if (!Buffer.isEncoding(encoding)) { - throw new TypeError('"encoding" must be a valid string encoding') - } - - return isModern - ? Buffer.from(string, encoding) - : new Buffer(string, encoding) -} - -function bufferFrom$1 (value, encodingOrOffset, length) { - if (typeof value === 'number') { - throw new TypeError('"value" argument must not be a number') - } - - if (isArrayBuffer(value)) { - return fromArrayBuffer(value, encodingOrOffset, length) - } - - if (typeof value === 'string') { - return fromString(value, encodingOrOffset) - } - - return isModern - ? Buffer.from(value) - : new Buffer(value) -} - -var bufferFrom_1 = bufferFrom$1; - -var typedarray = {}; - -(function (exports) { -var undefined$1 = (void 0); // Paranoia - -// Beyond this value, index getters/setters (i.e. array[0], array[1]) are so slow to -// create, and consume so much memory, that the browser appears frozen. -var MAX_ARRAY_LENGTH = 1e5; - -// Approximations of internal ECMAScript conversion functions -var ECMAScript = (function() { - // Stash a copy in case other scripts modify these - var opts = Object.prototype.toString, - ophop = Object.prototype.hasOwnProperty; - - return { - // Class returns internal [[Class]] property, used to avoid cross-frame instanceof issues: - Class: function(v) { return opts.call(v).replace(/^\[object *|\]$/g, ''); }, - HasProperty: function(o, p) { return p in o; }, - HasOwnProperty: function(o, p) { return ophop.call(o, p); }, - IsCallable: function(o) { return typeof o === 'function'; }, - ToInt32: function(v) { return v >> 0; }, - ToUint32: function(v) { return v >>> 0; } - }; -}()); - -// Snapshot intrinsics -var LN2 = Math.LN2, - abs = Math.abs, - floor = Math.floor, - log = Math.log, - min = Math.min, - pow = Math.pow, - round = Math.round; - -// ES5: lock down object properties -function configureProperties(obj) { - if (getOwnPropNames && defineProp) { - var props = getOwnPropNames(obj), i; - for (i = 0; i < props.length; i += 1) { - defineProp(obj, props[i], { - value: obj[props[i]], - writable: false, - enumerable: false, - configurable: false - }); - } - } -} - -// emulate ES5 getter/setter API using legacy APIs -// http://blogs.msdn.com/b/ie/archive/2010/09/07/transitioning-existing-code-to-the-es5-getter-setter-apis.aspx -// (second clause tests for Object.defineProperty() in IE<9 that only supports extending DOM prototypes, but -// note that IE<9 does not support __defineGetter__ or __defineSetter__ so it just renders the method harmless) -var defineProp; -if (Object.defineProperty && (function() { - try { - Object.defineProperty({}, 'x', {}); - return true; - } catch (e) { - return false; - } - })()) { - defineProp = Object.defineProperty; -} else { - defineProp = function(o, p, desc) { - if (!o === Object(o)) throw new TypeError("Object.defineProperty called on non-object"); - if (ECMAScript.HasProperty(desc, 'get') && Object.prototype.__defineGetter__) { Object.prototype.__defineGetter__.call(o, p, desc.get); } - if (ECMAScript.HasProperty(desc, 'set') && Object.prototype.__defineSetter__) { Object.prototype.__defineSetter__.call(o, p, desc.set); } - if (ECMAScript.HasProperty(desc, 'value')) { o[p] = desc.value; } - return o; - }; -} - -var getOwnPropNames = Object.getOwnPropertyNames || function (o) { - if (o !== Object(o)) throw new TypeError("Object.getOwnPropertyNames called on non-object"); - var props = [], p; - for (p in o) { - if (ECMAScript.HasOwnProperty(o, p)) { - props.push(p); - } - } - return props; -}; - -// ES5: Make obj[index] an alias for obj._getter(index)/obj._setter(index, value) -// for index in 0 ... obj.length -function makeArrayAccessors(obj) { - if (!defineProp) { return; } - - if (obj.length > MAX_ARRAY_LENGTH) throw new RangeError("Array too large for polyfill"); - - function makeArrayAccessor(index) { - defineProp(obj, index, { - 'get': function() { return obj._getter(index); }, - 'set': function(v) { obj._setter(index, v); }, - enumerable: true, - configurable: false - }); - } - - var i; - for (i = 0; i < obj.length; i += 1) { - makeArrayAccessor(i); - } -} - -// Internal conversion functions: -// pack() - take a number (interpreted as Type), output a byte array -// unpack() - take a byte array, output a Type-like number - -function as_signed(value, bits) { var s = 32 - bits; return (value << s) >> s; } -function as_unsigned(value, bits) { var s = 32 - bits; return (value << s) >>> s; } - -function packI8(n) { return [n & 0xff]; } -function unpackI8(bytes) { return as_signed(bytes[0], 8); } - -function packU8(n) { return [n & 0xff]; } -function unpackU8(bytes) { return as_unsigned(bytes[0], 8); } - -function packU8Clamped(n) { n = round(Number(n)); return [n < 0 ? 0 : n > 0xff ? 0xff : n & 0xff]; } - -function packI16(n) { return [(n >> 8) & 0xff, n & 0xff]; } -function unpackI16(bytes) { return as_signed(bytes[0] << 8 | bytes[1], 16); } - -function packU16(n) { return [(n >> 8) & 0xff, n & 0xff]; } -function unpackU16(bytes) { return as_unsigned(bytes[0] << 8 | bytes[1], 16); } - -function packI32(n) { return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; } -function unpackI32(bytes) { return as_signed(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32); } - -function packU32(n) { return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; } -function unpackU32(bytes) { return as_unsigned(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32); } - -function packIEEE754(v, ebits, fbits) { - - var bias = (1 << (ebits - 1)) - 1, - s, e, f, i, bits, str, bytes; - - function roundToEven(n) { - var w = floor(n), f = n - w; - if (f < 0.5) - return w; - if (f > 0.5) - return w + 1; - return w % 2 ? w + 1 : w; - } - - // Compute sign, exponent, fraction - if (v !== v) { - // NaN - // http://dev.w3.org/2006/webapi/WebIDL/#es-type-mapping - e = (1 << ebits) - 1; f = pow(2, fbits - 1); s = 0; - } else if (v === Infinity || v === -Infinity) { - e = (1 << ebits) - 1; f = 0; s = (v < 0) ? 1 : 0; - } else if (v === 0) { - e = 0; f = 0; s = (1 / v === -Infinity) ? 1 : 0; - } else { - s = v < 0; - v = abs(v); - - if (v >= pow(2, 1 - bias)) { - e = min(floor(log(v) / LN2), 1023); - f = roundToEven(v / pow(2, e) * pow(2, fbits)); - if (f / pow(2, fbits) >= 2) { - e = e + 1; - f = 1; - } - if (e > bias) { - // Overflow - e = (1 << ebits) - 1; - f = 0; - } else { - // Normalized - e = e + bias; - f = f - pow(2, fbits); - } - } else { - // Denormalized - e = 0; - f = roundToEven(v / pow(2, 1 - bias - fbits)); - } - } - - // Pack sign, exponent, fraction - bits = []; - for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = floor(f / 2); } - for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = floor(e / 2); } - bits.push(s ? 1 : 0); - bits.reverse(); - str = bits.join(''); - - // Bits to bytes - bytes = []; - while (str.length) { - bytes.push(parseInt(str.substring(0, 8), 2)); - str = str.substring(8); - } - return bytes; -} - -function unpackIEEE754(bytes, ebits, fbits) { - - // Bytes to bits - var bits = [], i, j, b, str, - bias, s, e, f; - - for (i = bytes.length; i; i -= 1) { - b = bytes[i - 1]; - for (j = 8; j; j -= 1) { - bits.push(b % 2 ? 1 : 0); b = b >> 1; - } - } - bits.reverse(); - str = bits.join(''); - - // Unpack sign, exponent, fraction - bias = (1 << (ebits - 1)) - 1; - s = parseInt(str.substring(0, 1), 2) ? -1 : 1; - e = parseInt(str.substring(1, 1 + ebits), 2); - f = parseInt(str.substring(1 + ebits), 2); - - // Produce number - if (e === (1 << ebits) - 1) { - return f !== 0 ? NaN : s * Infinity; - } else if (e > 0) { - // Normalized - return s * pow(2, e - bias) * (1 + f / pow(2, fbits)); - } else if (f !== 0) { - // Denormalized - return s * pow(2, -(bias - 1)) * (f / pow(2, fbits)); - } else { - return s < 0 ? -0 : 0; - } -} - -function unpackF64(b) { return unpackIEEE754(b, 11, 52); } -function packF64(v) { return packIEEE754(v, 11, 52); } -function unpackF32(b) { return unpackIEEE754(b, 8, 23); } -function packF32(v) { return packIEEE754(v, 8, 23); } - - -// -// 3 The ArrayBuffer Type -// - -(function() { - - /** @constructor */ - var ArrayBuffer = function ArrayBuffer(length) { - length = ECMAScript.ToInt32(length); - if (length < 0) throw new RangeError('ArrayBuffer size is not a small enough positive integer'); - - this.byteLength = length; - this._bytes = []; - this._bytes.length = length; - - var i; - for (i = 0; i < this.byteLength; i += 1) { - this._bytes[i] = 0; - } - - configureProperties(this); - }; - - exports.ArrayBuffer = exports.ArrayBuffer || ArrayBuffer; - - // - // 4 The ArrayBufferView Type - // - - // NOTE: this constructor is not exported - /** @constructor */ - var ArrayBufferView = function ArrayBufferView() { - //this.buffer = null; - //this.byteOffset = 0; - //this.byteLength = 0; - }; - - // - // 5 The Typed Array View Types - // - - function makeConstructor(bytesPerElement, pack, unpack) { - // Each TypedArray type requires a distinct constructor instance with - // identical logic, which this produces. - - var ctor; - ctor = function(buffer, byteOffset, length) { - var array, sequence, i, s; - - if (!arguments.length || typeof arguments[0] === 'number') { - // Constructor(unsigned long length) - this.length = ECMAScript.ToInt32(arguments[0]); - if (length < 0) throw new RangeError('ArrayBufferView size is not a small enough positive integer'); - - this.byteLength = this.length * this.BYTES_PER_ELEMENT; - this.buffer = new ArrayBuffer(this.byteLength); - this.byteOffset = 0; - } else if (typeof arguments[0] === 'object' && arguments[0].constructor === ctor) { - // Constructor(TypedArray array) - array = arguments[0]; - - this.length = array.length; - this.byteLength = this.length * this.BYTES_PER_ELEMENT; - this.buffer = new ArrayBuffer(this.byteLength); - this.byteOffset = 0; - - for (i = 0; i < this.length; i += 1) { - this._setter(i, array._getter(i)); - } - } else if (typeof arguments[0] === 'object' && - !(arguments[0] instanceof ArrayBuffer || ECMAScript.Class(arguments[0]) === 'ArrayBuffer')) { - // Constructor(sequence array) - sequence = arguments[0]; - - this.length = ECMAScript.ToUint32(sequence.length); - this.byteLength = this.length * this.BYTES_PER_ELEMENT; - this.buffer = new ArrayBuffer(this.byteLength); - this.byteOffset = 0; - - for (i = 0; i < this.length; i += 1) { - s = sequence[i]; - this._setter(i, Number(s)); - } - } else if (typeof arguments[0] === 'object' && - (arguments[0] instanceof ArrayBuffer || ECMAScript.Class(arguments[0]) === 'ArrayBuffer')) { - // Constructor(ArrayBuffer buffer, - // optional unsigned long byteOffset, optional unsigned long length) - this.buffer = buffer; - - this.byteOffset = ECMAScript.ToUint32(byteOffset); - if (this.byteOffset > this.buffer.byteLength) { - throw new RangeError("byteOffset out of range"); - } - - if (this.byteOffset % this.BYTES_PER_ELEMENT) { - // The given byteOffset must be a multiple of the element - // size of the specific type, otherwise an exception is raised. - throw new RangeError("ArrayBuffer length minus the byteOffset is not a multiple of the element size."); - } - - if (arguments.length < 3) { - this.byteLength = this.buffer.byteLength - this.byteOffset; - - if (this.byteLength % this.BYTES_PER_ELEMENT) { - throw new RangeError("length of buffer minus byteOffset not a multiple of the element size"); - } - this.length = this.byteLength / this.BYTES_PER_ELEMENT; - } else { - this.length = ECMAScript.ToUint32(length); - this.byteLength = this.length * this.BYTES_PER_ELEMENT; - } - - if ((this.byteOffset + this.byteLength) > this.buffer.byteLength) { - throw new RangeError("byteOffset and length reference an area beyond the end of the buffer"); - } - } else { - throw new TypeError("Unexpected argument type(s)"); - } - - this.constructor = ctor; - - configureProperties(this); - makeArrayAccessors(this); - }; - - ctor.prototype = new ArrayBufferView(); - ctor.prototype.BYTES_PER_ELEMENT = bytesPerElement; - ctor.prototype._pack = pack; - ctor.prototype._unpack = unpack; - ctor.BYTES_PER_ELEMENT = bytesPerElement; - - // getter type (unsigned long index); - ctor.prototype._getter = function(index) { - if (arguments.length < 1) throw new SyntaxError("Not enough arguments"); - - index = ECMAScript.ToUint32(index); - if (index >= this.length) { - return undefined$1; - } - - var bytes = [], i, o; - for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT; - i < this.BYTES_PER_ELEMENT; - i += 1, o += 1) { - bytes.push(this.buffer._bytes[o]); - } - return this._unpack(bytes); - }; - - // NONSTANDARD: convenience alias for getter: type get(unsigned long index); - ctor.prototype.get = ctor.prototype._getter; - - // setter void (unsigned long index, type value); - ctor.prototype._setter = function(index, value) { - if (arguments.length < 2) throw new SyntaxError("Not enough arguments"); - - index = ECMAScript.ToUint32(index); - if (index >= this.length) { - return undefined$1; - } - - var bytes = this._pack(value), i, o; - for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT; - i < this.BYTES_PER_ELEMENT; - i += 1, o += 1) { - this.buffer._bytes[o] = bytes[i]; - } - }; - - // void set(TypedArray array, optional unsigned long offset); - // void set(sequence array, optional unsigned long offset); - ctor.prototype.set = function(index, value) { - if (arguments.length < 1) throw new SyntaxError("Not enough arguments"); - var array, sequence, offset, len, - i, s, d, - byteOffset, byteLength, tmp; - - if (typeof arguments[0] === 'object' && arguments[0].constructor === this.constructor) { - // void set(TypedArray array, optional unsigned long offset); - array = arguments[0]; - offset = ECMAScript.ToUint32(arguments[1]); - - if (offset + array.length > this.length) { - throw new RangeError("Offset plus length of array is out of range"); - } - - byteOffset = this.byteOffset + offset * this.BYTES_PER_ELEMENT; - byteLength = array.length * this.BYTES_PER_ELEMENT; - - if (array.buffer === this.buffer) { - tmp = []; - for (i = 0, s = array.byteOffset; i < byteLength; i += 1, s += 1) { - tmp[i] = array.buffer._bytes[s]; - } - for (i = 0, d = byteOffset; i < byteLength; i += 1, d += 1) { - this.buffer._bytes[d] = tmp[i]; - } - } else { - for (i = 0, s = array.byteOffset, d = byteOffset; - i < byteLength; i += 1, s += 1, d += 1) { - this.buffer._bytes[d] = array.buffer._bytes[s]; - } - } - } else if (typeof arguments[0] === 'object' && typeof arguments[0].length !== 'undefined') { - // void set(sequence array, optional unsigned long offset); - sequence = arguments[0]; - len = ECMAScript.ToUint32(sequence.length); - offset = ECMAScript.ToUint32(arguments[1]); - - if (offset + len > this.length) { - throw new RangeError("Offset plus length of array is out of range"); - } - - for (i = 0; i < len; i += 1) { - s = sequence[i]; - this._setter(offset + i, Number(s)); - } - } else { - throw new TypeError("Unexpected argument type(s)"); - } - }; - - // TypedArray subarray(long begin, optional long end); - ctor.prototype.subarray = function(start, end) { - function clamp(v, min, max) { return v < min ? min : v > max ? max : v; } - - start = ECMAScript.ToInt32(start); - end = ECMAScript.ToInt32(end); - - if (arguments.length < 1) { start = 0; } - if (arguments.length < 2) { end = this.length; } - - if (start < 0) { start = this.length + start; } - if (end < 0) { end = this.length + end; } - - start = clamp(start, 0, this.length); - end = clamp(end, 0, this.length); - - var len = end - start; - if (len < 0) { - len = 0; - } - - return new this.constructor( - this.buffer, this.byteOffset + start * this.BYTES_PER_ELEMENT, len); - }; - - return ctor; - } - - var Int8Array = makeConstructor(1, packI8, unpackI8); - var Uint8Array = makeConstructor(1, packU8, unpackU8); - var Uint8ClampedArray = makeConstructor(1, packU8Clamped, unpackU8); - var Int16Array = makeConstructor(2, packI16, unpackI16); - var Uint16Array = makeConstructor(2, packU16, unpackU16); - var Int32Array = makeConstructor(4, packI32, unpackI32); - var Uint32Array = makeConstructor(4, packU32, unpackU32); - var Float32Array = makeConstructor(4, packF32, unpackF32); - var Float64Array = makeConstructor(8, packF64, unpackF64); - - exports.Int8Array = exports.Int8Array || Int8Array; - exports.Uint8Array = exports.Uint8Array || Uint8Array; - exports.Uint8ClampedArray = exports.Uint8ClampedArray || Uint8ClampedArray; - exports.Int16Array = exports.Int16Array || Int16Array; - exports.Uint16Array = exports.Uint16Array || Uint16Array; - exports.Int32Array = exports.Int32Array || Int32Array; - exports.Uint32Array = exports.Uint32Array || Uint32Array; - exports.Float32Array = exports.Float32Array || Float32Array; - exports.Float64Array = exports.Float64Array || Float64Array; -}()); - -// -// 6 The DataView View Type -// - -(function() { - function r(array, index) { - return ECMAScript.IsCallable(array.get) ? array.get(index) : array[index]; - } - - var IS_BIG_ENDIAN = (function() { - var u16array = new(exports.Uint16Array)([0x1234]), - u8array = new(exports.Uint8Array)(u16array.buffer); - return r(u8array, 0) === 0x12; - }()); - - // Constructor(ArrayBuffer buffer, - // optional unsigned long byteOffset, - // optional unsigned long byteLength) - /** @constructor */ - var DataView = function DataView(buffer, byteOffset, byteLength) { - if (arguments.length === 0) { - buffer = new exports.ArrayBuffer(0); - } else if (!(buffer instanceof exports.ArrayBuffer || ECMAScript.Class(buffer) === 'ArrayBuffer')) { - throw new TypeError("TypeError"); - } - - this.buffer = buffer || new exports.ArrayBuffer(0); - - this.byteOffset = ECMAScript.ToUint32(byteOffset); - if (this.byteOffset > this.buffer.byteLength) { - throw new RangeError("byteOffset out of range"); - } - - if (arguments.length < 3) { - this.byteLength = this.buffer.byteLength - this.byteOffset; - } else { - this.byteLength = ECMAScript.ToUint32(byteLength); - } - - if ((this.byteOffset + this.byteLength) > this.buffer.byteLength) { - throw new RangeError("byteOffset and length reference an area beyond the end of the buffer"); - } - - configureProperties(this); - }; - - function makeGetter(arrayType) { - return function(byteOffset, littleEndian) { - - byteOffset = ECMAScript.ToUint32(byteOffset); - - if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength) { - throw new RangeError("Array index out of range"); - } - byteOffset += this.byteOffset; - - var uint8Array = new exports.Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT), - bytes = [], i; - for (i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1) { - bytes.push(r(uint8Array, i)); - } - - if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN)) { - bytes.reverse(); - } - - return r(new arrayType(new exports.Uint8Array(bytes).buffer), 0); - }; - } - - DataView.prototype.getUint8 = makeGetter(exports.Uint8Array); - DataView.prototype.getInt8 = makeGetter(exports.Int8Array); - DataView.prototype.getUint16 = makeGetter(exports.Uint16Array); - DataView.prototype.getInt16 = makeGetter(exports.Int16Array); - DataView.prototype.getUint32 = makeGetter(exports.Uint32Array); - DataView.prototype.getInt32 = makeGetter(exports.Int32Array); - DataView.prototype.getFloat32 = makeGetter(exports.Float32Array); - DataView.prototype.getFloat64 = makeGetter(exports.Float64Array); - - function makeSetter(arrayType) { - return function(byteOffset, value, littleEndian) { - - byteOffset = ECMAScript.ToUint32(byteOffset); - if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength) { - throw new RangeError("Array index out of range"); - } - - // Get bytes - var typeArray = new arrayType([value]), - byteArray = new exports.Uint8Array(typeArray.buffer), - bytes = [], i, byteView; - - for (i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1) { - bytes.push(r(byteArray, i)); - } - - // Flip if necessary - if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN)) { - bytes.reverse(); - } - - // Write them - byteView = new exports.Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT); - byteView.set(bytes); - }; - } - - DataView.prototype.setUint8 = makeSetter(exports.Uint8Array); - DataView.prototype.setInt8 = makeSetter(exports.Int8Array); - DataView.prototype.setUint16 = makeSetter(exports.Uint16Array); - DataView.prototype.setInt16 = makeSetter(exports.Int16Array); - DataView.prototype.setUint32 = makeSetter(exports.Uint32Array); - DataView.prototype.setInt32 = makeSetter(exports.Int32Array); - DataView.prototype.setFloat32 = makeSetter(exports.Float32Array); - DataView.prototype.setFloat64 = makeSetter(exports.Float64Array); - - exports.DataView = exports.DataView || DataView; - -}()); -}(typedarray)); - -var Writable = require$$1.Writable; -var inherits = inherits$2.exports; -var bufferFrom = bufferFrom_1; - -if (typeof Uint8Array === 'undefined') { - var U8 = typedarray.Uint8Array; -} else { - var U8 = Uint8Array; -} - -function ConcatStream(opts, cb) { - if (!(this instanceof ConcatStream)) return new ConcatStream(opts, cb) - - if (typeof opts === 'function') { - cb = opts; - opts = {}; - } - if (!opts) opts = {}; - - var encoding = opts.encoding; - var shouldInferEncoding = false; - - if (!encoding) { - shouldInferEncoding = true; - } else { - encoding = String(encoding).toLowerCase(); - if (encoding === 'u8' || encoding === 'uint8') { - encoding = 'uint8array'; - } - } - - Writable.call(this, { objectMode: true }); - - this.encoding = encoding; - this.shouldInferEncoding = shouldInferEncoding; - - if (cb) this.on('finish', function () { cb(this.getBody()); }); - this.body = []; -} - -var concatStream = ConcatStream; -inherits(ConcatStream, Writable); - -ConcatStream.prototype._write = function(chunk, enc, next) { - this.body.push(chunk); - next(); -}; - -ConcatStream.prototype.inferEncoding = function (buff) { - var firstBuffer = buff === undefined ? this.body[0] : buff; - if (Buffer.isBuffer(firstBuffer)) return 'buffer' - if (typeof Uint8Array !== 'undefined' && firstBuffer instanceof Uint8Array) return 'uint8array' - if (Array.isArray(firstBuffer)) return 'array' - if (typeof firstBuffer === 'string') return 'string' - if (Object.prototype.toString.call(firstBuffer) === "[object Object]") return 'object' - return 'buffer' -}; - -ConcatStream.prototype.getBody = function () { - if (!this.encoding && this.body.length === 0) return [] - if (this.shouldInferEncoding) this.encoding = this.inferEncoding(); - if (this.encoding === 'array') return arrayConcat(this.body) - if (this.encoding === 'string') return stringConcat(this.body) - if (this.encoding === 'buffer') return bufferConcat(this.body) - if (this.encoding === 'uint8array') return u8Concat(this.body) - return this.body -}; - -function isArrayish (arr) { - return /Array\]$/.test(Object.prototype.toString.call(arr)) -} - -function isBufferish (p) { - return typeof p === 'string' || isArrayish(p) || (p && typeof p.subarray === 'function') -} - -function stringConcat (parts) { - var strings = []; - for (var i = 0; i < parts.length; i++) { - var p = parts[i]; - if (typeof p === 'string') { - strings.push(p); - } else if (Buffer.isBuffer(p)) { - strings.push(p); - } else if (isBufferish(p)) { - strings.push(bufferFrom(p)); - } else { - strings.push(bufferFrom(String(p))); - } - } - if (Buffer.isBuffer(parts[0])) { - strings = Buffer.concat(strings); - strings = strings.toString('utf8'); - } else { - strings = strings.join(''); - } - return strings -} - -function bufferConcat (parts) { - var bufs = []; - for (var i = 0; i < parts.length; i++) { - var p = parts[i]; - if (Buffer.isBuffer(p)) { - bufs.push(p); - } else if (isBufferish(p)) { - bufs.push(bufferFrom(p)); - } else { - bufs.push(bufferFrom(String(p))); - } - } - return Buffer.concat(bufs) -} - -function arrayConcat (parts) { - var res = []; - for (var i = 0; i < parts.length; i++) { - res.push.apply(res, parts[i]); - } - return res -} - -function u8Concat (parts) { - var len = 0; - for (var i = 0; i < parts.length; i++) { - if (typeof parts[i] === 'string') { - parts[i] = bufferFrom(parts[i]); - } - len += parts[i].length; - } - var u8 = new U8(len); - for (var i = 0, offset = 0; i < parts.length; i++) { - var part = parts[i]; - for (var j = 0; j < part.length; j++) { - u8[offset++] = part[j]; - } - } - return u8 -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('trough').Callback} Callback - * @typedef {import('./index.js').Settings} Settings - */ - -const debug$9 = createDebug('unified-engine:file-set-pipeline:stdin'); - -/** - * @param {Context} context - * @param {Settings} settings - * @param {Callback} next - */ -function stdin(context, settings, next) { - if (settings.files && settings.files.length > 0) { - debug$9('Ignoring `streamIn`'); - - /** @type {Error|undefined} */ - let error; - - if (settings.filePath) { - error = new Error( - 'Do not pass both `--file-path` and real files.\nDid you mean to pass stdin instead of files?' - ); - } - - next(error); - - return - } - - // @ts-expect-error: does exist on `stdin`. - if (settings.streamIn.isTTY) { - debug$9('Cannot read from `tty` stream'); - next(new Error('No input')); - - return - } - - debug$9('Reading from `streamIn`'); - - settings.streamIn.pipe( - concatStream({encoding: 'string'}, (value) => { - const file = toVFile(settings.filePath); - - debug$9('Read from `streamIn`'); - - file.cwd = settings.cwd; - file.value = value; - file.data.unifiedEngineGiven = true; - file.data.unifiedEngineStreamIn = true; - - context.files = [file]; - - // If `out` was not set, set `out`. - settings.out = - settings.out === null || settings.out === undefined - ? true - : settings.out; - - next(); - }) - ); -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('trough').Pipeline} Pipeline - */ - -class FileSet extends EventEmitter$1 { - /** - * FileSet constructor. - * A FileSet is created to process multiple files through unified processors. - * This set, containing all files, is exposed to plugins as an argument to the - * attacher. - */ - constructor() { - super(); - - /** @type {Array.} */ - this.files = []; - /** @type {string[]} */ - this.origins = []; - /** @type {Completer[]} */ - this.plugins = []; - /** @type {number} */ - this.expected = 0; - /** @type {number} */ - this.actual = 0; - /** @type {Pipeline} */ - this.pipeline = trough(); - - // Called when a single file has completed it’s pipeline, triggering `done` - // when all files are complete. - this.on('one', () => { - this.actual++; - - if (this.actual >= this.expected) { - this.emit('done'); - } - }); - } - - /** - * Access the files in a set. - */ - valueOf() { - return this.files - } - - /** - * Attach middleware to the pipeline on `fileSet`. - * - * @param {Completer} plugin - */ - use(plugin) { - const pipeline = this.pipeline; - let duplicate = false; - - if (plugin && plugin.pluginId) { - duplicate = this.plugins.some((fn) => fn.pluginId === plugin.pluginId); - } - - if (!duplicate && this.plugins.includes(plugin)) { - duplicate = true; - } - - if (!duplicate) { - this.plugins.push(plugin); - pipeline.use(plugin); - } - - return this - } - - /** - * Add a file to be processed. - * The given file is processed like other files with a few differences: - * - * * Ignored when their file path is already added - * * Never written to the file system or streamOut - * * Not reported for - * - * @param {string|VFile} file - */ - add(file) { - if (typeof file === 'string') { - file = toVFile(file); - } - - // Prevent files from being added multiple times. - if (this.origins.includes(file.history[0])) { - return this - } - - this.origins.push(file.history[0]); - - // Add. - this.valueOf().push(file); - this.expected++; - - // Force an asynchronous operation. - // This ensures that files which fall through the file pipeline immediately - // (such as, when already fatally failed) still queue up correctly. - setImmediate(() => { - this.emit('add', file); - }); - - return this - } -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('trough').Callback} Callback - * @typedef {import('./index.js').Context} Context - */ - -const debug$8 = createDebug('unified-engine:file-pipeline:read'); - -/** - * Fill a file with its value when not already filled. - * - * @param {Context} context - * @param {VFile} file - * @param {Callback} next - */ -function read$1(context, file, next) { - let filePath = file.path; - - if (file.value || file.data.unifiedEngineStreamIn) { - debug$8('Not reading file `%s` with `value`', filePath); - next(); - } else if (statistics(file).fatal) { - debug$8('Not reading failed file `%s`', filePath); - next(); - } else { - filePath = path$c.resolve(context.settings.cwd, filePath); - - debug$8('Reading `%s` in `%s`', filePath, 'utf8'); - fs$a.readFile(filePath, 'utf8', (error, value) => { - debug$8('Read `%s` (error: %s)', filePath, error); - - file.value = value || ''; - - next(error); - }); - } -} - -/** - * Has own property. - * - * @type {Function} - */ - -var has = Object.prototype.hasOwnProperty; - -/** - * To string. - * - * @type {Function} - */ - -var toString$1 = Object.prototype.toString; - -/** - * Test whether a value is "empty". - * - * @param {Mixed} val - * @return {Boolean} - */ - -function isEmpty(val) { - // Null and Undefined... - if (val == null) return true - - // Booleans... - if ('boolean' == typeof val) return false - - // Numbers... - if ('number' == typeof val) return val === 0 - - // Strings... - if ('string' == typeof val) return val.length === 0 - - // Functions... - if ('function' == typeof val) return val.length === 0 - - // Arrays... - if (Array.isArray(val)) return val.length === 0 - - // Errors... - if (val instanceof Error) return val.message === '' - - // Objects... - if (val.toString == toString$1) { - switch (val.toString()) { - - // Maps, Sets, Files and Errors... - case '[object File]': - case '[object Map]': - case '[object Set]': { - return val.size === 0 - } - - // Plain objects... - case '[object Object]': { - for (var key in val) { - if (has.call(val, key)) return false - } - - return true - } - } - } - - // Anything else... - return false -} - -/** - * Export `isEmpty`. - * - * @type {Function} - */ - -var lib$1 = isEmpty; - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('trough').Callback} Callback - * @typedef {import('./index.js').Context} Context - */ - -const debug$7 = createDebug('unified-engine:file-pipeline:configure'); - -/** - * Collect configuration for a file based on the context. - * - * @param {Context} context - * @param {VFile} file - * @param {Callback} next - */ -function configure$2(context, file, next) { - if (statistics(file).fatal) { - return next() - } - - context.configuration.load(file.path, (error, configuration) => { - let index = -1; - - if (!configuration) { - return next(error) - } - - // Could be missing if a `configTransform` returns weird things. - /* c8 ignore next 1 */ - const plugins = configuration.plugins || []; - - // Store configuration on the context object. - debug$7('Using settings `%j`', configuration.settings); - context.processor.data('settings', configuration.settings); - - debug$7('Using `%d` plugins', plugins.length); - - while (++index < plugins.length) { - const plugin = plugins[index][0]; - let options = plugins[index][1]; - - if (options === false) { - continue - } - - // Allow for default arguments in es2020. - /* c8 ignore next 6 */ - if ( - options === null || - (typeof options === 'object' && lib$1(options)) - ) { - options = undefined; - } - - debug$7( - 'Using plugin `%s`, with options `%j`', - // @ts-expect-error: `displayName` sure can exist on functions. - plugin.displayName || plugin.name || 'function', - options - ); - - try { - context.processor.use(plugin, options, context.fileSet); - /* Should not happen anymore! */ - /* c8 ignore next 3 */ - } catch (error_) { - return next(error_) - } - } - - next(); - }); -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('./index.js').Context} Context - */ - -const debug$6 = createDebug('unified-engine:file-pipeline:parse'); - -/** - * Fill a file with a tree. - * - * @param {Context} context - * @param {VFile} file - */ -function parse$2(context, file) { - if (statistics(file).fatal) { - return - } - - if (context.settings.treeIn) { - debug$6('Not parsing already parsed document'); - - try { - context.tree = parseJson_1(file.toString()); - } catch (error) { - const message = file.message( - new Error('Cannot read file as JSON\n' + error.message) - ); - message.fatal = true; - } - - // Add the preferred extension to ensure the file, when serialized, is - // correctly recognised. - // Only add it if there is a path — not if the file is for example stdin. - if (file.path) { - file.extname = context.settings.extensions[0]; - } - - file.value = ''; - - return - } - - debug$6('Parsing `%s`', file.path); - - context.tree = context.processor.parse(file); - - debug$6('Parsed document'); -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('trough').Callback} Callback - * @typedef {import('./index.js').Context} Context - */ - -const debug$5 = createDebug('unified-engine:file-pipeline:transform'); - -/** - * Transform the tree associated with a file with configured plugins. - * - * @param {Context} context - * @param {VFile} file - * @param {Callback} next - */ -function transform$2(context, file, next) { - if (statistics(file).fatal) { - next(); - } else { - debug$5('Transforming document `%s`', file.path); - // @ts-expect-error: `tree` is defined at this point. - context.processor.run(context.tree, file, (error, node) => { - debug$5('Transformed document (error: %s)', error); - context.tree = node; - next(error); - }); - } -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('trough').Callback} Callback - * @typedef {import('./index.js').Context} Context - */ - -const debug$4 = createDebug('unified-engine:file-pipeline:queue'); - -const own$a = {}.hasOwnProperty; - -/** - * Queue all files which came this far. - * When the last file gets here, run the file-set pipeline and flush the queue. - * - * @param {Context} context - * @param {VFile} file - * @param {Callback} next - */ -function queue(context, file, next) { - let origin = file.history[0]; - // @ts-expect-error: store a completion map on the `fileSet`. - let map = context.fileSet.complete; - let complete = true; - - if (!map) { - map = {}; - // @ts-expect-error: store a completion map on the `fileSet`. - context.fileSet.complete = map; - } - - debug$4('Queueing `%s`', origin); - - map[origin] = next; - - const files = context.fileSet.valueOf(); - let index = -1; - while (++index < files.length) { - each(files[index]); - } - - if (!complete) { - debug$4('Not flushing: some files cannot be flushed'); - return - } - - // @ts-expect-error: Reset map. - context.fileSet.complete = {}; - context.fileSet.pipeline.run(context.fileSet, done); - - /** - * @param {VFile} file - */ - function each(file) { - const key = file.history[0]; - - if (statistics(file).fatal) { - return - } - - if (typeof map[key] === 'function') { - debug$4('`%s` can be flushed', key); - } else { - debug$4('Interupting flush: `%s` is not finished', key); - complete = false; - } - } - - /** - * @param {Error|Null} error - */ - function done(error) { - debug$4('Flushing: all files can be flushed'); - - // Flush. - for (origin in map) { - if (own$a.call(map, origin)) { - map[origin](error); - } - } - } -} - -var own$9 = {}.hasOwnProperty; - -var bold = ansiColor(1, 22); -var dim = ansiColor(2, 22); -var yellow = ansiColor(33, 39); -var green = ansiColor(32, 39); - -// ANSI color regex. -/* eslint-disable-next-line no-control-regex */ -var colorExpression = /(?:(?:\u001B\[)|\u009B)(?:\d{1,3})?(?:(?:;\d{0,3})*)?[A-M|f-m]|\u001B[A-M]/g; - -/** - * Inspects a node, without using color. - * - * @param {unknown} node - * @param {InspectOptions} [options] - * @returns {string} - */ -function inspectNoColor(node, options) { - return inspectColor(node, options).replace(colorExpression, '') -} - -/** - * Inspects a node, using color. - * - * @param {unknown} tree - * @param {InspectOptions} [options] - * @returns {string} - */ -function inspectColor(tree, options) { - var positions = - !options || - options.showPositions === null || - options.showPositions === undefined - ? true - : options.showPositions; - - return inspectValue(tree) - - /** - * @param {unknown} node - * @returns {string} - */ - function inspectValue(node) { - if (node && typeof node === 'object' && 'length' in node) { - // @ts-ignore looks like a list of nodes. - return inspectNodes(node) - } - - // @ts-ignore looks like a single node. - if (node && node.type) { - // @ts-ignore looks like a single node. - return inspectTree(node) - } - - return inspectNonTree(node) - } - - /** - * @param {unknown} value - * @returns {string} - */ - function inspectNonTree(value) { - return JSON.stringify(value) - } - - /** - * @param {Node[]} nodes - * @returns {string} - */ - function inspectNodes(nodes) { - /** @type {Array.} */ - var result = []; - var index = -1; - - while (++index < nodes.length) { - result.push( - dim((index < nodes.length - 1 ? '├' : '└') + '─' + index) + - ' ' + - indent( - inspectValue(nodes[index]), - (index < nodes.length - 1 ? dim('│') : ' ') + ' ', - true - ) - ); - } - - return result.join('\n') - } - - /** - * @param {Object.} object - * @returns {string} - */ - function inspectFields(object) { - /** @type {Array.} */ - var result = []; - /** @type {string} */ - var key; - /** @type {unknown} */ - var value; - /** @type {string} */ - var formatted; - - for (key in object) { - /* c8 ignore next 1 */ - if (!own$9.call(object, key)) continue - - value = object[key]; - - if ( - value === undefined || - // Standard keys defined by unist that we format differently. - // - key === 'type' || - key === 'value' || - key === 'children' || - key === 'position' || - // Ignore `name` (from xast) and `tagName` (from `hast`) when string. - (typeof value === 'string' && (key === 'name' || key === 'tagName')) - ) { - continue - } - - // A single node. - if ( - value && - typeof value === 'object' && - // @ts-ignore looks like a node. - value.type && - key !== 'data' && - key !== 'attributes' && - key !== 'properties' - ) { - // @ts-ignore looks like a node. - formatted = inspectTree(value); - } - // A list of nodes. - else if ( - value && - typeof value === 'object' && - 'length' in value && - value[0] && - value[0].type - ) { - // @ts-ignore looks like a list of nodes. - formatted = '\n' + inspectNodes(value); - } else { - formatted = inspectNonTree(value); - } - - result.push( - key + dim(':') + (/\s/.test(formatted.charAt(0)) ? '' : ' ') + formatted - ); - } - - return indent( - result.join('\n'), - // @ts-ignore looks like a parent node. - (object.children && object.children.length > 0 ? dim('│') : ' ') + ' ' - ) - } - - /** - * @param {Node} node - * @returns {string} - */ - function inspectTree(node) { - var result = [formatNode(node)]; - var fields = inspectFields(node); - // @ts-ignore looks like a parent. - var content = inspectNodes(node.children || []); - if (fields) result.push(fields); - if (content) result.push(content); - return result.join('\n') - } - - /** - * Colored node formatter. - * - * @param {Node} node - * @returns {string} - */ - function formatNode(node) { - var result = [bold(node.type)]; - var kind = node.tagName || node.name; - var position = positions ? stringifyPosition(node.position) : ''; - - if (typeof kind === 'string') { - result.push('<', kind, '>'); - } - - if (node.children) { - // @ts-ignore looks like a parent. - result.push(dim('['), yellow(node.children.length), dim(']')); - } else if (typeof node.value === 'string') { - result.push(' ', green(inspectNonTree(node.value))); - } - - if (position) { - result.push(' ', dim('('), position, dim(')')); - } - - return result.join('') - } -} - -/** - * @param {string} value - * @param {string} indentation - * @param {boolean} [ignoreFirst=false] - * @returns {string} - */ -function indent(value, indentation, ignoreFirst) { - var lines = value.split('\n'); - var index = ignoreFirst ? 0 : -1; - - if (!value) return value - - while (++index < lines.length) { - lines[index] = indentation + lines[index]; - } - - return lines.join('\n') -} - -/** - * @param {Position} value - * @returns {string} - */ -function stringifyPosition(value) { - /** @type {Position} */ - // @ts-ignore - var position = value || {}; - /** @type {Array.} */ - var result = []; - /** @type {Array.} */ - var positions = []; - /** @type {Array.} */ - var offsets = []; - - point(position.start); - point(position.end); - - if (positions.length > 0) result.push(positions.join('-')); - if (offsets.length > 0) result.push(offsets.join('-')); - - return result.join(', ') - - /** - * @param {Point} value - */ - function point(value) { - if (value) { - positions.push((value.line || 1) + ':' + (value.column || 1)); - - if ('offset' in value) { - offsets.push(String(value.offset || 0)); - } - } - } -} - -/** - * Factory to wrap values in ANSI colours. - * - * @param {number} open - * @param {number} close - * @returns {function(string): string} - */ -function ansiColor(open, close) { - return color - - /** - * @param {string} value - * @returns {string} - */ - function color(value) { - return '\u001B[' + open + 'm' + value + '\u001B[' + close + 'm' - } -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('./index.js').Context} Context - */ - -const debug$3 = createDebug('unified-engine:file-pipeline:stringify'); - -/** - * Stringify a tree. - * - * @param {Context} context - * @param {VFile} file - */ -function stringify$1(context, file) { - /** @type {unknown} */ - let value; - - if (statistics(file).fatal) { - debug$3('Not compiling failed document'); - return - } - - if ( - !context.settings.output && - !context.settings.out && - !context.settings.alwaysStringify - ) { - debug$3('Not compiling document without output settings'); - return - } - - debug$3('Compiling `%s`', file.path); - - if (context.settings.inspect) { - // Add a `txt` extension if there is a path. - if (file.path) { - file.extname = '.txt'; - } - - value = - (context.settings.color ? inspectColor : inspectNoColor)(context.tree) + - '\n'; - } else if (context.settings.treeOut) { - // Add a `json` extension to ensure the file is correctly seen as JSON. - // Only add it if there is a path — not if the file is for example stdin. - if (file.path) { - file.extname = '.json'; - } - - // Add the line feed to create a valid UNIX file. - value = JSON.stringify(context.tree, null, 2) + '\n'; - } else { - // @ts-expect-error: `tree` is defined if we came this far. - value = context.processor.stringify(context.tree, file); - } - - if (value === undefined || value === null) ; else if (typeof value === 'string' || isBuffer(value)) { - // @ts-expect-error: `isBuffer` checks buffer. - file.value = value; - } else { - file.result = value; - } - - debug$3('Serialized document'); -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('trough').Callback} Callback - * @typedef {import('./index.js').Context} Context - */ - -const debug$2 = createDebug('unified-engine:file-pipeline:copy'); - -/** - * Move a file. - * - * @param {Context} context - * @param {VFile} file - * @param {Callback} next - */ -function copy(context, file, next) { - const output = context.settings.output; - const currentPath = file.path; - - if (typeof output !== 'string') { - debug$2('Not copying'); - next(); - return - } - - const outpath = path$c.resolve(context.settings.cwd, output); - - debug$2('Copying `%s`', currentPath); - - fs$a.stat(outpath, (error, stats) => { - if (error) { - if ( - error.code !== 'ENOENT' || - output.charAt(output.length - 1) === path$c.sep - ) { - return next( - new Error('Cannot read output directory. Error:\n' + error.message) - ) - } - - // This is either given an error, or the parent exists which is a directory, - // but we should keep the basename of the given file. - fs$a.stat(path$c.dirname(outpath), (error) => { - if (error) { - next( - new Error('Cannot read parent directory. Error:\n' + error.message) - ); - } else { - done(false); - } - }); - } else { - done(stats.isDirectory()); - } - }); - - /** - * @param {boolean} directory - */ - function done(directory) { - if (!directory && context.fileSet.expected > 1) { - return next( - new Error('Cannot write multiple files to single output: ' + outpath) - ) - } - - file[directory ? 'dirname' : 'path'] = path$c.relative(file.cwd, outpath); - - debug$2('Copying document from %s to %s', currentPath, file.path); - - next(); - } -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('trough').Callback} Callback - * @typedef {import('./index.js').Context} Context - */ - -const debug$1 = createDebug('unified-engine:file-pipeline:stdout'); - -/** - * Write a virtual file to `streamOut`. - * Ignored when `output` is given, more than one file was processed, or `out` - * is false. - * - * @param {Context} context - * @param {VFile} file - * @param {Callback} next - */ -function stdout(context, file, next) { - if (!file.data.unifiedEngineGiven) { - debug$1('Ignoring programmatically added file'); - next(); - } else if ( - statistics(file).fatal || - context.settings.output || - !context.settings.out - ) { - debug$1('Ignoring writing to `streamOut`'); - next(); - } else { - debug$1('Writing document to `streamOut`'); - context.settings.streamOut.write(file.toString(), next); - } -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('trough').Callback} Callback - * @typedef {import('./index.js').Context} Context - */ - -const debug = createDebug('unified-engine:file-pipeline:file-system'); - -/** - * Write a virtual file to the file-system. - * Ignored when `output` is not given. - * - * @param {Context} context - * @param {VFile} file - * @param {Callback} next - */ -function fileSystem(context, file, next) { - if (!context.settings.output) { - debug('Ignoring writing to file-system'); - return next() - } - - if (!file.data.unifiedEngineGiven) { - debug('Ignoring programmatically added file'); - return next() - } - - let destinationPath = file.path; - - if (!destinationPath) { - debug('Cannot write file without a `destinationPath`'); - return next(new Error('Cannot write file without an output path')) - } - - if (statistics(file).fatal) { - debug('Cannot write file with a fatal error'); - return next() - } - - destinationPath = path$c.resolve(context.settings.cwd, destinationPath); - debug('Writing document to `%s`', destinationPath); - - file.stored = true; - fs$a.writeFile(destinationPath, file.toString(), next); -} - -/** - * @typedef {import('trough').Pipeline} Pipeline - * @typedef {import('vfile').VFile} VFile - * @typedef {import('vfile-message').VFileMessage} VFileMessage - * @typedef {import('unist').Node} Node - * @typedef {import('unified').Processor} Processor - * @typedef {import('../file-set.js').FileSet} FileSet - * @typedef {import('../configuration.js').Configuration} Configuration - * @typedef {import('../index.js').Settings} Settings - */ - -// This pipeline ensures each of the pipes always runs: even if the read pipe -// fails, queue and write run. -const filePipeline = trough() - .use(chunk(trough().use(read$1).use(configure$2).use(parse$2).use(transform$2))) - .use(chunk(trough().use(queue))) - .use(chunk(trough().use(stringify$1).use(copy).use(stdout).use(fileSystem))); - -/** - * Factory to run a pipe. - * Wraps a pipe to trigger an error on the `file` in `context`, but still call - * `next`. - * - * @param {Pipeline} pipe - */ -function chunk(pipe) { - return run - - /** - * Run the bound pipe and handle any errors. - * - * @param {Context} context - * @param {VFile} file - * @param {() => void} next - */ - function run(context, file, next) { - pipe.run(context, file, (/** @type {VFileMessage|null} */ error) => { - const messages = file.messages; - - if (error) { - const index = messages.indexOf(error); - - if (index === -1) { - Object.assign(file.message(error), {fatal: true}); - } else { - messages[index].fatal = true; - } - } - - next(); - }); - } -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('trough').Callback} Callback - * @typedef {import('./index.js').Settings} Settings - * @typedef {import('./index.js').Configuration} Configuration - */ - -/** - * Transform all files. - * - * @param {Context} context - * @param {Settings} settings - * @param {Callback} next - */ -function transform$1(context, settings, next) { - const fileSet = new FileSet(); - - context.fileSet = fileSet; - - fileSet.on('add', (/** @type {VFile} */ file) => { - filePipeline.run( - { - configuration: context.configuration, - // Needed `any`s - // type-coverage:ignore-next-line - processor: settings.processor(), - fileSet, - settings - }, - file, - (/** @type {Error|null} */ error) => { - // Does not occur as all failures in `filePipeLine` are failed on each - // file. - // Still, just to ensure things work in the future, we add an extra check. - /* c8 ignore next 4 */ - if (error) { - Object.assign(file.message(error), {fatal: true}); - } - - fileSet.emit('one', file); - } - ); - }); - - fileSet.on('done', next); - - if (context.files.length === 0) { - next(); - } else { - let index = -1; - while (++index < context.files.length) { - fileSet.add(context.files[index]); - } - } -} - -function hasFlag(flag, argv = process$1.argv) { - const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--'); - const position = argv.indexOf(prefix + flag); - const terminatorPosition = argv.indexOf('--'); - return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition); -} - -const {env} = process$1; - -let flagForceColor; -if (hasFlag('no-color') || - hasFlag('no-colors') || - hasFlag('color=false') || - hasFlag('color=never')) { - flagForceColor = 0; -} else if (hasFlag('color') || - hasFlag('colors') || - hasFlag('color=true') || - hasFlag('color=always')) { - flagForceColor = 1; -} - -function envForceColor() { - if ('FORCE_COLOR' in env) { - if (env.FORCE_COLOR === 'true') { - return 1; - } - - if (env.FORCE_COLOR === 'false') { - return 0; - } - - return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3); - } -} - -function translateLevel(level) { - if (level === 0) { - return false; - } - - return { - level, - hasBasic: true, - has256: level >= 2, - has16m: level >= 3 - }; -} - -function _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) { - const noFlagForceColor = envForceColor(); - if (noFlagForceColor !== undefined) { - flagForceColor = noFlagForceColor; - } - - const forceColor = sniffFlags ? flagForceColor : noFlagForceColor; - - if (forceColor === 0) { - return 0; - } - - if (sniffFlags) { - if (hasFlag('color=16m') || - hasFlag('color=full') || - hasFlag('color=truecolor')) { - return 3; - } - - if (hasFlag('color=256')) { - return 2; - } - } - - if (haveStream && !streamIsTTY && forceColor === undefined) { - return 0; - } - - const min = forceColor || 0; - - if (env.TERM === 'dumb') { - return min; - } - - if (process$1.platform === 'win32') { - // Windows 10 build 10586 is the first Windows release that supports 256 colors. - // Windows 10 build 14931 is the first release that supports 16m/TrueColor. - const osRelease = require$$0$2.release().split('.'); - if ( - Number(osRelease[0]) >= 10 && - Number(osRelease[2]) >= 10586 - ) { - return Number(osRelease[2]) >= 14931 ? 3 : 2; - } - - return 1; - } - - if ('CI' in env) { - if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'GITHUB_ACTIONS', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') { - return 1; - } - - return min; - } - - if ('TEAMCITY_VERSION' in env) { - return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; - } - - if (env.COLORTERM === 'truecolor') { - return 3; - } - - if ('TERM_PROGRAM' in env) { - const version = Number.parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); - - switch (env.TERM_PROGRAM) { - case 'iTerm.app': - return version >= 3 ? 3 : 2; - case 'Apple_Terminal': - return 2; - // No default - } - } - - if (/-256(color)?$/i.test(env.TERM)) { - return 2; - } - - if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { - return 1; - } - - if ('COLORTERM' in env) { - return 1; - } - - return min; -} - -function createSupportsColor(stream, options = {}) { - const level = _supportsColor(stream, { - streamIsTTY: stream && stream.isTTY, - ...options - }); - - return translateLevel(level); -} - -const supportsColor = { - stdout: createSupportsColor({isTTY: tty$1.isatty(1)}), - stderr: createSupportsColor({isTTY: tty$1.isatty(2)}) -}; - -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'); -} - -function stripAnsi(string) { - if (typeof string !== 'string') { - throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``); - } - - return string.replace(ansiRegex(), ''); -} - -/* eslint-disable yoda */ - -function isFullwidthCodePoint(codePoint) { - if (!Number.isInteger(codePoint)) { - return false; - } - - // Code points are derived from: - // https://unicode.org/Public/UNIDATA/EastAsianWidth.txt - return codePoint >= 0x1100 && ( - codePoint <= 0x115F || // Hangul Jamo - codePoint === 0x2329 || // LEFT-POINTING ANGLE BRACKET - codePoint === 0x232A || // RIGHT-POINTING ANGLE BRACKET - // CJK Radicals Supplement .. Enclosed CJK Letters and Months - (0x2E80 <= codePoint && codePoint <= 0x3247 && codePoint !== 0x303F) || - // Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A - (0x3250 <= codePoint && codePoint <= 0x4DBF) || - // CJK Unified Ideographs .. Yi Radicals - (0x4E00 <= codePoint && codePoint <= 0xA4C6) || - // Hangul Jamo Extended-A - (0xA960 <= codePoint && codePoint <= 0xA97C) || - // Hangul Syllables - (0xAC00 <= codePoint && codePoint <= 0xD7A3) || - // CJK Compatibility Ideographs - (0xF900 <= codePoint && codePoint <= 0xFAFF) || - // Vertical Forms - (0xFE10 <= codePoint && codePoint <= 0xFE19) || - // CJK Compatibility Forms .. Small Form Variants - (0xFE30 <= codePoint && codePoint <= 0xFE6B) || - // Halfwidth and Fullwidth Forms - (0xFF01 <= codePoint && codePoint <= 0xFF60) || - (0xFFE0 <= codePoint && codePoint <= 0xFFE6) || - // Kana Supplement - (0x1B000 <= codePoint && codePoint <= 0x1B001) || - // Enclosed Ideographic Supplement - (0x1F200 <= codePoint && codePoint <= 0x1F251) || - // CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane - (0x20000 <= codePoint && codePoint <= 0x3FFFD) - ); -} - -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; -}; - -function stringWidth(string) { - if (typeof string !== 'string' || string.length === 0) { - return 0; - } - - string = stripAnsi(string); - - if (string.length === 0) { - return 0; - } - - string = string.replace(emojiRegex(), ' '); - - let width = 0; - - for (let index = 0; index < string.length; index++) { - const codePoint = string.codePointAt(index); - - // Ignore control characters - if (codePoint <= 0x1F || (codePoint >= 0x7F && codePoint <= 0x9F)) { - continue; - } - - // Ignore combining characters - if (codePoint >= 0x300 && codePoint <= 0x36F) { - continue; - } - - // Surrogates - if (codePoint > 0xFFFF) { - index++; - } - - width += isFullwidthCodePoint(codePoint) ? 2 : 1; - } - - return width; -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('vfile-message').VFileMessage} VFileMessage - */ - -var severities = {true: 2, false: 1, null: 0, undefined: 0}; - -/** - * @template {VFile} F - * @param {F} file - * @returns {F} - */ -function sort(file) { - file.messages.sort(comparator); - return file -} - -/** - * @param {VFileMessage} a - * @param {VFileMessage} b - * @returns {number} - */ -function comparator(a, b) { - return ( - check$1(a, b, 'line') || - check$1(a, b, 'column') || - severities[b.fatal] - severities[a.fatal] || - compare(a, b, 'source') || - compare(a, b, 'ruleId') || - compare(a, b, 'reason') || - 0 - ) -} - -/** - * @param {VFileMessage} a - * @param {VFileMessage} b - * @param {string} property - * @returns {number} - */ -function check$1(a, b, property) { - return (a[property] || 0) - (b[property] || 0) -} - -/** - * @param {VFileMessage} a - * @param {VFileMessage} b - * @param {string} property - * @returns {number} - */ -function compare(a, b, property) { - return String(a[property] || '').localeCompare(b[property] || '') -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('vfile-message').VFileMessage} VFileMessage - * @typedef {import('vfile-statistics').Statistics} Statistics - * - * @typedef Options - * @property {boolean} [color] - * @property {boolean} [silent=false] - * @property {boolean} [quiet=false] - * @property {boolean} [verbose=false] - * @property {string} [defaultName=''] - * - * @typedef _Row - * @property {string} place - * @property {string} label - * @property {string} reason - * @property {string} ruleId - * @property {string} source - * - * @typedef _FileRow - * @property {'file'} type - * @property {VFile} file - * @property {Statistics} stats - * - * @typedef {{[x: string]: number}} _Sizes - * - * @typedef _Info - * @property {Array.<_FileRow|_Row>} rows - * @property {Statistics} stats - * @property {_Sizes} sizes - */ - -const own$8 = {}.hasOwnProperty; - -// @ts-expect-error Types are incorrect. -const supported = supportsColor.stderr.hasBasic; - -// `log-symbols` without chalk, ignored for Windows: -/* c8 ignore next 4 */ -const chars = - process.platform === 'win32' - ? {error: '×', warning: '‼'} - : {error: '✖', warning: '⚠'}; - -const labels = { - true: 'error', - false: 'warning', - null: 'info', - undefined: 'info' -}; - -/** - * Report a file’s messages. - * - * @param {Error|VFile|Array.} [files] - * @param {Options} [options] - * @returns {string} - */ -function reporter$1(files, options = {}) { - /** @type {boolean|undefined} */ - let one; - - if (!files) { - return '' - } - - // Error. - if ('name' in files && 'message' in files) { - return String(files.stack || files) - } - - // One file. - if (!Array.isArray(files)) { - one = true; - files = [files]; - } - - return format(transform(files, options), one, options) -} - -/** - * @param {Array.} files - * @param {Options} options - * @returns {_Info} - */ -function transform(files, options) { - /** @type {Array.<_FileRow|_Row>} */ - const rows = []; - /** @type {Array.} */ - const all = []; - /** @type {_Sizes} */ - const sizes = {}; - let index = -1; - - while (++index < files.length) { - // @ts-expect-error it works fine. - const messages = sort({messages: [...files[index].messages]}).messages; - /** @type {Array.<_Row>} */ - const messageRows = []; - let offset = -1; - - while (++offset < messages.length) { - const message = messages[offset]; - - if (!options.silent || message.fatal) { - all.push(message); - - const row = { - place: stringifyPosition$1( - message.position - ? message.position.end.line && message.position.end.column - ? message.position - : message.position.start - : undefined - ), - label: labels[/** @type {keyof labels} */ (String(message.fatal))], - reason: - (message.stack || message.message) + - (options.verbose && message.note ? '\n' + message.note : ''), - ruleId: message.ruleId || '', - source: message.source || '' - }; - - /** @type {keyof row} */ - let key; - - for (key in row) { - // eslint-disable-next-line max-depth - if (own$8.call(row, key)) { - sizes[key] = Math.max(size$1(row[key]), sizes[key] || 0); - } - } - - messageRows.push(row); - } - } - - if ((!options.quiet && !options.silent) || messageRows.length > 0) { - rows.push( - {type: 'file', file: files[index], stats: statistics(messages)}, - ...messageRows - ); - } - } - - return {rows, stats: statistics(all), sizes} -} - -/** - * @param {_Info} map - * @param {boolean|undefined} one - * @param {Options} options - */ -// eslint-disable-next-line complexity -function format(map, one, options) { - /** @type {boolean} */ - const enabled = - options.color === undefined || options.color === null - ? supported - : options.color; - /** @type {Array.} */ - const lines = []; - let index = -1; - - while (++index < map.rows.length) { - const row = map.rows[index]; - - if ('type' in row) { - const stats = row.stats; - let line = row.file.history[0] || options.defaultName || ''; - - line = - one && !options.defaultName && !row.file.history[0] - ? '' - : (enabled - ? '\u001B[4m' /* Underline. */ + - (stats.fatal - ? '\u001B[31m' /* Red. */ - : stats.total - ? '\u001B[33m' /* Yellow. */ - : '\u001B[32m') /* Green. */ + - line + - '\u001B[39m\u001B[24m' - : line) + - (row.file.stored && row.file.path !== row.file.history[0] - ? ' > ' + row.file.path - : ''); - - if (!stats.total) { - line = - (line ? line + ': ' : '') + - (row.file.stored - ? enabled - ? '\u001B[33mwritten\u001B[39m' /* Yellow. */ - : 'written' - : 'no issues found'); - } - - if (line) { - if (index && !('type' in map.rows[index - 1])) { - lines.push(''); - } - - lines.push(line); - } - } else { - let reason = row.reason; - const match = /\r?\n|\r/.exec(reason); - /** @type {string} */ - let rest; - - if (match) { - rest = reason.slice(match.index); - reason = reason.slice(0, match.index); - } else { - rest = ''; - } - - lines.push( - ( - ' ' + - ' '.repeat(map.sizes.place - size$1(row.place)) + - row.place + - ' ' + - (enabled - ? (row.label === 'error' - ? '\u001B[31m' /* Red. */ - : '\u001B[33m') /* Yellow. */ + - row.label + - '\u001B[39m' - : row.label) + - ' '.repeat(map.sizes.label - size$1(row.label)) + - ' ' + - reason + - ' '.repeat(map.sizes.reason - size$1(reason)) + - ' ' + - row.ruleId + - ' '.repeat(map.sizes.ruleId - size$1(row.ruleId)) + - ' ' + - (row.source || '') - ).replace(/ +$/, '') + rest - ); - } - } - - const stats = map.stats; - - if (stats.fatal || stats.warn) { - let line = ''; - - if (stats.fatal) { - line = - (enabled - ? '\u001B[31m' /* Red. */ + chars.error + '\u001B[39m' - : chars.error) + - ' ' + - stats.fatal + - ' ' + - (labels.true + (stats.fatal === 1 ? '' : 's')); - } - - if (stats.warn) { - line = - (line ? line + ', ' : '') + - (enabled - ? '\u001B[33m' /* Yellow. */ + chars.warning + '\u001B[39m' - : chars.warning) + - ' ' + - stats.warn + - ' ' + - (labels.false + (stats.warn === 1 ? '' : 's')); - } - - if (stats.total !== stats.fatal && stats.total !== stats.warn) { - line = stats.total + ' messages (' + line + ')'; - } - - lines.push('', line); - } - - return lines.join('\n') -} - -/** - * Get the length of `value`, ignoring ANSI sequences. - * - * @param {string} value - * @returns {number} - */ -function size$1(value) { - const match = /\r?\n|\r/.exec(value); - return stringWidth(match ? value.slice(0, match.index) : value) -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('../index.js').VFileReporter} VFileReporter - * @typedef {import('./index.js').Settings} Settings - * @typedef {import('./index.js').Configuration} Configuration - */ - -/** - * @typedef Context - * @property {Array.} files - * @property {Configuration} [configuration] - */ - -/** - * @param {Context} context - * @param {Settings} settings - */ -async function log(context, settings) { - /** @type {VFileReporter} */ - let func = reporter$1; - - if (typeof settings.reporter === 'string') { - try { - // @ts-expect-error: Assume loaded value is a vfile reporter. - func = await loadPlugin(settings.reporter, { - cwd: settings.cwd, - prefix: 'vfile-reporter' - }); - } catch { - throw new Error('Could not find reporter `' + settings.reporter + '`') - } - } else if (settings.reporter) { - func = settings.reporter; - } - - let diagnostics = func( - context.files.filter((file) => file.data.unifiedEngineGiven), - Object.assign({}, settings.reporterOptions, { - quiet: settings.quiet, - silent: settings.silent, - color: settings.color - }) - ); - - if (diagnostics) { - if (diagnostics.charAt(diagnostics.length - 1) !== '\n') { - diagnostics += '\n'; - } - - return new Promise((resolve) => { - settings.streamError.write(diagnostics, resolve); - }) - } -} - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('../configuration.js').Configuration} Configuration - * @typedef {import('../index.js').Settings} Settings - */ - -const fileSetPipeline = trough() - .use(configure$3) - .use(fileSystem$1) - .use(stdin) - .use(transform$1) - .use(log); - -/** - * @typedef {import('vfile').VFile} VFile - * @typedef {import('unified').Processor} Processor - * @typedef {import('./file-set.js').FileSet} FileSet - * @typedef {import('./file-set.js').Completer} Completer - * @typedef {import('./ignore.js').ResolveFrom} ResolveFrom - * @typedef {import('./configuration.js').ConfigTransform} ConfigTransform - * @typedef {import('./configuration.js').Preset} Preset - * - * @typedef VFileReporterFields - * @property {boolean} [color] - * @property {boolean} [quiet] - * @property {boolean} [silent] - * - * @typedef {{[key: string]: unknown} & VFileReporterFields} VFileReporterOptions - * - * @callback VFileReporter - * @param {VFile[]} files - * @param {VFileReporterOptions} options - * @returns {string} - * - * @typedef Settings - * @property {Options['processor']} processor - * @property {Exclude} cwd - * @property {Exclude} files - * @property {Exclude} extensions - * @property {Exclude} streamIn - * @property {Options['filePath']} filePath - * @property {Exclude} streamOut - * @property {Exclude} streamError - * @property {Options['out']} out - * @property {Options['output']} output - * @property {Options['alwaysStringify']} alwaysStringify - * @property {Options['tree']} tree - * @property {Options['treeIn']} treeIn - * @property {Options['treeOut']} treeOut - * @property {Options['inspect']} inspect - * @property {Options['rcName']} rcName - * @property {Options['packageField']} packageField - * @property {Options['detectConfig']} detectConfig - * @property {Options['rcPath']} rcPath - * @property {Exclude} settings - * @property {Options['ignoreName']} ignoreName - * @property {Options['detectIgnore']} detectIgnore - * @property {Options['ignorePath']} ignorePath - * @property {Options['ignorePathResolveFrom']} ignorePathResolveFrom - * @property {Exclude} ignorePatterns - * @property {Options['silentlyIgnore']} silentlyIgnore - * @property {Options['plugins']} plugins - * @property {Options['pluginPrefix']} pluginPrefix - * @property {Options['configTransform']} configTransform - * @property {Options['defaultConfig']} defaultConfig - * @property {Options['reporter']} reporter - * @property {Options['reporterOptions']} reporterOptions - * @property {Options['color']} color - * @property {Options['silent']} silent - * @property {Options['quiet']} quiet - * @property {Options['frail']} frail - * - * @typedef Options - * Options for unified engine - * @property {() => Processor} processor - * Unified processor to transform files - * @property {string} [cwd] - * Directory to search files in, load plugins from, and more. - * Defaults to `process.cwd()`. - * @property {Array} [files] - * Paths or globs to files and directories, or virtual files, to process. - * @property {string[]} [extensions] - * If `files` matches directories, include `files` with `extensions` - * @property {NodeJS.ReadableStream} [streamIn] - * Stream to read from if no files are found or given. - * Defaults to `process.stdin`. - * @property {string} [filePath] - * File path to process the given file on `streamIn` as. - * @property {NodeJS.WritableStream} [streamOut] - * Stream to write processed files to. - * Defaults to `process.stdout`. - * @property {NodeJS.WritableStream} [streamError] - * Stream to write the report (if any) to. - * Defaults to `process.stderr`. - * @property {boolean} [out=false] - * Whether to write the processed file to `streamOut` - * @property {boolean|string} [output=false] - * Whether to write successfully processed files, and where to. - * - * * When `true`, overwrites the given files - * * When `false`, does not write to the file system - * * When pointing to an existing directory, files are written to that - * directory and keep their original basenames - * * When the parent directory of the given path exists and one file is - * processed, the file is written to the given path - * @property {boolean} [alwaysStringify=false] - * Whether to always serialize successfully processed files. - * @property {boolean} [tree=false] - * Whether to treat both input and output as a syntax tree. - * @property {boolean} [treeIn] - * Whether to treat input as a syntax tree. - * Defaults to `options.tree`. - * @property {boolean} [treeOut] - * Whether to treat output as a syntax tree. - * Defaults to `options.tree`. - * @property {boolean} [inspect=false] - * Whether to output a formatted syntax tree. - * @property {string} [rcName] - * Name of configuration files to load. - * @property {string} [packageField] - * Property at which configuration can be found in `package.json` files - * @property {boolean} [detectConfig] - * Whether to search for configuration files. - * Defaults to `true` if `rcName` or `packageField` are given - * @property {string} [rcPath] - * Filepath to a configuration file to load. - * @property {Preset['settings']} [settings] - * Configuration for the parser and compiler of the processor. - * @property {string} [ignoreName] - * Name of ignore files to load. - * @property {boolean} [detectIgnore] - * Whether to search for ignore files. - * Defaults to `true` if `ignoreName` is given. - * @property {string} [ignorePath] - * Filepath to an ignore file to load. - * @property {ResolveFrom} [ignorePathResolveFrom] - * Resolve patterns in `ignorePath` from the current working - * directory (`'cwd'`) or the ignore file’s directory (`'dir'`, default). - * @property {string[]} [ignorePatterns] - * Patterns to ignore in addition to ignore files - * @property {boolean} [silentlyIgnore=false] - * Skip given files if they are ignored. - * @property {Preset['plugins']} [plugins] - * Plugins to use. - * @property {string} [pluginPrefix] - * Prefix to use when searching for plugins - * @property {ConfigTransform} [configTransform] - * Transform config files from a different schema. - * @property {Preset} [defaultConfig] - * Default configuration to use if no config file is given or found. - * @property {VFileReporter|string} [reporter] - * Reporter to use - * Defaults to `vfile-reporter` - * @property {VFileReporterOptions} [reporterOptions] - * Config to pass to the used reporter. - * @property {VFileReporterOptions['color']} [color=false] - * Whether to report with ANSI color sequences. - * @property {VFileReporterOptions['silent']} [silent=false] - * Report only fatal errors - * @property {VFileReporterOptions['quiet']} [quiet=false] - * Do not report successful files - * @property {boolean} [frail=false] - * Call back with an unsuccessful (`1`) code on warnings as well as errors - * - * @typedef Context - * Processing context. - * @property {VFile[]} [files] - * Processed files. - * @property {FileSet} [fileSet] - * Internally used information - * - * @callback Callback - * Callback called when processing according to options is complete. - * Invoked with either a fatal error if processing went horribly wrong - * (probably due to incorrect configuration), or a status code and the - * processing context. - * @param {Error|null} error - * @param {0|1} [status] - * @param {Context} [context] - * @returns {void} - */ - -/** - * Run the file set pipeline once. - * `callback` is called with a fatal error, or with a status code (`0` on - * success, `1` on failure). - * - * @param {Options} options - * @param {Callback} callback - */ -function engine(options, callback) { - /** @type {Settings} */ - const settings = {}; - /** @type {NodeJS.ReadStream} */ - // @ts-expect-error: `PassThrough` sure is readable. - let stdin = new PassThrough(); - - try { - stdin = process$2.stdin; - // Obscure bug in Node (seen on Windows). - // See: , - // . - /* c8 ignore next 1 */ - } catch {} - - if (!callback) { - throw new Error('Missing `callback`') - } - - // Needed `any`s - // type-coverage:ignore-next-line - if (!options || !options.processor) { - return next(new Error('Missing `processor`')) - } - - // Processor. - // Needed `any`s - // type-coverage:ignore-next-line - settings.processor = options.processor; - - // Path to run as. - settings.cwd = options.cwd || process$2.cwd(); - - // Input. - settings.files = options.files || []; - settings.extensions = (options.extensions || []).map((ext) => - ext.charAt(0) === '.' ? ext : '.' + ext - ); - - settings.filePath = options.filePath; - settings.streamIn = options.streamIn || stdin; - - // Output. - settings.streamOut = options.streamOut || process$2.stdout; - settings.streamError = options.streamError || process$2.stderr; - settings.alwaysStringify = options.alwaysStringify; - settings.output = options.output; - settings.out = options.out; - - // Null overwrites config settings, `undefined` does not. - if (settings.output === null || settings.output === undefined) { - settings.output = undefined; - } - - if (settings.output && settings.out) { - return next(new Error('Cannot accept both `output` and `out`')) - } - - // Process phase management. - const tree = options.tree || false; - - settings.treeIn = options.treeIn; - settings.treeOut = options.treeOut; - settings.inspect = options.inspect; - - if (settings.treeIn === null || settings.treeIn === undefined) { - settings.treeIn = tree; - } - - if (settings.treeOut === null || settings.treeOut === undefined) { - settings.treeOut = tree; - } - - // Configuration. - const detectConfig = options.detectConfig; - const hasConfig = Boolean(options.rcName || options.packageField); - - if (detectConfig && !hasConfig) { - return next( - new Error('Missing `rcName` or `packageField` with `detectConfig`') - ) - } - - settings.detectConfig = - detectConfig === null || detectConfig === undefined - ? hasConfig - : detectConfig; - settings.rcName = options.rcName; - settings.rcPath = options.rcPath; - settings.packageField = options.packageField; - settings.settings = options.settings || {}; - settings.configTransform = options.configTransform; - settings.defaultConfig = options.defaultConfig; - - // Ignore. - const detectIgnore = options.detectIgnore; - const hasIgnore = Boolean(options.ignoreName); - - settings.detectIgnore = - detectIgnore === null || detectIgnore === undefined - ? hasIgnore - : detectIgnore; - settings.ignoreName = options.ignoreName; - settings.ignorePath = options.ignorePath; - settings.ignorePathResolveFrom = options.ignorePathResolveFrom || 'dir'; - settings.ignorePatterns = options.ignorePatterns || []; - settings.silentlyIgnore = Boolean(options.silentlyIgnore); - - if (detectIgnore && !hasIgnore) { - return next(new Error('Missing `ignoreName` with `detectIgnore`')) - } - - // Plugins. - settings.pluginPrefix = options.pluginPrefix; - settings.plugins = options.plugins || []; - - // Reporting. - settings.reporter = options.reporter; - settings.reporterOptions = options.reporterOptions; - settings.color = options.color || false; - settings.silent = options.silent; - settings.quiet = options.quiet; - settings.frail = options.frail; - - // Process. - fileSetPipeline.run({files: options.files || []}, settings, next); - - /** - * @param {Error|null} error - * @param {Context} [context] - */ - function next(error, context) { - const stats = statistics((context || {}).files); - const failed = Boolean( - settings.frail ? stats.fatal || stats.warn : stats.fatal - ); - - if (error) { - callback(error); - } else { - callback(null, failed ? 1 : 0, context); - } - } -} - -var textTable = function (rows_, opts) { - if (!opts) opts = {}; - var hsep = opts.hsep === undefined ? ' ' : opts.hsep; - var align = opts.align || []; - var stringLength = opts.stringLength - || function (s) { return String(s).length; } - ; - - var dotsizes = reduce(rows_, function (acc, row) { - forEach(row, function (c, ix) { - var n = dotindex(c); - if (!acc[ix] || n > acc[ix]) acc[ix] = n; - }); - return acc; - }, []); - - var rows = map$2(rows_, function (row) { - return map$2(row, function (c_, ix) { - var c = String(c_); - if (align[ix] === '.') { - var index = dotindex(c); - var size = dotsizes[ix] + (/\./.test(c) ? 1 : 2) - - (stringLength(c) - index) - ; - return c + Array(size).join(' '); - } - else return c; - }); - }); - - var sizes = reduce(rows, function (acc, row) { - forEach(row, function (c, ix) { - var n = stringLength(c); - if (!acc[ix] || n > acc[ix]) acc[ix] = n; - }); - return acc; - }, []); - - return map$2(rows, function (row) { - return map$2(row, function (c, ix) { - var n = (sizes[ix] - stringLength(c)) || 0; - var s = Array(Math.max(n + 1, 1)).join(' '); - if (align[ix] === 'r' || align[ix] === '.') { - return s + c; - } - if (align[ix] === 'c') { - return Array(Math.ceil(n / 2 + 1)).join(' ') - + c + Array(Math.floor(n / 2 + 1)).join(' ') - ; - } - - return c + s; - }).join(hsep).replace(/\s+$/, ''); - }).join('\n'); -}; - -function dotindex (c) { - var m = /\.[^.]*$/.exec(c); - return m ? m.index + 1 : c.length; -} - -function reduce (xs, f, init) { - if (xs.reduce) return xs.reduce(f, init); - var i = 0; - var acc = arguments.length >= 3 ? init : xs[i++]; - for (; i < xs.length; i++) { - f(acc, xs[i], i); - } - return acc; -} - -function forEach (xs, f) { - if (xs.forEach) return xs.forEach(f); - for (var i = 0; i < xs.length; i++) { - f.call(xs, xs[i], i); - } -} - -function map$2 (xs, f) { - if (xs.map) return xs.map(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - res.push(f.call(xs, xs[i], i)); - } - return res; -} - -var camelcase$1 = {exports: {}}; - -const preserveCamelCase = (string, locale) => { - let isLastCharLower = false; - let isLastCharUpper = false; - let isLastLastCharUpper = false; - - for (let i = 0; i < string.length; i++) { - const character = string[i]; - - if (isLastCharLower && /[\p{Lu}]/u.test(character)) { - string = string.slice(0, i) + '-' + string.slice(i); - isLastCharLower = false; - isLastLastCharUpper = isLastCharUpper; - isLastCharUpper = true; - i++; - } else if (isLastCharUpper && isLastLastCharUpper && /[\p{Ll}]/u.test(character)) { - string = string.slice(0, i - 1) + '-' + string.slice(i - 1); - isLastLastCharUpper = isLastCharUpper; - isLastCharUpper = false; - isLastCharLower = true; - } else { - isLastCharLower = character.toLocaleLowerCase(locale) === character && character.toLocaleUpperCase(locale) !== character; - isLastLastCharUpper = isLastCharUpper; - isLastCharUpper = character.toLocaleUpperCase(locale) === character && character.toLocaleLowerCase(locale) !== character; - } - } - - return string; -}; - -const preserveConsecutiveUppercase = input => { - return input.replace(/^[\p{Lu}](?![\p{Lu}])/gu, m1 => m1.toLowerCase()); -}; - -const postProcess = (input, options) => { - return input.replace(/[_.\- ]+([\p{Alpha}\p{N}_]|$)/gu, (_, p1) => p1.toLocaleUpperCase(options.locale)) - .replace(/\d+([\p{Alpha}\p{N}_]|$)/gu, m => m.toLocaleUpperCase(options.locale)); -}; - -const camelCase = (input, options) => { - if (!(typeof input === 'string' || Array.isArray(input))) { - throw new TypeError('Expected the input to be `string | string[]`'); - } - - options = { - pascalCase: false, - preserveConsecutiveUppercase: false, - ...options - }; - - if (Array.isArray(input)) { - input = input.map(x => x.trim()) - .filter(x => x.length) - .join('-'); - } else { - input = input.trim(); - } - - if (input.length === 0) { - return ''; - } - - if (input.length === 1) { - return options.pascalCase ? input.toLocaleUpperCase(options.locale) : input.toLocaleLowerCase(options.locale); - } - - const hasUpperCase = input !== input.toLocaleLowerCase(options.locale); - - if (hasUpperCase) { - input = preserveCamelCase(input, options.locale); - } - - input = input.replace(/^[_.\- ]+/, ''); - - if (options.preserveConsecutiveUppercase) { - input = preserveConsecutiveUppercase(input); - } else { - input = input.toLocaleLowerCase(); - } - - if (options.pascalCase) { - input = input.charAt(0).toLocaleUpperCase(options.locale) + input.slice(1); - } - - return postProcess(input, options); -}; - -camelcase$1.exports = camelCase; -// TODO: Remove this for the next major release -camelcase$1.exports.default = camelCase; - -var camelcase = camelcase$1.exports; - -var minimist = function (args, opts) { - if (!opts) opts = {}; - - var flags = { bools : {}, strings : {}, unknownFn: null }; - - if (typeof opts['unknown'] === 'function') { - flags.unknownFn = opts['unknown']; - } - - if (typeof opts['boolean'] === 'boolean' && opts['boolean']) { - flags.allBools = true; - } else { - [].concat(opts['boolean']).filter(Boolean).forEach(function (key) { - flags.bools[key] = true; - }); - } - - var aliases = {}; - Object.keys(opts.alias || {}).forEach(function (key) { - aliases[key] = [].concat(opts.alias[key]); - aliases[key].forEach(function (x) { - aliases[x] = [key].concat(aliases[key].filter(function (y) { - return x !== y; - })); - }); - }); - - [].concat(opts.string).filter(Boolean).forEach(function (key) { - flags.strings[key] = true; - if (aliases[key]) { - flags.strings[aliases[key]] = true; - } - }); - - var defaults = opts['default'] || {}; - - var argv = { _ : [] }; - Object.keys(flags.bools).forEach(function (key) { - setArg(key, defaults[key] === undefined ? false : defaults[key]); - }); - - var notFlags = []; - - if (args.indexOf('--') !== -1) { - notFlags = args.slice(args.indexOf('--')+1); - args = args.slice(0, args.indexOf('--')); - } - - function argDefined(key, arg) { - return (flags.allBools && /^--[^=]+$/.test(arg)) || - flags.strings[key] || flags.bools[key] || aliases[key]; - } - - function setArg (key, val, arg) { - if (arg && flags.unknownFn && !argDefined(key, arg)) { - if (flags.unknownFn(arg) === false) return; - } - - var value = !flags.strings[key] && isNumber(val) - ? Number(val) : val - ; - setKey(argv, key.split('.'), value); - - (aliases[key] || []).forEach(function (x) { - setKey(argv, x.split('.'), value); - }); - } - - function setKey (obj, keys, value) { - var o = obj; - for (var i = 0; i < keys.length-1; i++) { - var key = keys[i]; - if (key === '__proto__') return; - if (o[key] === undefined) o[key] = {}; - if (o[key] === Object.prototype || o[key] === Number.prototype - || o[key] === String.prototype) o[key] = {}; - if (o[key] === Array.prototype) o[key] = []; - o = o[key]; - } - - var key = keys[keys.length - 1]; - if (key === '__proto__') return; - if (o === Object.prototype || o === Number.prototype - || o === String.prototype) o = {}; - if (o === Array.prototype) o = []; - if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') { - o[key] = value; - } - else if (Array.isArray(o[key])) { - o[key].push(value); - } - else { - o[key] = [ o[key], value ]; - } - } - - function aliasIsBoolean(key) { - return aliases[key].some(function (x) { - return flags.bools[x]; - }); - } - - for (var i = 0; i < args.length; i++) { - var arg = args[i]; - - if (/^--.+=/.test(arg)) { - // Using [\s\S] instead of . because js doesn't support the - // 'dotall' regex modifier. See: - // http://stackoverflow.com/a/1068308/13216 - var m = arg.match(/^--([^=]+)=([\s\S]*)$/); - var key = m[1]; - var value = m[2]; - if (flags.bools[key]) { - value = value !== 'false'; - } - setArg(key, value, arg); - } - else if (/^--no-.+/.test(arg)) { - var key = arg.match(/^--no-(.+)/)[1]; - setArg(key, false, arg); - } - else if (/^--.+/.test(arg)) { - var key = arg.match(/^--(.+)/)[1]; - var next = args[i + 1]; - if (next !== undefined && !/^-/.test(next) - && !flags.bools[key] - && !flags.allBools - && (aliases[key] ? !aliasIsBoolean(key) : true)) { - setArg(key, next, arg); - i++; - } - else if (/^(true|false)$/.test(next)) { - setArg(key, next === 'true', arg); - i++; - } - else { - setArg(key, flags.strings[key] ? '' : true, arg); - } - } - else if (/^-[^-]+/.test(arg)) { - var letters = arg.slice(1,-1).split(''); - - var broken = false; - for (var j = 0; j < letters.length; j++) { - var next = arg.slice(j+2); - - if (next === '-') { - setArg(letters[j], next, arg); - continue; - } - - if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) { - setArg(letters[j], next.split('=')[1], arg); - broken = true; - break; - } - - if (/[A-Za-z]/.test(letters[j]) - && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { - setArg(letters[j], next, arg); - broken = true; - break; - } - - if (letters[j+1] && letters[j+1].match(/\W/)) { - setArg(letters[j], arg.slice(j+2), arg); - broken = true; - break; - } - else { - setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); - } - } - - var key = arg.slice(-1)[0]; - if (!broken && key !== '-') { - if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) - && !flags.bools[key] - && (aliases[key] ? !aliasIsBoolean(key) : true)) { - setArg(key, args[i+1], arg); - i++; - } - else if (args[i+1] && /^(true|false)$/.test(args[i+1])) { - setArg(key, args[i+1] === 'true', arg); - i++; - } - else { - setArg(key, flags.strings[key] ? '' : true, arg); - } - } - } - else { - if (!flags.unknownFn || flags.unknownFn(arg) !== false) { - argv._.push( - flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) - ); - } - if (opts.stopEarly) { - argv._.push.apply(argv._, args.slice(i + 1)); - break; - } - } - } - - Object.keys(defaults).forEach(function (key) { - if (!hasKey(argv, key.split('.'))) { - setKey(argv, key.split('.'), defaults[key]); - - (aliases[key] || []).forEach(function (x) { - setKey(argv, x.split('.'), defaults[key]); - }); - } - }); - - if (opts['--']) { - argv['--'] = new Array(); - notFlags.forEach(function(key) { - argv['--'].push(key); - }); - } - else { - notFlags.forEach(function(key) { - argv._.push(key); - }); - } - - return argv; -}; - -function hasKey (obj, keys) { - var o = obj; - keys.slice(0,-1).forEach(function (key) { - o = (o[key] || {}); - }); - - var key = keys[keys.length - 1]; - return key in o; -} - -function isNumber (x) { - if (typeof x === 'number') return true; - if (/^0x[0-9a-f]+$/i.test(x)) return true; - return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); -} - -// This is a generated file. Do not edit. -var Space_Separator = /[\u1680\u2000-\u200A\u202F\u205F\u3000]/; -var ID_Start = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/; -var ID_Continue = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/; - -var unicode = { - Space_Separator: Space_Separator, - ID_Start: ID_Start, - ID_Continue: ID_Continue -}; - -var util = { - isSpaceSeparator (c) { - return typeof c === 'string' && unicode.Space_Separator.test(c) - }, - - isIdStartChar (c) { - return typeof c === 'string' && ( - (c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - (c === '$') || (c === '_') || - unicode.ID_Start.test(c) - ) - }, - - isIdContinueChar (c) { - return typeof c === 'string' && ( - (c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - (c >= '0' && c <= '9') || - (c === '$') || (c === '_') || - (c === '\u200C') || (c === '\u200D') || - unicode.ID_Continue.test(c) - ) - }, - - isDigit (c) { - return typeof c === 'string' && /[0-9]/.test(c) - }, - - isHexDigit (c) { - return typeof c === 'string' && /[0-9A-Fa-f]/.test(c) - }, -}; - -let source; -let parseState; -let stack; -let pos; -let line; -let column; -let token; -let key; -let root$1; - -var parse$1 = function parse (text, reviver) { - source = String(text); - parseState = 'start'; - stack = []; - pos = 0; - line = 1; - column = 0; - token = undefined; - key = undefined; - root$1 = undefined; - - do { - token = lex(); - - // This code is unreachable. - // if (!parseStates[parseState]) { - // throw invalidParseState() - // } - - parseStates[parseState](); - } while (token.type !== 'eof') - - if (typeof reviver === 'function') { - return internalize({'': root$1}, '', reviver) - } - - return root$1 -}; - -function internalize (holder, name, reviver) { - const value = holder[name]; - if (value != null && typeof value === 'object') { - for (const key in value) { - const replacement = internalize(value, key, reviver); - if (replacement === undefined) { - delete value[key]; - } else { - value[key] = replacement; - } - } - } - - return reviver.call(holder, name, value) -} - -let lexState; -let buffer; -let doubleQuote; -let sign; -let c; - -function lex () { - lexState = 'default'; - buffer = ''; - doubleQuote = false; - sign = 1; - - for (;;) { - c = peek(); - - // This code is unreachable. - // if (!lexStates[lexState]) { - // throw invalidLexState(lexState) - // } - - const token = lexStates[lexState](); - if (token) { - return token - } - } -} - -function peek () { - if (source[pos]) { - return String.fromCodePoint(source.codePointAt(pos)) - } -} - -function read () { - const c = peek(); - - if (c === '\n') { - line++; - column = 0; - } else if (c) { - column += c.length; - } else { - column++; - } - - if (c) { - pos += c.length; - } - - return c -} - -const lexStates = { - default () { - switch (c) { - case '\t': - case '\v': - case '\f': - case ' ': - case '\u00A0': - case '\uFEFF': - case '\n': - case '\r': - case '\u2028': - case '\u2029': - read(); - return - - case '/': - read(); - lexState = 'comment'; - return - - case undefined: - read(); - return newToken('eof') - } - - if (util.isSpaceSeparator(c)) { - read(); - return - } - - // This code is unreachable. - // if (!lexStates[parseState]) { - // throw invalidLexState(parseState) - // } - - return lexStates[parseState]() - }, - - comment () { - switch (c) { - case '*': - read(); - lexState = 'multiLineComment'; - return - - case '/': - read(); - lexState = 'singleLineComment'; - return - } - - throw invalidChar(read()) - }, - - multiLineComment () { - switch (c) { - case '*': - read(); - lexState = 'multiLineCommentAsterisk'; - return - - case undefined: - throw invalidChar(read()) - } - - read(); - }, - - multiLineCommentAsterisk () { - switch (c) { - case '*': - read(); - return - - case '/': - read(); - lexState = 'default'; - return - - case undefined: - throw invalidChar(read()) - } - - read(); - lexState = 'multiLineComment'; - }, - - singleLineComment () { - switch (c) { - case '\n': - case '\r': - case '\u2028': - case '\u2029': - read(); - lexState = 'default'; - return - - case undefined: - read(); - return newToken('eof') - } - - read(); - }, - - value () { - switch (c) { - case '{': - case '[': - return newToken('punctuator', read()) - - case 'n': - read(); - literal('ull'); - return newToken('null', null) - - case 't': - read(); - literal('rue'); - return newToken('boolean', true) - - case 'f': - read(); - literal('alse'); - return newToken('boolean', false) - - case '-': - case '+': - if (read() === '-') { - sign = -1; - } - - lexState = 'sign'; - return - - case '.': - buffer = read(); - lexState = 'decimalPointLeading'; - return - - case '0': - buffer = read(); - lexState = 'zero'; - return - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - buffer = read(); - lexState = 'decimalInteger'; - return - - case 'I': - read(); - literal('nfinity'); - return newToken('numeric', Infinity) - - case 'N': - read(); - literal('aN'); - return newToken('numeric', NaN) - - case '"': - case "'": - doubleQuote = (read() === '"'); - buffer = ''; - lexState = 'string'; - return - } - - throw invalidChar(read()) - }, - - identifierNameStartEscape () { - if (c !== 'u') { - throw invalidChar(read()) - } - - read(); - const u = unicodeEscape(); - switch (u) { - case '$': - case '_': - break - - default: - if (!util.isIdStartChar(u)) { - throw invalidIdentifier() - } - - break - } - - buffer += u; - lexState = 'identifierName'; - }, - - identifierName () { - switch (c) { - case '$': - case '_': - case '\u200C': - case '\u200D': - buffer += read(); - return - - case '\\': - read(); - lexState = 'identifierNameEscape'; - return - } - - if (util.isIdContinueChar(c)) { - buffer += read(); - return - } - - return newToken('identifier', buffer) - }, - - identifierNameEscape () { - if (c !== 'u') { - throw invalidChar(read()) - } - - read(); - const u = unicodeEscape(); - switch (u) { - case '$': - case '_': - case '\u200C': - case '\u200D': - break - - default: - if (!util.isIdContinueChar(u)) { - throw invalidIdentifier() - } - - break - } - - buffer += u; - lexState = 'identifierName'; - }, - - sign () { - switch (c) { - case '.': - buffer = read(); - lexState = 'decimalPointLeading'; - return - - case '0': - buffer = read(); - lexState = 'zero'; - return - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - buffer = read(); - lexState = 'decimalInteger'; - return - - case 'I': - read(); - literal('nfinity'); - return newToken('numeric', sign * Infinity) - - case 'N': - read(); - literal('aN'); - return newToken('numeric', NaN) - } - - throw invalidChar(read()) - }, - - zero () { - switch (c) { - case '.': - buffer += read(); - lexState = 'decimalPoint'; - return - - case 'e': - case 'E': - buffer += read(); - lexState = 'decimalExponent'; - return - - case 'x': - case 'X': - buffer += read(); - lexState = 'hexadecimal'; - return - } - - return newToken('numeric', sign * 0) - }, - - decimalInteger () { - switch (c) { - case '.': - buffer += read(); - lexState = 'decimalPoint'; - return - - case 'e': - case 'E': - buffer += read(); - lexState = 'decimalExponent'; - return - } - - if (util.isDigit(c)) { - buffer += read(); - return - } - - return newToken('numeric', sign * Number(buffer)) - }, - - decimalPointLeading () { - if (util.isDigit(c)) { - buffer += read(); - lexState = 'decimalFraction'; - return - } - - throw invalidChar(read()) - }, - - decimalPoint () { - switch (c) { - case 'e': - case 'E': - buffer += read(); - lexState = 'decimalExponent'; - return - } - - if (util.isDigit(c)) { - buffer += read(); - lexState = 'decimalFraction'; - return - } - - return newToken('numeric', sign * Number(buffer)) - }, - - decimalFraction () { - switch (c) { - case 'e': - case 'E': - buffer += read(); - lexState = 'decimalExponent'; - return - } - - if (util.isDigit(c)) { - buffer += read(); - return - } - - return newToken('numeric', sign * Number(buffer)) - }, - - decimalExponent () { - switch (c) { - case '+': - case '-': - buffer += read(); - lexState = 'decimalExponentSign'; - return - } - - if (util.isDigit(c)) { - buffer += read(); - lexState = 'decimalExponentInteger'; - return - } - - throw invalidChar(read()) - }, - - decimalExponentSign () { - if (util.isDigit(c)) { - buffer += read(); - lexState = 'decimalExponentInteger'; - return - } - - throw invalidChar(read()) - }, - - decimalExponentInteger () { - if (util.isDigit(c)) { - buffer += read(); - return - } - - return newToken('numeric', sign * Number(buffer)) - }, - - hexadecimal () { - if (util.isHexDigit(c)) { - buffer += read(); - lexState = 'hexadecimalInteger'; - return - } - - throw invalidChar(read()) - }, - - hexadecimalInteger () { - if (util.isHexDigit(c)) { - buffer += read(); - return - } - - return newToken('numeric', sign * Number(buffer)) - }, - - string () { - switch (c) { - case '\\': - read(); - buffer += escape(); - return - - case '"': - if (doubleQuote) { - read(); - return newToken('string', buffer) - } - - buffer += read(); - return - - case "'": - if (!doubleQuote) { - read(); - return newToken('string', buffer) - } - - buffer += read(); - return - - case '\n': - case '\r': - throw invalidChar(read()) - - case '\u2028': - case '\u2029': - separatorChar(c); - break - - case undefined: - throw invalidChar(read()) - } - - buffer += read(); - }, - - start () { - switch (c) { - case '{': - case '[': - return newToken('punctuator', read()) - - // This code is unreachable since the default lexState handles eof. - // case undefined: - // return newToken('eof') - } - - lexState = 'value'; - }, - - beforePropertyName () { - switch (c) { - case '$': - case '_': - buffer = read(); - lexState = 'identifierName'; - return - - case '\\': - read(); - lexState = 'identifierNameStartEscape'; - return - - case '}': - return newToken('punctuator', read()) - - case '"': - case "'": - doubleQuote = (read() === '"'); - lexState = 'string'; - return - } - - if (util.isIdStartChar(c)) { - buffer += read(); - lexState = 'identifierName'; - return - } - - throw invalidChar(read()) - }, - - afterPropertyName () { - if (c === ':') { - return newToken('punctuator', read()) - } - - throw invalidChar(read()) - }, - - beforePropertyValue () { - lexState = 'value'; - }, - - afterPropertyValue () { - switch (c) { - case ',': - case '}': - return newToken('punctuator', read()) - } - - throw invalidChar(read()) - }, - - beforeArrayValue () { - if (c === ']') { - return newToken('punctuator', read()) - } - - lexState = 'value'; - }, - - afterArrayValue () { - switch (c) { - case ',': - case ']': - return newToken('punctuator', read()) - } - - throw invalidChar(read()) - }, - - end () { - // This code is unreachable since it's handled by the default lexState. - // if (c === undefined) { - // read() - // return newToken('eof') - // } - - throw invalidChar(read()) - }, -}; - -function newToken (type, value) { - return { - type, - value, - line, - column, - } -} - -function literal (s) { - for (const c of s) { - const p = peek(); - - if (p !== c) { - throw invalidChar(read()) - } - - read(); - } -} - -function escape () { - const c = peek(); - switch (c) { - case 'b': - read(); - return '\b' - - case 'f': - read(); - return '\f' - - case 'n': - read(); - return '\n' - - case 'r': - read(); - return '\r' - - case 't': - read(); - return '\t' - - case 'v': - read(); - return '\v' - - case '0': - read(); - if (util.isDigit(peek())) { - throw invalidChar(read()) - } - - return '\0' - - case 'x': - read(); - return hexEscape() - - case 'u': - read(); - return unicodeEscape() - - case '\n': - case '\u2028': - case '\u2029': - read(); - return '' - - case '\r': - read(); - if (peek() === '\n') { - read(); - } - - return '' - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - throw invalidChar(read()) - - case undefined: - throw invalidChar(read()) - } - - return read() -} - -function hexEscape () { - let buffer = ''; - let c = peek(); - - if (!util.isHexDigit(c)) { - throw invalidChar(read()) - } - - buffer += read(); - - c = peek(); - if (!util.isHexDigit(c)) { - throw invalidChar(read()) - } - - buffer += read(); - - return String.fromCodePoint(parseInt(buffer, 16)) -} - -function unicodeEscape () { - let buffer = ''; - let count = 4; - - while (count-- > 0) { - const c = peek(); - if (!util.isHexDigit(c)) { - throw invalidChar(read()) - } - - buffer += read(); - } - - return String.fromCodePoint(parseInt(buffer, 16)) -} - -const parseStates = { - start () { - if (token.type === 'eof') { - throw invalidEOF() - } - - push$1(); - }, - - beforePropertyName () { - switch (token.type) { - case 'identifier': - case 'string': - key = token.value; - parseState = 'afterPropertyName'; - return - - case 'punctuator': - // This code is unreachable since it's handled by the lexState. - // if (token.value !== '}') { - // throw invalidToken() - // } - - pop(); - return - - case 'eof': - throw invalidEOF() - } - - // This code is unreachable since it's handled by the lexState. - // throw invalidToken() - }, - - afterPropertyName () { - // This code is unreachable since it's handled by the lexState. - // if (token.type !== 'punctuator' || token.value !== ':') { - // throw invalidToken() - // } - - if (token.type === 'eof') { - throw invalidEOF() - } - - parseState = 'beforePropertyValue'; - }, - - beforePropertyValue () { - if (token.type === 'eof') { - throw invalidEOF() - } - - push$1(); - }, - - beforeArrayValue () { - if (token.type === 'eof') { - throw invalidEOF() - } - - if (token.type === 'punctuator' && token.value === ']') { - pop(); - return - } - - push$1(); - }, - - afterPropertyValue () { - // This code is unreachable since it's handled by the lexState. - // if (token.type !== 'punctuator') { - // throw invalidToken() - // } - - if (token.type === 'eof') { - throw invalidEOF() - } - - switch (token.value) { - case ',': - parseState = 'beforePropertyName'; - return - - case '}': - pop(); - } - - // This code is unreachable since it's handled by the lexState. - // throw invalidToken() - }, - - afterArrayValue () { - // This code is unreachable since it's handled by the lexState. - // if (token.type !== 'punctuator') { - // throw invalidToken() - // } - - if (token.type === 'eof') { - throw invalidEOF() - } - - switch (token.value) { - case ',': - parseState = 'beforeArrayValue'; - return - - case ']': - pop(); - } - - // This code is unreachable since it's handled by the lexState. - // throw invalidToken() - }, - - end () { - // This code is unreachable since it's handled by the lexState. - // if (token.type !== 'eof') { - // throw invalidToken() - // } - }, -}; - -function push$1 () { - let value; - - switch (token.type) { - case 'punctuator': - switch (token.value) { - case '{': - value = {}; - break - - case '[': - value = []; - break - } - - break - - case 'null': - case 'boolean': - case 'numeric': - case 'string': - value = token.value; - break - - // This code is unreachable. - // default: - // throw invalidToken() - } - - if (root$1 === undefined) { - root$1 = value; - } else { - const parent = stack[stack.length - 1]; - if (Array.isArray(parent)) { - parent.push(value); - } else { - parent[key] = value; - } - } - - if (value !== null && typeof value === 'object') { - stack.push(value); - - if (Array.isArray(value)) { - parseState = 'beforeArrayValue'; - } else { - parseState = 'beforePropertyName'; - } - } else { - const current = stack[stack.length - 1]; - if (current == null) { - parseState = 'end'; - } else if (Array.isArray(current)) { - parseState = 'afterArrayValue'; - } else { - parseState = 'afterPropertyValue'; - } - } -} - -function pop () { - stack.pop(); - - const current = stack[stack.length - 1]; - if (current == null) { - parseState = 'end'; - } else if (Array.isArray(current)) { - parseState = 'afterArrayValue'; - } else { - parseState = 'afterPropertyValue'; - } -} - -// This code is unreachable. -// function invalidParseState () { -// return new Error(`JSON5: invalid parse state '${parseState}'`) -// } - -// This code is unreachable. -// function invalidLexState (state) { -// return new Error(`JSON5: invalid lex state '${state}'`) -// } - -function invalidChar (c) { - if (c === undefined) { - return syntaxError(`JSON5: invalid end of input at ${line}:${column}`) - } - - return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`) -} - -function invalidEOF () { - return syntaxError(`JSON5: invalid end of input at ${line}:${column}`) -} - -// This code is unreachable. -// function invalidToken () { -// if (token.type === 'eof') { -// return syntaxError(`JSON5: invalid end of input at ${line}:${column}`) -// } - -// const c = String.fromCodePoint(token.value.codePointAt(0)) -// return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`) -// } - -function invalidIdentifier () { - column -= 5; - return syntaxError(`JSON5: invalid identifier character at ${line}:${column}`) -} - -function separatorChar (c) { - console.warn(`JSON5: '${formatChar(c)}' in strings is not valid ECMAScript; consider escaping`); -} - -function formatChar (c) { - const replacements = { - "'": "\\'", - '"': '\\"', - '\\': '\\\\', - '\b': '\\b', - '\f': '\\f', - '\n': '\\n', - '\r': '\\r', - '\t': '\\t', - '\v': '\\v', - '\0': '\\0', - '\u2028': '\\u2028', - '\u2029': '\\u2029', - }; - - if (replacements[c]) { - return replacements[c] - } - - if (c < ' ') { - const hexString = c.charCodeAt(0).toString(16); - return '\\x' + ('00' + hexString).substring(hexString.length) - } - - return c -} - -function syntaxError (message) { - const err = new SyntaxError(message); - err.lineNumber = line; - err.columnNumber = column; - return err -} - -var stringify = function stringify (value, replacer, space) { - const stack = []; - let indent = ''; - let propertyList; - let replacerFunc; - let gap = ''; - let quote; - - if ( - replacer != null && - typeof replacer === 'object' && - !Array.isArray(replacer) - ) { - space = replacer.space; - quote = replacer.quote; - replacer = replacer.replacer; - } - - if (typeof replacer === 'function') { - replacerFunc = replacer; - } else if (Array.isArray(replacer)) { - propertyList = []; - for (const v of replacer) { - let item; - - if (typeof v === 'string') { - item = v; - } else if ( - typeof v === 'number' || - v instanceof String || - v instanceof Number - ) { - item = String(v); - } - - if (item !== undefined && propertyList.indexOf(item) < 0) { - propertyList.push(item); - } - } - } - - if (space instanceof Number) { - space = Number(space); - } else if (space instanceof String) { - space = String(space); - } - - if (typeof space === 'number') { - if (space > 0) { - space = Math.min(10, Math.floor(space)); - gap = ' '.substr(0, space); - } - } else if (typeof space === 'string') { - gap = space.substr(0, 10); - } - - return serializeProperty('', {'': value}) - - function serializeProperty (key, holder) { - let value = holder[key]; - if (value != null) { - if (typeof value.toJSON5 === 'function') { - value = value.toJSON5(key); - } else if (typeof value.toJSON === 'function') { - value = value.toJSON(key); - } - } - - if (replacerFunc) { - value = replacerFunc.call(holder, key, value); - } - - if (value instanceof Number) { - value = Number(value); - } else if (value instanceof String) { - value = String(value); - } else if (value instanceof Boolean) { - value = value.valueOf(); - } - - switch (value) { - case null: return 'null' - case true: return 'true' - case false: return 'false' - } - - if (typeof value === 'string') { - return quoteString(value) - } - - if (typeof value === 'number') { - return String(value) - } - - if (typeof value === 'object') { - return Array.isArray(value) ? serializeArray(value) : serializeObject(value) - } - - return undefined - } - - function quoteString (value) { - const quotes = { - "'": 0.1, - '"': 0.2, - }; - - const replacements = { - "'": "\\'", - '"': '\\"', - '\\': '\\\\', - '\b': '\\b', - '\f': '\\f', - '\n': '\\n', - '\r': '\\r', - '\t': '\\t', - '\v': '\\v', - '\0': '\\0', - '\u2028': '\\u2028', - '\u2029': '\\u2029', - }; - - let product = ''; - - for (let i = 0; i < value.length; i++) { - const c = value[i]; - switch (c) { - case "'": - case '"': - quotes[c]++; - product += c; - continue - - case '\0': - if (util.isDigit(value[i + 1])) { - product += '\\x00'; - continue - } - } - - if (replacements[c]) { - product += replacements[c]; - continue - } - - if (c < ' ') { - let hexString = c.charCodeAt(0).toString(16); - product += '\\x' + ('00' + hexString).substring(hexString.length); - continue - } - - product += c; - } - - const quoteChar = quote || Object.keys(quotes).reduce((a, b) => (quotes[a] < quotes[b]) ? a : b); - - product = product.replace(new RegExp(quoteChar, 'g'), replacements[quoteChar]); - - return quoteChar + product + quoteChar - } - - function serializeObject (value) { - if (stack.indexOf(value) >= 0) { - throw TypeError('Converting circular structure to JSON5') - } - - stack.push(value); - - let stepback = indent; - indent = indent + gap; - - let keys = propertyList || Object.keys(value); - let partial = []; - for (const key of keys) { - const propertyString = serializeProperty(key, value); - if (propertyString !== undefined) { - let member = serializeKey(key) + ':'; - if (gap !== '') { - member += ' '; - } - member += propertyString; - partial.push(member); - } - } - - let final; - if (partial.length === 0) { - final = '{}'; - } else { - let properties; - if (gap === '') { - properties = partial.join(','); - final = '{' + properties + '}'; - } else { - let separator = ',\n' + indent; - properties = partial.join(separator); - final = '{\n' + indent + properties + ',\n' + stepback + '}'; - } - } - - stack.pop(); - indent = stepback; - return final - } - - function serializeKey (key) { - if (key.length === 0) { - return quoteString(key) - } - - const firstChar = String.fromCodePoint(key.codePointAt(0)); - if (!util.isIdStartChar(firstChar)) { - return quoteString(key) - } - - for (let i = firstChar.length; i < key.length; i++) { - if (!util.isIdContinueChar(String.fromCodePoint(key.codePointAt(i)))) { - return quoteString(key) - } - } - - return key - } - - function serializeArray (value) { - if (stack.indexOf(value) >= 0) { - throw TypeError('Converting circular structure to JSON5') - } - - stack.push(value); - - let stepback = indent; - indent = indent + gap; - - let partial = []; - for (let i = 0; i < value.length; i++) { - const propertyString = serializeProperty(String(i), value); - partial.push((propertyString !== undefined) ? propertyString : 'null'); - } - - let final; - if (partial.length === 0) { - final = '[]'; - } else { - if (gap === '') { - let properties = partial.join(','); - final = '[' + properties + ']'; - } else { - let separator = ',\n' + indent; - let properties = partial.join(separator); - final = '[\n' + indent + properties + ',\n' + stepback + ']'; - } - } - - stack.pop(); - indent = stepback; - return final - } -}; - -const JSON5 = { - parse: parse$1, - stringify, -}; - -var lib = JSON5; - -/** - * @typedef Option - * @property {'boolean'|'string'} [type='string'] - * @property {string} long - * @property {string} description - * @property {string} [value] - * @property {string} [short] - * @property {boolean|string} [default=''] - * @property {boolean} [truelike=false] - */ - -/** @type {Option[]} */ -const schema = [ - { - long: 'help', - description: 'output usage information', - short: 'h', - type: 'boolean', - default: false - }, - { - long: 'version', - description: 'output version number', - short: 'v', - type: 'boolean', - default: false - }, - { - long: 'output', - description: 'specify output location', - short: 'o', - value: '[path]' - }, - { - long: 'rc-path', - description: 'specify configuration file', - short: 'r', - type: 'string', - value: '' - }, - { - long: 'ignore-path', - description: 'specify ignore file', - short: 'i', - type: 'string', - value: '' - }, - { - long: 'setting', - description: 'specify settings', - short: 's', - type: 'string', - value: '' - }, - { - long: 'ext', - description: 'specify extensions', - short: 'e', - type: 'string', - value: '' - }, - { - long: 'use', - description: 'use plugins', - short: 'u', - type: 'string', - value: '' - }, - { - long: 'watch', - description: 'watch for changes and reprocess', - short: 'w', - type: 'boolean', - default: false - }, - { - long: 'quiet', - description: 'output only warnings and errors', - short: 'q', - type: 'boolean', - default: false - }, - { - long: 'silent', - description: 'output only errors', - short: 'S', - type: 'boolean', - default: false - }, - { - long: 'frail', - description: 'exit with 1 on warnings', - short: 'f', - type: 'boolean', - default: false - }, - { - long: 'tree', - description: 'specify input and output as syntax tree', - short: 't', - type: 'boolean', - default: false - }, - { - long: 'report', - description: 'specify reporter', - type: 'string', - value: '' - }, - { - long: 'file-path', - description: 'specify path to process as', - type: 'string', - value: '' - }, - { - long: 'ignore-path-resolve-from', - description: 'resolve patterns in `ignore-path` from its directory or cwd', - type: 'string', - value: 'dir|cwd', - default: 'dir' - }, - { - long: 'ignore-pattern', - description: 'specify ignore patterns', - type: 'string', - value: '' - }, - { - long: 'silently-ignore', - description: 'do not fail when given ignored files', - type: 'boolean' - }, - { - long: 'tree-in', - description: 'specify input as syntax tree', - type: 'boolean' - }, - { - long: 'tree-out', - description: 'output syntax tree', - type: 'boolean' - }, - { - long: 'inspect', - description: 'output formatted syntax tree', - type: 'boolean' - }, - { - long: 'stdout', - description: 'specify writing to stdout', - type: 'boolean', - truelike: true - }, - { - long: 'color', - description: 'specify color in report', - type: 'boolean', - default: true - }, - { - long: 'config', - description: 'search for configuration files', - type: 'boolean', - default: true - }, - { - long: 'ignore', - description: 'search for ignore files', - type: 'boolean', - default: true - } -]; - -/** - * @typedef {import('unified-engine').Options} EngineOptions - * @typedef {import('./schema.js').Option} Option - * - * @typedef {Required< - * Pick< - * EngineOptions, - * | 'extensions' - * | 'ignoreName' - * | 'packageField' - * | 'pluginPrefix' - * | 'processor' - * | 'rcName' - * > - * >} RequiredEngineOptions - * - * @typedef ArgsOptionsFields - * @property {string} name - * Name of executable - * @property {string} description - * Description of executable - * @property {string} version - * Version (semver) of executable - * - * @typedef {RequiredEngineOptions & Pick & ArgsOptionsFields} Options - */ - -const own$7 = {}.hasOwnProperty; - -/** - * Schema for `minimist`. - */ -const minischema = { - unknown: handleUnknownArgument, - /** @type {Record} */ - default: {}, - /** @type {Record} */ - alias: {}, - /** @type {string[]} */ - string: [], - /** @type {string[]} */ - boolean: [] -}; - -let index = -1; -while (++index < schema.length) { - addEach(schema[index]); -} - -/** - * Parse CLI options. - * - * @param {string[]} flags - * @param {Options} configuration - */ -function options(flags, configuration) { - const extension = configuration.extensions[0]; - const name = configuration.name; - const config = toCamelCase(minimist(flags, minischema)); - let index = -1; - - while (++index < schema.length) { - const option = schema[index]; - if (option.type === 'string' && config[option.long] === '') { - throw fault('Missing value:%s', inspect(option).join(' ')) - } - } - - const ext = commaSeparated(/** @type {string} */ (config.ext)); - const report = reporter(/** @type {string} */ (config.report)); - const help = [ - inspectAll(schema), - '', - 'Examples:', - '', - ' # Process `input.' + extension + '`', - ' $ ' + name + ' input.' + extension + ' -o output.' + extension, - '', - ' # Pipe', - ' $ ' + name + ' < input.' + extension + ' > output.' + extension, - '', - ' # Rewrite all applicable files', - ' $ ' + name + ' . -o' - ].join('\n'); - - return { - helpMessage: help, - cwd: configuration.cwd, - processor: configuration.processor, - help: config.help, - version: config.version, - files: config._, - filePath: config.filePath, - watch: config.watch, - extensions: ext.length === 0 ? configuration.extensions : ext, - output: config.output, - out: config.stdout, - tree: config.tree, - treeIn: config.treeIn, - treeOut: config.treeOut, - inspect: config.inspect, - rcName: configuration.rcName, - packageField: configuration.packageField, - rcPath: config.rcPath, - detectConfig: config.config, - settings: /** @type {Record} */ ( - settings$1(/** @type {string} */ (config.setting)) - ), - ignoreName: configuration.ignoreName, - ignorePath: config.ignorePath, - ignorePathResolveFrom: config.ignorePathResolveFrom, - ignorePatterns: commaSeparated( - /** @type {string} */ (config.ignorePattern) - ), - silentlyIgnore: config.silentlyIgnore, - detectIgnore: config.ignore, - pluginPrefix: configuration.pluginPrefix, - plugins: plugins$1(/** @type {string} */ (config.use)), - reporter: report[0], - reporterOptions: report[1], - color: config.color, - silent: config.silent, - quiet: config.quiet, - frail: config.frail - } -} - -/** - * @param {Option} option - */ -function addEach(option) { - const value = option.default; - - minischema.default[option.long] = value === undefined ? null : value; - - if (option.type && option.type in minischema) { - minischema[option.type].push(option.long); - } - - if (option.short) { - minischema.alias[option.short] = option.long; - } -} - -/** - * Parse `extensions`. - * - * @param {string[]|string|null|undefined} value - * @returns {string[]} - */ -function commaSeparated(value) { - return flatten(normalize(value).map((d) => splitList(d))) -} - -/** - * Parse `plugins`. - * - * @param {string[]|string|null|undefined} value - * @returns {Record|undefined>} - */ -function plugins$1(value) { - const normalized = normalize(value).map((d) => splitOptions(d)); - let index = -1; - /** @type {Record|undefined>} */ - const result = {}; - - while (++index < normalized.length) { - const value = normalized[index]; - result[value[0]] = value[1] ? parseConfig(value[1], {}) : undefined; - } - - return result -} - -/** - * Parse `reporter`: only one is accepted. - * - * @param {string[]|string|null|undefined} value - * @returns {[string|undefined, Record|undefined]} - */ -function reporter(value) { - const all = normalize(value) - .map((d) => splitOptions(d)) - .map( - /** - * @returns {[string, Record|undefined]} - */ - (value) => [value[0], value[1] ? parseConfig(value[1], {}) : undefined] - ); - - return all[all.length - 1] || [] -} - -/** - * Parse `settings`. - * - * @param {string[]|string|null|undefined} value - * @returns {Record} - */ -function settings$1(value) { - const normalized = normalize(value); - let index = -1; - /** @type {Record} */ - const cache = {}; - - while (++index < normalized.length) { - parseConfig(normalized[index], cache); - } - - return cache -} - -/** - * Parse configuration. - * - * @param {string} value - * @param {Record} cache - * @returns {Record} - */ -function parseConfig(value, cache) { - /** @type {Record} */ - let flags; - /** @type {string} */ - let flag; - - try { - flags = toCamelCase(parseJSON(value)); - } catch (error) { - throw fault( - 'Cannot parse `%s` as JSON: %s', - value, - // Fix position - error.message.replace(/at(?= position)/, 'around') - ) - } - - for (flag in flags) { - if (own$7.call(flags, flag)) { - cache[flag] = flags[flag]; - } - } - - return cache -} - -/** - * Handle an unknown flag. - * - * @param {string} flag - * @returns {boolean} - */ -function handleUnknownArgument(flag) { - // Not a glob. - if (flag.charAt(0) === '-') { - // Long options, always unknown. - if (flag.charAt(1) === '-') { - throw fault( - 'Unknown option `%s`, expected:\n%s', - flag, - inspectAll(schema) - ) - } - - // Short options, can be grouped. - const found = flag.slice(1).split(''); - const known = schema.filter((d) => d.short); - const knownKeys = new Set(known.map((d) => d.short)); - let index = -1; - - while (++index < found.length) { - const key = found[index]; - if (!knownKeys.has(key)) { - throw fault( - 'Unknown short option `-%s`, expected:\n%s', - key, - inspectAll(known) - ) - } - } - } - - return true -} - -/** - * Inspect all `options`. - * - * @param {Option[]} options - * @returns {string} - */ -function inspectAll(options) { - return textTable(options.map((d) => inspect(d))) -} - -/** - * Inspect one `option`. - * - * @param {Option} option - * @returns {string[]} - */ -function inspect(option) { - let description = option.description; - let long = option.long; - - if (option.default === true || option.truelike) { - description += ' (on by default)'; - long = '[no-]' + long; - } - - return [ - '', - option.short ? '-' + option.short : '', - '--' + long + (option.value ? ' ' + option.value : ''), - description - ] -} - -/** - * Normalize `value`. - * - * @param {string[]|string|null|undefined} value - * @returns {string[]} - */ -function normalize(value) { - if (!value) { - return [] - } - - if (typeof value === 'string') { - return [value] - } - - return flatten(value.map((d) => normalize(d))) -} - -/** - * Flatten `values`. - * - * @param {string|string[]|string[][]} values - * @returns {string[]} - */ -function flatten(values) { - // @ts-expect-error: TS is wrong. - return values.flat() -} - -/** - * @param {string} value - * @returns {string[]} - */ -function splitOptions(value) { - return value.split('=') -} - -/** - * @param {string} value - * @returns {string[]} - */ -function splitList(value) { - return value.split(',') -} - -/** - * Transform the keys on an object to camel-case, recursivly. - * - * @param {Record} object - * @returns {Record} - */ -function toCamelCase(object) { - /** @type {Record} */ - const result = {}; - /** @type {string} */ - let key; - - for (key in object) { - if (own$7.call(object, key)) { - let value = object[key]; - - if (value && typeof value === 'object' && !Array.isArray(value)) { - // @ts-expect-error: looks like an object. - value = toCamelCase(value); - } - - result[camelcase(key)] = value; - } - } - - return result -} - -/** - * Parse a (lazy?) JSON config. - * - * @param {string} value - * @returns {Record} - */ -function parseJSON(value) { - return lib.parse('{' + value + '}') -} - -/** - * @typedef {import('unified-engine').Options} EngineOptions - * @typedef {import('unified-engine').Context} EngineContext - * @typedef {import('unified-engine').Callback} EngineCallback - * @typedef {import('./options.js').Options} Options - */ - -// Fake TTY stream. -const ttyStream = Object.assign(new stream.Readable(), {isTTY: true}); - -// Exit, lazily, with the correct exit status code. -let exitStatus = 0; - -process$2.on('exit', onexit); - -// Handle uncaught errors, such as from unexpected async behaviour. -process$2.on('uncaughtException', fail); - -/** - * Start the CLI. - * - * @param {Options} cliConfig - */ -function args(cliConfig) { - /** @type {EngineOptions & {help: boolean, helpMessage: string, watch: boolean, version: boolean}} */ - let config; - /** @type {chokidar.FSWatcher|undefined} */ - let watcher; - /** @type {boolean|string|undefined} */ - let output; - - try { - // @ts-expect-error: Close enough. - config = options(process$2.argv.slice(2), cliConfig); - } catch (error) { - return fail(error, true) - } - - if (config.help) { - process$2.stdout.write( - [ - 'Usage: ' + cliConfig.name + ' [options] [path | glob ...]', - '', - ' ' + cliConfig.description, - '', - 'Options:', - '', - config.helpMessage, - '' - ].join('\n'), - noop$1 - ); - - return - } - - if (config.version) { - process$2.stdout.write(cliConfig.version + '\n', noop$1); - - return - } - - // Modify `config` for watching. - if (config.watch) { - output = config.output; - - // Do not read from stdin(4). - config.streamIn = ttyStream; - - // Do not write to stdout(4). - config.out = false; - - process$2.stderr.write( - source$1.bold('Watching...') + ' (press CTRL+C to exit)\n', - noop$1 - ); - - // Prevent infinite loop if set to regeneration. - if (output === true) { - config.output = false; - - process$2.stderr.write( - source$1.yellow('Note') + ': Ignoring `--output` until exit.\n', - noop$1 - ); - } - } - - // Initial run. - engine(config, done); - - /** - * Handle complete run. - * - * @type {EngineCallback} - */ - function done(error, code, context) { - if (error) { - clean(); - fail(error); - } else { - exitStatus = code || 0; - - if (config.watch && !watcher && context) { - subscribe(context); - } - } - } - - // Clean the watcher. - function clean() { - if (watcher) { - watcher.close(); - watcher = undefined; - } - } - - /** - * Subscribe a chokidar watcher to all processed files. - * - * @param {EngineContext} context - */ - function subscribe(context) { - watcher = chokidar - // @ts-expect-error: `fileSet` is available. - .watch(context.fileSet.origins, {cwd: config.cwd, ignoreInitial: true}) - .on('error', done) - .on('change', (filePath) => { - config.files = [filePath]; - engine(config, done); - }); - - process$2.on('SIGINT', onsigint); - - /** - * Handle a SIGINT. - */ - function onsigint() { - // Hide the `^C` in terminal. - process$2.stderr.write('\n', noop$1); - - clean(); - - // Do another process if `output` specified regeneration. - if (output === true) { - config.output = output; - config.watch = false; - engine(config, done); - } - } - } -} - -/** - * Print an error, optionally with stack. - * - * @param {Error} error - * @param {boolean} [pretty=false] - */ -function fail(error, pretty) { - // Old versions of Node - /* c8 ignore next 1 */ - const message = String((pretty ? error : error.stack) || error); - - exitStatus = 1; - - process$2.stderr.write(message.trim() + '\n', noop$1); -} - -function onexit() { - /* eslint-disable unicorn/no-process-exit */ - process$2.exit(exitStatus); - /* eslint-enable unicorn/no-process-exit */ -} - -function noop$1() {} - -var require$$0 = [ - "md", - "markdown", - "mdown", - "mkdn", - "mkd", - "mdwn", - "mkdown", - "ron" -]; - -var markdownExtensions = require$$0; - -/** - * Throw a given error. - * - * @param {Error | null | undefined} [error] - */ -function bail(error) { - if (error) { - throw error - } -} - -var hasOwn = Object.prototype.hasOwnProperty; -var toStr = Object.prototype.toString; -var defineProperty = Object.defineProperty; -var gOPD = Object.getOwnPropertyDescriptor; - -var isArray = function isArray(arr) { - if (typeof Array.isArray === 'function') { - return Array.isArray(arr); - } - - return toStr.call(arr) === '[object Array]'; -}; - -var isPlainObject = function isPlainObject(obj) { - if (!obj || toStr.call(obj) !== '[object Object]') { - return false; - } - - var hasOwnConstructor = hasOwn.call(obj, 'constructor'); - var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf'); - // Not own constructor property must be Object - if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) { - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - var key; - for (key in obj) { /**/ } - - return typeof key === 'undefined' || hasOwn.call(obj, key); -}; - -// If name is '__proto__', and Object.defineProperty is available, define __proto__ as an own property on target -var setProperty = function setProperty(target, options) { - if (defineProperty && options.name === '__proto__') { - defineProperty(target, options.name, { - enumerable: true, - configurable: true, - value: options.newValue, - writable: true - }); - } else { - target[options.name] = options.newValue; - } -}; - -// Return undefined instead of __proto__ if '__proto__' is not an own property -var getProperty = function getProperty(obj, name) { - if (name === '__proto__') { - if (!hasOwn.call(obj, name)) { - return void 0; - } else if (gOPD) { - // In early versions of node, obj['__proto__'] is buggy when obj has - // __proto__ as an own property. Object.getOwnPropertyDescriptor() works. - return gOPD(obj, name).value; - } - } - - return obj[name]; -}; - -var extend = function extend() { - var options, name, src, copy, copyIsArray, clone; - var target = arguments[0]; - var i = 1; - var length = arguments.length; - var deep = false; - - // Handle a deep copy situation - if (typeof target === 'boolean') { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - if (target == null || (typeof target !== 'object' && typeof target !== 'function')) { - target = {}; - } - - for (; i < length; ++i) { - options = arguments[i]; - // Only deal with non-null/undefined values - if (options != null) { - // Extend the base object - for (name in options) { - src = getProperty(target, name); - copy = getProperty(options, name); - - // Prevent never-ending loop - if (target !== copy) { - // Recurse if we're merging plain objects or arrays - if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { - if (copyIsArray) { - copyIsArray = false; - clone = src && isArray(src) ? src : []; - } else { - clone = src && isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - setProperty(target, { name: name, newValue: extend(deep, clone, copy) }); - - // Don't bring in undefined values - } else if (typeof copy !== 'undefined') { - setProperty(target, { name: name, newValue: copy }); - } - } - } - } - } - - // Return the modified object - return target; -}; - -/** - * @typedef {import('unist').Node} Node - * @typedef {import('vfile').VFileCompatible} VFileCompatible - * @typedef {import('vfile').VFileValue} VFileValue - * @typedef {import('..').Processor} Processor - * @typedef {import('..').Plugin} Plugin - * @typedef {import('..').Preset} Preset - * @typedef {import('..').Pluggable} Pluggable - * @typedef {import('..').PluggableList} PluggableList - * @typedef {import('..').Transformer} Transformer - * @typedef {import('..').Parser} Parser - * @typedef {import('..').Compiler} Compiler - * @typedef {import('..').RunCallback} RunCallback - * @typedef {import('..').ProcessCallback} ProcessCallback - * - * @typedef Context - * @property {Node} tree - * @property {VFile} file - */ - -// Expose a frozen processor. -const unified = base().freeze(); - -const own$6 = {}.hasOwnProperty; - -// Function to create the first processor. -/** - * @returns {Processor} - */ -function base() { - const transformers = trough(); - /** @type {Processor['attachers']} */ - const attachers = []; - /** @type {Record} */ - let namespace = {}; - /** @type {boolean|undefined} */ - let frozen; - let freezeIndex = -1; - - // Data management. - // @ts-expect-error: overloads are handled. - processor.data = data; - processor.Parser = undefined; - processor.Compiler = undefined; - - // Lock. - processor.freeze = freeze; - - // Plugins. - processor.attachers = attachers; - // @ts-expect-error: overloads are handled. - processor.use = use; - - // API. - processor.parse = parse; - processor.stringify = stringify; - // @ts-expect-error: overloads are handled. - processor.run = run; - processor.runSync = runSync; - // @ts-expect-error: overloads are handled. - processor.process = process; - processor.processSync = processSync; - - // Expose. - return processor - - // Create a new processor based on the processor in the current scope. - /** @type {Processor} */ - function processor() { - const destination = base(); - let index = -1; - - while (++index < attachers.length) { - destination.use(...attachers[index]); - } - - destination.data(extend(true, {}, namespace)); - - return destination - } - - /** - * @param {string|Record} [key] - * @param {unknown} [value] - * @returns {unknown} - */ - function data(key, value) { - if (typeof key === 'string') { - // Set `key`. - if (arguments.length === 2) { - assertUnfrozen('data', frozen); - namespace[key] = value; - return processor - } - - // Get `key`. - return (own$6.call(namespace, key) && namespace[key]) || null - } - - // Set space. - if (key) { - assertUnfrozen('data', frozen); - namespace = key; - return processor - } - - // Get space. - return namespace - } - - /** @type {Processor['freeze']} */ - function freeze() { - if (frozen) { - return processor - } - - while (++freezeIndex < attachers.length) { - const [attacher, ...options] = attachers[freezeIndex]; - - if (options[0] === false) { - continue - } - - if (options[0] === true) { - options[1] = undefined; - } - - /** @type {Transformer|void} */ - const transformer = attacher.call(processor, ...options); - - if (typeof transformer === 'function') { - transformers.use(transformer); - } - } - - frozen = true; - freezeIndex = Number.POSITIVE_INFINITY; - - return processor - } - - /** - * @param {Pluggable|null|undefined} [value] - * @param {...unknown} options - * @returns {Processor} - */ - function use(value, ...options) { - /** @type {Record|undefined} */ - let settings; - - assertUnfrozen('use', frozen); - - if (value === null || value === undefined) ; else if (typeof value === 'function') { - addPlugin(value, ...options); - } else if (typeof value === 'object') { - if (Array.isArray(value)) { - addList(value); - } else { - addPreset(value); - } - } else { - throw new TypeError('Expected usable value, not `' + value + '`') - } - - if (settings) { - namespace.settings = Object.assign(namespace.settings || {}, settings); - } - - return processor - - /** - * @param {import('..').Pluggable} value - * @returns {void} - */ - function add(value) { - if (typeof value === 'function') { - addPlugin(value); - } else if (typeof value === 'object') { - if (Array.isArray(value)) { - const [plugin, ...options] = value; - addPlugin(plugin, ...options); - } else { - addPreset(value); - } - } else { - throw new TypeError('Expected usable value, not `' + value + '`') - } - } - - /** - * @param {Preset} result - * @returns {void} - */ - function addPreset(result) { - addList(result.plugins); - - if (result.settings) { - settings = Object.assign(settings || {}, result.settings); - } - } - - /** - * @param {PluggableList|null|undefined} [plugins] - * @returns {void} - */ - function addList(plugins) { - let index = -1; - - if (plugins === null || plugins === undefined) ; else if (Array.isArray(plugins)) { - while (++index < plugins.length) { - const thing = plugins[index]; - add(thing); - } - } else { - throw new TypeError('Expected a list of plugins, not `' + plugins + '`') - } - } - - /** - * @param {Plugin} plugin - * @param {...unknown} [value] - * @returns {void} - */ - function addPlugin(plugin, value) { - let index = -1; - /** @type {Processor['attachers'][number]|undefined} */ - let entry; - - while (++index < attachers.length) { - if (attachers[index][0] === plugin) { - entry = attachers[index]; - break - } - } - - if (entry) { - if (isPlainObject$1(entry[1]) && isPlainObject$1(value)) { - value = extend(true, entry[1], value); - } - - entry[1] = value; - } else { - // @ts-expect-error: fine. - attachers.push([...arguments]); - } - } - } - - /** @type {Processor['parse']} */ - function parse(doc) { - processor.freeze(); - const file = vfile(doc); - const Parser = processor.Parser; - assertParser('parse', Parser); - - if (newable(Parser, 'parse')) { - // @ts-expect-error: `newable` checks this. - return new Parser(String(file), file).parse() - } - - // @ts-expect-error: `newable` checks this. - return Parser(String(file), file) // eslint-disable-line new-cap - } - - /** @type {Processor['stringify']} */ - function stringify(node, doc) { - processor.freeze(); - const file = vfile(doc); - const Compiler = processor.Compiler; - assertCompiler('stringify', Compiler); - assertNode(node); - - if (newable(Compiler, 'compile')) { - // @ts-expect-error: `newable` checks this. - return new Compiler(node, file).compile() - } - - // @ts-expect-error: `newable` checks this. - return Compiler(node, file) // eslint-disable-line new-cap - } - - /** - * @param {Node} node - * @param {VFileCompatible|RunCallback} [doc] - * @param {RunCallback} [callback] - * @returns {Promise|void} - */ - function run(node, doc, callback) { - assertNode(node); - processor.freeze(); - - if (!callback && typeof doc === 'function') { - callback = doc; - doc = undefined; - } - - if (!callback) { - return new Promise(executor) - } - - executor(null, callback); - - /** - * @param {null|((node: Node) => void)} resolve - * @param {(error: Error) => void} reject - * @returns {void} - */ - function executor(resolve, reject) { - // @ts-expect-error: `doc` can’t be a callback anymore, we checked. - transformers.run(node, vfile(doc), done); - - /** - * @param {Error|null} error - * @param {Node} tree - * @param {VFile} file - * @returns {void} - */ - function done(error, tree, file) { - tree = tree || node; - if (error) { - reject(error); - } else if (resolve) { - resolve(tree); - } else { - // @ts-expect-error: `callback` is defined if `resolve` is not. - callback(null, tree, file); - } - } - } - } - - /** @type {Processor['runSync']} */ - function runSync(node, file) { - /** @type {Node|undefined} */ - let result; - /** @type {boolean|undefined} */ - let complete; - - processor.run(node, file, done); - - assertDone('runSync', 'run', complete); - - // @ts-expect-error: we either bailed on an error or have a tree. - return result - - /** - * @param {Error|null} [error] - * @param {Node} [tree] - * @returns {void} - */ - function done(error, tree) { - bail(error); - result = tree; - complete = true; - } - } - - /** - * @param {VFileCompatible} doc - * @param {ProcessCallback} [callback] - * @returns {Promise|undefined} - */ - function process(doc, callback) { - processor.freeze(); - assertParser('process', processor.Parser); - assertCompiler('process', processor.Compiler); - - if (!callback) { - return new Promise(executor) - } - - executor(null, callback); - - /** - * @param {null|((file: VFile) => void)} resolve - * @param {(error?: Error|null|undefined) => void} reject - * @returns {void} - */ - function executor(resolve, reject) { - const file = vfile(doc); - - processor.run(processor.parse(file), file, (error, tree, file) => { - if (error || !tree || !file) { - done(error); - } else { - /** @type {unknown} */ - const result = processor.stringify(tree, file); - - if (result === undefined || result === null) ; else if (looksLikeAVFileValue(result)) { - file.value = result; - } else { - file.result = result; - } - - done(error, file); - } - }); - - /** - * @param {Error|null|undefined} [error] - * @param {VFile|undefined} [file] - * @returns {void} - */ - function done(error, file) { - if (error || !file) { - reject(error); - } else if (resolve) { - resolve(file); - } else { - // @ts-expect-error: `callback` is defined if `resolve` is not. - callback(null, file); - } - } - } - } - - /** @type {Processor['processSync']} */ - function processSync(doc) { - /** @type {boolean|undefined} */ - let complete; - - processor.freeze(); - assertParser('processSync', processor.Parser); - assertCompiler('processSync', processor.Compiler); - - const file = vfile(doc); - - processor.process(file, done); - - assertDone('processSync', 'process', complete); - - return file - - /** - * @param {Error|null|undefined} [error] - * @returns {void} - */ - function done(error) { - complete = true; - bail(error); - } - } -} - -/** - * Check if `value` is a constructor. - * - * @param {unknown} value - * @param {string} name - * @returns {boolean} - */ -function newable(value, name) { - return ( - typeof value === 'function' && - // Prototypes do exist. - // type-coverage:ignore-next-line - value.prototype && - // A function with keys in its prototype is probably a constructor. - // Classes’ prototype methods are not enumerable, so we check if some value - // exists in the prototype. - // type-coverage:ignore-next-line - (keys(value.prototype) || name in value.prototype) - ) -} - -/** - * Check if `value` is an object with keys. - * - * @param {Record} value - * @returns {boolean} - */ -function keys(value) { - /** @type {string} */ - let key; - - for (key in value) { - if (own$6.call(value, key)) { - return true - } - } - - return false -} - -/** - * Assert a parser is available. - * - * @param {string} name - * @param {unknown} value - * @returns {asserts value is Parser} - */ -function assertParser(name, value) { - if (typeof value !== 'function') { - throw new TypeError('Cannot `' + name + '` without `Parser`') - } -} - -/** - * Assert a compiler is available. - * - * @param {string} name - * @param {unknown} value - * @returns {asserts value is Compiler} - */ -function assertCompiler(name, value) { - if (typeof value !== 'function') { - throw new TypeError('Cannot `' + name + '` without `Compiler`') - } -} - -/** - * Assert the processor is not frozen. - * - * @param {string} name - * @param {unknown} frozen - * @returns {asserts frozen is false} - */ -function assertUnfrozen(name, frozen) { - if (frozen) { - throw new Error( - 'Cannot call `' + - name + - '` on a frozen processor.\nCreate a new processor first, by calling it: use `processor()` instead of `processor`.' - ) - } -} - -/** - * Assert `node` is a unist node. - * - * @param {unknown} node - * @returns {asserts node is Node} - */ -function assertNode(node) { - // `isPlainObj` unfortunately uses `any` instead of `unknown`. - // type-coverage:ignore-next-line - if (!isPlainObject$1(node) || typeof node.type !== 'string') { - throw new TypeError('Expected node, got `' + node + '`') - // Fine. - } -} - -/** - * Assert that `complete` is `true`. - * - * @param {string} name - * @param {string} asyncName - * @param {unknown} complete - * @returns {asserts complete is true} - */ -function assertDone(name, asyncName, complete) { - if (!complete) { - throw new Error( - '`' + name + '` finished async. Use `' + asyncName + '` instead' - ) - } -} - -/** - * @param {VFileCompatible} [value] - * @returns {VFile} - */ -function vfile(value) { - return looksLikeAVFile(value) ? value : new VFile(value) -} - -/** - * @param {VFileCompatible} [value] - * @returns {value is VFile} - */ -function looksLikeAVFile(value) { - return Boolean( - value && - typeof value === 'object' && - 'message' in value && - 'messages' in value - ) -} - -/** - * @param {unknown} [value] - * @returns {value is VFileValue} - */ -function looksLikeAVFileValue(value) { - return typeof value === 'string' || isBuffer(value) -} - -/** - * @typedef Options - * @property {boolean} [includeImageAlt=true] - */ - -/** - * Get the text content of a node. - * Prefer the node’s plain-text fields, otherwise serialize its children, - * and if the given value is an array, serialize the nodes in it. - * - * @param {unknown} node - * @param {Options} [options] - * @returns {string} - */ -function toString(node, options) { - var {includeImageAlt = true} = options || {}; - return one(node, includeImageAlt) -} - -/** - * @param {unknown} node - * @param {boolean} includeImageAlt - * @returns {string} - */ -function one(node, includeImageAlt) { - return ( - (node && - typeof node === 'object' && - // @ts-ignore looks like a literal. - (node.value || - // @ts-ignore looks like an image. - (includeImageAlt ? node.alt : '') || - // @ts-ignore looks like a parent. - ('children' in node && all(node.children, includeImageAlt)) || - (Array.isArray(node) && all(node, includeImageAlt)))) || - '' - ) -} - -/** - * @param {Array.} values - * @param {boolean} includeImageAlt - * @returns {string} - */ -function all(values, includeImageAlt) { - /** @type {Array.} */ - var result = []; - var index = -1; - - while (++index < values.length) { - result[index] = one(values[index], includeImageAlt); - } - - return result.join('') -} - -/** - * Like `Array#splice`, but smarter for giant arrays. - * - * `Array#splice` takes all items to be inserted as individual argument which - * causes a stack overflow in V8 when trying to insert 100k items for instance. - * - * Otherwise, this does not return the removed items, and takes `items` as an - * array instead of rest parameters. - * - * @template {unknown} T - * @param {T[]} list - * @param {number} start - * @param {number} remove - * @param {T[]} items - * @returns {void} - */ -function splice(list, start, remove, items) { - const end = list.length; - let chunkStart = 0; - /** @type {unknown[]} */ - - let parameters; // Make start between zero and `end` (included). - - if (start < 0) { - start = -start > end ? 0 : end + start; - } else { - start = start > end ? end : start; - } - - remove = remove > 0 ? remove : 0; // No need to chunk the items if there’s only a couple (10k) items. - - if (items.length < 10000) { - parameters = Array.from(items); - parameters.unshift(start, remove) // @ts-expect-error Hush, it’s fine. - ;[].splice.apply(list, parameters); - } else { - // Delete `remove` items starting from `start` - if (remove) [].splice.apply(list, [start, remove]); // Insert the items in chunks to not cause stack overflows. - - while (chunkStart < items.length) { - parameters = items.slice(chunkStart, chunkStart + 10000); - parameters.unshift(start, 0) // @ts-expect-error Hush, it’s fine. - ;[].splice.apply(list, parameters); - chunkStart += 10000; - start += 10000; - } - } -} -/** - * Append `items` (an array) at the end of `list` (another array). - * When `list` was empty, returns `items` instead. - * - * This prevents a potentially expensive operation when `list` is empty, - * and adds items in batches to prevent V8 from hanging. - * - * @template {unknown} T - * @param {T[]} list - * @param {T[]} items - * @returns {T[]} - */ - -function push(list, items) { - if (list.length > 0) { - splice(list, list.length, 0, items); - return list - } - - return items -} - -/** - * @typedef {import('micromark-util-types').NormalizedExtension} NormalizedExtension - * @typedef {import('micromark-util-types').Extension} Extension - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').HtmlExtension} HtmlExtension - */ - -const hasOwnProperty = {}.hasOwnProperty; - -/** - * Combine several syntax extensions into one. - * - * @param {Extension[]} extensions List of syntax extensions. - * @returns {NormalizedExtension} A single combined extension. - */ -function combineExtensions(extensions) { - /** @type {NormalizedExtension} */ - const all = {}; - let index = -1; - - while (++index < extensions.length) { - syntaxExtension(all, extensions[index]); - } - - return all -} - -/** - * Merge `extension` into `all`. - * - * @param {NormalizedExtension} all Extension to merge into. - * @param {Extension} extension Extension to merge. - * @returns {void} - */ -function syntaxExtension(all, extension) { - /** @type {string} */ - let hook; - - for (hook in extension) { - const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined; - const left = maybe || (all[hook] = {}); - const right = extension[hook]; - /** @type {string} */ - let code; - - for (code in right) { - if (!hasOwnProperty.call(left, code)) left[code] = []; - const value = right[code]; - constructs( - // @ts-expect-error Looks like a list. - left[code], - Array.isArray(value) ? value : value ? [value] : [] - ); - } - } -} - -/** - * Merge `list` into `existing` (both lists of constructs). - * Mutates `existing`. - * - * @param {unknown[]} existing - * @param {unknown[]} list - * @returns {void} - */ -function constructs(existing, list) { - let index = -1; - /** @type {unknown[]} */ - const before = []; - - while (++index < list.length) { -(list[index].add === 'after' ? existing : before).push(list[index]); - } - - splice(existing, 0, 0, before); -} - -/** - * Combine several HTML extensions into one. - * - * @param {HtmlExtension[]} htmlExtensions List of HTML extensions. - * @returns {HtmlExtension} A single combined extension. - */ -function combineHtmlExtensions(htmlExtensions) { - /** @type {HtmlExtension} */ - const handlers = {}; - let index = -1; - - while (++index < htmlExtensions.length) { - htmlExtension(handlers, htmlExtensions[index]); - } - - return handlers -} - -/** - * Merge `extension` into `all`. - * - * @param {HtmlExtension} all Extension to merge into. - * @param {HtmlExtension} extension Extension to merge. - * @returns {void} - */ -function htmlExtension(all, extension) { - /** @type {string} */ - let hook; - - for (hook in extension) { - const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined; - const left = maybe || (all[hook] = {}); - const right = extension[hook]; - /** @type {string} */ - let type; - - if (right) { - for (type in right) { - left[type] = right[type]; - } - } - } -} - -// This module is generated by `script/`. -// -// CommonMark handles attention (emphasis, strong) markers based on what comes -// before or after them. -// One such difference is if those characters are Unicode punctuation. -// This script is generated from the Unicode data. -const unicodePunctuationRegex = - /[!-/:-@[-`{-~\u00A1\u00A7\u00AB\u00B6\u00B7\u00BB\u00BF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\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\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\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]/; - -/** - * @typedef {import('micromark-util-types').Code} Code - */ -/** - * Check whether the character code represents an ASCII alpha (`a` through `z`, - * case insensitive). - * - * An **ASCII alpha** is an ASCII upper alpha or ASCII lower alpha. - * - * An **ASCII upper alpha** is a character in the inclusive range U+0041 (`A`) - * to U+005A (`Z`). - * - * An **ASCII lower alpha** is a character in the inclusive range U+0061 (`a`) - * to U+007A (`z`). - */ - -const asciiAlpha = regexCheck(/[A-Za-z]/); -/** - * Check whether the character code represents an ASCII digit (`0` through `9`). - * - * An **ASCII digit** is a character in the inclusive range U+0030 (`0`) to - * U+0039 (`9`). - */ - -const asciiDigit = regexCheck(/\d/); -/** - * Check whether the character code represents an ASCII hex digit (`a` through - * `f`, case insensitive, or `0` through `9`). - * - * An **ASCII hex digit** is an ASCII digit (see `asciiDigit`), ASCII upper hex - * digit, or an ASCII lower hex digit. - * - * An **ASCII upper hex digit** is a character in the inclusive range U+0041 - * (`A`) to U+0046 (`F`). - * - * An **ASCII lower hex digit** is a character in the inclusive range U+0061 - * (`a`) to U+0066 (`f`). - */ - -const asciiHexDigit = regexCheck(/[\dA-Fa-f]/); -/** - * Check whether the character code represents an ASCII alphanumeric (`a` - * through `z`, case insensitive, or `0` through `9`). - * - * An **ASCII alphanumeric** is an ASCII digit (see `asciiDigit`) or ASCII alpha - * (see `asciiAlpha`). - */ - -const asciiAlphanumeric = regexCheck(/[\dA-Za-z]/); -/** - * Check whether the character code represents ASCII punctuation. - * - * An **ASCII punctuation** is a character in the inclusive ranges U+0021 - * EXCLAMATION MARK (`!`) to U+002F SLASH (`/`), U+003A COLON (`:`) to U+0040 AT - * SIGN (`@`), U+005B LEFT SQUARE BRACKET (`[`) to U+0060 GRAVE ACCENT - * (`` ` ``), or U+007B LEFT CURLY BRACE (`{`) to U+007E TILDE (`~`). - */ - -const asciiPunctuation = regexCheck(/[!-/:-@[-`{-~]/); -/** - * Check whether the character code represents an ASCII atext. - * - * atext is an ASCII alphanumeric (see `asciiAlphanumeric`), or a character in - * the inclusive ranges U+0023 NUMBER SIGN (`#`) to U+0027 APOSTROPHE (`'`), - * U+002A ASTERISK (`*`), U+002B PLUS SIGN (`+`), U+002D DASH (`-`), U+002F - * SLASH (`/`), U+003D EQUALS TO (`=`), U+003F QUESTION MARK (`?`), U+005E - * CARET (`^`) to U+0060 GRAVE ACCENT (`` ` ``), or U+007B LEFT CURLY BRACE - * (`{`) to U+007E TILDE (`~`). - * - * See: - * **\[RFC5322]**: - * [Internet Message Format](https://tools.ietf.org/html/rfc5322). - * P. Resnick. - * IETF. - */ - -const asciiAtext = regexCheck(/[#-'*+\--9=?A-Z^-~]/); -/** - * Check whether a character code is an ASCII control character. - * - * An **ASCII control** is a character in the inclusive range U+0000 NULL (NUL) - * to U+001F (US), or U+007F (DEL). - * - * @param {Code} code - * @returns {code is number} - */ - -function asciiControl(code) { - return ( - // Special whitespace codes (which have negative values), C0 and Control - // character DEL - code !== null && (code < 32 || code === 127) - ) -} -/** - * Check whether a character code is a markdown line ending (see - * `markdownLineEnding`) or markdown space (see `markdownSpace`). - * - * @param {Code} code - * @returns {code is number} - */ - -function markdownLineEndingOrSpace(code) { - return code !== null && (code < 0 || code === 32) -} -/** - * Check whether a character code is a markdown line ending. - * - * A **markdown line ending** is the virtual characters M-0003 CARRIAGE RETURN - * LINE FEED (CRLF), M-0004 LINE FEED (LF) and M-0005 CARRIAGE RETURN (CR). - * - * In micromark, the actual character U+000A LINE FEED (LF) and U+000D CARRIAGE - * RETURN (CR) are replaced by these virtual characters depending on whether - * they occurred together. - * - * @param {Code} code - * @returns {code is number} - */ - -function markdownLineEnding(code) { - return code !== null && code < -2 -} -/** - * Check whether a character code is a markdown space. - * - * A **markdown space** is the concrete character U+0020 SPACE (SP) and the - * virtual characters M-0001 VIRTUAL SPACE (VS) and M-0002 HORIZONTAL TAB (HT). - * - * In micromark, the actual character U+0009 CHARACTER TABULATION (HT) is - * replaced by one M-0002 HORIZONTAL TAB (HT) and between 0 and 3 M-0001 VIRTUAL - * SPACE (VS) characters, depending on the column at which the tab occurred. - * - * @param {Code} code - * @returns {code is number} - */ - -function markdownSpace(code) { - return code === -2 || code === -1 || code === 32 -} -/** - * Check whether the character code represents Unicode whitespace. - * - * Note that this does handle micromark specific markdown whitespace characters. - * See `markdownLineEndingOrSpace` to check that. - * - * A **Unicode whitespace** is a character in the Unicode `Zs` (Separator, - * Space) category, or U+0009 CHARACTER TABULATION (HT), U+000A LINE FEED (LF), - * U+000C (FF), or U+000D CARRIAGE RETURN (CR) (**\[UNICODE]**). - * - * See: - * **\[UNICODE]**: - * [The Unicode Standard](https://www.unicode.org/versions/). - * Unicode Consortium. - */ - -const unicodeWhitespace = regexCheck(/\s/); -/** - * Check whether the character code represents Unicode punctuation. - * - * A **Unicode punctuation** is a character in the Unicode `Pc` (Punctuation, - * Connector), `Pd` (Punctuation, Dash), `Pe` (Punctuation, Close), `Pf` - * (Punctuation, Final quote), `Pi` (Punctuation, Initial quote), `Po` - * (Punctuation, Other), or `Ps` (Punctuation, Open) categories, or an ASCII - * punctuation (see `asciiPunctuation`). - * - * See: - * **\[UNICODE]**: - * [The Unicode Standard](https://www.unicode.org/versions/). - * Unicode Consortium. - */ -// Size note: removing ASCII from the regex and using `asciiPunctuation` here -// In fact adds to the bundle size. - -const unicodePunctuation = regexCheck(unicodePunctuationRegex); -/** - * Create a code check from a regex. - * - * @param {RegExp} regex - * @returns {(code: Code) => code is number} - */ - -function regexCheck(regex) { - return check - /** - * Check whether a code matches the bound regex. - * - * @param {Code} code Character code - * @returns {code is number} Whether the character code matches the bound regex - */ - - function check(code) { - return code !== null && regex.test(String.fromCharCode(code)) - } -} - -/** - * @typedef {import('micromark-util-types').Effects} Effects - * @typedef {import('micromark-util-types').State} State - */ -/** - * @param {Effects} effects - * @param {State} ok - * @param {string} type - * @param {number} [max=Infinity] - * @returns {State} - */ - -function factorySpace(effects, ok, type, max) { - const limit = max ? max - 1 : Number.POSITIVE_INFINITY; - let size = 0; - return start - /** @type {State} */ - - function start(code) { - if (markdownSpace(code)) { - effects.enter(type); - return prefix(code) - } - - return ok(code) - } - /** @type {State} */ - - function prefix(code) { - if (markdownSpace(code) && size++ < limit) { - effects.consume(code); - return prefix - } - - effects.exit(type); - return ok(code) - } -} - -/** - * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct - * @typedef {import('micromark-util-types').Initializer} Initializer - * @typedef {import('micromark-util-types').Token} Token - * @typedef {import('micromark-util-types').State} State - */ - -/** @type {InitialConstruct} */ -const content$1 = { - tokenize: initializeContent -}; -/** @type {Initializer} */ - -function initializeContent(effects) { - const contentStart = effects.attempt( - this.parser.constructs.contentInitial, - afterContentStartConstruct, - paragraphInitial - ); - /** @type {Token} */ - - let previous; - return contentStart - /** @type {State} */ - - function afterContentStartConstruct(code) { - if (code === null) { - effects.consume(code); - return - } - - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - return factorySpace(effects, contentStart, 'linePrefix') - } - /** @type {State} */ - - function paragraphInitial(code) { - effects.enter('paragraph'); - return lineStart(code) - } - /** @type {State} */ - - function lineStart(code) { - const token = effects.enter('chunkText', { - contentType: 'text', - previous - }); - - if (previous) { - previous.next = token; - } - - previous = token; - return data(code) - } - /** @type {State} */ - - function data(code) { - if (code === null) { - effects.exit('chunkText'); - effects.exit('paragraph'); - effects.consume(code); - return - } - - if (markdownLineEnding(code)) { - effects.consume(code); - effects.exit('chunkText'); - return lineStart - } // Data. - - effects.consume(code); - return data - } -} - -/** - * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct - * @typedef {import('micromark-util-types').Initializer} Initializer - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').Token} Token - * @typedef {import('micromark-util-types').State} State - * @typedef {import('micromark-util-types').Point} Point - */ -/** @type {InitialConstruct} */ - -const document$2 = { - tokenize: initializeDocument -}; -/** @type {Construct} */ - -const containerConstruct = { - tokenize: tokenizeContainer -}; -/** @type {Initializer} */ - -function initializeDocument(effects) { - const self = this; - /** @type {StackItem[]} */ - - const stack = []; - let continued = 0; - /** @type {TokenizeContext|undefined} */ - - let childFlow; - /** @type {Token|undefined} */ - - let childToken; - /** @type {number} */ - - let lineStartOffset; - return start - /** @type {State} */ - - function start(code) { - // First we iterate through the open blocks, starting with the root - // document, and descending through last children down to the last open - // block. - // Each block imposes a condition that the line must satisfy if the block is - // to remain open. - // For example, a block quote requires a `>` character. - // A paragraph requires a non-blank line. - // In this phase we may match all or just some of the open blocks. - // But we cannot close unmatched blocks yet, because we may have a lazy - // continuation line. - if (continued < stack.length) { - const item = stack[continued]; - self.containerState = item[1]; - return effects.attempt( - item[0].continuation, - documentContinue, - checkNewContainers - )(code) - } // Done. - - return checkNewContainers(code) - } - /** @type {State} */ - - function documentContinue(code) { - continued++; // Note: this field is called `_closeFlow` but it also closes containers. - // Perhaps a good idea to rename it but it’s already used in the wild by - // extensions. - - if (self.containerState._closeFlow) { - self.containerState._closeFlow = undefined; - - if (childFlow) { - closeFlow(); - } // Note: this algorithm for moving events around is similar to the - // algorithm when dealing with lazy lines in `writeToChild`. - - const indexBeforeExits = self.events.length; - let indexBeforeFlow = indexBeforeExits; - /** @type {Point|undefined} */ - - let point; // Find the flow chunk. - - while (indexBeforeFlow--) { - if ( - self.events[indexBeforeFlow][0] === 'exit' && - self.events[indexBeforeFlow][1].type === 'chunkFlow' - ) { - point = self.events[indexBeforeFlow][1].end; - break - } - } - - exitContainers(continued); // Fix positions. - - let index = indexBeforeExits; - - while (index < self.events.length) { - self.events[index][1].end = Object.assign({}, point); - index++; - } // Inject the exits earlier (they’re still also at the end). - - splice( - self.events, - indexBeforeFlow + 1, - 0, - self.events.slice(indexBeforeExits) - ); // Discard the duplicate exits. - - self.events.length = index; - return checkNewContainers(code) - } - - return start(code) - } - /** @type {State} */ - - function checkNewContainers(code) { - // Next, after consuming the continuation markers for existing blocks, we - // look for new block starts (e.g. `>` for a block quote). - // If we encounter a new block start, we close any blocks unmatched in - // step 1 before creating the new block as a child of the last matched - // block. - if (continued === stack.length) { - // No need to `check` whether there’s a container, of `exitContainers` - // would be moot. - // We can instead immediately `attempt` to parse one. - if (!childFlow) { - return documentContinued(code) - } // If we have concrete content, such as block HTML or fenced code, - // we can’t have containers “pierce” into them, so we can immediately - // start. - - if (childFlow.currentConstruct && childFlow.currentConstruct.concrete) { - return flowStart(code) - } // If we do have flow, it could still be a blank line, - // but we’d be interrupting it w/ a new container if there’s a current - // construct. - - self.interrupt = Boolean(childFlow.currentConstruct); - } // Check if there is a new container. - - self.containerState = {}; - return effects.check( - containerConstruct, - thereIsANewContainer, - thereIsNoNewContainer - )(code) - } - /** @type {State} */ - - function thereIsANewContainer(code) { - if (childFlow) closeFlow(); - exitContainers(continued); - return documentContinued(code) - } - /** @type {State} */ - - function thereIsNoNewContainer(code) { - self.parser.lazy[self.now().line] = continued !== stack.length; - lineStartOffset = self.now().offset; - return flowStart(code) - } - /** @type {State} */ - - function documentContinued(code) { - // Try new containers. - self.containerState = {}; - return effects.attempt( - containerConstruct, - containerContinue, - flowStart - )(code) - } - /** @type {State} */ - - function containerContinue(code) { - continued++; - stack.push([self.currentConstruct, self.containerState]); // Try another. - - return documentContinued(code) - } - /** @type {State} */ - - function flowStart(code) { - if (code === null) { - if (childFlow) closeFlow(); - exitContainers(0); - effects.consume(code); - return - } - - childFlow = childFlow || self.parser.flow(self.now()); - effects.enter('chunkFlow', { - contentType: 'flow', - previous: childToken, - _tokenizer: childFlow - }); - return flowContinue(code) - } - /** @type {State} */ - - function flowContinue(code) { - if (code === null) { - writeToChild(effects.exit('chunkFlow'), true); - exitContainers(0); - effects.consume(code); - return - } - - if (markdownLineEnding(code)) { - effects.consume(code); - writeToChild(effects.exit('chunkFlow')); // Get ready for the next line. - - continued = 0; - self.interrupt = undefined; - return start - } - - effects.consume(code); - return flowContinue - } - /** - * @param {Token} token - * @param {boolean} [eof] - * @returns {void} - */ - - function writeToChild(token, eof) { - const stream = self.sliceStream(token); - if (eof) stream.push(null); - token.previous = childToken; - if (childToken) childToken.next = token; - childToken = token; - childFlow.defineSkip(token.start); - childFlow.write(stream); // Alright, so we just added a lazy line: - // - // ```markdown - // > a - // b. - // - // Or: - // - // > ~~~c - // d - // - // Or: - // - // > | e | - // f - // ``` - // - // The construct in the second example (fenced code) does not accept lazy - // lines, so it marked itself as done at the end of its first line, and - // then the content construct parses `d`. - // Most constructs in markdown match on the first line: if the first line - // forms a construct, a non-lazy line can’t “unmake” it. - // - // The construct in the third example is potentially a GFM table, and - // those are *weird*. - // It *could* be a table, from the first line, if the following line - // matches a condition. - // In this case, that second line is lazy, which “unmakes” the first line - // and turns the whole into one content block. - // - // We’ve now parsed the non-lazy and the lazy line, and can figure out - // whether the lazy line started a new flow block. - // If it did, we exit the current containers between the two flow blocks. - - if (self.parser.lazy[token.start.line]) { - let index = childFlow.events.length; - - while (index--) { - if ( - // The token starts before the line ending… - childFlow.events[index][1].start.offset < lineStartOffset && - (!childFlow.events[index][1].end || // …or ends after it. - childFlow.events[index][1].end.offset > lineStartOffset) - ) { - // Exit: there’s still something open, which means it’s a lazy line - // part of something. - return - } - } // Note: this algorithm for moving events around is similar to the - // algorithm when closing flow in `documentContinue`. - - const indexBeforeExits = self.events.length; - let indexBeforeFlow = indexBeforeExits; - /** @type {boolean|undefined} */ - - let seen; - /** @type {Point|undefined} */ - - let point; // Find the previous chunk (the one before the lazy line). - - while (indexBeforeFlow--) { - if ( - self.events[indexBeforeFlow][0] === 'exit' && - self.events[indexBeforeFlow][1].type === 'chunkFlow' - ) { - if (seen) { - point = self.events[indexBeforeFlow][1].end; - break - } - - seen = true; - } - } - - exitContainers(continued); // Fix positions. - - index = indexBeforeExits; - - while (index < self.events.length) { - self.events[index][1].end = Object.assign({}, point); - index++; - } // Inject the exits earlier (they’re still also at the end). - - splice( - self.events, - indexBeforeFlow + 1, - 0, - self.events.slice(indexBeforeExits) - ); // Discard the duplicate exits. - - self.events.length = index; - } - } - /** - * @param {number} size - * @returns {void} - */ - - function exitContainers(size) { - let index = stack.length; // Exit open containers. - - while (index-- > size) { - const entry = stack[index]; - self.containerState = entry[1]; - entry[0].exit.call(self, effects); - } - - stack.length = size; - } - - function closeFlow() { - childFlow.write([null]); - childToken = undefined; - childFlow = undefined; - self.containerState._closeFlow = undefined; - } -} -/** @type {Tokenizer} */ - -function tokenizeContainer(effects, ok, nok) { - return factorySpace( - effects, - effects.attempt(this.parser.constructs.document, ok, nok), - 'linePrefix', - this.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4 - ) -} - -/** - * @typedef {import('micromark-util-types').Code} Code - */ - -/** - * Classify whether a character code represents whitespace, punctuation, or - * something else. - * - * Used for attention (emphasis, strong), whose sequences can open or close - * based on the class of surrounding characters. - * - * Note that eof (`null`) is seen as whitespace. - * - * @param {Code} code - * @returns {number|undefined} - */ -function classifyCharacter(code) { - if ( - code === null || - markdownLineEndingOrSpace(code) || - unicodeWhitespace(code) - ) { - return 1 - } - - if (unicodePunctuation(code)) { - return 2 - } -} - -/** - * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext - * @typedef {import('micromark-util-types').Event} Event - * @typedef {import('micromark-util-types').Resolver} Resolver - */ - -/** - * Call all `resolveAll`s. - * - * @param {{resolveAll?: Resolver}[]} constructs - * @param {Event[]} events - * @param {TokenizeContext} context - * @returns {Event[]} - */ -function resolveAll(constructs, events, context) { - /** @type {Resolver[]} */ - const called = []; - let index = -1; - - while (++index < constructs.length) { - const resolve = constructs[index].resolveAll; - - if (resolve && !called.includes(resolve)) { - events = resolve(events, context); - called.push(resolve); - } - } - - return events -} - -/** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').Resolver} Resolver - * @typedef {import('micromark-util-types').State} State - * @typedef {import('micromark-util-types').Token} Token - * @typedef {import('micromark-util-types').Event} Event - * @typedef {import('micromark-util-types').Code} Code - * @typedef {import('micromark-util-types').Point} Point - */ - -/** @type {Construct} */ -const attention = { - name: 'attention', - tokenize: tokenizeAttention, - resolveAll: resolveAllAttention -}; -/** - * Take all events and resolve attention to emphasis or strong. - * - * @type {Resolver} - */ - -function resolveAllAttention(events, context) { - let index = -1; - /** @type {number} */ - - let open; - /** @type {Token} */ - - let group; - /** @type {Token} */ - - let text; - /** @type {Token} */ - - let openingSequence; - /** @type {Token} */ - - let closingSequence; - /** @type {number} */ - - let use; - /** @type {Event[]} */ - - let nextEvents; - /** @type {number} */ - - let offset; // Walk through all events. - // - // Note: performance of this is fine on an mb of normal markdown, but it’s - // a bottleneck for malicious stuff. - - while (++index < events.length) { - // Find a token that can close. - if ( - events[index][0] === 'enter' && - events[index][1].type === 'attentionSequence' && - events[index][1]._close - ) { - open = index; // Now walk back to find an opener. - - while (open--) { - // Find a token that can open the closer. - if ( - events[open][0] === 'exit' && - events[open][1].type === 'attentionSequence' && - events[open][1]._open && // If the markers are the same: - context.sliceSerialize(events[open][1]).charCodeAt(0) === - context.sliceSerialize(events[index][1]).charCodeAt(0) - ) { - // If the opening can close or the closing can open, - // and the close size *is not* a multiple of three, - // but the sum of the opening and closing size *is* multiple of three, - // then don’t match. - if ( - (events[open][1]._close || events[index][1]._open) && - (events[index][1].end.offset - events[index][1].start.offset) % 3 && - !( - (events[open][1].end.offset - - events[open][1].start.offset + - events[index][1].end.offset - - events[index][1].start.offset) % - 3 - ) - ) { - continue - } // Number of markers to use from the sequence. - - use = - events[open][1].end.offset - events[open][1].start.offset > 1 && - events[index][1].end.offset - events[index][1].start.offset > 1 - ? 2 - : 1; - const start = Object.assign({}, events[open][1].end); - const end = Object.assign({}, events[index][1].start); - movePoint(start, -use); - movePoint(end, use); - openingSequence = { - type: use > 1 ? 'strongSequence' : 'emphasisSequence', - start, - end: Object.assign({}, events[open][1].end) - }; - closingSequence = { - type: use > 1 ? 'strongSequence' : 'emphasisSequence', - start: Object.assign({}, events[index][1].start), - end - }; - text = { - type: use > 1 ? 'strongText' : 'emphasisText', - start: Object.assign({}, events[open][1].end), - end: Object.assign({}, events[index][1].start) - }; - group = { - type: use > 1 ? 'strong' : 'emphasis', - start: Object.assign({}, openingSequence.start), - end: Object.assign({}, closingSequence.end) - }; - events[open][1].end = Object.assign({}, openingSequence.start); - events[index][1].start = Object.assign({}, closingSequence.end); - nextEvents = []; // If there are more markers in the opening, add them before. - - if (events[open][1].end.offset - events[open][1].start.offset) { - nextEvents = push(nextEvents, [ - ['enter', events[open][1], context], - ['exit', events[open][1], context] - ]); - } // Opening. - - nextEvents = push(nextEvents, [ - ['enter', group, context], - ['enter', openingSequence, context], - ['exit', openingSequence, context], - ['enter', text, context] - ]); // Between. - - nextEvents = push( - nextEvents, - resolveAll( - context.parser.constructs.insideSpan.null, - events.slice(open + 1, index), - context - ) - ); // Closing. - - nextEvents = push(nextEvents, [ - ['exit', text, context], - ['enter', closingSequence, context], - ['exit', closingSequence, context], - ['exit', group, context] - ]); // If there are more markers in the closing, add them after. - - if (events[index][1].end.offset - events[index][1].start.offset) { - offset = 2; - nextEvents = push(nextEvents, [ - ['enter', events[index][1], context], - ['exit', events[index][1], context] - ]); - } else { - offset = 0; - } - - splice(events, open - 1, index - open + 3, nextEvents); - index = open + nextEvents.length - offset - 2; - break - } - } - } - } // Remove remaining sequences. - - index = -1; - - while (++index < events.length) { - if (events[index][1].type === 'attentionSequence') { - events[index][1].type = 'data'; - } - } - - return events -} -/** @type {Tokenizer} */ - -function tokenizeAttention(effects, ok) { - const attentionMarkers = this.parser.constructs.attentionMarkers.null; - const previous = this.previous; - const before = classifyCharacter(previous); - /** @type {NonNullable} */ - - let marker; - return start - /** @type {State} */ - - function start(code) { - effects.enter('attentionSequence'); - marker = code; - return sequence(code) - } - /** @type {State} */ - - function sequence(code) { - if (code === marker) { - effects.consume(code); - return sequence - } - - const token = effects.exit('attentionSequence'); - const after = classifyCharacter(code); - const open = - !after || (after === 2 && before) || attentionMarkers.includes(code); - const close = - !before || (before === 2 && after) || attentionMarkers.includes(previous); - token._open = Boolean(marker === 42 ? open : open && (before || !close)); - token._close = Boolean(marker === 42 ? close : close && (after || !open)); - return ok(code) - } -} -/** - * Move a point a bit. - * - * Note: `move` only works inside lines! It’s not possible to move past other - * chunks (replacement characters, tabs, or line endings). - * - * @param {Point} point - * @param {number} offset - * @returns {void} - */ - -function movePoint(point, offset) { - point.column += offset; - point.offset += offset; - point._bufferIndex += offset; -} - -/** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State - */ - -/** @type {Construct} */ -const autolink = { - name: 'autolink', - tokenize: tokenizeAutolink -}; -/** @type {Tokenizer} */ - -function tokenizeAutolink(effects, ok, nok) { - let size = 1; - return start - /** @type {State} */ - - function start(code) { - effects.enter('autolink'); - effects.enter('autolinkMarker'); - effects.consume(code); - effects.exit('autolinkMarker'); - effects.enter('autolinkProtocol'); - return open - } - /** @type {State} */ - - function open(code) { - if (asciiAlpha(code)) { - effects.consume(code); - return schemeOrEmailAtext - } - - return asciiAtext(code) ? emailAtext(code) : nok(code) - } - /** @type {State} */ - - function schemeOrEmailAtext(code) { - return code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code) - ? schemeInsideOrEmailAtext(code) - : emailAtext(code) - } - /** @type {State} */ - - function schemeInsideOrEmailAtext(code) { - if (code === 58) { - effects.consume(code); - return urlInside - } - - if ( - (code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code)) && - size++ < 32 - ) { - effects.consume(code); - return schemeInsideOrEmailAtext - } - - return emailAtext(code) - } - /** @type {State} */ - - function urlInside(code) { - if (code === 62) { - effects.exit('autolinkProtocol'); - return end(code) - } - - if (code === null || code === 32 || code === 60 || asciiControl(code)) { - return nok(code) - } - - effects.consume(code); - return urlInside - } - /** @type {State} */ - - function emailAtext(code) { - if (code === 64) { - effects.consume(code); - size = 0; - return emailAtSignOrDot - } - - if (asciiAtext(code)) { - effects.consume(code); - return emailAtext - } - - return nok(code) - } - /** @type {State} */ - - function emailAtSignOrDot(code) { - return asciiAlphanumeric(code) ? emailLabel(code) : nok(code) - } - /** @type {State} */ - - function emailLabel(code) { - if (code === 46) { - effects.consume(code); - size = 0; - return emailAtSignOrDot - } - - if (code === 62) { - // Exit, then change the type. - effects.exit('autolinkProtocol').type = 'autolinkEmail'; - return end(code) - } - - return emailValue(code) - } - /** @type {State} */ - - function emailValue(code) { - if ((code === 45 || asciiAlphanumeric(code)) && size++ < 63) { - effects.consume(code); - return code === 45 ? emailValue : emailLabel - } - - return nok(code) - } - /** @type {State} */ - - function end(code) { - effects.enter('autolinkMarker'); - effects.consume(code); - effects.exit('autolinkMarker'); - effects.exit('autolink'); - return ok - } -} - -/** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State - */ - -/** @type {Construct} */ -const blankLine = { - tokenize: tokenizeBlankLine, - partial: true -}; -/** @type {Tokenizer} */ - -function tokenizeBlankLine(effects, ok, nok) { - return factorySpace(effects, afterWhitespace, 'linePrefix') - /** @type {State} */ - - function afterWhitespace(code) { - return code === null || markdownLineEnding(code) ? ok(code) : nok(code) - } -} - -/** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').Exiter} Exiter - * @typedef {import('micromark-util-types').State} State - */ - -/** @type {Construct} */ -const blockQuote = { - name: 'blockQuote', - tokenize: tokenizeBlockQuoteStart, - continuation: { - tokenize: tokenizeBlockQuoteContinuation - }, - exit: exit$1 -}; -/** @type {Tokenizer} */ - -function tokenizeBlockQuoteStart(effects, ok, nok) { - const self = this; - return start - /** @type {State} */ - - function start(code) { - if (code === 62) { - const state = self.containerState; - - if (!state.open) { - effects.enter('blockQuote', { - _container: true - }); - state.open = true; - } - - effects.enter('blockQuotePrefix'); - effects.enter('blockQuoteMarker'); - effects.consume(code); - effects.exit('blockQuoteMarker'); - return after - } - - return nok(code) - } - /** @type {State} */ - - function after(code) { - if (markdownSpace(code)) { - effects.enter('blockQuotePrefixWhitespace'); - effects.consume(code); - effects.exit('blockQuotePrefixWhitespace'); - effects.exit('blockQuotePrefix'); - return ok - } - - effects.exit('blockQuotePrefix'); - return ok(code) - } -} -/** @type {Tokenizer} */ - -function tokenizeBlockQuoteContinuation(effects, ok, nok) { - return factorySpace( - effects, - effects.attempt(blockQuote, ok, nok), - 'linePrefix', - this.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4 - ) -} -/** @type {Exiter} */ - -function exit$1(effects) { - effects.exit('blockQuote'); -} - -/** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State - */ - -/** @type {Construct} */ -const characterEscape = { - name: 'characterEscape', - tokenize: tokenizeCharacterEscape -}; -/** @type {Tokenizer} */ - -function tokenizeCharacterEscape(effects, ok, nok) { - return start - /** @type {State} */ - - function start(code) { - effects.enter('characterEscape'); - effects.enter('escapeMarker'); - effects.consume(code); - effects.exit('escapeMarker'); - return open - } - /** @type {State} */ - - function open(code) { - if (asciiPunctuation(code)) { - effects.enter('characterEscapeValue'); - effects.consume(code); - effects.exit('characterEscapeValue'); - effects.exit('characterEscape'); - return ok - } - - return nok(code) + return nok(code) } } @@ -37539,14370 +5256,18694 @@ var characterEntities = { zwnj: '‌' }; -var own$5 = {}.hasOwnProperty; +var own$6 = {}.hasOwnProperty; + +/** + * @param {string} characters + * @returns {string|false} + */ +function decodeEntity(characters) { + return own$6.call(characterEntities, characters) + ? characterEntities[characters] + : false +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').Token} Token + * @typedef {import('micromark-util-types').State} State + * @typedef {import('micromark-util-types').Code} Code + */ + +/** @type {Construct} */ +const characterReference = { + name: 'characterReference', + tokenize: tokenizeCharacterReference +}; +/** @type {Tokenizer} */ + +function tokenizeCharacterReference(effects, ok, nok) { + const self = this; + let size = 0; + /** @type {number} */ + + let max; + /** @type {(code: Code) => code is number} */ + + let test; + return start + /** @type {State} */ + + function start(code) { + effects.enter('characterReference'); + effects.enter('characterReferenceMarker'); + effects.consume(code); + effects.exit('characterReferenceMarker'); + return open + } + /** @type {State} */ + + function open(code) { + if (code === 35) { + effects.enter('characterReferenceMarkerNumeric'); + effects.consume(code); + effects.exit('characterReferenceMarkerNumeric'); + return numeric + } + + effects.enter('characterReferenceValue'); + max = 31; + test = asciiAlphanumeric; + return value(code) + } + /** @type {State} */ + + function numeric(code) { + if (code === 88 || code === 120) { + effects.enter('characterReferenceMarkerHexadecimal'); + effects.consume(code); + effects.exit('characterReferenceMarkerHexadecimal'); + effects.enter('characterReferenceValue'); + max = 6; + test = asciiHexDigit; + return value + } + + effects.enter('characterReferenceValue'); + max = 7; + test = asciiDigit; + return value(code) + } + /** @type {State} */ + + function value(code) { + /** @type {Token} */ + let token; + + if (code === 59 && size) { + token = effects.exit('characterReferenceValue'); + + if ( + test === asciiAlphanumeric && + !decodeEntity(self.sliceSerialize(token)) + ) { + return nok(code) + } + + effects.enter('characterReferenceMarker'); + effects.consume(code); + effects.exit('characterReferenceMarker'); + effects.exit('characterReference'); + return ok + } + + if (test(code) && size++ < max) { + effects.consume(code); + return value + } + + return nok(code) + } +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State + * @typedef {import('micromark-util-types').Code} Code + */ + +/** @type {Construct} */ +const codeFenced = { + name: 'codeFenced', + tokenize: tokenizeCodeFenced, + concrete: true +}; +/** @type {Tokenizer} */ + +function tokenizeCodeFenced(effects, ok, nok) { + const self = this; + /** @type {Construct} */ + + const closingFenceConstruct = { + tokenize: tokenizeClosingFence, + partial: true + }; + /** @type {Construct} */ + + const nonLazyLine = { + tokenize: tokenizeNonLazyLine, + partial: true + }; + const tail = this.events[this.events.length - 1]; + const initialPrefix = + tail && tail[1].type === 'linePrefix' + ? tail[2].sliceSerialize(tail[1], true).length + : 0; + let sizeOpen = 0; + /** @type {NonNullable} */ + + let marker; + return start + /** @type {State} */ + + function start(code) { + effects.enter('codeFenced'); + effects.enter('codeFencedFence'); + effects.enter('codeFencedFenceSequence'); + marker = code; + return sequenceOpen(code) + } + /** @type {State} */ + + function sequenceOpen(code) { + if (code === marker) { + effects.consume(code); + sizeOpen++; + return sequenceOpen + } + + effects.exit('codeFencedFenceSequence'); + return sizeOpen < 3 + ? nok(code) + : factorySpace(effects, infoOpen, 'whitespace')(code) + } + /** @type {State} */ + + function infoOpen(code) { + if (code === null || markdownLineEnding(code)) { + return openAfter(code) + } + + effects.enter('codeFencedFenceInfo'); + effects.enter('chunkString', { + contentType: 'string' + }); + return info(code) + } + /** @type {State} */ + + function info(code) { + if (code === null || markdownLineEndingOrSpace(code)) { + effects.exit('chunkString'); + effects.exit('codeFencedFenceInfo'); + return factorySpace(effects, infoAfter, 'whitespace')(code) + } + + if (code === 96 && code === marker) return nok(code) + effects.consume(code); + return info + } + /** @type {State} */ + + function infoAfter(code) { + if (code === null || markdownLineEnding(code)) { + return openAfter(code) + } + + effects.enter('codeFencedFenceMeta'); + effects.enter('chunkString', { + contentType: 'string' + }); + return meta(code) + } + /** @type {State} */ + + function meta(code) { + if (code === null || markdownLineEnding(code)) { + effects.exit('chunkString'); + effects.exit('codeFencedFenceMeta'); + return openAfter(code) + } + + if (code === 96 && code === marker) return nok(code) + effects.consume(code); + return meta + } + /** @type {State} */ + + function openAfter(code) { + effects.exit('codeFencedFence'); + return self.interrupt ? ok(code) : contentStart(code) + } + /** @type {State} */ + + function contentStart(code) { + if (code === null) { + return after(code) + } + + if (markdownLineEnding(code)) { + return effects.attempt( + nonLazyLine, + effects.attempt( + closingFenceConstruct, + after, + initialPrefix + ? factorySpace( + effects, + contentStart, + 'linePrefix', + initialPrefix + 1 + ) + : contentStart + ), + after + )(code) + } + + effects.enter('codeFlowValue'); + return contentContinue(code) + } + /** @type {State} */ + + function contentContinue(code) { + if (code === null || markdownLineEnding(code)) { + effects.exit('codeFlowValue'); + return contentStart(code) + } + + effects.consume(code); + return contentContinue + } + /** @type {State} */ + + function after(code) { + effects.exit('codeFenced'); + return ok(code) + } + /** @type {Tokenizer} */ + + function tokenizeNonLazyLine(effects, ok, nok) { + const self = this; + return start + /** @type {State} */ + + function start(code) { + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return lineStart + } + /** @type {State} */ + + function lineStart(code) { + return self.parser.lazy[self.now().line] ? nok(code) : ok(code) + } + } + /** @type {Tokenizer} */ + + function tokenizeClosingFence(effects, ok, nok) { + let size = 0; + return factorySpace( + effects, + closingSequenceStart, + 'linePrefix', + this.parser.constructs.disable.null.includes('codeIndented') + ? undefined + : 4 + ) + /** @type {State} */ + + function closingSequenceStart(code) { + effects.enter('codeFencedFence'); + effects.enter('codeFencedFenceSequence'); + return closingSequence(code) + } + /** @type {State} */ + + function closingSequence(code) { + if (code === marker) { + effects.consume(code); + size++; + return closingSequence + } + + if (size < sizeOpen) return nok(code) + effects.exit('codeFencedFenceSequence'); + return factorySpace(effects, closingSequenceEnd, 'whitespace')(code) + } + /** @type {State} */ + + function closingSequenceEnd(code) { + if (code === null || markdownLineEnding(code)) { + effects.exit('codeFencedFence'); + return ok(code) + } + + return nok(code) + } + } +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').Resolver} Resolver + * @typedef {import('micromark-util-types').Token} Token + * @typedef {import('micromark-util-types').State} State + */ + +/** @type {Construct} */ +const codeIndented = { + name: 'codeIndented', + tokenize: tokenizeCodeIndented +}; +/** @type {Construct} */ + +const indentedContent = { + tokenize: tokenizeIndentedContent, + partial: true +}; +/** @type {Tokenizer} */ + +function tokenizeCodeIndented(effects, ok, nok) { + const self = this; + return start + /** @type {State} */ + + function start(code) { + effects.enter('codeIndented'); + return factorySpace(effects, afterStartPrefix, 'linePrefix', 4 + 1)(code) + } + /** @type {State} */ + + function afterStartPrefix(code) { + const tail = self.events[self.events.length - 1]; + return tail && + tail[1].type === 'linePrefix' && + tail[2].sliceSerialize(tail[1], true).length >= 4 + ? afterPrefix(code) + : nok(code) + } + /** @type {State} */ + + function afterPrefix(code) { + if (code === null) { + return after(code) + } + + if (markdownLineEnding(code)) { + return effects.attempt(indentedContent, afterPrefix, after)(code) + } + + effects.enter('codeFlowValue'); + return content(code) + } + /** @type {State} */ + + function content(code) { + if (code === null || markdownLineEnding(code)) { + effects.exit('codeFlowValue'); + return afterPrefix(code) + } + + effects.consume(code); + return content + } + /** @type {State} */ + + function after(code) { + effects.exit('codeIndented'); + return ok(code) + } +} +/** @type {Tokenizer} */ + +function tokenizeIndentedContent(effects, ok, nok) { + const self = this; + return start + /** @type {State} */ + + function start(code) { + // If this is a lazy line, it can’t be code. + if (self.parser.lazy[self.now().line]) { + return nok(code) + } + + if (markdownLineEnding(code)) { + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return start + } + + return factorySpace(effects, afterPrefix, 'linePrefix', 4 + 1)(code) + } + /** @type {State} */ + + function afterPrefix(code) { + const tail = self.events[self.events.length - 1]; + return tail && + tail[1].type === 'linePrefix' && + tail[2].sliceSerialize(tail[1], true).length >= 4 + ? ok(code) + : markdownLineEnding(code) + ? start(code) + : nok(code) + } +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Resolver} Resolver + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').Previous} Previous + * @typedef {import('micromark-util-types').Token} Token + * @typedef {import('micromark-util-types').State} State + */ + +/** @type {Construct} */ +const codeText = { + name: 'codeText', + tokenize: tokenizeCodeText, + resolve: resolveCodeText, + previous: previous$1 +}; +/** @type {Resolver} */ + +function resolveCodeText(events) { + let tailExitIndex = events.length - 4; + let headEnterIndex = 3; + /** @type {number} */ + + let index; + /** @type {number|undefined} */ + + let enter; // If we start and end with an EOL or a space. + + if ( + (events[headEnterIndex][1].type === 'lineEnding' || + events[headEnterIndex][1].type === 'space') && + (events[tailExitIndex][1].type === 'lineEnding' || + events[tailExitIndex][1].type === 'space') + ) { + index = headEnterIndex; // And we have data. + + while (++index < tailExitIndex) { + if (events[index][1].type === 'codeTextData') { + // Then we have padding. + events[headEnterIndex][1].type = 'codeTextPadding'; + events[tailExitIndex][1].type = 'codeTextPadding'; + headEnterIndex += 2; + tailExitIndex -= 2; + break + } + } + } // Merge adjacent spaces and data. + + index = headEnterIndex - 1; + tailExitIndex++; + + while (++index <= tailExitIndex) { + if (enter === undefined) { + if (index !== tailExitIndex && events[index][1].type !== 'lineEnding') { + enter = index; + } + } else if ( + index === tailExitIndex || + events[index][1].type === 'lineEnding' + ) { + events[enter][1].type = 'codeTextData'; + + if (index !== enter + 2) { + events[enter][1].end = events[index - 1][1].end; + events.splice(enter + 2, index - enter - 2); + tailExitIndex -= index - enter - 2; + index = enter + 2; + } + + enter = undefined; + } + } + + return events +} +/** @type {Previous} */ + +function previous$1(code) { + // If there is a previous code, there will always be a tail. + return ( + code !== 96 || + this.events[this.events.length - 1][1].type === 'characterEscape' + ) +} +/** @type {Tokenizer} */ + +function tokenizeCodeText(effects, ok, nok) { + let sizeOpen = 0; + /** @type {number} */ + + let size; + /** @type {Token} */ + + let token; + return start + /** @type {State} */ + + function start(code) { + effects.enter('codeText'); + effects.enter('codeTextSequence'); + return openingSequence(code) + } + /** @type {State} */ + + function openingSequence(code) { + if (code === 96) { + effects.consume(code); + sizeOpen++; + return openingSequence + } + + effects.exit('codeTextSequence'); + return gap(code) + } + /** @type {State} */ + + function gap(code) { + // EOF. + if (code === null) { + return nok(code) + } // Closing fence? + // Could also be data. + + if (code === 96) { + token = effects.enter('codeTextSequence'); + size = 0; + return closingSequence(code) + } // Tabs don’t work, and virtual spaces don’t make sense. + + if (code === 32) { + effects.enter('space'); + effects.consume(code); + effects.exit('space'); + return gap + } + + if (markdownLineEnding(code)) { + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return gap + } // Data. + + effects.enter('codeTextData'); + return data(code) + } // In code. + + /** @type {State} */ + + function data(code) { + if ( + code === null || + code === 32 || + code === 96 || + markdownLineEnding(code) + ) { + effects.exit('codeTextData'); + return gap(code) + } + + effects.consume(code); + return data + } // Closing fence. + + /** @type {State} */ + + function closingSequence(code) { + // More. + if (code === 96) { + effects.consume(code); + size++; + return closingSequence + } // Done! + + if (size === sizeOpen) { + effects.exit('codeTextSequence'); + effects.exit('codeText'); + return ok(code) + } // More or less accents: mark as data. + + token.type = 'codeTextData'; + return data(code) + } +} + +/** + * @typedef {import('micromark-util-types').Token} Token + * @typedef {import('micromark-util-types').Chunk} Chunk + * @typedef {import('micromark-util-types').Event} Event + */ + +/** + * Tokenize subcontent. + * + * @param {Event[]} events + * @returns {boolean} + */ +function subtokenize(events) { + /** @type {Record} */ + const jumps = {}; + let index = -1; + /** @type {Event} */ + + let event; + /** @type {number|undefined} */ + + let lineIndex; + /** @type {number} */ + + let otherIndex; + /** @type {Event} */ + + let otherEvent; + /** @type {Event[]} */ + + let parameters; + /** @type {Event[]} */ + + let subevents; + /** @type {boolean|undefined} */ + + let more; + + while (++index < events.length) { + while (index in jumps) { + index = jumps[index]; + } + + event = events[index]; // Add a hook for the GFM tasklist extension, which needs to know if text + // is in the first content of a list item. + + if ( + index && + event[1].type === 'chunkFlow' && + events[index - 1][1].type === 'listItemPrefix' + ) { + subevents = event[1]._tokenizer.events; + otherIndex = 0; + + if ( + otherIndex < subevents.length && + subevents[otherIndex][1].type === 'lineEndingBlank' + ) { + otherIndex += 2; + } + + if ( + otherIndex < subevents.length && + subevents[otherIndex][1].type === 'content' + ) { + while (++otherIndex < subevents.length) { + if (subevents[otherIndex][1].type === 'content') { + break + } + + if (subevents[otherIndex][1].type === 'chunkText') { + subevents[otherIndex][1]._isInFirstContentOfListItem = true; + otherIndex++; + } + } + } + } // Enter. + + if (event[0] === 'enter') { + if (event[1].contentType) { + Object.assign(jumps, subcontent(events, index)); + index = jumps[index]; + more = true; + } + } // Exit. + else if (event[1]._container) { + otherIndex = index; + lineIndex = undefined; + + while (otherIndex--) { + otherEvent = events[otherIndex]; + + if ( + otherEvent[1].type === 'lineEnding' || + otherEvent[1].type === 'lineEndingBlank' + ) { + if (otherEvent[0] === 'enter') { + if (lineIndex) { + events[lineIndex][1].type = 'lineEndingBlank'; + } + + otherEvent[1].type = 'lineEnding'; + lineIndex = otherIndex; + } + } else { + break + } + } + + if (lineIndex) { + // Fix position. + event[1].end = Object.assign({}, events[lineIndex][1].start); // Switch container exit w/ line endings. + + parameters = events.slice(lineIndex, index); + parameters.unshift(event); + splice(events, lineIndex, index - lineIndex + 1, parameters); + } + } + } + + return !more +} +/** + * Tokenize embedded tokens. + * + * @param {Event[]} events + * @param {number} eventIndex + * @returns {Record} + */ + +function subcontent(events, eventIndex) { + const token = events[eventIndex][1]; + const context = events[eventIndex][2]; + let startPosition = eventIndex - 1; + /** @type {number[]} */ + + const startPositions = []; + const tokenizer = + token._tokenizer || context.parser[token.contentType](token.start); + const childEvents = tokenizer.events; + /** @type {[number, number][]} */ + + const jumps = []; + /** @type {Record} */ + + const gaps = {}; + /** @type {Chunk[]} */ + + let stream; + /** @type {Token|undefined} */ + + let previous; + let index = -1; + /** @type {Token|undefined} */ + + let current = token; + let adjust = 0; + let start = 0; + const breaks = [start]; // Loop forward through the linked tokens to pass them in order to the + // subtokenizer. + + while (current) { + // Find the position of the event for this token. + while (events[++startPosition][1] !== current) { + // Empty. + } + + startPositions.push(startPosition); + + if (!current._tokenizer) { + stream = context.sliceStream(current); + + if (!current.next) { + stream.push(null); + } + + if (previous) { + tokenizer.defineSkip(current.start); + } + + if (current._isInFirstContentOfListItem) { + tokenizer._gfmTasklistFirstContentOfListItem = true; + } + + tokenizer.write(stream); + + if (current._isInFirstContentOfListItem) { + tokenizer._gfmTasklistFirstContentOfListItem = undefined; + } + } // Unravel the next token. + + previous = current; + current = current.next; + } // Now, loop back through all events (and linked tokens), to figure out which + // parts belong where. + + current = token; + + while (++index < childEvents.length) { + if ( + // Find a void token that includes a break. + childEvents[index][0] === 'exit' && + childEvents[index - 1][0] === 'enter' && + childEvents[index][1].type === childEvents[index - 1][1].type && + childEvents[index][1].start.line !== childEvents[index][1].end.line + ) { + start = index + 1; + breaks.push(start); // Help GC. + + current._tokenizer = undefined; + current.previous = undefined; + current = current.next; + } + } // Help GC. + + tokenizer.events = []; // If there’s one more token (which is the cases for lines that end in an + // EOF), that’s perfect: the last point we found starts it. + // If there isn’t then make sure any remaining content is added to it. + + if (current) { + // Help GC. + current._tokenizer = undefined; + current.previous = undefined; + } else { + breaks.pop(); + } // Now splice the events from the subtokenizer into the current events, + // moving back to front so that splice indices aren’t affected. + + index = breaks.length; + + while (index--) { + const slice = childEvents.slice(breaks[index], breaks[index + 1]); + const start = startPositions.pop(); + jumps.unshift([start, start + slice.length - 1]); + splice(events, start, 2, slice); + } + + index = -1; + + while (++index < jumps.length) { + gaps[adjust + jumps[index][0]] = adjust + jumps[index][1]; + adjust += jumps[index][1] - jumps[index][0] - 1; + } + + return gaps +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Resolver} Resolver + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').Token} Token + * @typedef {import('micromark-util-types').State} State + */ + +/** + * No name because it must not be turned off. + * @type {Construct} + */ +const content = { + tokenize: tokenizeContent, + resolve: resolveContent +}; +/** @type {Construct} */ + +const continuationConstruct = { + tokenize: tokenizeContinuation, + partial: true +}; +/** + * Content is transparent: it’s parsed right now. That way, definitions are also + * parsed right now: before text in paragraphs (specifically, media) are parsed. + * + * @type {Resolver} + */ + +function resolveContent(events) { + subtokenize(events); + return events +} +/** @type {Tokenizer} */ + +function tokenizeContent(effects, ok) { + /** @type {Token} */ + let previous; + return start + /** @type {State} */ + + function start(code) { + effects.enter('content'); + previous = effects.enter('chunkContent', { + contentType: 'content' + }); + return data(code) + } + /** @type {State} */ + + function data(code) { + if (code === null) { + return contentEnd(code) + } + + if (markdownLineEnding(code)) { + return effects.check( + continuationConstruct, + contentContinue, + contentEnd + )(code) + } // Data. + + effects.consume(code); + return data + } + /** @type {State} */ + + function contentEnd(code) { + effects.exit('chunkContent'); + effects.exit('content'); + return ok(code) + } + /** @type {State} */ + + function contentContinue(code) { + effects.consume(code); + effects.exit('chunkContent'); + previous.next = effects.enter('chunkContent', { + contentType: 'content', + previous + }); + previous = previous.next; + return data + } +} +/** @type {Tokenizer} */ + +function tokenizeContinuation(effects, ok, nok) { + const self = this; + return startLookahead + /** @type {State} */ + + function startLookahead(code) { + effects.exit('chunkContent'); + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return factorySpace(effects, prefixed, 'linePrefix') + } + /** @type {State} */ + + function prefixed(code) { + if (code === null || markdownLineEnding(code)) { + return nok(code) + } + + const tail = self.events[self.events.length - 1]; + + if ( + !self.parser.constructs.disable.null.includes('codeIndented') && + tail && + tail[1].type === 'linePrefix' && + tail[2].sliceSerialize(tail[1], true).length >= 4 + ) { + return ok(code) + } + + return effects.interrupt(self.parser.constructs.flow, nok, ok)(code) + } +} + +/** + * @typedef {import('micromark-util-types').Effects} Effects + * @typedef {import('micromark-util-types').State} State + */ + +/** + * @param {Effects} effects + * @param {State} ok + * @param {State} nok + * @param {string} type + * @param {string} literalType + * @param {string} literalMarkerType + * @param {string} rawType + * @param {string} stringType + * @param {number} [max=Infinity] + * @returns {State} + */ +// eslint-disable-next-line max-params +function factoryDestination( + effects, + ok, + nok, + type, + literalType, + literalMarkerType, + rawType, + stringType, + max +) { + const limit = max || Number.POSITIVE_INFINITY; + let balance = 0; + return start + /** @type {State} */ + + function start(code) { + if (code === 60) { + effects.enter(type); + effects.enter(literalType); + effects.enter(literalMarkerType); + effects.consume(code); + effects.exit(literalMarkerType); + return destinationEnclosedBefore + } + + if (code === null || code === 41 || asciiControl(code)) { + return nok(code) + } + + effects.enter(type); + effects.enter(rawType); + effects.enter(stringType); + effects.enter('chunkString', { + contentType: 'string' + }); + return destinationRaw(code) + } + /** @type {State} */ + + function destinationEnclosedBefore(code) { + if (code === 62) { + effects.enter(literalMarkerType); + effects.consume(code); + effects.exit(literalMarkerType); + effects.exit(literalType); + effects.exit(type); + return ok + } + + effects.enter(stringType); + effects.enter('chunkString', { + contentType: 'string' + }); + return destinationEnclosed(code) + } + /** @type {State} */ + + function destinationEnclosed(code) { + if (code === 62) { + effects.exit('chunkString'); + effects.exit(stringType); + return destinationEnclosedBefore(code) + } + + if (code === null || code === 60 || markdownLineEnding(code)) { + return nok(code) + } + + effects.consume(code); + return code === 92 ? destinationEnclosedEscape : destinationEnclosed + } + /** @type {State} */ + + function destinationEnclosedEscape(code) { + if (code === 60 || code === 62 || code === 92) { + effects.consume(code); + return destinationEnclosed + } + + return destinationEnclosed(code) + } + /** @type {State} */ + + function destinationRaw(code) { + if (code === 40) { + if (++balance > limit) return nok(code) + effects.consume(code); + return destinationRaw + } + + if (code === 41) { + if (!balance--) { + effects.exit('chunkString'); + effects.exit(stringType); + effects.exit(rawType); + effects.exit(type); + return ok(code) + } + + effects.consume(code); + return destinationRaw + } + + if (code === null || markdownLineEndingOrSpace(code)) { + if (balance) return nok(code) + effects.exit('chunkString'); + effects.exit(stringType); + effects.exit(rawType); + effects.exit(type); + return ok(code) + } + + if (asciiControl(code)) return nok(code) + effects.consume(code); + return code === 92 ? destinationRawEscape : destinationRaw + } + /** @type {State} */ + + function destinationRawEscape(code) { + if (code === 40 || code === 41 || code === 92) { + effects.consume(code); + return destinationRaw + } + + return destinationRaw(code) + } +} + +/** + * @typedef {import('micromark-util-types').Effects} Effects + * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext + * @typedef {import('micromark-util-types').State} State + */ + +/** + * @this {TokenizeContext} + * @param {Effects} effects + * @param {State} ok + * @param {State} nok + * @param {string} type + * @param {string} markerType + * @param {string} stringType + * @returns {State} + */ +// eslint-disable-next-line max-params +function factoryLabel(effects, ok, nok, type, markerType, stringType) { + const self = this; + let size = 0; + /** @type {boolean} */ + + let data; + return start + /** @type {State} */ + + function start(code) { + effects.enter(type); + effects.enter(markerType); + effects.consume(code); + effects.exit(markerType); + effects.enter(stringType); + return atBreak + } + /** @type {State} */ + + function atBreak(code) { + if ( + code === null || + code === 91 || + (code === 93 && !data) || + /* Hidden footnotes hook */ + + /* c8 ignore next 3 */ + (code === 94 && + !size && + '_hiddenFootnoteSupport' in self.parser.constructs) || + size > 999 + ) { + return nok(code) + } + + if (code === 93) { + effects.exit(stringType); + effects.enter(markerType); + effects.consume(code); + effects.exit(markerType); + effects.exit(type); + return ok + } + + if (markdownLineEnding(code)) { + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return atBreak + } + + effects.enter('chunkString', { + contentType: 'string' + }); + return label(code) + } + /** @type {State} */ + + function label(code) { + if ( + code === null || + code === 91 || + code === 93 || + markdownLineEnding(code) || + size++ > 999 + ) { + effects.exit('chunkString'); + return atBreak(code) + } + + effects.consume(code); + data = data || !markdownSpace(code); + return code === 92 ? labelEscape : label + } + /** @type {State} */ + + function labelEscape(code) { + if (code === 91 || code === 92 || code === 93) { + effects.consume(code); + size++; + return label + } + + return label(code) + } +} + +/** + * @typedef {import('micromark-util-types').Effects} Effects + * @typedef {import('micromark-util-types').State} State + * @typedef {import('micromark-util-types').Code} Code + */ + +/** + * @param {Effects} effects + * @param {State} ok + * @param {State} nok + * @param {string} type + * @param {string} markerType + * @param {string} stringType + * @returns {State} + */ +// eslint-disable-next-line max-params +function factoryTitle(effects, ok, nok, type, markerType, stringType) { + /** @type {NonNullable} */ + let marker; + return start + /** @type {State} */ + + function start(code) { + effects.enter(type); + effects.enter(markerType); + effects.consume(code); + effects.exit(markerType); + marker = code === 40 ? 41 : code; + return atFirstTitleBreak + } + /** @type {State} */ + + function atFirstTitleBreak(code) { + if (code === marker) { + effects.enter(markerType); + effects.consume(code); + effects.exit(markerType); + effects.exit(type); + return ok + } + + effects.enter(stringType); + return atTitleBreak(code) + } + /** @type {State} */ + + function atTitleBreak(code) { + if (code === marker) { + effects.exit(stringType); + return atFirstTitleBreak(marker) + } + + if (code === null) { + return nok(code) + } // Note: blank lines can’t exist in content. + + if (markdownLineEnding(code)) { + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return factorySpace(effects, atTitleBreak, 'linePrefix') + } + + effects.enter('chunkString', { + contentType: 'string' + }); + return title(code) + } + /** @type {State} */ + + function title(code) { + if (code === marker || code === null || markdownLineEnding(code)) { + effects.exit('chunkString'); + return atTitleBreak(code) + } + + effects.consume(code); + return code === 92 ? titleEscape : title + } + /** @type {State} */ + + function titleEscape(code) { + if (code === marker || code === 92) { + effects.consume(code); + return title + } + + return title(code) + } +} + +/** + * @typedef {import('micromark-util-types').Effects} Effects + * @typedef {import('micromark-util-types').State} State + */ + +/** + * @param {Effects} effects + * @param {State} ok + */ +function factoryWhitespace(effects, ok) { + /** @type {boolean} */ + let seen; + return start + /** @type {State} */ + + function start(code) { + if (markdownLineEnding(code)) { + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + seen = true; + return start + } + + if (markdownSpace(code)) { + return factorySpace( + effects, + start, + seen ? 'linePrefix' : 'lineSuffix' + )(code) + } + + return ok(code) + } +} + +/** + * Normalize an identifier (such as used in definitions). + * + * @param {string} value + * @returns {string} + */ +function normalizeIdentifier(value) { + return ( + value // Collapse Markdown whitespace. + .replace(/[\t\n\r ]+/g, ' ') // Trim. + .replace(/^ | $/g, '') // Some characters are considered “uppercase”, but if their lowercase + // counterpart is uppercased will result in a different uppercase + // character. + // Hence, to get that form, we perform both lower- and uppercase. + // Upper case makes sure keys will not interact with default prototypal + // methods: no method is uppercase. + .toLowerCase() + .toUpperCase() + ) +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State + */ + +/** @type {Construct} */ +const definition$1 = { + name: 'definition', + tokenize: tokenizeDefinition +}; +/** @type {Construct} */ + +const titleConstruct = { + tokenize: tokenizeTitle, + partial: true +}; +/** @type {Tokenizer} */ + +function tokenizeDefinition(effects, ok, nok) { + const self = this; + /** @type {string} */ + + let identifier; + return start + /** @type {State} */ + + function start(code) { + effects.enter('definition'); + return factoryLabel.call( + self, + effects, + labelAfter, + nok, + 'definitionLabel', + 'definitionLabelMarker', + 'definitionLabelString' + )(code) + } + /** @type {State} */ + + function labelAfter(code) { + identifier = normalizeIdentifier( + self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1) + ); + + if (code === 58) { + effects.enter('definitionMarker'); + effects.consume(code); + effects.exit('definitionMarker'); // Note: blank lines can’t exist in content. + + return factoryWhitespace( + effects, + factoryDestination( + effects, + effects.attempt( + titleConstruct, + factorySpace(effects, after, 'whitespace'), + factorySpace(effects, after, 'whitespace') + ), + nok, + 'definitionDestination', + 'definitionDestinationLiteral', + 'definitionDestinationLiteralMarker', + 'definitionDestinationRaw', + 'definitionDestinationString' + ) + ) + } + + return nok(code) + } + /** @type {State} */ + + function after(code) { + if (code === null || markdownLineEnding(code)) { + effects.exit('definition'); + + if (!self.parser.defined.includes(identifier)) { + self.parser.defined.push(identifier); + } + + return ok(code) + } + + return nok(code) + } +} +/** @type {Tokenizer} */ + +function tokenizeTitle(effects, ok, nok) { + return start + /** @type {State} */ + + function start(code) { + return markdownLineEndingOrSpace(code) + ? factoryWhitespace(effects, before)(code) + : nok(code) + } + /** @type {State} */ + + function before(code) { + if (code === 34 || code === 39 || code === 40) { + return factoryTitle( + effects, + factorySpace(effects, after, 'whitespace'), + nok, + 'definitionTitle', + 'definitionTitleMarker', + 'definitionTitleString' + )(code) + } + + return nok(code) + } + /** @type {State} */ + + function after(code) { + return code === null || markdownLineEnding(code) ? ok(code) : nok(code) + } +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State + */ + +/** @type {Construct} */ +const hardBreakEscape = { + name: 'hardBreakEscape', + tokenize: tokenizeHardBreakEscape +}; +/** @type {Tokenizer} */ + +function tokenizeHardBreakEscape(effects, ok, nok) { + return start + /** @type {State} */ + + function start(code) { + effects.enter('hardBreakEscape'); + effects.enter('escapeMarker'); + effects.consume(code); + return open + } + /** @type {State} */ + + function open(code) { + if (markdownLineEnding(code)) { + effects.exit('escapeMarker'); + effects.exit('hardBreakEscape'); + return ok(code) + } + + return nok(code) + } +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Resolver} Resolver + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').Token} Token + * @typedef {import('micromark-util-types').State} State + */ + +/** @type {Construct} */ +const headingAtx = { + name: 'headingAtx', + tokenize: tokenizeHeadingAtx, + resolve: resolveHeadingAtx +}; +/** @type {Resolver} */ + +function resolveHeadingAtx(events, context) { + let contentEnd = events.length - 2; + let contentStart = 3; + /** @type {Token} */ + + let content; + /** @type {Token} */ + + let text; // Prefix whitespace, part of the opening. + + if (events[contentStart][1].type === 'whitespace') { + contentStart += 2; + } // Suffix whitespace, part of the closing. + + if ( + contentEnd - 2 > contentStart && + events[contentEnd][1].type === 'whitespace' + ) { + contentEnd -= 2; + } + + if ( + events[contentEnd][1].type === 'atxHeadingSequence' && + (contentStart === contentEnd - 1 || + (contentEnd - 4 > contentStart && + events[contentEnd - 2][1].type === 'whitespace')) + ) { + contentEnd -= contentStart + 1 === contentEnd ? 2 : 4; + } + + if (contentEnd > contentStart) { + content = { + type: 'atxHeadingText', + start: events[contentStart][1].start, + end: events[contentEnd][1].end + }; + text = { + type: 'chunkText', + start: events[contentStart][1].start, + end: events[contentEnd][1].end, + // @ts-expect-error Constants are fine to assign. + contentType: 'text' + }; + splice(events, contentStart, contentEnd - contentStart + 1, [ + ['enter', content, context], + ['enter', text, context], + ['exit', text, context], + ['exit', content, context] + ]); + } + + return events +} +/** @type {Tokenizer} */ + +function tokenizeHeadingAtx(effects, ok, nok) { + const self = this; + let size = 0; + return start + /** @type {State} */ + + function start(code) { + effects.enter('atxHeading'); + effects.enter('atxHeadingSequence'); + return fenceOpenInside(code) + } + /** @type {State} */ + + function fenceOpenInside(code) { + if (code === 35 && size++ < 6) { + effects.consume(code); + return fenceOpenInside + } + + if (code === null || markdownLineEndingOrSpace(code)) { + effects.exit('atxHeadingSequence'); + return self.interrupt ? ok(code) : headingBreak(code) + } + + return nok(code) + } + /** @type {State} */ + + function headingBreak(code) { + if (code === 35) { + effects.enter('atxHeadingSequence'); + return sequence(code) + } + + if (code === null || markdownLineEnding(code)) { + effects.exit('atxHeading'); + return ok(code) + } + + if (markdownSpace(code)) { + return factorySpace(effects, headingBreak, 'whitespace')(code) + } + + effects.enter('atxHeadingText'); + return data(code) + } + /** @type {State} */ + + function sequence(code) { + if (code === 35) { + effects.consume(code); + return sequence + } + + effects.exit('atxHeadingSequence'); + return headingBreak(code) + } + /** @type {State} */ + + function data(code) { + if (code === null || code === 35 || markdownLineEndingOrSpace(code)) { + effects.exit('atxHeadingText'); + return headingBreak(code) + } + + effects.consume(code); + return data + } +} + +/** + * List of lowercase HTML tag names which when parsing HTML (flow), result + * in more relaxed rules (condition 6): because they are known blocks, the + * HTML-like syntax doesn’t have to be strictly parsed. + * For tag names not in this list, a more strict algorithm (condition 7) is used + * to detect whether the HTML-like syntax is seen as HTML (flow) or not. + * + * This is copied from: + * . + */ +const htmlBlockNames = [ + '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' +]; + +/** + * List of lowercase HTML tag names which when parsing HTML (flow), result in + * HTML that can include lines w/o exiting, until a closing tag also in this + * list is found (condition 1). + * + * This module is copied from: + * . + * + * Note that `textarea` is not available in `CommonMark@0.29` but has been + * merged to the primary branch and is slated to be released in the next release + * of CommonMark. + */ +const htmlRawNames = ['pre', 'script', 'style', 'textarea']; + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Resolver} Resolver + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State + * @typedef {import('micromark-util-types').Code} Code + */ +/** @type {Construct} */ + +const htmlFlow = { + name: 'htmlFlow', + tokenize: tokenizeHtmlFlow, + resolveTo: resolveToHtmlFlow, + concrete: true +}; +/** @type {Construct} */ + +const nextBlankConstruct = { + tokenize: tokenizeNextBlank, + partial: true +}; +/** @type {Resolver} */ + +function resolveToHtmlFlow(events) { + let index = events.length; + + while (index--) { + if (events[index][0] === 'enter' && events[index][1].type === 'htmlFlow') { + break + } + } + + if (index > 1 && events[index - 2][1].type === 'linePrefix') { + // Add the prefix start to the HTML token. + events[index][1].start = events[index - 2][1].start; // Add the prefix start to the HTML line token. + + events[index + 1][1].start = events[index - 2][1].start; // Remove the line prefix. + + events.splice(index - 2, 2); + } + + return events +} +/** @type {Tokenizer} */ + +function tokenizeHtmlFlow(effects, ok, nok) { + const self = this; + /** @type {number} */ + + let kind; + /** @type {boolean} */ + + let startTag; + /** @type {string} */ + + let buffer; + /** @type {number} */ + + let index; + /** @type {Code} */ + + let marker; + return start + /** @type {State} */ + + function start(code) { + effects.enter('htmlFlow'); + effects.enter('htmlFlowData'); + effects.consume(code); + return open + } + /** @type {State} */ + + function open(code) { + if (code === 33) { + effects.consume(code); + return declarationStart + } + + if (code === 47) { + effects.consume(code); + return tagCloseStart + } + + if (code === 63) { + effects.consume(code); + kind = 3; // While we’re in an instruction instead of a declaration, we’re on a `?` + // right now, so we do need to search for `>`, similar to declarations. + + return self.interrupt ? ok : continuationDeclarationInside + } + + if (asciiAlpha(code)) { + effects.consume(code); + buffer = String.fromCharCode(code); + startTag = true; + return tagName + } + + return nok(code) + } + /** @type {State} */ + + function declarationStart(code) { + if (code === 45) { + effects.consume(code); + kind = 2; + return commentOpenInside + } + + if (code === 91) { + effects.consume(code); + kind = 5; + buffer = 'CDATA['; + index = 0; + return cdataOpenInside + } + + if (asciiAlpha(code)) { + effects.consume(code); + kind = 4; + return self.interrupt ? ok : continuationDeclarationInside + } + + return nok(code) + } + /** @type {State} */ + + function commentOpenInside(code) { + if (code === 45) { + effects.consume(code); + return self.interrupt ? ok : continuationDeclarationInside + } + + return nok(code) + } + /** @type {State} */ + + function cdataOpenInside(code) { + if (code === buffer.charCodeAt(index++)) { + effects.consume(code); + return index === buffer.length + ? self.interrupt + ? ok + : continuation + : cdataOpenInside + } + + return nok(code) + } + /** @type {State} */ + + function tagCloseStart(code) { + if (asciiAlpha(code)) { + effects.consume(code); + buffer = String.fromCharCode(code); + return tagName + } + + return nok(code) + } + /** @type {State} */ + + function tagName(code) { + if ( + code === null || + code === 47 || + code === 62 || + markdownLineEndingOrSpace(code) + ) { + if ( + code !== 47 && + startTag && + htmlRawNames.includes(buffer.toLowerCase()) + ) { + kind = 1; + return self.interrupt ? ok(code) : continuation(code) + } + + if (htmlBlockNames.includes(buffer.toLowerCase())) { + kind = 6; + + if (code === 47) { + effects.consume(code); + return basicSelfClosing + } + + return self.interrupt ? ok(code) : continuation(code) + } + + kind = 7; // Do not support complete HTML when interrupting + + return self.interrupt && !self.parser.lazy[self.now().line] + ? nok(code) + : startTag + ? completeAttributeNameBefore(code) + : completeClosingTagAfter(code) + } + + if (code === 45 || asciiAlphanumeric(code)) { + effects.consume(code); + buffer += String.fromCharCode(code); + return tagName + } + + return nok(code) + } + /** @type {State} */ + + function basicSelfClosing(code) { + if (code === 62) { + effects.consume(code); + return self.interrupt ? ok : continuation + } + + return nok(code) + } + /** @type {State} */ + + function completeClosingTagAfter(code) { + if (markdownSpace(code)) { + effects.consume(code); + return completeClosingTagAfter + } + + return completeEnd(code) + } + /** @type {State} */ + + function completeAttributeNameBefore(code) { + if (code === 47) { + effects.consume(code); + return completeEnd + } + + if (code === 58 || code === 95 || asciiAlpha(code)) { + effects.consume(code); + return completeAttributeName + } + + if (markdownSpace(code)) { + effects.consume(code); + return completeAttributeNameBefore + } + + return completeEnd(code) + } + /** @type {State} */ + + function completeAttributeName(code) { + if ( + code === 45 || + code === 46 || + code === 58 || + code === 95 || + asciiAlphanumeric(code) + ) { + effects.consume(code); + return completeAttributeName + } + + return completeAttributeNameAfter(code) + } + /** @type {State} */ + + function completeAttributeNameAfter(code) { + if (code === 61) { + effects.consume(code); + return completeAttributeValueBefore + } + + if (markdownSpace(code)) { + effects.consume(code); + return completeAttributeNameAfter + } + + return completeAttributeNameBefore(code) + } + /** @type {State} */ + + function completeAttributeValueBefore(code) { + if ( + code === null || + code === 60 || + code === 61 || + code === 62 || + code === 96 + ) { + return nok(code) + } + + if (code === 34 || code === 39) { + effects.consume(code); + marker = code; + return completeAttributeValueQuoted + } + + if (markdownSpace(code)) { + effects.consume(code); + return completeAttributeValueBefore + } + + marker = null; + return completeAttributeValueUnquoted(code) + } + /** @type {State} */ + + function completeAttributeValueQuoted(code) { + if (code === null || markdownLineEnding(code)) { + return nok(code) + } + + if (code === marker) { + effects.consume(code); + return completeAttributeValueQuotedAfter + } + + effects.consume(code); + return completeAttributeValueQuoted + } + /** @type {State} */ + + function completeAttributeValueUnquoted(code) { + if ( + code === null || + code === 34 || + code === 39 || + code === 60 || + code === 61 || + code === 62 || + code === 96 || + markdownLineEndingOrSpace(code) + ) { + return completeAttributeNameAfter(code) + } + + effects.consume(code); + return completeAttributeValueUnquoted + } + /** @type {State} */ + + function completeAttributeValueQuotedAfter(code) { + if (code === 47 || code === 62 || markdownSpace(code)) { + return completeAttributeNameBefore(code) + } + + return nok(code) + } + /** @type {State} */ + + function completeEnd(code) { + if (code === 62) { + effects.consume(code); + return completeAfter + } + + return nok(code) + } + /** @type {State} */ + + function completeAfter(code) { + if (markdownSpace(code)) { + effects.consume(code); + return completeAfter + } + + return code === null || markdownLineEnding(code) + ? continuation(code) + : nok(code) + } + /** @type {State} */ + + function continuation(code) { + if (code === 45 && kind === 2) { + effects.consume(code); + return continuationCommentInside + } + + if (code === 60 && kind === 1) { + effects.consume(code); + return continuationRawTagOpen + } + + if (code === 62 && kind === 4) { + effects.consume(code); + return continuationClose + } + + if (code === 63 && kind === 3) { + effects.consume(code); + return continuationDeclarationInside + } + + if (code === 93 && kind === 5) { + effects.consume(code); + return continuationCharacterDataInside + } + + if (markdownLineEnding(code) && (kind === 6 || kind === 7)) { + return effects.check( + nextBlankConstruct, + continuationClose, + continuationAtLineEnding + )(code) + } + + if (code === null || markdownLineEnding(code)) { + return continuationAtLineEnding(code) + } + + effects.consume(code); + return continuation + } + /** @type {State} */ + + function continuationAtLineEnding(code) { + effects.exit('htmlFlowData'); + return htmlContinueStart(code) + } + /** @type {State} */ + + function htmlContinueStart(code) { + if (code === null) { + return done(code) + } + + if (markdownLineEnding(code)) { + return effects.attempt( + { + tokenize: htmlLineEnd, + partial: true + }, + htmlContinueStart, + done + )(code) + } + + effects.enter('htmlFlowData'); + return continuation(code) + } + /** @type {Tokenizer} */ + + function htmlLineEnd(effects, ok, nok) { + return start + /** @type {State} */ + + function start(code) { + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return lineStart + } + /** @type {State} */ + + function lineStart(code) { + return self.parser.lazy[self.now().line] ? nok(code) : ok(code) + } + } + /** @type {State} */ + + function continuationCommentInside(code) { + if (code === 45) { + effects.consume(code); + return continuationDeclarationInside + } + + return continuation(code) + } + /** @type {State} */ + + function continuationRawTagOpen(code) { + if (code === 47) { + effects.consume(code); + buffer = ''; + return continuationRawEndTag + } + + return continuation(code) + } + /** @type {State} */ + + function continuationRawEndTag(code) { + if (code === 62 && htmlRawNames.includes(buffer.toLowerCase())) { + effects.consume(code); + return continuationClose + } + + if (asciiAlpha(code) && buffer.length < 8) { + effects.consume(code); + buffer += String.fromCharCode(code); + return continuationRawEndTag + } + + return continuation(code) + } + /** @type {State} */ + + function continuationCharacterDataInside(code) { + if (code === 93) { + effects.consume(code); + return continuationDeclarationInside + } + + return continuation(code) + } + /** @type {State} */ + + function continuationDeclarationInside(code) { + if (code === 62) { + effects.consume(code); + return continuationClose + } + + return continuation(code) + } + /** @type {State} */ + + function continuationClose(code) { + if (code === null || markdownLineEnding(code)) { + effects.exit('htmlFlowData'); + return done(code) + } + + effects.consume(code); + return continuationClose + } + /** @type {State} */ + + function done(code) { + effects.exit('htmlFlow'); + return ok(code) + } +} +/** @type {Tokenizer} */ + +function tokenizeNextBlank(effects, ok, nok) { + return start + /** @type {State} */ + + function start(code) { + effects.exit('htmlFlowData'); + effects.enter('lineEndingBlank'); + effects.consume(code); + effects.exit('lineEndingBlank'); + return effects.attempt(blankLine, ok, nok) + } +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State + * @typedef {import('micromark-util-types').Code} Code + */ + +/** @type {Construct} */ +const htmlText = { + name: 'htmlText', + tokenize: tokenizeHtmlText +}; +/** @type {Tokenizer} */ + +function tokenizeHtmlText(effects, ok, nok) { + const self = this; + /** @type {NonNullable|undefined} */ + + let marker; + /** @type {string} */ + + let buffer; + /** @type {number} */ + + let index; + /** @type {State} */ + + let returnState; + return start + /** @type {State} */ + + function start(code) { + effects.enter('htmlText'); + effects.enter('htmlTextData'); + effects.consume(code); + return open + } + /** @type {State} */ + + function open(code) { + if (code === 33) { + effects.consume(code); + return declarationOpen + } + + if (code === 47) { + effects.consume(code); + return tagCloseStart + } + + if (code === 63) { + effects.consume(code); + return instruction + } + + if (asciiAlpha(code)) { + effects.consume(code); + return tagOpen + } + + return nok(code) + } + /** @type {State} */ + + function declarationOpen(code) { + if (code === 45) { + effects.consume(code); + return commentOpen + } + + if (code === 91) { + effects.consume(code); + buffer = 'CDATA['; + index = 0; + return cdataOpen + } + + if (asciiAlpha(code)) { + effects.consume(code); + return declaration + } + + return nok(code) + } + /** @type {State} */ + + function commentOpen(code) { + if (code === 45) { + effects.consume(code); + return commentStart + } + + return nok(code) + } + /** @type {State} */ + + function commentStart(code) { + if (code === null || code === 62) { + return nok(code) + } + + if (code === 45) { + effects.consume(code); + return commentStartDash + } + + return comment(code) + } + /** @type {State} */ + + function commentStartDash(code) { + if (code === null || code === 62) { + return nok(code) + } + + return comment(code) + } + /** @type {State} */ + + function comment(code) { + if (code === null) { + return nok(code) + } + + if (code === 45) { + effects.consume(code); + return commentClose + } + + if (markdownLineEnding(code)) { + returnState = comment; + return atLineEnding(code) + } + + effects.consume(code); + return comment + } + /** @type {State} */ + + function commentClose(code) { + if (code === 45) { + effects.consume(code); + return end + } + + return comment(code) + } + /** @type {State} */ + + function cdataOpen(code) { + if (code === buffer.charCodeAt(index++)) { + effects.consume(code); + return index === buffer.length ? cdata : cdataOpen + } + + return nok(code) + } + /** @type {State} */ + + function cdata(code) { + if (code === null) { + return nok(code) + } + + if (code === 93) { + effects.consume(code); + return cdataClose + } + + if (markdownLineEnding(code)) { + returnState = cdata; + return atLineEnding(code) + } + + effects.consume(code); + return cdata + } + /** @type {State} */ + + function cdataClose(code) { + if (code === 93) { + effects.consume(code); + return cdataEnd + } + + return cdata(code) + } + /** @type {State} */ + + function cdataEnd(code) { + if (code === 62) { + return end(code) + } + + if (code === 93) { + effects.consume(code); + return cdataEnd + } + + return cdata(code) + } + /** @type {State} */ + + function declaration(code) { + if (code === null || code === 62) { + return end(code) + } + + if (markdownLineEnding(code)) { + returnState = declaration; + return atLineEnding(code) + } + + effects.consume(code); + return declaration + } + /** @type {State} */ + + function instruction(code) { + if (code === null) { + return nok(code) + } + + if (code === 63) { + effects.consume(code); + return instructionClose + } + + if (markdownLineEnding(code)) { + returnState = instruction; + return atLineEnding(code) + } + + effects.consume(code); + return instruction + } + /** @type {State} */ + + function instructionClose(code) { + return code === 62 ? end(code) : instruction(code) + } + /** @type {State} */ + + function tagCloseStart(code) { + if (asciiAlpha(code)) { + effects.consume(code); + return tagClose + } + + return nok(code) + } + /** @type {State} */ + + function tagClose(code) { + if (code === 45 || asciiAlphanumeric(code)) { + effects.consume(code); + return tagClose + } + + return tagCloseBetween(code) + } + /** @type {State} */ + + function tagCloseBetween(code) { + if (markdownLineEnding(code)) { + returnState = tagCloseBetween; + return atLineEnding(code) + } + + if (markdownSpace(code)) { + effects.consume(code); + return tagCloseBetween + } + + return end(code) + } + /** @type {State} */ + + function tagOpen(code) { + if (code === 45 || asciiAlphanumeric(code)) { + effects.consume(code); + return tagOpen + } + + if (code === 47 || code === 62 || markdownLineEndingOrSpace(code)) { + return tagOpenBetween(code) + } + + return nok(code) + } + /** @type {State} */ + + function tagOpenBetween(code) { + if (code === 47) { + effects.consume(code); + return end + } + + if (code === 58 || code === 95 || asciiAlpha(code)) { + effects.consume(code); + return tagOpenAttributeName + } + + if (markdownLineEnding(code)) { + returnState = tagOpenBetween; + return atLineEnding(code) + } + + if (markdownSpace(code)) { + effects.consume(code); + return tagOpenBetween + } + + return end(code) + } + /** @type {State} */ + + function tagOpenAttributeName(code) { + if ( + code === 45 || + code === 46 || + code === 58 || + code === 95 || + asciiAlphanumeric(code) + ) { + effects.consume(code); + return tagOpenAttributeName + } + + return tagOpenAttributeNameAfter(code) + } + /** @type {State} */ + + function tagOpenAttributeNameAfter(code) { + if (code === 61) { + effects.consume(code); + return tagOpenAttributeValueBefore + } + + if (markdownLineEnding(code)) { + returnState = tagOpenAttributeNameAfter; + return atLineEnding(code) + } + + if (markdownSpace(code)) { + effects.consume(code); + return tagOpenAttributeNameAfter + } + + return tagOpenBetween(code) + } + /** @type {State} */ + + function tagOpenAttributeValueBefore(code) { + if ( + code === null || + code === 60 || + code === 61 || + code === 62 || + code === 96 + ) { + return nok(code) + } + + if (code === 34 || code === 39) { + effects.consume(code); + marker = code; + return tagOpenAttributeValueQuoted + } + + if (markdownLineEnding(code)) { + returnState = tagOpenAttributeValueBefore; + return atLineEnding(code) + } + + if (markdownSpace(code)) { + effects.consume(code); + return tagOpenAttributeValueBefore + } + + effects.consume(code); + marker = undefined; + return tagOpenAttributeValueUnquoted + } + /** @type {State} */ + + function tagOpenAttributeValueQuoted(code) { + if (code === marker) { + effects.consume(code); + return tagOpenAttributeValueQuotedAfter + } + + if (code === null) { + return nok(code) + } + + if (markdownLineEnding(code)) { + returnState = tagOpenAttributeValueQuoted; + return atLineEnding(code) + } + + effects.consume(code); + return tagOpenAttributeValueQuoted + } + /** @type {State} */ + + function tagOpenAttributeValueQuotedAfter(code) { + if (code === 62 || code === 47 || markdownLineEndingOrSpace(code)) { + return tagOpenBetween(code) + } + + return nok(code) + } + /** @type {State} */ + + function tagOpenAttributeValueUnquoted(code) { + if ( + code === null || + code === 34 || + code === 39 || + code === 60 || + code === 61 || + code === 96 + ) { + return nok(code) + } + + if (code === 62 || markdownLineEndingOrSpace(code)) { + return tagOpenBetween(code) + } + + effects.consume(code); + return tagOpenAttributeValueUnquoted + } // We can’t have blank lines in content, so no need to worry about empty + // tokens. + + /** @type {State} */ + + function atLineEnding(code) { + effects.exit('htmlTextData'); + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return factorySpace( + effects, + afterPrefix, + 'linePrefix', + self.parser.constructs.disable.null.includes('codeIndented') + ? undefined + : 4 + ) + } + /** @type {State} */ + + function afterPrefix(code) { + effects.enter('htmlTextData'); + return returnState(code) + } + /** @type {State} */ + + function end(code) { + if (code === 62) { + effects.consume(code); + effects.exit('htmlTextData'); + effects.exit('htmlText'); + return ok + } + + return nok(code) + } +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Resolver} Resolver + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').Event} Event + * @typedef {import('micromark-util-types').Token} Token + * @typedef {import('micromark-util-types').State} State + * @typedef {import('micromark-util-types').Code} Code + */ + +/** @type {Construct} */ +const labelEnd = { + name: 'labelEnd', + tokenize: tokenizeLabelEnd, + resolveTo: resolveToLabelEnd, + resolveAll: resolveAllLabelEnd +}; +/** @type {Construct} */ + +const resourceConstruct = { + tokenize: tokenizeResource +}; +/** @type {Construct} */ + +const fullReferenceConstruct = { + tokenize: tokenizeFullReference +}; +/** @type {Construct} */ + +const collapsedReferenceConstruct = { + tokenize: tokenizeCollapsedReference +}; +/** @type {Resolver} */ + +function resolveAllLabelEnd(events) { + let index = -1; + /** @type {Token} */ + + let token; + + while (++index < events.length) { + token = events[index][1]; + + if ( + token.type === 'labelImage' || + token.type === 'labelLink' || + token.type === 'labelEnd' + ) { + // Remove the marker. + events.splice(index + 1, token.type === 'labelImage' ? 4 : 2); + token.type = 'data'; + index++; + } + } + + return events +} +/** @type {Resolver} */ + +function resolveToLabelEnd(events, context) { + let index = events.length; + let offset = 0; + /** @type {Token} */ + + let token; + /** @type {number|undefined} */ + + let open; + /** @type {number|undefined} */ + + let close; + /** @type {Event[]} */ + + let media; // Find an opening. + + while (index--) { + token = events[index][1]; + + if (open) { + // If we see another link, or inactive link label, we’ve been here before. + if ( + token.type === 'link' || + (token.type === 'labelLink' && token._inactive) + ) { + break + } // Mark other link openings as inactive, as we can’t have links in + // links. + + if (events[index][0] === 'enter' && token.type === 'labelLink') { + token._inactive = true; + } + } else if (close) { + if ( + events[index][0] === 'enter' && + (token.type === 'labelImage' || token.type === 'labelLink') && + !token._balanced + ) { + open = index; + + if (token.type !== 'labelLink') { + offset = 2; + break + } + } + } else if (token.type === 'labelEnd') { + close = index; + } + } + + const group = { + type: events[open][1].type === 'labelLink' ? 'link' : 'image', + start: Object.assign({}, events[open][1].start), + end: Object.assign({}, events[events.length - 1][1].end) + }; + const label = { + type: 'label', + start: Object.assign({}, events[open][1].start), + end: Object.assign({}, events[close][1].end) + }; + const text = { + type: 'labelText', + start: Object.assign({}, events[open + offset + 2][1].end), + end: Object.assign({}, events[close - 2][1].start) + }; + media = [ + ['enter', group, context], + ['enter', label, context] + ]; // Opening marker. + + media = push(media, events.slice(open + 1, open + offset + 3)); // Text open. + + media = push(media, [['enter', text, context]]); // Between. + + media = push( + media, + resolveAll( + context.parser.constructs.insideSpan.null, + events.slice(open + offset + 4, close - 3), + context + ) + ); // Text close, marker close, label close. + + media = push(media, [ + ['exit', text, context], + events[close - 2], + events[close - 1], + ['exit', label, context] + ]); // Reference, resource, or so. + + media = push(media, events.slice(close + 1)); // Media close. + + media = push(media, [['exit', group, context]]); + splice(events, open, events.length, media); + return events +} +/** @type {Tokenizer} */ + +function tokenizeLabelEnd(effects, ok, nok) { + const self = this; + let index = self.events.length; + /** @type {Token} */ + + let labelStart; + /** @type {boolean} */ + + let defined; // Find an opening. + + while (index--) { + if ( + (self.events[index][1].type === 'labelImage' || + self.events[index][1].type === 'labelLink') && + !self.events[index][1]._balanced + ) { + labelStart = self.events[index][1]; + break + } + } + + return start + /** @type {State} */ + + function start(code) { + if (!labelStart) { + return nok(code) + } // It’s a balanced bracket, but contains a link. + + if (labelStart._inactive) return balanced(code) + defined = self.parser.defined.includes( + normalizeIdentifier( + self.sliceSerialize({ + start: labelStart.end, + end: self.now() + }) + ) + ); + effects.enter('labelEnd'); + effects.enter('labelMarker'); + effects.consume(code); + effects.exit('labelMarker'); + effects.exit('labelEnd'); + return afterLabelEnd + } + /** @type {State} */ + + function afterLabelEnd(code) { + // Resource: `[asd](fgh)`. + if (code === 40) { + return effects.attempt( + resourceConstruct, + ok, + defined ? ok : balanced + )(code) + } // Collapsed (`[asd][]`) or full (`[asd][fgh]`) reference? + + if (code === 91) { + return effects.attempt( + fullReferenceConstruct, + ok, + defined + ? effects.attempt(collapsedReferenceConstruct, ok, balanced) + : balanced + )(code) + } // Shortcut reference: `[asd]`? + + return defined ? ok(code) : balanced(code) + } + /** @type {State} */ + + function balanced(code) { + labelStart._balanced = true; + return nok(code) + } +} +/** @type {Tokenizer} */ + +function tokenizeResource(effects, ok, nok) { + return start + /** @type {State} */ + + function start(code) { + effects.enter('resource'); + effects.enter('resourceMarker'); + effects.consume(code); + effects.exit('resourceMarker'); + return factoryWhitespace(effects, open) + } + /** @type {State} */ + + function open(code) { + if (code === 41) { + return end(code) + } + + return factoryDestination( + effects, + destinationAfter, + nok, + 'resourceDestination', + 'resourceDestinationLiteral', + 'resourceDestinationLiteralMarker', + 'resourceDestinationRaw', + 'resourceDestinationString', + 3 + )(code) + } + /** @type {State} */ + + function destinationAfter(code) { + return markdownLineEndingOrSpace(code) + ? factoryWhitespace(effects, between)(code) + : end(code) + } + /** @type {State} */ + + function between(code) { + if (code === 34 || code === 39 || code === 40) { + return factoryTitle( + effects, + factoryWhitespace(effects, end), + nok, + 'resourceTitle', + 'resourceTitleMarker', + 'resourceTitleString' + )(code) + } + + return end(code) + } + /** @type {State} */ + + function end(code) { + if (code === 41) { + effects.enter('resourceMarker'); + effects.consume(code); + effects.exit('resourceMarker'); + effects.exit('resource'); + return ok + } + + return nok(code) + } +} +/** @type {Tokenizer} */ + +function tokenizeFullReference(effects, ok, nok) { + const self = this; + return start + /** @type {State} */ + + function start(code) { + return factoryLabel.call( + self, + effects, + afterLabel, + nok, + 'reference', + 'referenceMarker', + 'referenceString' + )(code) + } + /** @type {State} */ + + function afterLabel(code) { + return self.parser.defined.includes( + normalizeIdentifier( + self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1) + ) + ) + ? ok(code) + : nok(code) + } +} +/** @type {Tokenizer} */ + +function tokenizeCollapsedReference(effects, ok, nok) { + return start + /** @type {State} */ + + function start(code) { + effects.enter('reference'); + effects.enter('referenceMarker'); + effects.consume(code); + effects.exit('referenceMarker'); + return open + } + /** @type {State} */ + + function open(code) { + if (code === 93) { + effects.enter('referenceMarker'); + effects.consume(code); + effects.exit('referenceMarker'); + effects.exit('reference'); + return ok + } + + return nok(code) + } +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State + */ +/** @type {Construct} */ + +const labelStartImage = { + name: 'labelStartImage', + tokenize: tokenizeLabelStartImage, + resolveAll: labelEnd.resolveAll +}; +/** @type {Tokenizer} */ + +function tokenizeLabelStartImage(effects, ok, nok) { + const self = this; + return start + /** @type {State} */ + + function start(code) { + effects.enter('labelImage'); + effects.enter('labelImageMarker'); + effects.consume(code); + effects.exit('labelImageMarker'); + return open + } + /** @type {State} */ + + function open(code) { + if (code === 91) { + effects.enter('labelMarker'); + effects.consume(code); + effects.exit('labelMarker'); + effects.exit('labelImage'); + return after + } + + return nok(code) + } + /** @type {State} */ + + function after(code) { + /* Hidden footnotes hook */ + + /* c8 ignore next 3 */ + return code === 94 && '_hiddenFootnoteSupport' in self.parser.constructs + ? nok(code) + : ok(code) + } +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State + */ +/** @type {Construct} */ + +const labelStartLink = { + name: 'labelStartLink', + tokenize: tokenizeLabelStartLink, + resolveAll: labelEnd.resolveAll +}; +/** @type {Tokenizer} */ + +function tokenizeLabelStartLink(effects, ok, nok) { + const self = this; + return start + /** @type {State} */ + + function start(code) { + effects.enter('labelLink'); + effects.enter('labelMarker'); + effects.consume(code); + effects.exit('labelMarker'); + effects.exit('labelLink'); + return after + } + /** @type {State} */ + + function after(code) { + /* Hidden footnotes hook. */ + + /* c8 ignore next 3 */ + return code === 94 && '_hiddenFootnoteSupport' in self.parser.constructs + ? nok(code) + : ok(code) + } +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State + */ + +/** @type {Construct} */ +const lineEnding = { + name: 'lineEnding', + tokenize: tokenizeLineEnding +}; +/** @type {Tokenizer} */ + +function tokenizeLineEnding(effects, ok) { + return start + /** @type {State} */ + + function start(code) { + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return factorySpace(effects, ok, 'linePrefix') + } +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State + * @typedef {import('micromark-util-types').Code} Code + */ + +/** @type {Construct} */ +const thematicBreak$1 = { + name: 'thematicBreak', + tokenize: tokenizeThematicBreak +}; +/** @type {Tokenizer} */ + +function tokenizeThematicBreak(effects, ok, nok) { + let size = 0; + /** @type {NonNullable} */ + + let marker; + return start + /** @type {State} */ + + function start(code) { + effects.enter('thematicBreak'); + marker = code; + return atBreak(code) + } + /** @type {State} */ + + function atBreak(code) { + if (code === marker) { + effects.enter('thematicBreakSequence'); + return sequence(code) + } + + if (markdownSpace(code)) { + return factorySpace(effects, atBreak, 'whitespace')(code) + } + + if (size < 3 || (code !== null && !markdownLineEnding(code))) { + return nok(code) + } + + effects.exit('thematicBreak'); + return ok(code) + } + /** @type {State} */ + + function sequence(code) { + if (code === marker) { + effects.consume(code); + size++; + return sequence + } + + effects.exit('thematicBreakSequence'); + return atBreak(code) + } +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext + * @typedef {import('micromark-util-types').Exiter} Exiter + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State + * @typedef {import('micromark-util-types').Code} Code + */ +/** @type {Construct} */ + +const list$1 = { + name: 'list', + tokenize: tokenizeListStart, + continuation: { + tokenize: tokenizeListContinuation + }, + exit: tokenizeListEnd +}; +/** @type {Construct} */ + +const listItemPrefixWhitespaceConstruct = { + tokenize: tokenizeListItemPrefixWhitespace, + partial: true +}; +/** @type {Construct} */ + +const indentConstruct = { + tokenize: tokenizeIndent, + partial: true +}; +/** + * @type {Tokenizer} + * @this {TokenizeContextWithState} + */ + +function tokenizeListStart(effects, ok, nok) { + const self = this; + const tail = self.events[self.events.length - 1]; + let initialSize = + tail && tail[1].type === 'linePrefix' + ? tail[2].sliceSerialize(tail[1], true).length + : 0; + let size = 0; + return start + /** @type {State} */ + + function start(code) { + const kind = + self.containerState.type || + (code === 42 || code === 43 || code === 45 + ? 'listUnordered' + : 'listOrdered'); + + if ( + kind === 'listUnordered' + ? !self.containerState.marker || code === self.containerState.marker + : asciiDigit(code) + ) { + if (!self.containerState.type) { + self.containerState.type = kind; + effects.enter(kind, { + _container: true + }); + } + + if (kind === 'listUnordered') { + effects.enter('listItemPrefix'); + return code === 42 || code === 45 + ? effects.check(thematicBreak$1, nok, atMarker)(code) + : atMarker(code) + } + + if (!self.interrupt || code === 49) { + effects.enter('listItemPrefix'); + effects.enter('listItemValue'); + return inside(code) + } + } + + return nok(code) + } + /** @type {State} */ + + function inside(code) { + if (asciiDigit(code) && ++size < 10) { + effects.consume(code); + return inside + } + + if ( + (!self.interrupt || size < 2) && + (self.containerState.marker + ? code === self.containerState.marker + : code === 41 || code === 46) + ) { + effects.exit('listItemValue'); + return atMarker(code) + } + + return nok(code) + } + /** + * @type {State} + **/ + + function atMarker(code) { + effects.enter('listItemMarker'); + effects.consume(code); + effects.exit('listItemMarker'); + self.containerState.marker = self.containerState.marker || code; + return effects.check( + blankLine, // Can’t be empty when interrupting. + self.interrupt ? nok : onBlank, + effects.attempt( + listItemPrefixWhitespaceConstruct, + endOfPrefix, + otherPrefix + ) + ) + } + /** @type {State} */ + + function onBlank(code) { + self.containerState.initialBlankLine = true; + initialSize++; + return endOfPrefix(code) + } + /** @type {State} */ + + function otherPrefix(code) { + if (markdownSpace(code)) { + effects.enter('listItemPrefixWhitespace'); + effects.consume(code); + effects.exit('listItemPrefixWhitespace'); + return endOfPrefix + } + + return nok(code) + } + /** @type {State} */ + + function endOfPrefix(code) { + self.containerState.size = + initialSize + + self.sliceSerialize(effects.exit('listItemPrefix'), true).length; + return ok(code) + } +} +/** + * @type {Tokenizer} + * @this {TokenizeContextWithState} + */ + +function tokenizeListContinuation(effects, ok, nok) { + const self = this; + self.containerState._closeFlow = undefined; + return effects.check(blankLine, onBlank, notBlank) + /** @type {State} */ + + function onBlank(code) { + self.containerState.furtherBlankLines = + self.containerState.furtherBlankLines || + self.containerState.initialBlankLine; // We have a blank line. + // Still, try to consume at most the items size. + + return factorySpace( + effects, + ok, + 'listItemIndent', + self.containerState.size + 1 + )(code) + } + /** @type {State} */ + + function notBlank(code) { + if (self.containerState.furtherBlankLines || !markdownSpace(code)) { + self.containerState.furtherBlankLines = undefined; + self.containerState.initialBlankLine = undefined; + return notInCurrentItem(code) + } + + self.containerState.furtherBlankLines = undefined; + self.containerState.initialBlankLine = undefined; + return effects.attempt(indentConstruct, ok, notInCurrentItem)(code) + } + /** @type {State} */ + + function notInCurrentItem(code) { + // While we do continue, we signal that the flow should be closed. + self.containerState._closeFlow = true; // As we’re closing flow, we’re no longer interrupting. + + self.interrupt = undefined; + return factorySpace( + effects, + effects.attempt(list$1, ok, nok), + 'linePrefix', + self.parser.constructs.disable.null.includes('codeIndented') + ? undefined + : 4 + )(code) + } +} +/** + * @type {Tokenizer} + * @this {TokenizeContextWithState} + */ + +function tokenizeIndent(effects, ok, nok) { + const self = this; + return factorySpace( + effects, + afterPrefix, + 'listItemIndent', + self.containerState.size + 1 + ) + /** @type {State} */ + + function afterPrefix(code) { + const tail = self.events[self.events.length - 1]; + return tail && + tail[1].type === 'listItemIndent' && + tail[2].sliceSerialize(tail[1], true).length === self.containerState.size + ? ok(code) + : nok(code) + } +} +/** + * @type {Exiter} + * @this {TokenizeContextWithState} + */ + +function tokenizeListEnd(effects) { + effects.exit(this.containerState.type); +} +/** + * @type {Tokenizer} + * @this {TokenizeContextWithState} + */ + +function tokenizeListItemPrefixWhitespace(effects, ok, nok) { + const self = this; + return factorySpace( + effects, + afterPrefix, + 'listItemPrefixWhitespace', + self.parser.constructs.disable.null.includes('codeIndented') + ? undefined + : 4 + 1 + ) + /** @type {State} */ + + function afterPrefix(code) { + const tail = self.events[self.events.length - 1]; + return !markdownSpace(code) && + tail && + tail[1].type === 'listItemPrefixWhitespace' + ? ok(code) + : nok(code) + } +} + +/** + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').Resolver} Resolver + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer + * @typedef {import('micromark-util-types').State} State + * @typedef {import('micromark-util-types').Code} Code + */ + +/** @type {Construct} */ +const setextUnderline = { + name: 'setextUnderline', + tokenize: tokenizeSetextUnderline, + resolveTo: resolveToSetextUnderline +}; +/** @type {Resolver} */ + +function resolveToSetextUnderline(events, context) { + let index = events.length; + /** @type {number|undefined} */ + + let content; + /** @type {number|undefined} */ + + let text; + /** @type {number|undefined} */ + + let definition; // Find the opening of the content. + // It’ll always exist: we don’t tokenize if it isn’t there. + + while (index--) { + if (events[index][0] === 'enter') { + if (events[index][1].type === 'content') { + content = index; + break + } + + if (events[index][1].type === 'paragraph') { + text = index; + } + } // Exit + else { + if (events[index][1].type === 'content') { + // Remove the content end (if needed we’ll add it later) + events.splice(index, 1); + } + + if (!definition && events[index][1].type === 'definition') { + definition = index; + } + } + } + + const heading = { + type: 'setextHeading', + start: Object.assign({}, events[text][1].start), + end: Object.assign({}, events[events.length - 1][1].end) + }; // Change the paragraph to setext heading text. + + events[text][1].type = 'setextHeadingText'; // If we have definitions in the content, we’ll keep on having content, + // but we need move it. + + if (definition) { + events.splice(text, 0, ['enter', heading, context]); + events.splice(definition + 1, 0, ['exit', events[content][1], context]); + events[content][1].end = Object.assign({}, events[definition][1].end); + } else { + events[content][1] = heading; + } // Add the heading exit at the end. + + events.push(['exit', heading, context]); + return events +} +/** @type {Tokenizer} */ + +function tokenizeSetextUnderline(effects, ok, nok) { + const self = this; + let index = self.events.length; + /** @type {NonNullable} */ + + let marker; + /** @type {boolean} */ + + let paragraph; // Find an opening. + + while (index--) { + // Skip enter/exit of line ending, line prefix, and content. + // We can now either have a definition or a paragraph. + if ( + self.events[index][1].type !== 'lineEnding' && + self.events[index][1].type !== 'linePrefix' && + self.events[index][1].type !== 'content' + ) { + paragraph = self.events[index][1].type === 'paragraph'; + break + } + } + + return start + /** @type {State} */ + + function start(code) { + if (!self.parser.lazy[self.now().line] && (self.interrupt || paragraph)) { + effects.enter('setextHeadingLine'); + effects.enter('setextHeadingLineSequence'); + marker = code; + return closingSequence(code) + } + + return nok(code) + } + /** @type {State} */ + + function closingSequence(code) { + if (code === marker) { + effects.consume(code); + return closingSequence + } + + effects.exit('setextHeadingLineSequence'); + return factorySpace(effects, closingSequenceEnd, 'lineSuffix')(code) + } + /** @type {State} */ + + function closingSequenceEnd(code) { + if (code === null || markdownLineEnding(code)) { + effects.exit('setextHeadingLine'); + return ok(code) + } + + return nok(code) + } +} + +/** + * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct + * @typedef {import('micromark-util-types').Initializer} Initializer + * @typedef {import('micromark-util-types').State} State + */ + +/** @type {InitialConstruct} */ +const flow$1 = { + tokenize: initializeFlow +}; +/** @type {Initializer} */ + +function initializeFlow(effects) { + const self = this; + const initial = effects.attempt( + // Try to parse a blank line. + blankLine, + atBlankEnding, // Try to parse initial flow (essentially, only code). + effects.attempt( + this.parser.constructs.flowInitial, + afterConstruct, + factorySpace( + effects, + effects.attempt( + this.parser.constructs.flow, + afterConstruct, + effects.attempt(content, afterConstruct) + ), + 'linePrefix' + ) + ) + ); + return initial + /** @type {State} */ + + function atBlankEnding(code) { + if (code === null) { + effects.consume(code); + return + } + + effects.enter('lineEndingBlank'); + effects.consume(code); + effects.exit('lineEndingBlank'); + self.currentConstruct = undefined; + return initial + } + /** @type {State} */ + + function afterConstruct(code) { + if (code === null) { + effects.consume(code); + return + } + + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + self.currentConstruct = undefined; + return initial + } +} + +/** + * @typedef {import('micromark-util-types').Resolver} Resolver + * @typedef {import('micromark-util-types').Initializer} Initializer + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct + * @typedef {import('micromark-util-types').State} State + * @typedef {import('micromark-util-types').Code} Code + */ +const resolver = { + resolveAll: createResolver() +}; +const string$1 = initializeFactory('string'); +const text$3 = initializeFactory('text'); +/** + * @param {'string'|'text'} field + * @returns {InitialConstruct} + */ + +function initializeFactory(field) { + return { + tokenize: initializeText, + resolveAll: createResolver( + field === 'text' ? resolveAllLineSuffixes : undefined + ) + } + /** @type {Initializer} */ + + function initializeText(effects) { + const self = this; + const constructs = this.parser.constructs[field]; + const text = effects.attempt(constructs, start, notText); + return start + /** @type {State} */ + + function start(code) { + return atBreak(code) ? text(code) : notText(code) + } + /** @type {State} */ + + function notText(code) { + if (code === null) { + effects.consume(code); + return + } + + effects.enter('data'); + effects.consume(code); + return data + } + /** @type {State} */ + + function data(code) { + if (atBreak(code)) { + effects.exit('data'); + return text(code) + } // Data. + + effects.consume(code); + return data + } + /** + * @param {Code} code + * @returns {boolean} + */ + + function atBreak(code) { + if (code === null) { + return true + } + + const list = constructs[code]; + let index = -1; + + if (list) { + while (++index < list.length) { + const item = list[index]; + + if (!item.previous || item.previous.call(self, self.previous)) { + return true + } + } + } + + return false + } + } +} +/** + * @param {Resolver} [extraResolver] + * @returns {Resolver} + */ + +function createResolver(extraResolver) { + return resolveAllText + /** @type {Resolver} */ + + function resolveAllText(events, context) { + let index = -1; + /** @type {number|undefined} */ + + let enter; // A rather boring computation (to merge adjacent `data` events) which + // improves mm performance by 29%. + + while (++index <= events.length) { + if (enter === undefined) { + if (events[index] && events[index][1].type === 'data') { + enter = index; + index++; + } + } else if (!events[index] || events[index][1].type !== 'data') { + // Don’t do anything if there is one data token. + if (index !== enter + 2) { + events[enter][1].end = events[index - 1][1].end; + events.splice(enter + 2, index - enter - 2); + index = enter + 2; + } + + enter = undefined; + } + } + + return extraResolver ? extraResolver(events, context) : events + } +} +/** + * A rather ugly set of instructions which again looks at chunks in the input + * stream. + * The reason to do this here is that it is *much* faster to parse in reverse. + * And that we can’t hook into `null` to split the line suffix before an EOF. + * To do: figure out if we can make this into a clean utility, or even in core. + * As it will be useful for GFMs literal autolink extension (and maybe even + * tables?) + * + * @type {Resolver} + */ + +function resolveAllLineSuffixes(events, context) { + let eventIndex = -1; + + while (++eventIndex <= events.length) { + if ( + (eventIndex === events.length || + events[eventIndex][1].type === 'lineEnding') && + events[eventIndex - 1][1].type === 'data' + ) { + const data = events[eventIndex - 1][1]; + const chunks = context.sliceStream(data); + let index = chunks.length; + let bufferIndex = -1; + let size = 0; + /** @type {boolean|undefined} */ + + let tabs; + + while (index--) { + const chunk = chunks[index]; + + if (typeof chunk === 'string') { + bufferIndex = chunk.length; + + while (chunk.charCodeAt(bufferIndex - 1) === 32) { + size++; + bufferIndex--; + } + + if (bufferIndex) break + bufferIndex = -1; + } // Number + else if (chunk === -2) { + tabs = true; + size++; + } else if (chunk === -1) ; else { + // Replacement character, exit. + index++; + break + } + } + + if (size) { + const token = { + type: + eventIndex === events.length || tabs || size < 2 + ? 'lineSuffix' + : 'hardBreakTrailing', + start: { + line: data.end.line, + column: data.end.column - size, + offset: data.end.offset - size, + _index: data.start._index + index, + _bufferIndex: index + ? bufferIndex + : data.start._bufferIndex + bufferIndex + }, + end: Object.assign({}, data.end) + }; + data.end = Object.assign({}, token.start); + + if (data.start.offset === data.end.offset) { + Object.assign(data, token); + } else { + events.splice( + eventIndex, + 0, + ['enter', token, context], + ['exit', token, context] + ); + eventIndex += 2; + } + } + + eventIndex++; + } + } + + return events +} + +/** + * @typedef {import('micromark-util-types').Code} Code + * @typedef {import('micromark-util-types').Chunk} Chunk + * @typedef {import('micromark-util-types').Point} Point + * @typedef {import('micromark-util-types').Token} Token + * @typedef {import('micromark-util-types').Effects} Effects + * @typedef {import('micromark-util-types').State} State + * @typedef {import('micromark-util-types').Construct} Construct + * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct + * @typedef {import('micromark-util-types').ConstructRecord} ConstructRecord + * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext + * @typedef {import('micromark-util-types').ParseContext} ParseContext + */ + +/** + * Create a tokenizer. + * Tokenizers deal with one type of data (e.g., containers, flow, text). + * The parser is the object dealing with it all. + * `initialize` works like other constructs, except that only its `tokenize` + * function is used, in which case it doesn’t receive an `ok` or `nok`. + * `from` can be given to set the point before the first character, although + * when further lines are indented, they must be set with `defineSkip`. + * + * @param {ParseContext} parser + * @param {InitialConstruct} initialize + * @param {Omit} [from] + * @returns {TokenizeContext} + */ +function createTokenizer(parser, initialize, from) { + /** @type {Point} */ + let point = Object.assign( + from + ? Object.assign({}, from) + : { + line: 1, + column: 1, + offset: 0 + }, + { + _index: 0, + _bufferIndex: -1 + } + ); + /** @type {Record} */ + + const columnStart = {}; + /** @type {Construct[]} */ + + const resolveAllConstructs = []; + /** @type {Chunk[]} */ + + let chunks = []; + /** @type {Token[]} */ + + let stack = []; + /** + * Tools used for tokenizing. + * + * @type {Effects} + */ + + const effects = { + consume, + enter, + exit, + attempt: constructFactory(onsuccessfulconstruct), + check: constructFactory(onsuccessfulcheck), + interrupt: constructFactory(onsuccessfulcheck, { + interrupt: true + }) + }; + /** + * State and tools for resolving and serializing. + * + * @type {TokenizeContext} + */ + + const context = { + previous: null, + code: null, + containerState: {}, + events: [], + parser, + sliceStream, + sliceSerialize, + now, + defineSkip, + write + }; + /** + * The state function. + * + * @type {State|void} + */ + + let state = initialize.tokenize.call(context, effects); + + if (initialize.resolveAll) { + resolveAllConstructs.push(initialize); + } + + return context + /** @type {TokenizeContext['write']} */ + + function write(slice) { + chunks = push(chunks, slice); + main(); // Exit if we’re not done, resolve might change stuff. + + if (chunks[chunks.length - 1] !== null) { + return [] + } + + addResult(initialize, 0); // Otherwise, resolve, and exit. + + context.events = resolveAll(resolveAllConstructs, context.events, context); + return context.events + } // + // Tools. + // + + /** @type {TokenizeContext['sliceSerialize']} */ + + function sliceSerialize(token, expandTabs) { + return serializeChunks(sliceStream(token), expandTabs) + } + /** @type {TokenizeContext['sliceStream']} */ + + function sliceStream(token) { + return sliceChunks(chunks, token) + } + /** @type {TokenizeContext['now']} */ + + function now() { + return Object.assign({}, point) + } + /** @type {TokenizeContext['defineSkip']} */ + + function defineSkip(value) { + columnStart[value.line] = value.column; + accountForPotentialSkip(); + } // + // State management. + // + + /** + * Main loop (note that `_index` and `_bufferIndex` in `point` are modified by + * `consume`). + * Here is where we walk through the chunks, which either include strings of + * several characters, or numerical character codes. + * The reason to do this in a loop instead of a call is so the stack can + * drain. + * + * @returns {void} + */ + + function main() { + /** @type {number} */ + let chunkIndex; + + while (point._index < chunks.length) { + const chunk = chunks[point._index]; // If we’re in a buffer chunk, loop through it. + + if (typeof chunk === 'string') { + chunkIndex = point._index; + + if (point._bufferIndex < 0) { + point._bufferIndex = 0; + } + + while ( + point._index === chunkIndex && + point._bufferIndex < chunk.length + ) { + go(chunk.charCodeAt(point._bufferIndex)); + } + } else { + go(chunk); + } + } + } + /** + * Deal with one code. + * + * @param {Code} code + * @returns {void} + */ + + function go(code) { + state = state(code); + } + /** @type {Effects['consume']} */ + + function consume(code) { + if (markdownLineEnding(code)) { + point.line++; + point.column = 1; + point.offset += code === -3 ? 2 : 1; + accountForPotentialSkip(); + } else if (code !== -1) { + point.column++; + point.offset++; + } // Not in a string chunk. + + if (point._bufferIndex < 0) { + point._index++; + } else { + point._bufferIndex++; // At end of string chunk. + // @ts-expect-error Points w/ non-negative `_bufferIndex` reference + // strings. + + if (point._bufferIndex === chunks[point._index].length) { + point._bufferIndex = -1; + point._index++; + } + } // Expose the previous character. + + context.previous = code; // Mark as consumed. + } + /** @type {Effects['enter']} */ + + function enter(type, fields) { + /** @type {Token} */ + // @ts-expect-error Patch instead of assign required fields to help GC. + const token = fields || {}; + token.type = type; + token.start = now(); + context.events.push(['enter', token, context]); + stack.push(token); + return token + } + /** @type {Effects['exit']} */ + + function exit(type) { + const token = stack.pop(); + token.end = now(); + context.events.push(['exit', token, context]); + return token + } + /** + * Use results. + * + * @type {ReturnHandle} + */ + + function onsuccessfulconstruct(construct, info) { + addResult(construct, info.from); + } + /** + * Discard results. + * + * @type {ReturnHandle} + */ + + function onsuccessfulcheck(_, info) { + info.restore(); + } + /** + * Factory to attempt/check/interrupt. + * + * @param {ReturnHandle} onreturn + * @param {Record} [fields] + */ + + function constructFactory(onreturn, fields) { + return hook + /** + * Handle either an object mapping codes to constructs, a list of + * constructs, or a single construct. + * + * @param {Construct|Construct[]|ConstructRecord} constructs + * @param {State} returnState + * @param {State} [bogusState] + * @returns {State} + */ + + function hook(constructs, returnState, bogusState) { + /** @type {Construct[]} */ + let listOfConstructs; + /** @type {number} */ + + let constructIndex; + /** @type {Construct} */ + + let currentConstruct; + /** @type {Info} */ + + let info; + return Array.isArray(constructs) + ? /* c8 ignore next 1 */ + handleListOfConstructs(constructs) + : 'tokenize' in constructs // @ts-expect-error Looks like a construct. + ? handleListOfConstructs([constructs]) + : handleMapOfConstructs(constructs) + /** + * Handle a list of construct. + * + * @param {ConstructRecord} map + * @returns {State} + */ + + function handleMapOfConstructs(map) { + return start + /** @type {State} */ + + function start(code) { + const def = code !== null && map[code]; + const all = code !== null && map.null; + const list = [ + // To do: add more extension tests. + + /* c8 ignore next 2 */ + ...(Array.isArray(def) ? def : def ? [def] : []), + ...(Array.isArray(all) ? all : all ? [all] : []) + ]; + return handleListOfConstructs(list)(code) + } + } + /** + * Handle a list of construct. + * + * @param {Construct[]} list + * @returns {State} + */ + + function handleListOfConstructs(list) { + listOfConstructs = list; + constructIndex = 0; + + if (list.length === 0) { + return bogusState + } + + return handleConstruct(list[constructIndex]) + } + /** + * Handle a single construct. + * + * @param {Construct} construct + * @returns {State} + */ + + function handleConstruct(construct) { + return start + /** @type {State} */ + + function start(code) { + // To do: not needed to store if there is no bogus state, probably? + // Currently doesn’t work because `inspect` in document does a check + // w/o a bogus, which doesn’t make sense. But it does seem to help perf + // by not storing. + info = store(); + currentConstruct = construct; + + if (!construct.partial) { + context.currentConstruct = construct; + } + + if ( + construct.name && + context.parser.constructs.disable.null.includes(construct.name) + ) { + return nok() + } + + return construct.tokenize.call( + // If we do have fields, create an object w/ `context` as its + // prototype. + // This allows a “live binding”, which is needed for `interrupt`. + fields ? Object.assign(Object.create(context), fields) : context, + effects, + ok, + nok + )(code) + } + } + /** @type {State} */ + + function ok(code) { + onreturn(currentConstruct, info); + return returnState + } + /** @type {State} */ + + function nok(code) { + info.restore(); + + if (++constructIndex < listOfConstructs.length) { + return handleConstruct(listOfConstructs[constructIndex]) + } + + return bogusState + } + } + } + /** + * @param {Construct} construct + * @param {number} from + * @returns {void} + */ + + function addResult(construct, from) { + if (construct.resolveAll && !resolveAllConstructs.includes(construct)) { + resolveAllConstructs.push(construct); + } + + if (construct.resolve) { + splice( + context.events, + from, + context.events.length - from, + construct.resolve(context.events.slice(from), context) + ); + } + + if (construct.resolveTo) { + context.events = construct.resolveTo(context.events, context); + } + } + /** + * Store state. + * + * @returns {Info} + */ + + function store() { + const startPoint = now(); + const startPrevious = context.previous; + const startCurrentConstruct = context.currentConstruct; + const startEventsIndex = context.events.length; + const startStack = Array.from(stack); + return { + restore, + from: startEventsIndex + } + /** + * Restore state. + * + * @returns {void} + */ + + function restore() { + point = startPoint; + context.previous = startPrevious; + context.currentConstruct = startCurrentConstruct; + context.events.length = startEventsIndex; + stack = startStack; + accountForPotentialSkip(); + } + } + /** + * Move the current point a bit forward in the line when it’s on a column + * skip. + * + * @returns {void} + */ + + function accountForPotentialSkip() { + if (point.line in columnStart && point.column < 2) { + point.column = columnStart[point.line]; + point.offset += columnStart[point.line] - 1; + } + } +} +/** + * Get the chunks from a slice of chunks in the range of a token. + * + * @param {Chunk[]} chunks + * @param {Pick} token + * @returns {Chunk[]} + */ + +function sliceChunks(chunks, token) { + const startIndex = token.start._index; + const startBufferIndex = token.start._bufferIndex; + const endIndex = token.end._index; + const endBufferIndex = token.end._bufferIndex; + /** @type {Chunk[]} */ + + let view; + + if (startIndex === endIndex) { + // @ts-expect-error `_bufferIndex` is used on string chunks. + view = [chunks[startIndex].slice(startBufferIndex, endBufferIndex)]; + } else { + view = chunks.slice(startIndex, endIndex); + + if (startBufferIndex > -1) { + // @ts-expect-error `_bufferIndex` is used on string chunks. + view[0] = view[0].slice(startBufferIndex); + } + + if (endBufferIndex > 0) { + // @ts-expect-error `_bufferIndex` is used on string chunks. + view.push(chunks[endIndex].slice(0, endBufferIndex)); + } + } + + return view +} +/** + * Get the string value of a slice of chunks. + * + * @param {Chunk[]} chunks + * @param {boolean} [expandTabs=false] + * @returns {string} + */ + +function serializeChunks(chunks, expandTabs) { + let index = -1; + /** @type {string[]} */ + + const result = []; + /** @type {boolean|undefined} */ + + let atTab; + + while (++index < chunks.length) { + const chunk = chunks[index]; + /** @type {string} */ + + let value; + + if (typeof chunk === 'string') { + value = chunk; + } else + switch (chunk) { + case -5: { + value = '\r'; + break + } + + case -4: { + value = '\n'; + break + } + + case -3: { + value = '\r' + '\n'; + break + } + + case -2: { + value = expandTabs ? ' ' : '\t'; + break + } + + case -1: { + if (!expandTabs && atTab) continue + value = ' '; + break + } + + default: { + // Currently only replacement character. + value = String.fromCharCode(chunk); + } + } + + atTab = chunk === -2; + result.push(value); + } + + return result.join('') +} + +/** + * @typedef {import('micromark-util-types').Extension} Extension + */ +/** @type {Extension['document']} */ + +const document = { + [42]: list$1, + [43]: list$1, + [45]: list$1, + [48]: list$1, + [49]: list$1, + [50]: list$1, + [51]: list$1, + [52]: list$1, + [53]: list$1, + [54]: list$1, + [55]: list$1, + [56]: list$1, + [57]: list$1, + [62]: blockQuote +}; +/** @type {Extension['contentInitial']} */ + +const contentInitial = { + [91]: definition$1 +}; +/** @type {Extension['flowInitial']} */ + +const flowInitial = { + [-2]: codeIndented, + [-1]: codeIndented, + [32]: codeIndented +}; +/** @type {Extension['flow']} */ + +const flow = { + [35]: headingAtx, + [42]: thematicBreak$1, + [45]: [setextUnderline, thematicBreak$1], + [60]: htmlFlow, + [61]: setextUnderline, + [95]: thematicBreak$1, + [96]: codeFenced, + [126]: codeFenced +}; +/** @type {Extension['string']} */ + +const string = { + [38]: characterReference, + [92]: characterEscape +}; +/** @type {Extension['text']} */ + +const text$2 = { + [-5]: lineEnding, + [-4]: lineEnding, + [-3]: lineEnding, + [33]: labelStartImage, + [38]: characterReference, + [42]: attention, + [60]: [autolink, htmlText], + [91]: labelStartLink, + [92]: [hardBreakEscape, characterEscape], + [93]: labelEnd, + [95]: attention, + [96]: codeText +}; +/** @type {Extension['insideSpan']} */ + +const insideSpan = { + null: [attention, resolver] +}; +/** @type {Extension['attentionMarkers']} */ + +const attentionMarkers = { + null: [42, 95] +}; +/** @type {Extension['disable']} */ + +const disable = { + null: [] +}; + +var defaultConstructs = /*#__PURE__*/Object.freeze({ + __proto__: null, + document: document, + contentInitial: contentInitial, + flowInitial: flowInitial, + flow: flow, + string: string, + text: text$2, + insideSpan: insideSpan, + attentionMarkers: attentionMarkers, + disable: disable +}); + +/** + * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct + * @typedef {import('micromark-util-types').FullNormalizedExtension} FullNormalizedExtension + * @typedef {import('micromark-util-types').ParseOptions} ParseOptions + * @typedef {import('micromark-util-types').ParseContext} ParseContext + * @typedef {import('micromark-util-types').Create} Create + */ +/** + * @param {ParseOptions} [options] + * @returns {ParseContext} + */ + +function parse$1(options = {}) { + /** @type {FullNormalizedExtension} */ + // @ts-expect-error `defaultConstructs` is full, so the result will be too. + const constructs = combineExtensions( + // @ts-expect-error Same as above. + [defaultConstructs].concat(options.extensions || []) + ); + /** @type {ParseContext} */ + + const parser = { + defined: [], + lazy: {}, + constructs, + content: create(content$1), + document: create(document$1), + flow: create(flow$1), + string: create(string$1), + text: create(text$3) + }; + return parser + /** + * @param {InitialConstruct} initial + */ + + function create(initial) { + return creator + /** @type {Create} */ + + function creator(from) { + return createTokenizer(parser, initial, from) + } + } +} + +/** + * @typedef {import('micromark-util-types').Encoding} Encoding + * @typedef {import('micromark-util-types').Value} Value + * @typedef {import('micromark-util-types').Chunk} Chunk + * @typedef {import('micromark-util-types').Code} Code + */ + +/** + * @callback Preprocessor + * @param {Value} value + * @param {Encoding} [encoding] + * @param {boolean} [end=false] + * @returns {Chunk[]} + */ +const search = /[\0\t\n\r]/g; +/** + * @returns {Preprocessor} + */ + +function preprocess() { + let column = 1; + let buffer = ''; + /** @type {boolean|undefined} */ + + let start = true; + /** @type {boolean|undefined} */ + + let atCarriageReturn; + return preprocessor + /** @type {Preprocessor} */ + + function preprocessor(value, encoding, end) { + /** @type {Chunk[]} */ + const chunks = []; + /** @type {RegExpMatchArray|null} */ + + let match; + /** @type {number} */ + + let next; + /** @type {number} */ + + let startPosition; + /** @type {number} */ + + let endPosition; + /** @type {Code} */ + + let code; // @ts-expect-error `Buffer` does allow an encoding. + + value = buffer + value.toString(encoding); + startPosition = 0; + buffer = ''; + + if (start) { + if (value.charCodeAt(0) === 65279) { + startPosition++; + } + + start = undefined; + } + + while (startPosition < value.length) { + search.lastIndex = startPosition; + match = search.exec(value); + endPosition = + match && match.index !== undefined ? match.index : value.length; + code = value.charCodeAt(endPosition); + + if (!match) { + buffer = value.slice(startPosition); + break + } + + if (code === 10 && startPosition === endPosition && atCarriageReturn) { + chunks.push(-3); + atCarriageReturn = undefined; + } else { + if (atCarriageReturn) { + chunks.push(-5); + atCarriageReturn = undefined; + } + + if (startPosition < endPosition) { + chunks.push(value.slice(startPosition, endPosition)); + column += endPosition - startPosition; + } + + switch (code) { + case 0: { + chunks.push(65533); + column++; + break + } + + case 9: { + next = Math.ceil(column / 4) * 4; + chunks.push(-2); + + while (column++ < next) chunks.push(-1); + + break + } + + case 10: { + chunks.push(-4); + column = 1; + break + } + + default: { + atCarriageReturn = true; + column = 1; + } + } + } + + startPosition = endPosition + 1; + } + + if (end) { + if (atCarriageReturn) chunks.push(-5); + if (buffer) chunks.push(buffer); + chunks.push(null); + } + + return chunks + } +} + +/** + * @typedef {import('micromark-util-types').Event} Event + */ +/** + * @param {Event[]} events + * @returns {Event[]} + */ + +function postprocess(events) { + while (!subtokenize(events)) { + // Empty + } + + return events +} + +/** + * Turn the number (in string form as either hexa- or plain decimal) coming from + * a numeric character reference into a character. + * + * @param {string} value + * Value to decode. + * @param {number} base + * Numeric base. + * @returns {string} + */ +function decodeNumericCharacterReference(value, base) { + const code = Number.parseInt(value, base); + + if ( + // C0 except for HT, LF, FF, CR, space + code < 9 || + code === 11 || + (code > 13 && code < 32) || // Control character (DEL) of the basic block and C1 controls. + (code > 126 && code < 160) || // Lone high surrogates and low surrogates. + (code > 55295 && code < 57344) || // Noncharacters. + (code > 64975 && code < 65008) || + (code & 65535) === 65535 || + (code & 65535) === 65534 || // Out of range + code > 1114111 + ) { + return '\uFFFD' + } + + return String.fromCharCode(code) +} + +const characterEscapeOrReference = + /\\([!-/:-@[-`{-~])|&(#(?:\d{1,7}|x[\da-f]{1,6})|[\da-z]{1,31});/gi; +/** + * Utility to decode markdown strings (which occur in places such as fenced + * code info strings, destinations, labels, and titles). + * The “string” content type allows character escapes and -references. + * This decodes those. + * + * @param {string} value + * @returns {string} + */ + +function decodeString(value) { + return value.replace(characterEscapeOrReference, decode) +} +/** + * @param {string} $0 + * @param {string} $1 + * @param {string} $2 + * @returns {string} + */ + +function decode($0, $1, $2) { + if ($1) { + // Escape. + return $1 + } // Reference. + + const head = $2.charCodeAt(0); + + if (head === 35) { + const head = $2.charCodeAt(1); + const hex = head === 120 || head === 88; + return decodeNumericCharacterReference($2.slice(hex ? 2 : 1), hex ? 16 : 10) + } + + return decodeEntity($2) || $0 +} + +/** + * @typedef {import('micromark-util-types').Encoding} Encoding + * @typedef {import('micromark-util-types').Event} Event + * @typedef {import('micromark-util-types').ParseOptions} ParseOptions + * @typedef {import('micromark-util-types').Token} Token + * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext + * @typedef {import('micromark-util-types').Value} Value + * @typedef {import('unist').Parent} UnistParent + * @typedef {import('unist').Point} Point + * @typedef {import('mdast').PhrasingContent} PhrasingContent + * @typedef {import('mdast').Content} Content + * @typedef {Root|Content} Node + * @typedef {Extract} Parent + * @typedef {import('mdast').Break} Break + * @typedef {import('mdast').Blockquote} Blockquote + * @typedef {import('mdast').Code} Code + * @typedef {import('mdast').Definition} Definition + * @typedef {import('mdast').Emphasis} Emphasis + * @typedef {import('mdast').Heading} Heading + * @typedef {import('mdast').HTML} HTML + * @typedef {import('mdast').Image} Image + * @typedef {import('mdast').ImageReference} ImageReference + * @typedef {import('mdast').InlineCode} InlineCode + * @typedef {import('mdast').Link} Link + * @typedef {import('mdast').LinkReference} LinkReference + * @typedef {import('mdast').List} List + * @typedef {import('mdast').ListItem} ListItem + * @typedef {import('mdast').Paragraph} Paragraph + * @typedef {import('mdast').Root} Root + * @typedef {import('mdast').Strong} Strong + * @typedef {import('mdast').Text} Text + * @typedef {import('mdast').ThematicBreak} ThematicBreak + * + * @typedef {UnistParent & {type: 'fragment', children: PhrasingContent[]}} Fragment + */ +const own$5 = {}.hasOwnProperty; +/** + * @param value Markdown to parse (`string` or `Buffer`). + * @param [encoding] Character encoding to understand `value` as when it’s a `Buffer` (`string`, default: `'utf8'`). + * @param [options] Configuration + */ + +const fromMarkdown = + /** + * @param {Value} value + * @param {Encoding} [encoding] + * @param {Options} [options] + * @returns {Root} + */ + function (value, encoding, options) { + if (typeof encoding !== 'string') { + options = encoding; + encoding = undefined; + } + + return compiler(options)( + postprocess( + parse$1(options).document().write(preprocess()(value, encoding, true)) + ) + ) + }; +/** + * Note this compiler only understand complete buffering, not streaming. + * + * @param {Options} [options] + */ + +function compiler(options = {}) { + /** @type {NormalizedExtension} */ + // @ts-expect-error: our base has all required fields, so the result will too. + const config = configure$1( + { + transforms: [], + canContainEols: [ + 'emphasis', + 'fragment', + 'heading', + 'paragraph', + 'strong' + ], + enter: { + autolink: opener(link), + autolinkProtocol: onenterdata, + autolinkEmail: onenterdata, + atxHeading: opener(heading), + blockQuote: opener(blockQuote), + characterEscape: onenterdata, + characterReference: onenterdata, + codeFenced: opener(codeFlow), + codeFencedFenceInfo: buffer, + codeFencedFenceMeta: buffer, + codeIndented: opener(codeFlow, buffer), + codeText: opener(codeText, buffer), + codeTextData: onenterdata, + data: onenterdata, + codeFlowValue: onenterdata, + definition: opener(definition), + definitionDestinationString: buffer, + definitionLabelString: buffer, + definitionTitleString: buffer, + emphasis: opener(emphasis), + hardBreakEscape: opener(hardBreak), + hardBreakTrailing: opener(hardBreak), + htmlFlow: opener(html, buffer), + htmlFlowData: onenterdata, + htmlText: opener(html, buffer), + htmlTextData: onenterdata, + image: opener(image), + label: buffer, + link: opener(link), + listItem: opener(listItem), + listItemValue: onenterlistitemvalue, + listOrdered: opener(list, onenterlistordered), + listUnordered: opener(list), + paragraph: opener(paragraph), + reference: onenterreference, + referenceString: buffer, + resourceDestinationString: buffer, + resourceTitleString: buffer, + setextHeading: opener(heading), + strong: opener(strong), + thematicBreak: opener(thematicBreak) + }, + exit: { + atxHeading: closer(), + atxHeadingSequence: onexitatxheadingsequence, + autolink: closer(), + autolinkEmail: onexitautolinkemail, + autolinkProtocol: onexitautolinkprotocol, + blockQuote: closer(), + characterEscapeValue: onexitdata, + characterReferenceMarkerHexadecimal: onexitcharacterreferencemarker, + characterReferenceMarkerNumeric: onexitcharacterreferencemarker, + characterReferenceValue: onexitcharacterreferencevalue, + codeFenced: closer(onexitcodefenced), + codeFencedFence: onexitcodefencedfence, + codeFencedFenceInfo: onexitcodefencedfenceinfo, + codeFencedFenceMeta: onexitcodefencedfencemeta, + codeFlowValue: onexitdata, + codeIndented: closer(onexitcodeindented), + codeText: closer(onexitcodetext), + codeTextData: onexitdata, + data: onexitdata, + definition: closer(), + definitionDestinationString: onexitdefinitiondestinationstring, + definitionLabelString: onexitdefinitionlabelstring, + definitionTitleString: onexitdefinitiontitlestring, + emphasis: closer(), + hardBreakEscape: closer(onexithardbreak), + hardBreakTrailing: closer(onexithardbreak), + htmlFlow: closer(onexithtmlflow), + htmlFlowData: onexitdata, + htmlText: closer(onexithtmltext), + htmlTextData: onexitdata, + image: closer(onexitimage), + label: onexitlabel, + labelText: onexitlabeltext, + lineEnding: onexitlineending, + link: closer(onexitlink), + listItem: closer(), + listOrdered: closer(), + listUnordered: closer(), + paragraph: closer(), + referenceString: onexitreferencestring, + resourceDestinationString: onexitresourcedestinationstring, + resourceTitleString: onexitresourcetitlestring, + resource: onexitresource, + setextHeading: closer(onexitsetextheading), + setextHeadingLineSequence: onexitsetextheadinglinesequence, + setextHeadingText: onexitsetextheadingtext, + strong: closer(), + thematicBreak: closer() + } + }, + options.mdastExtensions || [] + ); + /** @type {CompileData} */ + + const data = {}; + return compile + /** + * @param {Array.} events + * @returns {Root} + */ + + function compile(events) { + /** @type {Root} */ + let tree = { + type: 'root', + children: [] + }; + /** @type {CompileContext['stack']} */ + + const stack = [tree]; + /** @type {CompileContext['tokenStack']} */ + + const tokenStack = []; + /** @type {Array.} */ + + const listStack = []; + /** @type {Omit} */ + + const context = { + stack, + tokenStack, + config, + enter, + exit, + buffer, + resume, + setData, + getData + }; + let index = -1; + + while (++index < events.length) { + // We preprocess lists to add `listItem` tokens, and to infer whether + // items the list itself are spread out. + if ( + events[index][1].type === 'listOrdered' || + events[index][1].type === 'listUnordered' + ) { + if (events[index][0] === 'enter') { + listStack.push(index); + } else { + const tail = listStack.pop(); + index = prepareList(events, tail, index); + } + } + } + + index = -1; + + while (++index < events.length) { + const handler = config[events[index][0]]; + + if (own$5.call(handler, events[index][1].type)) { + handler[events[index][1].type].call( + Object.assign( + { + sliceSerialize: events[index][2].sliceSerialize + }, + context + ), + events[index][1] + ); + } + } + + if (tokenStack.length > 0) { + throw new Error( + 'Cannot close document, a token (`' + + tokenStack[tokenStack.length - 1].type + + '`, ' + + stringifyPosition({ + start: tokenStack[tokenStack.length - 1].start, + end: tokenStack[tokenStack.length - 1].end + }) + + ') is still open' + ) + } // Figure out `root` position. + + tree.position = { + start: point( + events.length > 0 + ? events[0][1].start + : { + line: 1, + column: 1, + offset: 0 + } + ), + end: point( + events.length > 0 + ? events[events.length - 2][1].end + : { + line: 1, + column: 1, + offset: 0 + } + ) + }; + index = -1; + + while (++index < config.transforms.length) { + tree = config.transforms[index](tree) || tree; + } + + return tree + } + /** + * @param {Array.} events + * @param {number} start + * @param {number} length + * @returns {number} + */ + + function prepareList(events, start, length) { + let index = start - 1; + let containerBalance = -1; + let listSpread = false; + /** @type {Token|undefined} */ + + let listItem; + /** @type {number|undefined} */ + + let lineIndex; + /** @type {number|undefined} */ + + let firstBlankLineIndex; + /** @type {boolean|undefined} */ + + let atMarker; + + while (++index <= length) { + const event = events[index]; + + if ( + event[1].type === 'listUnordered' || + event[1].type === 'listOrdered' || + event[1].type === 'blockQuote' + ) { + if (event[0] === 'enter') { + containerBalance++; + } else { + containerBalance--; + } + + atMarker = undefined; + } else if (event[1].type === 'lineEndingBlank') { + if (event[0] === 'enter') { + if ( + listItem && + !atMarker && + !containerBalance && + !firstBlankLineIndex + ) { + firstBlankLineIndex = index; + } + + atMarker = undefined; + } + } else if ( + event[1].type === 'linePrefix' || + event[1].type === 'listItemValue' || + event[1].type === 'listItemMarker' || + event[1].type === 'listItemPrefix' || + event[1].type === 'listItemPrefixWhitespace' + ) ; else { + atMarker = undefined; + } + + if ( + (!containerBalance && + event[0] === 'enter' && + event[1].type === 'listItemPrefix') || + (containerBalance === -1 && + event[0] === 'exit' && + (event[1].type === 'listUnordered' || + event[1].type === 'listOrdered')) + ) { + if (listItem) { + let tailIndex = index; + lineIndex = undefined; -/** - * @param {string} characters - * @returns {string|false} - */ -function decodeEntity(characters) { - return own$5.call(characterEntities, characters) - ? characterEntities[characters] - : false -} + while (tailIndex--) { + const tailEvent = events[tailIndex]; -/** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').Token} Token - * @typedef {import('micromark-util-types').State} State - * @typedef {import('micromark-util-types').Code} Code - */ + if ( + tailEvent[1].type === 'lineEnding' || + tailEvent[1].type === 'lineEndingBlank' + ) { + if (tailEvent[0] === 'exit') continue -/** @type {Construct} */ -const characterReference = { - name: 'characterReference', - tokenize: tokenizeCharacterReference -}; -/** @type {Tokenizer} */ + if (lineIndex) { + events[lineIndex][1].type = 'lineEndingBlank'; + listSpread = true; + } -function tokenizeCharacterReference(effects, ok, nok) { - const self = this; - let size = 0; - /** @type {number} */ + tailEvent[1].type = 'lineEnding'; + lineIndex = tailIndex; + } else if ( + tailEvent[1].type === 'linePrefix' || + tailEvent[1].type === 'blockQuotePrefix' || + tailEvent[1].type === 'blockQuotePrefixWhitespace' || + tailEvent[1].type === 'blockQuoteMarker' || + tailEvent[1].type === 'listItemIndent' + ) ; else { + break + } + } - let max; - /** @type {(code: Code) => code is number} */ + if ( + firstBlankLineIndex && + (!lineIndex || firstBlankLineIndex < lineIndex) + ) { + // @ts-expect-error Patched. + listItem._spread = true; + } // Fix position. - let test; - return start - /** @type {State} */ + listItem.end = Object.assign( + {}, + lineIndex ? events[lineIndex][1].start : event[1].end + ); + events.splice(lineIndex || index, 0, ['exit', listItem, event[2]]); + index++; + length++; + } // Create a new list item. - function start(code) { - effects.enter('characterReference'); - effects.enter('characterReferenceMarker'); - effects.consume(code); - effects.exit('characterReferenceMarker'); - return open + if (event[1].type === 'listItemPrefix') { + listItem = { + type: 'listItem', + // @ts-expect-error Patched + _spread: false, + start: Object.assign({}, event[1].start) + }; // @ts-expect-error: `listItem` is most definitely defined, TS... + + events.splice(index, 0, ['enter', listItem, event[2]]); + index++; + length++; + firstBlankLineIndex = undefined; + atMarker = true; + } + } + } // @ts-expect-error Patched. + + events[start][1]._spread = listSpread; + return length } - /** @type {State} */ + /** + * @type {CompileContext['setData']} + * @param [value] + */ - function open(code) { - if (code === 35) { - effects.enter('characterReferenceMarkerNumeric'); - effects.consume(code); - effects.exit('characterReferenceMarkerNumeric'); - return numeric + function setData(key, value) { + data[key] = value; + } + /** + * @type {CompileContext['getData']} + * @template {string} K + * @param {K} key + * @returns {CompileData[K]} + */ + + function getData(key) { + return data[key] + } + /** + * @param {Point} d + * @returns {Point} + */ + + function point(d) { + return { + line: d.line, + column: d.column, + offset: d.offset } + } + /** + * @param {(token: Token) => Node} create + * @param {Handle} [and] + * @returns {Handle} + */ - effects.enter('characterReferenceValue'); - max = 31; - test = asciiAlphanumeric; - return value(code) + function opener(create, and) { + return open + /** + * @this {CompileContext} + * @param {Token} token + * @returns {void} + */ + + function open(token) { + enter.call(this, create(token), token); + if (and) and.call(this, token); + } } - /** @type {State} */ + /** @type {CompileContext['buffer']} */ - function numeric(code) { - if (code === 88 || code === 120) { - effects.enter('characterReferenceMarkerHexadecimal'); - effects.consume(code); - effects.exit('characterReferenceMarkerHexadecimal'); - effects.enter('characterReferenceValue'); - max = 6; - test = asciiHexDigit; - return value + function buffer() { + this.stack.push({ + type: 'fragment', + children: [] + }); + } + /** + * @type {CompileContext['enter']} + * @template {Node} N + * @this {CompileContext} + * @param {N} node + * @param {Token} token + * @returns {N} + */ + + function enter(node, token) { + const parent = this.stack[this.stack.length - 1]; + // @ts-expect-error: Assume `Node` can exist as a child of `parent`. + parent.children.push(node); + this.stack.push(node); + this.tokenStack.push(token); // @ts-expect-error: `end` will be patched later. + + node.position = { + start: point(token.start) + }; + return node + } + /** + * @param {Handle} [and] + * @returns {Handle} + */ + + function closer(and) { + return close + /** + * @this {CompileContext} + * @param {Token} token + * @returns {void} + */ + + function close(token) { + if (and) and.call(this, token); + exit.call(this, token); } + } + /** @type {CompileContext['exit']} */ - effects.enter('characterReferenceValue'); - max = 7; - test = asciiDigit; - return value(code) + function exit(token) { + const node = this.stack.pop(); + const open = this.tokenStack.pop(); + + if (!open) { + throw new Error( + 'Cannot close `' + + token.type + + '` (' + + stringifyPosition({ + start: token.start, + end: token.end + }) + + '): it’s not open' + ) + } else if (open.type !== token.type) { + throw new Error( + 'Cannot close `' + + token.type + + '` (' + + stringifyPosition({ + start: token.start, + end: token.end + }) + + '): a different token (`' + + open.type + + '`, ' + + stringifyPosition({ + start: open.start, + end: open.end + }) + + ') is open' + ) + } + + node.position.end = point(token.end); + return node } - /** @type {State} */ + /** + * @this {CompileContext} + * @returns {string} + */ - function value(code) { - /** @type {Token} */ - let token; + function resume() { + return toString(this.stack.pop()) + } // + // Handlers. + // - if (code === 59 && size) { - token = effects.exit('characterReferenceValue'); + /** @type {Handle} */ - if ( - test === asciiAlphanumeric && - !decodeEntity(self.sliceSerialize(token)) - ) { - return nok(code) - } + function onenterlistordered() { + setData('expectingFirstListItemValue', true); + } + /** @type {Handle} */ - effects.enter('characterReferenceMarker'); - effects.consume(code); - effects.exit('characterReferenceMarker'); - effects.exit('characterReference'); - return ok + function onenterlistitemvalue(token) { + if (getData('expectingFirstListItemValue')) { + const ancestor = this.stack[this.stack.length - 2]; + ancestor.start = Number.parseInt(this.sliceSerialize(token), 10); + setData('expectingFirstListItemValue'); } + } + /** @type {Handle} */ - if (test(code) && size++ < max) { - effects.consume(code); - return value + function onexitcodefencedfenceinfo() { + const data = this.resume(); + const node = this.stack[this.stack.length - 1]; + node.lang = data; + } + /** @type {Handle} */ + + function onexitcodefencedfencemeta() { + const data = this.resume(); + const node = this.stack[this.stack.length - 1]; + node.meta = data; + } + /** @type {Handle} */ + + function onexitcodefencedfence() { + // Exit if this is the closing fence. + if (getData('flowCodeInside')) return + this.buffer(); + setData('flowCodeInside', true); + } + /** @type {Handle} */ + + function onexitcodefenced() { + const data = this.resume(); + const node = this.stack[this.stack.length - 1]; + node.value = data.replace(/^(\r?\n|\r)|(\r?\n|\r)$/g, ''); + setData('flowCodeInside'); + } + /** @type {Handle} */ + + function onexitcodeindented() { + const data = this.resume(); + const node = this.stack[this.stack.length - 1]; + node.value = data.replace(/(\r?\n|\r)$/g, ''); + } + /** @type {Handle} */ + + function onexitdefinitionlabelstring(token) { + // Discard label, use the source content instead. + const label = this.resume(); + const node = this.stack[this.stack.length - 1]; + node.label = label; + node.identifier = normalizeIdentifier( + this.sliceSerialize(token) + ).toLowerCase(); + } + /** @type {Handle} */ + + function onexitdefinitiontitlestring() { + const data = this.resume(); + const node = this.stack[this.stack.length - 1]; + node.title = data; + } + /** @type {Handle} */ + + function onexitdefinitiondestinationstring() { + const data = this.resume(); + const node = this.stack[this.stack.length - 1]; + node.url = data; + } + /** @type {Handle} */ + + function onexitatxheadingsequence(token) { + const node = this.stack[this.stack.length - 1]; + + if (!node.depth) { + const depth = this.sliceSerialize(token).length; + node.depth = depth; } + } + /** @type {Handle} */ - return nok(code) + function onexitsetextheadingtext() { + setData('setextHeadingSlurpLineEnding', true); } -} + /** @type {Handle} */ -/** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State - * @typedef {import('micromark-util-types').Code} Code - */ + function onexitsetextheadinglinesequence(token) { + const node = this.stack[this.stack.length - 1]; + node.depth = this.sliceSerialize(token).charCodeAt(0) === 61 ? 1 : 2; + } + /** @type {Handle} */ -/** @type {Construct} */ -const codeFenced = { - name: 'codeFenced', - tokenize: tokenizeCodeFenced, - concrete: true -}; -/** @type {Tokenizer} */ + function onexitsetextheading() { + setData('setextHeadingSlurpLineEnding'); + } + /** @type {Handle} */ -function tokenizeCodeFenced(effects, ok, nok) { - const self = this; - /** @type {Construct} */ + function onenterdata(token) { + const parent = this.stack[this.stack.length - 1]; + /** @type {Node} */ - const closingFenceConstruct = { - tokenize: tokenizeClosingFence, - partial: true - }; - /** @type {Construct} */ + let tail = parent.children[parent.children.length - 1]; - const nonLazyLine = { - tokenize: tokenizeNonLazyLine, - partial: true - }; - const tail = this.events[this.events.length - 1]; - const initialPrefix = - tail && tail[1].type === 'linePrefix' - ? tail[2].sliceSerialize(tail[1], true).length - : 0; - let sizeOpen = 0; - /** @type {NonNullable} */ + if (!tail || tail.type !== 'text') { + // Add a new text node. + tail = text(); // @ts-expect-error: we’ll add `end` later. - let marker; - return start - /** @type {State} */ + tail.position = { + start: point(token.start) + }; // @ts-expect-error: Assume `parent` accepts `text`. - function start(code) { - effects.enter('codeFenced'); - effects.enter('codeFencedFence'); - effects.enter('codeFencedFenceSequence'); - marker = code; - return sequenceOpen(code) + parent.children.push(tail); + } + + this.stack.push(tail); } - /** @type {State} */ + /** @type {Handle} */ - function sequenceOpen(code) { - if (code === marker) { - effects.consume(code); - sizeOpen++; - return sequenceOpen + function onexitdata(token) { + const tail = this.stack.pop(); + tail.value += this.sliceSerialize(token); + tail.position.end = point(token.end); + } + /** @type {Handle} */ + + function onexitlineending(token) { + const context = this.stack[this.stack.length - 1]; + + // If we’re at a hard break, include the line ending in there. + if (getData('atHardBreak')) { + const tail = context.children[context.children.length - 1]; + tail.position.end = point(token.end); + setData('atHardBreak'); + return } - effects.exit('codeFencedFenceSequence'); - return sizeOpen < 3 - ? nok(code) - : factorySpace(effects, infoOpen, 'whitespace')(code) + if ( + !getData('setextHeadingSlurpLineEnding') && + config.canContainEols.includes(context.type) + ) { + onenterdata.call(this, token); + onexitdata.call(this, token); + } } - /** @type {State} */ + /** @type {Handle} */ + + function onexithardbreak() { + setData('atHardBreak', true); + } + /** @type {Handle} */ + + function onexithtmlflow() { + const data = this.resume(); + const node = this.stack[this.stack.length - 1]; + node.value = data; + } + /** @type {Handle} */ + + function onexithtmltext() { + const data = this.resume(); + const node = this.stack[this.stack.length - 1]; + node.value = data; + } + /** @type {Handle} */ + + function onexitcodetext() { + const data = this.resume(); + const node = this.stack[this.stack.length - 1]; + node.value = data; + } + /** @type {Handle} */ + + function onexitlink() { + const context = this.stack[this.stack.length - 1]; // To do: clean. + + if (getData('inReference')) { + context.type += 'Reference'; // @ts-expect-error: mutate. - function infoOpen(code) { - if (code === null || markdownLineEnding(code)) { - return openAfter(code) - } + context.referenceType = getData('referenceType') || 'shortcut'; // @ts-expect-error: mutate. - effects.enter('codeFencedFenceInfo'); - effects.enter('chunkString', { - contentType: 'string' - }); - return info(code) - } - /** @type {State} */ + delete context.url; + delete context.title; + } else { + // @ts-expect-error: mutate. + delete context.identifier; // @ts-expect-error: mutate. - function info(code) { - if (code === null || markdownLineEndingOrSpace(code)) { - effects.exit('chunkString'); - effects.exit('codeFencedFenceInfo'); - return factorySpace(effects, infoAfter, 'whitespace')(code) + delete context.label; } - if (code === 96 && code === marker) return nok(code) - effects.consume(code); - return info + setData('referenceType'); } - /** @type {State} */ + /** @type {Handle} */ - function infoAfter(code) { - if (code === null || markdownLineEnding(code)) { - return openAfter(code) - } + function onexitimage() { + const context = this.stack[this.stack.length - 1]; // To do: clean. - effects.enter('codeFencedFenceMeta'); - effects.enter('chunkString', { - contentType: 'string' - }); - return meta(code) - } - /** @type {State} */ + if (getData('inReference')) { + context.type += 'Reference'; // @ts-expect-error: mutate. - function meta(code) { - if (code === null || markdownLineEnding(code)) { - effects.exit('chunkString'); - effects.exit('codeFencedFenceMeta'); - return openAfter(code) + context.referenceType = getData('referenceType') || 'shortcut'; // @ts-expect-error: mutate. + + delete context.url; + delete context.title; + } else { + // @ts-expect-error: mutate. + delete context.identifier; // @ts-expect-error: mutate. + + delete context.label; } - if (code === 96 && code === marker) return nok(code) - effects.consume(code); - return meta + setData('referenceType'); } - /** @type {State} */ + /** @type {Handle} */ - function openAfter(code) { - effects.exit('codeFencedFence'); - return self.interrupt ? ok(code) : contentStart(code) + function onexitlabeltext(token) { + const ancestor = this.stack[this.stack.length - 2]; + const string = this.sliceSerialize(token); + ancestor.label = decodeString(string); + ancestor.identifier = normalizeIdentifier(string).toLowerCase(); } - /** @type {State} */ - - function contentStart(code) { - if (code === null) { - return after(code) - } + /** @type {Handle} */ - if (markdownLineEnding(code)) { - return effects.attempt( - nonLazyLine, - effects.attempt( - closingFenceConstruct, - after, - initialPrefix - ? factorySpace( - effects, - contentStart, - 'linePrefix', - initialPrefix + 1 - ) - : contentStart - ), - after - )(code) - } + function onexitlabel() { + const fragment = this.stack[this.stack.length - 1]; + const value = this.resume(); + const node = this.stack[this.stack.length - 1]; // Assume a reference. - effects.enter('codeFlowValue'); - return contentContinue(code) - } - /** @type {State} */ + setData('inReference', true); - function contentContinue(code) { - if (code === null || markdownLineEnding(code)) { - effects.exit('codeFlowValue'); - return contentStart(code) + if (node.type === 'link') { + // @ts-expect-error: Assume static phrasing content. + node.children = fragment.children; + } else { + node.alt = value; } + } + /** @type {Handle} */ - effects.consume(code); - return contentContinue + function onexitresourcedestinationstring() { + const data = this.resume(); + const node = this.stack[this.stack.length - 1]; + node.url = data; } - /** @type {State} */ + /** @type {Handle} */ - function after(code) { - effects.exit('codeFenced'); - return ok(code) + function onexitresourcetitlestring() { + const data = this.resume(); + const node = this.stack[this.stack.length - 1]; + node.title = data; } - /** @type {Tokenizer} */ + /** @type {Handle} */ - function tokenizeNonLazyLine(effects, ok, nok) { - const self = this; - return start - /** @type {State} */ + function onexitresource() { + setData('inReference'); + } + /** @type {Handle} */ - function start(code) { - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - return lineStart - } - /** @type {State} */ + function onenterreference() { + setData('referenceType', 'collapsed'); + } + /** @type {Handle} */ - function lineStart(code) { - return self.parser.lazy[self.now().line] ? nok(code) : ok(code) - } + function onexitreferencestring(token) { + const label = this.resume(); + const node = this.stack[this.stack.length - 1]; + node.label = label; + node.identifier = normalizeIdentifier( + this.sliceSerialize(token) + ).toLowerCase(); + setData('referenceType', 'full'); } - /** @type {Tokenizer} */ + /** @type {Handle} */ - function tokenizeClosingFence(effects, ok, nok) { - let size = 0; - return factorySpace( - effects, - closingSequenceStart, - 'linePrefix', - this.parser.constructs.disable.null.includes('codeIndented') - ? undefined - : 4 - ) - /** @type {State} */ + function onexitcharacterreferencemarker(token) { + setData('characterReferenceType', token.type); + } + /** @type {Handle} */ - function closingSequenceStart(code) { - effects.enter('codeFencedFence'); - effects.enter('codeFencedFenceSequence'); - return closingSequence(code) - } - /** @type {State} */ + function onexitcharacterreferencevalue(token) { + const data = this.sliceSerialize(token); + const type = getData('characterReferenceType'); + /** @type {string} */ - function closingSequence(code) { - if (code === marker) { - effects.consume(code); - size++; - return closingSequence - } + let value; - if (size < sizeOpen) return nok(code) - effects.exit('codeFencedFenceSequence'); - return factorySpace(effects, closingSequenceEnd, 'whitespace')(code) + if (type) { + value = decodeNumericCharacterReference( + data, + type === 'characterReferenceMarkerNumeric' ? 10 : 16 + ); + setData('characterReferenceType'); + } else { + // @ts-expect-error `decodeEntity` can return false for invalid named + // character references, but everything we’ve tokenized is valid. + value = decodeEntity(data); } - /** @type {State} */ - function closingSequenceEnd(code) { - if (code === null || markdownLineEnding(code)) { - effects.exit('codeFencedFence'); - return ok(code) - } + const tail = this.stack.pop(); + tail.value += value; + tail.position.end = point(token.end); + } + /** @type {Handle} */ - return nok(code) - } + function onexitautolinkprotocol(token) { + onexitdata.call(this, token); + const node = this.stack[this.stack.length - 1]; + node.url = this.sliceSerialize(token); } -} + /** @type {Handle} */ -/** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').Resolver} Resolver - * @typedef {import('micromark-util-types').Token} Token - * @typedef {import('micromark-util-types').State} State - */ + function onexitautolinkemail(token) { + onexitdata.call(this, token); + const node = this.stack[this.stack.length - 1]; + node.url = 'mailto:' + this.sliceSerialize(token); + } // + // Creaters. + // -/** @type {Construct} */ -const codeIndented = { - name: 'codeIndented', - tokenize: tokenizeCodeIndented -}; -/** @type {Construct} */ + /** @returns {Blockquote} */ -const indentedContent = { - tokenize: tokenizeIndentedContent, - partial: true -}; -/** @type {Tokenizer} */ + function blockQuote() { + return { + type: 'blockquote', + children: [] + } + } + /** @returns {Code} */ -function tokenizeCodeIndented(effects, ok, nok) { - const self = this; - return start - /** @type {State} */ + function codeFlow() { + return { + type: 'code', + lang: null, + meta: null, + value: '' + } + } + /** @returns {InlineCode} */ - function start(code) { - effects.enter('codeIndented'); - return factorySpace(effects, afterStartPrefix, 'linePrefix', 4 + 1)(code) + function codeText() { + return { + type: 'inlineCode', + value: '' + } } - /** @type {State} */ + /** @returns {Definition} */ - function afterStartPrefix(code) { - const tail = self.events[self.events.length - 1]; - return tail && - tail[1].type === 'linePrefix' && - tail[2].sliceSerialize(tail[1], true).length >= 4 - ? afterPrefix(code) - : nok(code) + function definition() { + return { + type: 'definition', + identifier: '', + label: null, + title: null, + url: '' + } } - /** @type {State} */ + /** @returns {Emphasis} */ - function afterPrefix(code) { - if (code === null) { - return after(code) + function emphasis() { + return { + type: 'emphasis', + children: [] } + } + /** @returns {Heading} */ - if (markdownLineEnding(code)) { - return effects.attempt(indentedContent, afterPrefix, after)(code) + function heading() { + // @ts-expect-error `depth` will be set later. + return { + type: 'heading', + depth: undefined, + children: [] } + } + /** @returns {Break} */ - effects.enter('codeFlowValue'); - return content(code) + function hardBreak() { + return { + type: 'break' + } } - /** @type {State} */ + /** @returns {HTML} */ - function content(code) { - if (code === null || markdownLineEnding(code)) { - effects.exit('codeFlowValue'); - return afterPrefix(code) + function html() { + return { + type: 'html', + value: '' } + } + /** @returns {Image} */ - effects.consume(code); - return content + function image() { + return { + type: 'image', + title: null, + url: '', + alt: null + } } - /** @type {State} */ + /** @returns {Link} */ - function after(code) { - effects.exit('codeIndented'); - return ok(code) + function link() { + return { + type: 'link', + title: null, + url: '', + children: [] + } } -} -/** @type {Tokenizer} */ + /** + * @param {Token} token + * @returns {List} + */ -function tokenizeIndentedContent(effects, ok, nok) { - const self = this; - return start - /** @type {State} */ + function list(token) { + return { + type: 'list', + ordered: token.type === 'listOrdered', + start: null, + // @ts-expect-error Patched. + spread: token._spread, + children: [] + } + } + /** + * @param {Token} token + * @returns {ListItem} + */ - function start(code) { - // If this is a lazy line, it can’t be code. - if (self.parser.lazy[self.now().line]) { - return nok(code) + function listItem(token) { + return { + type: 'listItem', + // @ts-expect-error Patched. + spread: token._spread, + checked: null, + children: [] } + } + /** @returns {Paragraph} */ - if (markdownLineEnding(code)) { - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - return start + function paragraph() { + return { + type: 'paragraph', + children: [] } + } + /** @returns {Strong} */ - return factorySpace(effects, afterPrefix, 'linePrefix', 4 + 1)(code) + function strong() { + return { + type: 'strong', + children: [] + } } - /** @type {State} */ + /** @returns {Text} */ - function afterPrefix(code) { - const tail = self.events[self.events.length - 1]; - return tail && - tail[1].type === 'linePrefix' && - tail[2].sliceSerialize(tail[1], true).length >= 4 - ? ok(code) - : markdownLineEnding(code) - ? start(code) - : nok(code) + function text() { + return { + type: 'text', + value: '' + } } -} + /** @returns {ThematicBreak} */ + function thematicBreak() { + return { + type: 'thematicBreak' + } + } +} /** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Resolver} Resolver - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').Previous} Previous - * @typedef {import('micromark-util-types').Token} Token - * @typedef {import('micromark-util-types').State} State + * @param {Extension} combined + * @param {Array.>} extensions + * @returns {Extension} */ -/** @type {Construct} */ -const codeText = { - name: 'codeText', - tokenize: tokenizeCodeText, - resolve: resolveCodeText, - previous: previous$1 -}; -/** @type {Resolver} */ - -function resolveCodeText(events) { - let tailExitIndex = events.length - 4; - let headEnterIndex = 3; - /** @type {number} */ - - let index; - /** @type {number|undefined} */ - - let enter; // If we start and end with an EOL or a space. - - if ( - (events[headEnterIndex][1].type === 'lineEnding' || - events[headEnterIndex][1].type === 'space') && - (events[tailExitIndex][1].type === 'lineEnding' || - events[tailExitIndex][1].type === 'space') - ) { - index = headEnterIndex; // And we have data. - - while (++index < tailExitIndex) { - if (events[index][1].type === 'codeTextData') { - // Then we have padding. - events[headEnterIndex][1].type = 'codeTextPadding'; - events[tailExitIndex][1].type = 'codeTextPadding'; - headEnterIndex += 2; - tailExitIndex -= 2; - break - } - } - } // Merge adjacent spaces and data. - - index = headEnterIndex - 1; - tailExitIndex++; - - while (++index <= tailExitIndex) { - if (enter === undefined) { - if (index !== tailExitIndex && events[index][1].type !== 'lineEnding') { - enter = index; - } - } else if ( - index === tailExitIndex || - events[index][1].type === 'lineEnding' - ) { - events[enter][1].type = 'codeTextData'; +function configure$1(combined, extensions) { + let index = -1; - if (index !== enter + 2) { - events[enter][1].end = events[index - 1][1].end; - events.splice(enter + 2, index - enter - 2); - tailExitIndex -= index - enter - 2; - index = enter + 2; - } + while (++index < extensions.length) { + const value = extensions[index]; - enter = undefined; + if (Array.isArray(value)) { + configure$1(combined, value); + } else { + extension(combined, value); } } - return events -} -/** @type {Previous} */ - -function previous$1(code) { - // If there is a previous code, there will always be a tail. - return ( - code !== 96 || - this.events[this.events.length - 1][1].type === 'characterEscape' - ) + return combined } -/** @type {Tokenizer} */ - -function tokenizeCodeText(effects, ok, nok) { - let sizeOpen = 0; - /** @type {number} */ +/** + * @param {Extension} combined + * @param {Extension} extension + * @returns {void} + */ - let size; - /** @type {Token} */ +function extension(combined, extension) { + /** @type {string} */ + let key; - let token; - return start - /** @type {State} */ + for (key in extension) { + if (own$5.call(extension, key)) { + const list = key === 'canContainEols' || key === 'transforms'; + const maybe = own$5.call(combined, key) ? combined[key] : undefined; + /* c8 ignore next */ - function start(code) { - effects.enter('codeText'); - effects.enter('codeTextSequence'); - return openingSequence(code) - } - /** @type {State} */ + const left = maybe || (combined[key] = list ? [] : {}); + const right = extension[key]; - function openingSequence(code) { - if (code === 96) { - effects.consume(code); - sizeOpen++; - return openingSequence + if (right) { + if (list) { + // @ts-expect-error: `left` is an array. + combined[key] = [...left, ...right]; + } else { + Object.assign(left, right); + } + } } - - effects.exit('codeTextSequence'); - return gap(code) } - /** @type {State} */ +} - function gap(code) { - // EOF. - if (code === null) { - return nok(code) - } // Closing fence? - // Could also be data. +/** + * @typedef {import('mdast').Root} Root + * @typedef {import('mdast-util-from-markdown').Options} Options + */ - if (code === 96) { - token = effects.enter('codeTextSequence'); - size = 0; - return closingSequence(code) - } // Tabs don’t work, and virtual spaces don’t make sense. +/** @type {import('unified').Plugin<[Options?] | void[], string, Root>} */ +function remarkParse(options) { + /** @type {import('unified').ParserFunction} */ + const parser = (doc) => { + // Assume options. + const settings = /** @type {Options} */ (this.data('settings')); - if (code === 32) { - effects.enter('space'); - effects.consume(code); - effects.exit('space'); - return gap - } + return fromMarkdown( + doc, + Object.assign({}, settings, options, { + // Note: these options are not in the readme. + // The goal is for them to be set by plugins on `data` instead of being + // passed by users. + extensions: this.data('micromarkExtensions') || [], + mdastExtensions: this.data('fromMarkdownExtensions') || [] + }) + ) + }; - if (markdownLineEnding(code)) { - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - return gap - } // Data. + Object.assign(this, {Parser: parser}); +} - effects.enter('codeTextData'); - return data(code) - } // In code. +var own$4 = {}.hasOwnProperty; - /** @type {State} */ +/** + * @callback Handler + * @param {...unknown} value + * @return {unknown} + * + * @typedef {Record} Handlers + * + * @typedef {Object} Options + * @property {Handler} [unknown] + * @property {Handler} [invalid] + * @property {Handlers} [handlers] + */ - function data(code) { - if ( - code === null || - code === 32 || - code === 96 || - markdownLineEnding(code) - ) { - effects.exit('codeTextData'); - return gap(code) - } +/** + * Handle values based on a property. + * + * @param {string} key + * @param {Options} [options] + */ +function zwitch(key, options) { + var settings = options || {}; - effects.consume(code); - return data - } // Closing fence. + /** + * Handle one value. + * Based on the bound `key`, a respective handler will be called. + * If `value` is not an object, or doesn’t have a `key` property, the special + * “invalid” handler will be called. + * If `value` has an unknown `key`, the special “unknown” handler will be + * called. + * + * All arguments, and the context object, are passed through to the handler, + * and it’s result is returned. + * + * @param {...unknown} [value] + * @this {unknown} + * @returns {unknown} + * @property {Handler} invalid + * @property {Handler} unknown + * @property {Handlers} handlers + */ + function one(value) { + var fn = one.invalid; + var handlers = one.handlers; - /** @type {State} */ + if (value && own$4.call(value, key)) { + fn = own$4.call(handlers, value[key]) ? handlers[value[key]] : one.unknown; + } - function closingSequence(code) { - // More. - if (code === 96) { - effects.consume(code); - size++; - return closingSequence - } // Done! + if (fn) { + return fn.apply(this, arguments) + } + } - if (size === sizeOpen) { - effects.exit('codeTextSequence'); - effects.exit('codeText'); - return ok(code) - } // More or less accents: mark as data. + one.handlers = settings.handlers || {}; + one.invalid = settings.invalid; + one.unknown = settings.unknown; - token.type = 'codeTextData'; - return data(code) - } + return one } /** - * @typedef {import('micromark-util-types').Token} Token - * @typedef {import('micromark-util-types').Chunk} Chunk - * @typedef {import('micromark-util-types').Event} Event + * @typedef {import('./types.js').Options} Options + * @typedef {import('./types.js').Context} Context */ /** - * Tokenize subcontent. - * - * @param {Event[]} events - * @returns {boolean} + * @param {Context} base + * @param {Options} extension + * @returns {Context} */ -function subtokenize(events) { - /** @type {Record} */ - const jumps = {}; +function configure(base, extension) { let index = -1; - /** @type {Event} */ - - let event; - /** @type {number|undefined} */ + /** @type {string} */ + let key; - let lineIndex; - /** @type {number} */ + // First do subextensions. + if (extension.extensions) { + while (++index < extension.extensions.length) { + configure(base, extension.extensions[index]); + } + } - let otherIndex; - /** @type {Event} */ + for (key in extension) { + if (key === 'extensions') ; else if (key === 'unsafe' || key === 'join') { + /* c8 ignore next 2 */ + // @ts-expect-error: hush. + base[key] = [...(base[key] || []), ...(extension[key] || [])]; + } else if (key === 'handlers') { + base[key] = Object.assign(base[key], extension[key] || {}); + } else { + // @ts-expect-error: hush. + base.options[key] = extension[key]; + } + } - let otherEvent; - /** @type {Event[]} */ + return base +} - let parameters; - /** @type {Event[]} */ +/** + * @typedef {import('../types.js').Node} Node + * @typedef {import('../types.js').Parent} Parent + * @typedef {import('../types.js').Join} Join + * @typedef {import('../types.js').Context} Context + */ - let subevents; - /** @type {boolean|undefined} */ +/** + * @param {Parent} parent + * @param {Context} context + * @returns {string} + */ +function containerFlow(parent, context) { + const indexStack = context.indexStack; + const children = parent.children || []; + /** @type {Array.} */ + const results = []; + let index = -1; - let more; + indexStack.push(-1); - while (++index < events.length) { - while (index in jumps) { - index = jumps[index]; - } + while (++index < children.length) { + const child = children[index]; - event = events[index]; // Add a hook for the GFM tasklist extension, which needs to know if text - // is in the first content of a list item. + indexStack[indexStack.length - 1] = index; - if ( - index && - event[1].type === 'chunkFlow' && - events[index - 1][1].type === 'listItemPrefix' - ) { - subevents = event[1]._tokenizer.events; - otherIndex = 0; + results.push( + context.handle(child, parent, context, {before: '\n', after: '\n'}) + ); - if ( - otherIndex < subevents.length && - subevents[otherIndex][1].type === 'lineEndingBlank' - ) { - otherIndex += 2; - } + if (child.type !== 'list') { + context.bulletLastUsed = undefined; + } - if ( - otherIndex < subevents.length && - subevents[otherIndex][1].type === 'content' - ) { - while (++otherIndex < subevents.length) { - if (subevents[otherIndex][1].type === 'content') { - break - } + if (index < children.length - 1) { + results.push(between(child, children[index + 1])); + } + } - if (subevents[otherIndex][1].type === 'chunkText') { - subevents[otherIndex][1]._isInFirstContentOfListItem = true; - otherIndex++; - } - } - } - } // Enter. + indexStack.pop(); - if (event[0] === 'enter') { - if (event[1].contentType) { - Object.assign(jumps, subcontent(events, index)); - index = jumps[index]; - more = true; - } - } // Exit. - else if (event[1]._container) { - otherIndex = index; - lineIndex = undefined; + return results.join('') - while (otherIndex--) { - otherEvent = events[otherIndex]; + /** + * @param {Node} left + * @param {Node} right + * @returns {string} + */ + function between(left, right) { + let index = context.join.length; - if ( - otherEvent[1].type === 'lineEnding' || - otherEvent[1].type === 'lineEndingBlank' - ) { - if (otherEvent[0] === 'enter') { - if (lineIndex) { - events[lineIndex][1].type = 'lineEndingBlank'; - } + while (index--) { + const result = context.join[index](left, right, parent, context); - otherEvent[1].type = 'lineEnding'; - lineIndex = otherIndex; - } - } else { - break - } + if (result === true || result === 1) { + break } - if (lineIndex) { - // Fix position. - event[1].end = Object.assign({}, events[lineIndex][1].start); // Switch container exit w/ line endings. + if (typeof result === 'number') { + return '\n'.repeat(1 + result) + } - parameters = events.slice(lineIndex, index); - parameters.unshift(event); - splice(events, lineIndex, index - lineIndex + 1, parameters); + if (result === false) { + return '\n\n\n\n' } } - } - return !more + return '\n\n' + } } + /** - * Tokenize embedded tokens. - * - * @param {Event[]} events - * @param {number} eventIndex - * @returns {Record} + * @callback Map + * @param {string} value + * @param {number} line + * @param {boolean} blank + * @returns {string} */ -function subcontent(events, eventIndex) { - const token = events[eventIndex][1]; - const context = events[eventIndex][2]; - let startPosition = eventIndex - 1; - /** @type {number[]} */ +const eol = /\r?\n|\r/g; - const startPositions = []; - const tokenizer = - token._tokenizer || context.parser[token.contentType](token.start); - const childEvents = tokenizer.events; - /** @type {[number, number][]} */ +/** + * @param {string} value + * @param {Map} map + * @returns {string} + */ +function indentLines(value, map) { + /** @type {Array.} */ + const result = []; + let start = 0; + let line = 0; + /** @type {RegExpExecArray|null} */ + let match; - const jumps = []; - /** @type {Record} */ + while ((match = eol.exec(value))) { + one(value.slice(start, match.index)); + result.push(match[0]); + start = match.index + match[0].length; + line++; + } - const gaps = {}; - /** @type {Chunk[]} */ + one(value.slice(start)); - let stream; - /** @type {Token|undefined} */ + return result.join('') - let previous; - let index = -1; - /** @type {Token|undefined} */ + /** + * @param {string} value + */ + function one(value) { + result.push(map(value, line, !value)); + } +} - let current = token; - let adjust = 0; - let start = 0; - const breaks = [start]; // Loop forward through the linked tokens to pass them in order to the - // subtokenizer. +/** + * @typedef {import('mdast').Blockquote} Blockquote + * @typedef {import('../types.js').Handle} Handle + * @typedef {import('../util/indent-lines.js').Map} Map + */ - while (current) { - // Find the position of the event for this token. - while (events[++startPosition][1] !== current) { - // Empty. - } +/** + * @type {Handle} + * @param {Blockquote} node + */ +function blockquote(node, _, context) { + const exit = context.enter('blockquote'); + const value = indentLines(containerFlow(node, context), map$2); + exit(); + return value +} - startPositions.push(startPosition); +/** @type {Map} */ +function map$2(line, _, blank) { + return '>' + (blank ? '' : ' ') + line +} - if (!current._tokenizer) { - stream = context.sliceStream(current); +/** + * @typedef {import('../types.js').Unsafe} Unsafe + */ - if (!current.next) { - stream.push(null); - } +/** + * @param {Array.} stack + * @param {Unsafe} pattern + * @returns {boolean} + */ +function patternInScope(stack, pattern) { + return ( + listInScope(stack, pattern.inConstruct, true) && + !listInScope(stack, pattern.notInConstruct, false) + ) +} - if (previous) { - tokenizer.defineSkip(current.start); - } +/** + * @param {Array.} stack + * @param {Unsafe['inConstruct']} list + * @param {boolean} none + * @returns {boolean} + */ +function listInScope(stack, list, none) { + if (!list) { + return none + } - if (current._isInFirstContentOfListItem) { - tokenizer._gfmTasklistFirstContentOfListItem = true; - } + if (typeof list === 'string') { + list = [list]; + } - tokenizer.write(stream); + let index = -1; - if (current._isInFirstContentOfListItem) { - tokenizer._gfmTasklistFirstContentOfListItem = undefined; - } - } // Unravel the next token. + while (++index < list.length) { + if (stack.includes(list[index])) { + return true + } + } - previous = current; - current = current.next; - } // Now, loop back through all events (and linked tokens), to figure out which - // parts belong where. + return false +} - current = token; +/** + * @typedef {import('../types.js').Handle} Handle + * @typedef {import('mdast').Break} Break + */ + +/** + * @type {Handle} + * @param {Break} _ + */ +function hardBreak(_, _1, context, safe) { + let index = -1; - while (++index < childEvents.length) { + while (++index < context.unsafe.length) { + // If we can’t put eols in this construct (setext headings, tables), use a + // space instead. if ( - // Find a void token that includes a break. - childEvents[index][0] === 'exit' && - childEvents[index - 1][0] === 'enter' && - childEvents[index][1].type === childEvents[index - 1][1].type && - childEvents[index][1].start.line !== childEvents[index][1].end.line + context.unsafe[index].character === '\n' && + patternInScope(context.stack, context.unsafe[index]) ) { - start = index + 1; - breaks.push(start); // Help GC. - - current._tokenizer = undefined; - current.previous = undefined; - current = current.next; + return /[ \t]/.test(safe.before) ? '' : ' ' } - } // Help GC. - - tokenizer.events = []; // If there’s one more token (which is the cases for lines that end in an - // EOF), that’s perfect: the last point we found starts it. - // If there isn’t then make sure any remaining content is added to it. + } - if (current) { - // Help GC. - current._tokenizer = undefined; - current.previous = undefined; - } else { - breaks.pop(); - } // Now splice the events from the subtokenizer into the current events, - // moving back to front so that splice indices aren’t affected. + return '\\\n' +} - index = breaks.length; +/** + * Get the count of the longest repeating streak of `character` in `value`. + * + * @param {string} value Content. + * @param {string} character Single character to look for + * @returns {number} Count of most frequent adjacent `character`s in `value` + */ +function longestStreak(value, character) { + var source = String(value); + var index = source.indexOf(character); + var expected = index; + var count = 0; + var max = 0; - while (index--) { - const slice = childEvents.slice(breaks[index], breaks[index + 1]); - const start = startPositions.pop(); - jumps.unshift([start, start + slice.length - 1]); - splice(events, start, 2, slice); + if (typeof character !== 'string' || character.length !== 1) { + throw new Error('Expected character') } - index = -1; + while (index !== -1) { + if (index === expected) { + if (++count > max) { + max = count; + } + } else { + count = 1; + } - while (++index < jumps.length) { - gaps[adjust + jumps[index][0]] = adjust + jumps[index][1]; - adjust += jumps[index][1] - jumps[index][0] - 1; + expected = index + 1; + index = source.indexOf(character, expected); } - return gaps + return max } /** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Resolver} Resolver - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').Token} Token - * @typedef {import('micromark-util-types').State} State + * @typedef {import('mdast').Code} Code + * @typedef {import('../types.js').Context} Context */ /** - * No name because it must not be turned off. - * @type {Construct} + * @param {Code} node + * @param {Context} context + * @returns {boolean} */ -const content = { - tokenize: tokenizeContent, - resolve: resolveContent -}; -/** @type {Construct} */ +function formatCodeAsIndented(node, context) { + return Boolean( + !context.options.fences && + node.value && + // If there’s no info… + !node.lang && + // And there’s a non-whitespace character… + /[^ \r\n]/.test(node.value) && + // And the value doesn’t start or end in a blank… + !/^[\t ]*(?:[\r\n]|$)|(?:^|[\r\n])[\t ]*$/.test(node.value) + ) +} -const continuationConstruct = { - tokenize: tokenizeContinuation, - partial: true -}; /** - * Content is transparent: it’s parsed right now. That way, definitions are also - * parsed right now: before text in paragraphs (specifically, media) are parsed. - * - * @type {Resolver} + * @typedef {import('../types.js').Context} Context + * @typedef {import('../types.js').Options} Options */ -function resolveContent(events) { - subtokenize(events); - return events +/** + * @param {Context} context + * @returns {Exclude} + */ +function checkFence(context) { + const marker = context.options.fence || '`'; + + if (marker !== '`' && marker !== '~') { + throw new Error( + 'Cannot serialize code with `' + + marker + + '` for `options.fence`, expected `` ` `` or `~`' + ) + } + + return marker } -/** @type {Tokenizer} */ -function tokenizeContent(effects, ok) { - /** @type {Token} */ - let previous; - return start - /** @type {State} */ +/** + * @typedef {import('../types.js').Unsafe} Unsafe + */ - function start(code) { - effects.enter('content'); - previous = effects.enter('chunkContent', { - contentType: 'content' - }); - return data(code) +/** + * @param {Unsafe} pattern + * @returns {RegExp} + */ +function patternCompile(pattern) { + if (!pattern._compiled) { + const before = + (pattern.atBreak ? '[\\r\\n][\\t ]*' : '') + + (pattern.before ? '(?:' + pattern.before + ')' : ''); + + pattern._compiled = new RegExp( + (before ? '(' + before + ')' : '') + + (/[|\\{}()[\]^$+*?.-]/.test(pattern.character) ? '\\' : '') + + pattern.character + + (pattern.after ? '(?:' + pattern.after + ')' : ''), + 'g' + ); } - /** @type {State} */ - function data(code) { - if (code === null) { - return contentEnd(code) + return pattern._compiled +} + +/** + * @typedef {import('../types.js').Context} Context + * @typedef {import('../types.js').SafeOptions} SafeOptions + */ + +/** + * @param {Context} context + * @param {string|null|undefined} input + * @param {SafeOptions & {encode?: Array.}} config + * @returns {string} + */ +function safe(context, input, config) { + const value = (config.before || '') + (input || '') + (config.after || ''); + /** @type {Array.} */ + const positions = []; + /** @type {Array.} */ + const result = []; + /** @type {Record} */ + const infos = {}; + let index = -1; + + while (++index < context.unsafe.length) { + const pattern = context.unsafe[index]; + + if (!patternInScope(context.stack, pattern)) { + continue } - if (markdownLineEnding(code)) { - return effects.check( - continuationConstruct, - contentContinue, - contentEnd - )(code) - } // Data. + const expression = patternCompile(pattern); + /** @type {RegExpExecArray|null} */ + let match; - effects.consume(code); - return data - } - /** @type {State} */ + while ((match = expression.exec(value))) { + const before = 'before' in pattern || Boolean(pattern.atBreak); + const after = 'after' in pattern; + const position = match.index + (before ? match[1].length : 0); - function contentEnd(code) { - effects.exit('chunkContent'); - effects.exit('content'); - return ok(code) - } - /** @type {State} */ + if (positions.includes(position)) { + if (infos[position].before && !before) { + infos[position].before = false; + } - function contentContinue(code) { - effects.consume(code); - effects.exit('chunkContent'); - previous.next = effects.enter('chunkContent', { - contentType: 'content', - previous - }); - previous = previous.next; - return data + if (infos[position].after && !after) { + infos[position].after = false; + } + } else { + positions.push(position); + infos[position] = {before, after}; + } + } } -} -/** @type {Tokenizer} */ -function tokenizeContinuation(effects, ok, nok) { - const self = this; - return startLookahead - /** @type {State} */ + positions.sort(numerical); - function startLookahead(code) { - effects.exit('chunkContent'); - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - return factorySpace(effects, prefixed, 'linePrefix') - } - /** @type {State} */ + let start = config.before ? config.before.length : 0; + const end = value.length - (config.after ? config.after.length : 0); + index = -1; - function prefixed(code) { - if (code === null || markdownLineEnding(code)) { - return nok(code) - } + while (++index < positions.length) { + const position = positions[index]; - const tail = self.events[self.events.length - 1]; + // Character before or after matched: + if (position < start || position >= end) { + continue + } + // If this character is supposed to be escaped because it has a condition on + // the next character, and the next character is definitly being escaped, + // then skip this escape. if ( - !self.parser.constructs.disable.null.includes('codeIndented') && - tail && - tail[1].type === 'linePrefix' && - tail[2].sliceSerialize(tail[1], true).length >= 4 + (position + 1 < end && + positions[index + 1] === position + 1 && + infos[position].after && + !infos[position + 1].before && + !infos[position + 1].after) || + (positions[index - 1] === position - 1 && + infos[position].before && + !infos[position - 1].before && + !infos[position - 1].after) ) { - return ok(code) + continue } - return effects.interrupt(self.parser.constructs.flow, nok, ok)(code) + if (start !== position) { + // If we have to use a character reference, an ampersand would be more + // correct, but as backslashes only care about punctuation, either will + // do the trick + result.push(escapeBackslashes(value.slice(start, position), '\\')); + } + + start = position; + + if ( + /[!-/:-@[-`{-~]/.test(value.charAt(position)) && + (!config.encode || !config.encode.includes(value.charAt(position))) + ) { + // Character escape. + result.push('\\'); + } else { + // Character reference. + result.push( + '&#x' + value.charCodeAt(position).toString(16).toUpperCase() + ';' + ); + start++; + } } + + result.push(escapeBackslashes(value.slice(start, end), config.after)); + + return result.join('') } /** - * @typedef {import('micromark-util-types').Effects} Effects - * @typedef {import('micromark-util-types').State} State + * @param {number} a + * @param {number} b + * @returns {number} */ +function numerical(a, b) { + return a - b +} /** - * @param {Effects} effects - * @param {State} ok - * @param {State} nok - * @param {string} type - * @param {string} literalType - * @param {string} literalMarkerType - * @param {string} rawType - * @param {string} stringType - * @param {number} [max=Infinity] - * @returns {State} + * @param {string} value + * @param {string} after + * @returns {string} */ -// eslint-disable-next-line max-params -function factoryDestination( - effects, - ok, - nok, - type, - literalType, - literalMarkerType, - rawType, - stringType, - max -) { - const limit = max || Number.POSITIVE_INFINITY; - let balance = 0; - return start - /** @type {State} */ - - function start(code) { - if (code === 60) { - effects.enter(type); - effects.enter(literalType); - effects.enter(literalMarkerType); - effects.consume(code); - effects.exit(literalMarkerType); - return destinationEnclosedBefore - } - - if (code === null || code === 41 || asciiControl(code)) { - return nok(code) - } +function escapeBackslashes(value, after) { + const expression = /\\(?=[!-/:-@[-`{-~])/g; + /** @type {Array.} */ + const positions = []; + /** @type {Array.} */ + const results = []; + const whole = value + after; + let index = -1; + let start = 0; + /** @type {RegExpExecArray|null} */ + let match; - effects.enter(type); - effects.enter(rawType); - effects.enter(stringType); - effects.enter('chunkString', { - contentType: 'string' - }); - return destinationRaw(code) + while ((match = expression.exec(whole))) { + positions.push(match.index); } - /** @type {State} */ - function destinationEnclosedBefore(code) { - if (code === 62) { - effects.enter(literalMarkerType); - effects.consume(code); - effects.exit(literalMarkerType); - effects.exit(literalType); - effects.exit(type); - return ok + while (++index < positions.length) { + if (start !== positions[index]) { + results.push(value.slice(start, positions[index])); } - effects.enter(stringType); - effects.enter('chunkString', { - contentType: 'string' - }); - return destinationEnclosed(code) + results.push('\\'); + start = positions[index]; } - /** @type {State} */ - - function destinationEnclosed(code) { - if (code === 62) { - effects.exit('chunkString'); - effects.exit(stringType); - return destinationEnclosedBefore(code) - } - - if (code === null || code === 60 || markdownLineEnding(code)) { - return nok(code) - } - effects.consume(code); - return code === 92 ? destinationEnclosedEscape : destinationEnclosed - } - /** @type {State} */ + results.push(value.slice(start)); - function destinationEnclosedEscape(code) { - if (code === 60 || code === 62 || code === 92) { - effects.consume(code); - return destinationEnclosed - } + return results.join('') +} - return destinationEnclosed(code) - } - /** @type {State} */ +/** + * @typedef {import('mdast').Code} Code + * @typedef {import('../types.js').Handle} Handle + * @typedef {import('../types.js').Exit} Exit + * @typedef {import('../util/indent-lines.js').Map} Map + */ - function destinationRaw(code) { - if (code === 40) { - if (++balance > limit) return nok(code) - effects.consume(code); - return destinationRaw - } +/** + * @type {Handle} + * @param {Code} node + */ +function code$1(node, _, context) { + const marker = checkFence(context); + const raw = node.value || ''; + const suffix = marker === '`' ? 'GraveAccent' : 'Tilde'; + /** @type {string} */ + let value; + /** @type {Exit} */ + let exit; - if (code === 41) { - if (!balance--) { - effects.exit('chunkString'); - effects.exit(stringType); - effects.exit(rawType); - effects.exit(type); - return ok(code) - } + if (formatCodeAsIndented(node, context)) { + exit = context.enter('codeIndented'); + value = indentLines(raw, map$1); + } else { + const sequence = marker.repeat(Math.max(longestStreak(raw, marker) + 1, 3)); + /** @type {Exit} */ + let subexit; + exit = context.enter('codeFenced'); + value = sequence; - effects.consume(code); - return destinationRaw + if (node.lang) { + subexit = context.enter('codeFencedLang' + suffix); + value += safe(context, node.lang, { + before: '`', + after: ' ', + encode: ['`'] + }); + subexit(); } - if (code === null || markdownLineEndingOrSpace(code)) { - if (balance) return nok(code) - effects.exit('chunkString'); - effects.exit(stringType); - effects.exit(rawType); - effects.exit(type); - return ok(code) + if (node.lang && node.meta) { + subexit = context.enter('codeFencedMeta' + suffix); + value += + ' ' + + safe(context, node.meta, { + before: ' ', + after: '\n', + encode: ['`'] + }); + subexit(); } - if (asciiControl(code)) return nok(code) - effects.consume(code); - return code === 92 ? destinationRawEscape : destinationRaw - } - /** @type {State} */ + value += '\n'; - function destinationRawEscape(code) { - if (code === 40 || code === 41 || code === 92) { - effects.consume(code); - return destinationRaw + if (raw) { + value += raw + '\n'; } - return destinationRaw(code) + value += sequence; } + + exit(); + return value +} + +/** @type {Map} */ +function map$1(line, _, blank) { + return (blank ? '' : ' ') + line } /** - * @typedef {import('micromark-util-types').Effects} Effects - * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext - * @typedef {import('micromark-util-types').State} State + * @typedef {import('mdast').Association} Association */ /** - * @this {TokenizeContext} - * @param {Effects} effects - * @param {State} ok - * @param {State} nok - * @param {string} type - * @param {string} markerType - * @param {string} stringType - * @returns {State} + * The `label` of an association is the string value: character escapes and + * references work, and casing is intact. + * The `identifier` is used to match one association to another: controversially, + * character escapes and references don’t work in this matching: `©` does + * not match `©`, and `\+` does not match `+`. + * But casing is ignored (and whitespace) is trimmed and collapsed: ` A\nb` + * matches `a b`. + * So, we do prefer the label when figuring out how we’re going to serialize: + * it has whitespace, casing, and we can ignore most useless character escapes + * and all character references. + * + * @param {Association} node + * @returns {string} */ -// eslint-disable-next-line max-params -function factoryLabel(effects, ok, nok, type, markerType, stringType) { - const self = this; - let size = 0; - /** @type {boolean} */ +function association(node) { + if (node.label || !node.identifier) { + return node.label || '' + } - let data; - return start - /** @type {State} */ + return decodeString(node.identifier) +} - function start(code) { - effects.enter(type); - effects.enter(markerType); - effects.consume(code); - effects.exit(markerType); - effects.enter(stringType); - return atBreak +/** + * @typedef {import('../types.js').Context} Context + * @typedef {import('../types.js').Options} Options + */ + +/** + * @param {Context} context + * @returns {Exclude} + */ +function checkQuote(context) { + const marker = context.options.quote || '"'; + + if (marker !== '"' && marker !== "'") { + throw new Error( + 'Cannot serialize title with `' + + marker + + '` for `options.quote`, expected `"`, or `\'`' + ) } - /** @type {State} */ - function atBreak(code) { - if ( - code === null || - code === 91 || - (code === 93 && !data) || - /* Hidden footnotes hook */ + return marker +} - /* c8 ignore next 3 */ - (code === 94 && - !size && - '_hiddenFootnoteSupport' in self.parser.constructs) || - size > 999 - ) { - return nok(code) - } +/** + * @typedef {import('mdast').Definition} Definition + * @typedef {import('../types.js').Handle} Handle + */ - if (code === 93) { - effects.exit(stringType); - effects.enter(markerType); - effects.consume(code); - effects.exit(markerType); - effects.exit(type); - return ok - } +/** + * @type {Handle} + * @param {Definition} node + */ +function definition(node, _, context) { + const marker = checkQuote(context); + const suffix = marker === '"' ? 'Quote' : 'Apostrophe'; + const exit = context.enter('definition'); + let subexit = context.enter('label'); + let value = + '[' + safe(context, association(node), {before: '[', after: ']'}) + ']: '; - if (markdownLineEnding(code)) { - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - return atBreak - } + subexit(); - effects.enter('chunkString', { - contentType: 'string' - }); - return label(code) + if ( + // If there’s no url, or… + !node.url || + // If there’s whitespace, enclosed is prettier. + /[ \t\r\n]/.test(node.url) + ) { + subexit = context.enter('destinationLiteral'); + value += '<' + safe(context, node.url, {before: '<', after: '>'}) + '>'; + } else { + // No whitespace, raw is prettier. + subexit = context.enter('destinationRaw'); + value += safe(context, node.url, {before: ' ', after: ' '}); } - /** @type {State} */ - function label(code) { - if ( - code === null || - code === 91 || - code === 93 || - markdownLineEnding(code) || - size++ > 999 - ) { - effects.exit('chunkString'); - return atBreak(code) - } + subexit(); - effects.consume(code); - data = data || !markdownSpace(code); - return code === 92 ? labelEscape : label + if (node.title) { + subexit = context.enter('title' + suffix); + value += + ' ' + + marker + + safe(context, node.title, {before: marker, after: marker}) + + marker; + subexit(); } - /** @type {State} */ - function labelEscape(code) { - if (code === 91 || code === 92 || code === 93) { - effects.consume(code); - size++; - return label - } + exit(); - return label(code) - } + return value } /** - * @typedef {import('micromark-util-types').Effects} Effects - * @typedef {import('micromark-util-types').State} State - * @typedef {import('micromark-util-types').Code} Code + * @typedef {import('../types.js').Context} Context + * @typedef {import('../types.js').Options} Options */ /** - * @param {Effects} effects - * @param {State} ok - * @param {State} nok - * @param {string} type - * @param {string} markerType - * @param {string} stringType - * @returns {State} + * @param {Context} context + * @returns {Exclude} */ -// eslint-disable-next-line max-params -function factoryTitle(effects, ok, nok, type, markerType, stringType) { - /** @type {NonNullable} */ - let marker; - return start - /** @type {State} */ +function checkEmphasis(context) { + const marker = context.options.emphasis || '*'; - function start(code) { - effects.enter(type); - effects.enter(markerType); - effects.consume(code); - effects.exit(markerType); - marker = code === 40 ? 41 : code; - return atFirstTitleBreak + if (marker !== '*' && marker !== '_') { + throw new Error( + 'Cannot serialize emphasis with `' + + marker + + '` for `options.emphasis`, expected `*`, or `_`' + ) } - /** @type {State} */ - function atFirstTitleBreak(code) { - if (code === marker) { - effects.enter(markerType); - effects.consume(code); - effects.exit(markerType); - effects.exit(type); - return ok - } + return marker +} - effects.enter(stringType); - return atTitleBreak(code) - } - /** @type {State} */ +/** + * @typedef {import('../types.js').Node} Node + * @typedef {import('../types.js').Parent} Parent + * @typedef {import('../types.js').SafeOptions} SafeOptions + * @typedef {import('../types.js').Context} Context + */ - function atTitleBreak(code) { - if (code === marker) { - effects.exit(stringType); - return atFirstTitleBreak(marker) - } +/** + * @param {Parent} parent + * @param {Context} context + * @param {SafeOptions} safeOptions + * @returns {string} + */ +function containerPhrasing(parent, context, safeOptions) { + const indexStack = context.indexStack; + const children = parent.children || []; + /** @type {Array.} */ + const results = []; + let index = -1; + let before = safeOptions.before; - if (code === null) { - return nok(code) - } // Note: blank lines can’t exist in content. + indexStack.push(-1); - if (markdownLineEnding(code)) { - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - return factorySpace(effects, atTitleBreak, 'linePrefix') - } + while (++index < children.length) { + const child = children[index]; + /** @type {string} */ + let after; - effects.enter('chunkString', { - contentType: 'string' - }); - return title(code) - } - /** @type {State} */ + indexStack[indexStack.length - 1] = index; - function title(code) { - if (code === marker || code === null || markdownLineEnding(code)) { - effects.exit('chunkString'); - return atTitleBreak(code) + if (index + 1 < children.length) { + // @ts-expect-error: hush, it’s actually a `zwitch`. + let handle = context.handle.handlers[children[index + 1].type]; + if (handle && handle.peek) handle = handle.peek; + after = handle + ? handle(children[index + 1], parent, context, { + before: '', + after: '' + }).charAt(0) + : ''; + } else { + after = safeOptions.after; } - effects.consume(code); - return code === 92 ? titleEscape : title - } - /** @type {State} */ - - function titleEscape(code) { - if (code === marker || code === 92) { - effects.consume(code); - return title + // In some cases, html (text) can be found in phrasing right after an eol. + // When we’d serialize that, in most cases that would be seen as html + // (flow). + // As we can’t escape or so to prevent it from happening, we take a somewhat + // reasonable approach: replace that eol with a space. + // See: + if ( + results.length > 0 && + (before === '\r' || before === '\n') && + child.type === 'html' + ) { + results[results.length - 1] = results[results.length - 1].replace( + /(\r?\n|\r)$/, + ' ' + ); + before = ' '; } - return title(code) + results.push(context.handle(child, parent, context, {before, after})); + + before = results[results.length - 1].slice(-1); } + + indexStack.pop(); + + return results.join('') } /** - * @typedef {import('micromark-util-types').Effects} Effects - * @typedef {import('micromark-util-types').State} State + * @typedef {import('mdast').Emphasis} Emphasis + * @typedef {import('../types.js').Handle} Handle */ +emphasis.peek = emphasisPeek; + +// To do: there are cases where emphasis cannot “form” depending on the +// previous or next character of sequences. +// There’s no way around that though, except for injecting zero-width stuff. +// Do we need to safeguard against that? /** - * @param {Effects} effects - * @param {State} ok + * @type {Handle} + * @param {Emphasis} node */ -function factoryWhitespace(effects, ok) { - /** @type {boolean} */ - let seen; - return start - /** @type {State} */ - - function start(code) { - if (markdownLineEnding(code)) { - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - seen = true; - return start - } - - if (markdownSpace(code)) { - return factorySpace( - effects, - start, - seen ? 'linePrefix' : 'lineSuffix' - )(code) - } - - return ok(code) - } +function emphasis(node, _, context) { + const marker = checkEmphasis(context); + const exit = context.enter('emphasis'); + const value = containerPhrasing(node, context, { + before: marker, + after: marker + }); + exit(); + return marker + value + marker } /** - * Normalize an identifier (such as used in definitions). - * - * @param {string} value - * @returns {string} + * @type {Handle} + * @param {Emphasis} _ */ -function normalizeIdentifier(value) { - return ( - value // Collapse Markdown whitespace. - .replace(/[\t\n\r ]+/g, ' ') // Trim. - .replace(/^ | $/g, '') // Some characters are considered “uppercase”, but if their lowercase - // counterpart is uppercased will result in a different uppercase - // character. - // Hence, to get that form, we perform both lower- and uppercase. - // Upper case makes sure keys will not interact with default prototypal - // methods: no method is uppercase. - .toLowerCase() - .toUpperCase() - ) +function emphasisPeek(_, _1, context) { + return context.options.emphasis || '*' } /** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State + * @typedef {import('unist').Node} Node + * @typedef {import('unist').Parent} Parent + * + * @typedef {string} Type + * @typedef {Object} Props + * + * @typedef {null|undefined|Type|Props|TestFunctionAnything|Array.} Test */ -/** @type {Construct} */ -const definition$1 = { - name: 'definition', - tokenize: tokenizeDefinition -}; -/** @type {Construct} */ - -const titleConstruct = { - tokenize: tokenizeTitle, - partial: true -}; -/** @type {Tokenizer} */ - -function tokenizeDefinition(effects, ok, nok) { - const self = this; - /** @type {string} */ - - let identifier; - return start - /** @type {State} */ +const convert = + /** + * @type {( + * ((test: T['type']|Partial|TestFunctionPredicate) => AssertPredicate) & + * ((test?: Test) => AssertAnything) + * )} + */ + ( + /** + * Generate an assertion from a check. + * @param {Test} [test] + * When nullish, checks if `node` is a `Node`. + * When `string`, works like passing `function (node) {return node.type === test}`. + * When `function` checks if function passed the node is true. + * When `object`, checks that all keys in test are in node, and that they have (strictly) equal values. + * When `array`, checks any one of the subtests pass. + * @returns {AssertAnything} + */ + function (test) { + if (test === undefined || test === null) { + return ok + } - function start(code) { - effects.enter('definition'); - return factoryLabel.call( - self, - effects, - labelAfter, - nok, - 'definitionLabel', - 'definitionLabelMarker', - 'definitionLabelString' - )(code) - } - /** @type {State} */ + if (typeof test === 'string') { + return typeFactory(test) + } - function labelAfter(code) { - identifier = normalizeIdentifier( - self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1) - ); + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory(test) : propsFactory(test) + } - if (code === 58) { - effects.enter('definitionMarker'); - effects.consume(code); - effects.exit('definitionMarker'); // Note: blank lines can’t exist in content. + if (typeof test === 'function') { + return castFactory(test) + } - return factoryWhitespace( - effects, - factoryDestination( - effects, - effects.attempt( - titleConstruct, - factorySpace(effects, after, 'whitespace'), - factorySpace(effects, after, 'whitespace') - ), - nok, - 'definitionDestination', - 'definitionDestinationLiteral', - 'definitionDestinationLiteralMarker', - 'definitionDestinationRaw', - 'definitionDestinationString' - ) - ) + throw new Error('Expected function, string, or object as test') } + ); +/** + * @param {Array.} tests + * @returns {AssertAnything} + */ +function anyFactory(tests) { + /** @type {Array.} */ + const checks = []; + let index = -1; - return nok(code) + while (++index < tests.length) { + checks[index] = convert(tests[index]); } - /** @type {State} */ - function after(code) { - if (code === null || markdownLineEnding(code)) { - effects.exit('definition'); + return castFactory(any) - if (!self.parser.defined.includes(identifier)) { - self.parser.defined.push(identifier); - } + /** + * @this {unknown} + * @param {unknown[]} parameters + * @returns {boolean} + */ + function any(...parameters) { + let index = -1; - return ok(code) + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true } - return nok(code) + return false } } -/** @type {Tokenizer} */ -function tokenizeTitle(effects, ok, nok) { - return start - /** @type {State} */ +/** + * Utility to assert each property in `test` is represented in `node`, and each + * values are strictly equal. + * + * @param {Props} check + * @returns {AssertAnything} + */ +function propsFactory(check) { + return castFactory(all) - function start(code) { - return markdownLineEndingOrSpace(code) - ? factoryWhitespace(effects, before)(code) - : nok(code) - } - /** @type {State} */ + /** + * @param {Node} node + * @returns {boolean} + */ + function all(node) { + /** @type {string} */ + let key; - function before(code) { - if (code === 34 || code === 39 || code === 40) { - return factoryTitle( - effects, - factorySpace(effects, after, 'whitespace'), - nok, - 'definitionTitle', - 'definitionTitleMarker', - 'definitionTitleString' - )(code) + for (key in check) { + // @ts-expect-error: hush, it sure works as an index. + if (node[key] !== check[key]) return false } - return nok(code) - } - /** @type {State} */ - - function after(code) { - return code === null || markdownLineEnding(code) ? ok(code) : nok(code) + return true } } /** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State + * Utility to convert a string into a function which checks a given node’s type + * for said string. + * + * @param {Type} check + * @returns {AssertAnything} */ +function typeFactory(check) { + return castFactory(type) -/** @type {Construct} */ -const hardBreakEscape = { - name: 'hardBreakEscape', - tokenize: tokenizeHardBreakEscape -}; -/** @type {Tokenizer} */ - -function tokenizeHardBreakEscape(effects, ok, nok) { - return start - /** @type {State} */ - - function start(code) { - effects.enter('hardBreakEscape'); - effects.enter('escapeMarker'); - effects.consume(code); - return open + /** + * @param {Node} node + */ + function type(node) { + return node && node.type === check } - /** @type {State} */ +} - function open(code) { - if (markdownLineEnding(code)) { - effects.exit('escapeMarker'); - effects.exit('hardBreakEscape'); - return ok(code) - } +/** + * Utility to convert a string into a function which checks a given node’s type + * for said string. + * @param {TestFunctionAnything} check + * @returns {AssertAnything} + */ +function castFactory(check) { + return assertion - return nok(code) + /** + * @this {unknown} + * @param {Array.} parameters + * @returns {boolean} + */ + function assertion(...parameters) { + // @ts-expect-error: spreading is fine. + return Boolean(check.call(this, ...parameters)) } } +// Utility to return true. +function ok() { + return true +} + /** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Resolver} Resolver - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').Token} Token - * @typedef {import('micromark-util-types').State} State + * @param {string} d + * @returns {string} */ +function color$1(d) { + return '\u001B[33m' + d + '\u001B[39m' +} -/** @type {Construct} */ -const headingAtx = { - name: 'headingAtx', - tokenize: tokenizeHeadingAtx, - resolve: resolveHeadingAtx -}; -/** @type {Resolver} */ +/** + * @typedef {import('unist').Node} Node + * @typedef {import('unist').Parent} Parent + * @typedef {import('unist-util-is').Test} Test + * @typedef {import('./complex-types').Action} Action + * @typedef {import('./complex-types').Index} Index + * @typedef {import('./complex-types').ActionTuple} ActionTuple + * @typedef {import('./complex-types').VisitorResult} VisitorResult + * @typedef {import('./complex-types').Visitor} Visitor + */ -function resolveHeadingAtx(events, context) { - let contentEnd = events.length - 2; - let contentStart = 3; - /** @type {Token} */ +/** + * Continue traversing as normal + */ +const CONTINUE$1 = true; +/** + * Do not traverse this node’s children + */ +const SKIP$1 = 'skip'; +/** + * Stop traversing immediately + */ +const EXIT$1 = false; - let content; - /** @type {Token} */ +/** + * Visit children of tree which pass a test + * + * @param tree Abstract syntax tree to walk + * @param test Test node, optional + * @param visitor Function to run for each node + * @param reverse Visit the tree in reverse order, defaults to false + */ +const visitParents$1 = + /** + * @type {( + * ((tree: Tree, test: Check, visitor: import('./complex-types').BuildVisitor, reverse?: boolean) => void) & + * ((tree: Tree, visitor: import('./complex-types').BuildVisitor, reverse?: boolean) => void) + * )} + */ + ( + /** + * @param {Node} tree + * @param {Test} test + * @param {import('./complex-types').Visitor} visitor + * @param {boolean} [reverse] + */ + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + // @ts-expect-error no visitor given, so `visitor` is test. + visitor = test; + test = null; + } - let text; // Prefix whitespace, part of the opening. + const is = convert(test); + const step = reverse ? -1 : 1; - if (events[contentStart][1].type === 'whitespace') { - contentStart += 2; - } // Suffix whitespace, part of the closing. + factory(tree, null, [])(); - if ( - contentEnd - 2 > contentStart && - events[contentEnd][1].type === 'whitespace' - ) { - contentEnd -= 2; - } + /** + * @param {Node} node + * @param {number?} index + * @param {Array.} parents + */ + function factory(node, index, parents) { + /** @type {Object.} */ + // @ts-expect-error: hush + const value = typeof node === 'object' && node !== null ? node : {}; + /** @type {string|undefined} */ + let name; - if ( - events[contentEnd][1].type === 'atxHeadingSequence' && - (contentStart === contentEnd - 1 || - (contentEnd - 4 > contentStart && - events[contentEnd - 2][1].type === 'whitespace')) - ) { - contentEnd -= contentStart + 1 === contentEnd ? 2 : 4; - } + if (typeof value.type === 'string') { + name = + typeof value.tagName === 'string' + ? value.tagName + : typeof value.name === 'string' + ? value.name + : undefined; - if (contentEnd > contentStart) { - content = { - type: 'atxHeadingText', - start: events[contentStart][1].start, - end: events[contentEnd][1].end - }; - text = { - type: 'chunkText', - start: events[contentStart][1].start, - end: events[contentEnd][1].end, - // @ts-expect-error Constants are fine to assign. - contentType: 'text' - }; - splice(events, contentStart, contentEnd - contentStart + 1, [ - ['enter', content, context], - ['enter', text, context], - ['exit', text, context], - ['exit', content, context] - ]); - } + Object.defineProperty(visit, 'name', { + value: + 'node (' + + color$1(value.type + (name ? '<' + name + '>' : '')) + + ')' + }); + } - return events -} -/** @type {Tokenizer} */ + return visit -function tokenizeHeadingAtx(effects, ok, nok) { - const self = this; - let size = 0; - return start - /** @type {State} */ + function visit() { + /** @type {ActionTuple} */ + let result = []; + /** @type {ActionTuple} */ + let subresult; + /** @type {number} */ + let offset; + /** @type {Array.} */ + let grandparents; - function start(code) { - effects.enter('atxHeading'); - effects.enter('atxHeadingSequence'); - return fenceOpenInside(code) - } - /** @type {State} */ + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$1(visitor(node, parents)); - function fenceOpenInside(code) { - if (code === 35 && size++ < 6) { - effects.consume(code); - return fenceOpenInside - } + if (result[0] === EXIT$1) { + return result + } + } - if (code === null || markdownLineEndingOrSpace(code)) { - effects.exit('atxHeadingSequence'); - return self.interrupt ? ok(code) : headingBreak(code) - } + // @ts-expect-error looks like a parent. + if (node.children && result[0] !== SKIP$1) { + // @ts-expect-error looks like a parent. + offset = (reverse ? node.children.length : -1) + step; + // @ts-expect-error looks like a parent. + grandparents = parents.concat(node); - return nok(code) - } - /** @type {State} */ + // @ts-expect-error looks like a parent. + while (offset > -1 && offset < node.children.length) { + // @ts-expect-error looks like a parent. + subresult = factory(node.children[offset], offset, grandparents)(); - function headingBreak(code) { - if (code === 35) { - effects.enter('atxHeadingSequence'); - return sequence(code) - } + if (subresult[0] === EXIT$1) { + return subresult + } - if (code === null || markdownLineEnding(code)) { - effects.exit('atxHeading'); - return ok(code) - } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } - if (markdownSpace(code)) { - return factorySpace(effects, headingBreak, 'whitespace')(code) + return result + } + } } + ); - effects.enter('atxHeadingText'); - return data(code) +/** + * @param {VisitorResult} value + * @returns {ActionTuple} + */ +function toResult$1(value) { + if (Array.isArray(value)) { + return value } - /** @type {State} */ - function sequence(code) { - if (code === 35) { - effects.consume(code); - return sequence - } - - effects.exit('atxHeadingSequence'); - return headingBreak(code) + if (typeof value === 'number') { + return [CONTINUE$1, value] } - /** @type {State} */ - - function data(code) { - if (code === null || code === 35 || markdownLineEndingOrSpace(code)) { - effects.exit('atxHeadingText'); - return headingBreak(code) - } - effects.consume(code); - return data - } + return [value] } /** - * List of lowercase HTML tag names which when parsing HTML (flow), result - * in more relaxed rules (condition 6): because they are known blocks, the - * HTML-like syntax doesn’t have to be strictly parsed. - * For tag names not in this list, a more strict algorithm (condition 7) is used - * to detect whether the HTML-like syntax is seen as HTML (flow) or not. - * - * This is copied from: - * . + * @typedef {import('unist').Node} Node + * @typedef {import('unist').Parent} Parent + * @typedef {import('unist-util-is').Test} Test + * @typedef {import('unist-util-visit-parents').VisitorResult} VisitorResult */ -const htmlBlockNames = [ - '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' -]; /** - * List of lowercase HTML tag names which when parsing HTML (flow), result in - * HTML that can include lines w/o exiting, until a closing tag also in this - * list is found (condition 1). - * - * This module is copied from: - * . + * Visit children of tree which pass a test * - * Note that `textarea` is not available in `CommonMark@0.29` but has been - * merged to the primary branch and is slated to be released in the next release - * of CommonMark. - */ -const htmlRawNames = ['pre', 'script', 'style', 'textarea']; - -/** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Resolver} Resolver - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State - * @typedef {import('micromark-util-types').Code} Code + * @param tree Abstract syntax tree to walk + * @param test Test, optional + * @param visitor Function to run for each node + * @param reverse Fisit the tree in reverse, defaults to false */ -/** @type {Construct} */ - -const htmlFlow = { - name: 'htmlFlow', - tokenize: tokenizeHtmlFlow, - resolveTo: resolveToHtmlFlow, - concrete: true -}; -/** @type {Construct} */ - -const nextBlankConstruct = { - tokenize: tokenizeNextBlank, - partial: true -}; -/** @type {Resolver} */ +const visit$1 = + /** + * @type {( + * ((tree: Tree, test: Check, visitor: Visitor, Check>>, reverse?: boolean) => void) & + * ((tree: Tree, visitor: Visitor>, reverse?: boolean) => void) + * )} + */ + ( + /** + * @param {Node} tree + * @param {Test} test + * @param {Visitor} visitor + * @param {boolean} [reverse] + */ + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } -function resolveToHtmlFlow(events) { - let index = events.length; + visitParents$1(tree, test, overload, reverse); - while (index--) { - if (events[index][0] === 'enter' && events[index][1].type === 'htmlFlow') { - break + /** + * @param {Node} node + * @param {Array.} parents + */ + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } } - } + ); - if (index > 1 && events[index - 2][1].type === 'linePrefix') { - // Add the prefix start to the HTML token. - events[index][1].start = events[index - 2][1].start; // Add the prefix start to the HTML line token. +/** + * @typedef {import('mdast').Heading} Heading + * @typedef {import('../types.js').Context} Context + */ - events[index + 1][1].start = events[index - 2][1].start; // Remove the line prefix. +/** + * @param {Heading} node + * @param {Context} context + * @returns {boolean} + */ +function formatHeadingAsSetext(node, context) { + let literalWithBreak = false; - events.splice(index - 2, 2); - } + // Look for literals with a line break. + // Note that this also + visit$1(node, (node) => { + if ( + ('value' in node && /\r?\n|\r/.test(node.value)) || + node.type === 'break' + ) { + literalWithBreak = true; + return EXIT$1 + } + }); - return events + return Boolean( + (!node.depth || node.depth < 3) && + toString(node) && + (context.options.setext || literalWithBreak) + ) } -/** @type {Tokenizer} */ - -function tokenizeHtmlFlow(effects, ok, nok) { - const self = this; - /** @type {number} */ - let kind; - /** @type {boolean} */ +/** + * @typedef {import('mdast').Heading} Heading + * @typedef {import('../types.js').Handle} Handle + * @typedef {import('../types.js').Exit} Exit + */ - let startTag; - /** @type {string} */ +/** + * @type {Handle} + * @param {Heading} node + */ +function heading(node, _, context) { + const rank = Math.max(Math.min(6, node.depth || 1), 1); - let buffer; - /** @type {number} */ + if (formatHeadingAsSetext(node, context)) { + const exit = context.enter('headingSetext'); + const subexit = context.enter('phrasing'); + const value = containerPhrasing(node, context, {before: '\n', after: '\n'}); + subexit(); + exit(); - let index; - /** @type {Code} */ + return ( + value + + '\n' + + (rank === 1 ? '=' : '-').repeat( + // The whole size… + value.length - + // Minus the position of the character after the last EOL (or + // 0 if there is none)… + (Math.max(value.lastIndexOf('\r'), value.lastIndexOf('\n')) + 1) + ) + ) + } - let marker; - return start - /** @type {State} */ + const sequence = '#'.repeat(rank); + const exit = context.enter('headingAtx'); + const subexit = context.enter('phrasing'); + let value = containerPhrasing(node, context, {before: '# ', after: '\n'}); - function start(code) { - effects.enter('htmlFlow'); - effects.enter('htmlFlowData'); - effects.consume(code); - return open + if (/^[\t ]/.test(value)) { + value = + '&#x' + + value.charCodeAt(0).toString(16).toUpperCase() + + ';' + + value.slice(1); } - /** @type {State} */ - - function open(code) { - if (code === 33) { - effects.consume(code); - return declarationStart - } - if (code === 47) { - effects.consume(code); - return tagCloseStart - } + value = value ? sequence + ' ' + value : sequence; - if (code === 63) { - effects.consume(code); - kind = 3; // While we’re in an instruction instead of a declaration, we’re on a `?` - // right now, so we do need to search for `>`, similar to declarations. + if (context.options.closeAtx) { + value += ' ' + sequence; + } - return self.interrupt ? ok : continuationDeclarationInside - } + subexit(); + exit(); - if (asciiAlpha(code)) { - effects.consume(code); - buffer = String.fromCharCode(code); - startTag = true; - return tagName - } + return value +} - return nok(code) - } - /** @type {State} */ +/** + * @typedef {import('mdast').HTML} HTML + * @typedef {import('../types.js').Handle} Handle + */ - function declarationStart(code) { - if (code === 45) { - effects.consume(code); - kind = 2; - return commentOpenInside - } +html.peek = htmlPeek; - if (code === 91) { - effects.consume(code); - kind = 5; - buffer = 'CDATA['; - index = 0; - return cdataOpenInside - } +/** + * @type {Handle} + * @param {HTML} node + */ +function html(node) { + return node.value || '' +} - if (asciiAlpha(code)) { - effects.consume(code); - kind = 4; - return self.interrupt ? ok : continuationDeclarationInside - } +/** + * @type {Handle} + */ +function htmlPeek() { + return '<' +} - return nok(code) - } - /** @type {State} */ +/** + * @typedef {import('mdast').Image} Image + * @typedef {import('../types.js').Handle} Handle + */ - function commentOpenInside(code) { - if (code === 45) { - effects.consume(code); - return self.interrupt ? ok : continuationDeclarationInside - } +image.peek = imagePeek; - return nok(code) - } - /** @type {State} */ +/** + * @type {Handle} + * @param {Image} node + */ +function image(node, _, context) { + const quote = checkQuote(context); + const suffix = quote === '"' ? 'Quote' : 'Apostrophe'; + const exit = context.enter('image'); + let subexit = context.enter('label'); + let value = '![' + safe(context, node.alt, {before: '[', after: ']'}) + ']('; - function cdataOpenInside(code) { - if (code === buffer.charCodeAt(index++)) { - effects.consume(code); - return index === buffer.length - ? self.interrupt - ? ok - : continuation - : cdataOpenInside - } + subexit(); - return nok(code) + if ( + // If there’s no url but there is a title… + (!node.url && node.title) || + // Or if there’s markdown whitespace or an eol, enclose. + /[ \t\r\n]/.test(node.url) + ) { + subexit = context.enter('destinationLiteral'); + value += '<' + safe(context, node.url, {before: '<', after: '>'}) + '>'; + } else { + // No whitespace, raw is prettier. + subexit = context.enter('destinationRaw'); + value += safe(context, node.url, { + before: '(', + after: node.title ? ' ' : ')' + }); } - /** @type {State} */ - function tagCloseStart(code) { - if (asciiAlpha(code)) { - effects.consume(code); - buffer = String.fromCharCode(code); - return tagName - } + subexit(); - return nok(code) + if (node.title) { + subexit = context.enter('title' + suffix); + value += + ' ' + + quote + + safe(context, node.title, {before: quote, after: quote}) + + quote; + subexit(); } - /** @type {State} */ - - function tagName(code) { - if ( - code === null || - code === 47 || - code === 62 || - markdownLineEndingOrSpace(code) - ) { - if ( - code !== 47 && - startTag && - htmlRawNames.includes(buffer.toLowerCase()) - ) { - kind = 1; - return self.interrupt ? ok(code) : continuation(code) - } - - if (htmlBlockNames.includes(buffer.toLowerCase())) { - kind = 6; - if (code === 47) { - effects.consume(code); - return basicSelfClosing - } + value += ')'; + exit(); - return self.interrupt ? ok(code) : continuation(code) - } + return value +} - kind = 7; // Do not support complete HTML when interrupting +/** + * @type {Handle} + */ +function imagePeek() { + return '!' +} - return self.interrupt && !self.parser.lazy[self.now().line] - ? nok(code) - : startTag - ? completeAttributeNameBefore(code) - : completeClosingTagAfter(code) - } +/** + * @typedef {import('mdast').ImageReference} ImageReference + * @typedef {import('../types.js').Handle} Handle + */ - if (code === 45 || asciiAlphanumeric(code)) { - effects.consume(code); - buffer += String.fromCharCode(code); - return tagName - } +imageReference.peek = imageReferencePeek; - return nok(code) - } - /** @type {State} */ +/** + * @type {Handle} + * @param {ImageReference} node + */ +function imageReference(node, _, context) { + const type = node.referenceType; + const exit = context.enter('imageReference'); + let subexit = context.enter('label'); + const alt = safe(context, node.alt, {before: '[', after: ']'}); + let value = '![' + alt + ']'; - function basicSelfClosing(code) { - if (code === 62) { - effects.consume(code); - return self.interrupt ? ok : continuation - } + subexit(); + // Hide the fact that we’re in phrasing, because escapes don’t work. + const stack = context.stack; + context.stack = []; + subexit = context.enter('reference'); + const reference = safe(context, association(node), {before: '[', after: ']'}); + subexit(); + context.stack = stack; + exit(); - return nok(code) + if (type === 'full' || !alt || alt !== reference) { + value += '[' + reference + ']'; + } else if (type !== 'shortcut') { + value += '[]'; } - /** @type {State} */ - function completeClosingTagAfter(code) { - if (markdownSpace(code)) { - effects.consume(code); - return completeClosingTagAfter - } + return value +} - return completeEnd(code) - } - /** @type {State} */ +/** + * @type {Handle} + */ +function imageReferencePeek() { + return '!' +} - function completeAttributeNameBefore(code) { - if (code === 47) { - effects.consume(code); - return completeEnd - } +/** + * @typedef {import('mdast').InlineCode} InlineCode + * @typedef {import('../types.js').Handle} Handle + */ - if (code === 58 || code === 95 || asciiAlpha(code)) { - effects.consume(code); - return completeAttributeName - } +inlineCode.peek = inlineCodePeek; - if (markdownSpace(code)) { - effects.consume(code); - return completeAttributeNameBefore - } +/** + * @type {Handle} + * @param {InlineCode} node + */ +function inlineCode(node, _, context) { + let value = node.value || ''; + let sequence = '`'; + let index = -1; - return completeEnd(code) + // If there is a single grave accent on its own in the code, use a fence of + // two. + // If there are two in a row, use one. + while (new RegExp('(^|[^`])' + sequence + '([^`]|$)').test(value)) { + sequence += '`'; } - /** @type {State} */ - - function completeAttributeName(code) { - if ( - code === 45 || - code === 46 || - code === 58 || - code === 95 || - asciiAlphanumeric(code) - ) { - effects.consume(code); - return completeAttributeName - } - return completeAttributeNameAfter(code) + // If this is not just spaces or eols (tabs don’t count), and either the + // first or last character are a space, eol, or tick, then pad with spaces. + if ( + /[^ \r\n]/.test(value) && + ((/^[ \r\n]/.test(value) && /[ \r\n]$/.test(value)) || /^`|`$/.test(value)) + ) { + value = ' ' + value + ' '; } - /** @type {State} */ - - function completeAttributeNameAfter(code) { - if (code === 61) { - effects.consume(code); - return completeAttributeValueBefore - } - if (markdownSpace(code)) { - effects.consume(code); - return completeAttributeNameAfter - } + // We have a potential problem: certain characters after eols could result in + // blocks being seen. + // For example, if someone injected the string `'\n# b'`, then that would + // result in an ATX heading. + // We can’t escape characters in `inlineCode`, but because eols are + // transformed to spaces when going from markdown to HTML anyway, we can swap + // them out. + while (++index < context.unsafe.length) { + const pattern = context.unsafe[index]; + const expression = patternCompile(pattern); + /** @type {RegExpExecArray|null} */ + let match; - return completeAttributeNameBefore(code) - } - /** @type {State} */ + // Only look for `atBreak`s. + // Btw: note that `atBreak` patterns will always start the regex at LF or + // CR. + if (!pattern.atBreak) continue - function completeAttributeValueBefore(code) { - if ( - code === null || - code === 60 || - code === 61 || - code === 62 || - code === 96 - ) { - return nok(code) - } + while ((match = expression.exec(value))) { + let position = match.index; - if (code === 34 || code === 39) { - effects.consume(code); - marker = code; - return completeAttributeValueQuoted - } + // Support CRLF (patterns only look for one of the characters). + if ( + value.charCodeAt(position) === 10 /* `\n` */ && + value.charCodeAt(position - 1) === 13 /* `\r` */ + ) { + position--; + } - if (markdownSpace(code)) { - effects.consume(code); - return completeAttributeValueBefore + value = value.slice(0, position) + ' ' + value.slice(match.index + 1); } - - marker = null; - return completeAttributeValueUnquoted(code) } - /** @type {State} */ - function completeAttributeValueQuoted(code) { - if (code === null || markdownLineEnding(code)) { - return nok(code) - } + return sequence + value + sequence +} - if (code === marker) { - effects.consume(code); - return completeAttributeValueQuotedAfter - } +/** + * @type {Handle} + */ +function inlineCodePeek() { + return '`' +} - effects.consume(code); - return completeAttributeValueQuoted - } - /** @type {State} */ +/** + * @typedef {import('mdast').Link} Link + * @typedef {import('../types.js').Context} Context + */ - function completeAttributeValueUnquoted(code) { - if ( - code === null || - code === 34 || - code === 39 || - code === 60 || - code === 61 || - code === 62 || - code === 96 || - markdownLineEndingOrSpace(code) - ) { - return completeAttributeNameAfter(code) - } +/** + * @param {Link} node + * @param {Context} context + * @returns {boolean} + */ +function formatLinkAsAutolink(node, context) { + const raw = toString(node); - effects.consume(code); - return completeAttributeValueUnquoted - } - /** @type {State} */ + return Boolean( + !context.options.resourceLink && + // If there’s a url… + node.url && + // And there’s a no title… + !node.title && + // And the content of `node` is a single text node… + node.children && + node.children.length === 1 && + node.children[0].type === 'text' && + // And if the url is the same as the content… + (raw === node.url || 'mailto:' + raw === node.url) && + // And that starts w/ a protocol… + /^[a-z][a-z+.-]+:/i.test(node.url) && + // And that doesn’t contain ASCII control codes (character escapes and + // references don’t work) or angle brackets… + !/[\0- <>\u007F]/.test(node.url) + ) +} + +/** + * @typedef {import('mdast').Link} Link + * @typedef {import('../types.js').Handle} Handle + * @typedef {import('../types.js').Exit} Exit + */ - function completeAttributeValueQuotedAfter(code) { - if (code === 47 || code === 62 || markdownSpace(code)) { - return completeAttributeNameBefore(code) - } +link.peek = linkPeek; - return nok(code) +/** + * @type {Handle} + * @param {Link} node + */ +function link(node, _, context) { + const quote = checkQuote(context); + const suffix = quote === '"' ? 'Quote' : 'Apostrophe'; + /** @type {Exit} */ + let exit; + /** @type {Exit} */ + let subexit; + /** @type {string} */ + let value; + + if (formatLinkAsAutolink(node, context)) { + // Hide the fact that we’re in phrasing, because escapes don’t work. + const stack = context.stack; + context.stack = []; + exit = context.enter('autolink'); + value = + '<' + containerPhrasing(node, context, {before: '<', after: '>'}) + '>'; + exit(); + context.stack = stack; + return value } - /** @type {State} */ - function completeEnd(code) { - if (code === 62) { - effects.consume(code); - return completeAfter - } + exit = context.enter('link'); + subexit = context.enter('label'); + value = + '[' + containerPhrasing(node, context, {before: '[', after: ']'}) + ']('; + subexit(); - return nok(code) + if ( + // If there’s no url but there is a title… + (!node.url && node.title) || + // Or if there’s markdown whitespace or an eol, enclose. + /[ \t\r\n]/.test(node.url) + ) { + subexit = context.enter('destinationLiteral'); + value += '<' + safe(context, node.url, {before: '<', after: '>'}) + '>'; + } else { + // No whitespace, raw is prettier. + subexit = context.enter('destinationRaw'); + value += safe(context, node.url, { + before: '(', + after: node.title ? ' ' : ')' + }); } - /** @type {State} */ - function completeAfter(code) { - if (markdownSpace(code)) { - effects.consume(code); - return completeAfter - } + subexit(); - return code === null || markdownLineEnding(code) - ? continuation(code) - : nok(code) + if (node.title) { + subexit = context.enter('title' + suffix); + value += + ' ' + + quote + + safe(context, node.title, {before: quote, after: quote}) + + quote; + subexit(); } - /** @type {State} */ - function continuation(code) { - if (code === 45 && kind === 2) { - effects.consume(code); - return continuationCommentInside - } + value += ')'; - if (code === 60 && kind === 1) { - effects.consume(code); - return continuationRawTagOpen - } + exit(); + return value +} - if (code === 62 && kind === 4) { - effects.consume(code); - return continuationClose - } +/** + * @type {Handle} + * @param {Link} node + */ +function linkPeek(node, _, context) { + return formatLinkAsAutolink(node, context) ? '<' : '[' +} - if (code === 63 && kind === 3) { - effects.consume(code); - return continuationDeclarationInside - } +/** + * @typedef {import('mdast').LinkReference} LinkReference + * @typedef {import('../types.js').Handle} Handle + */ - if (code === 93 && kind === 5) { - effects.consume(code); - return continuationCharacterDataInside - } +linkReference.peek = linkReferencePeek; - if (markdownLineEnding(code) && (kind === 6 || kind === 7)) { - return effects.check( - nextBlankConstruct, - continuationClose, - continuationAtLineEnding - )(code) - } +/** + * @type {Handle} + * @param {LinkReference} node + */ +function linkReference(node, _, context) { + const type = node.referenceType; + const exit = context.enter('linkReference'); + let subexit = context.enter('label'); + const text = containerPhrasing(node, context, {before: '[', after: ']'}); + let value = '[' + text + ']'; - if (code === null || markdownLineEnding(code)) { - return continuationAtLineEnding(code) - } + subexit(); + // Hide the fact that we’re in phrasing, because escapes don’t work. + const stack = context.stack; + context.stack = []; + subexit = context.enter('reference'); + const reference = safe(context, association(node), {before: '[', after: ']'}); + subexit(); + context.stack = stack; + exit(); - effects.consume(code); - return continuation + if (type === 'full' || !text || text !== reference) { + value += '[' + reference + ']'; + } else if (type !== 'shortcut') { + value += '[]'; } - /** @type {State} */ - function continuationAtLineEnding(code) { - effects.exit('htmlFlowData'); - return htmlContinueStart(code) - } - /** @type {State} */ + return value +} - function htmlContinueStart(code) { - if (code === null) { - return done(code) - } +/** + * @type {Handle} + */ +function linkReferencePeek() { + return '[' +} - if (markdownLineEnding(code)) { - return effects.attempt( - { - tokenize: htmlLineEnd, - partial: true - }, - htmlContinueStart, - done - )(code) - } +/** + * @typedef {import('../types.js').Context} Context + * @typedef {import('../types.js').Options} Options + */ - effects.enter('htmlFlowData'); - return continuation(code) - } - /** @type {Tokenizer} */ +/** + * @param {Context} context + * @returns {Exclude} + */ +function checkBullet(context) { + const marker = context.options.bullet || '*'; - function htmlLineEnd(effects, ok, nok) { - return start - /** @type {State} */ + if (marker !== '*' && marker !== '+' && marker !== '-') { + throw new Error( + 'Cannot serialize items with `' + + marker + + '` for `options.bullet`, expected `*`, `+`, or `-`' + ) + } - function start(code) { - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - return lineStart - } - /** @type {State} */ + return marker +} - function lineStart(code) { - return self.parser.lazy[self.now().line] ? nok(code) : ok(code) - } - } - /** @type {State} */ +/** + * @typedef {import('../types.js').Context} Context + * @typedef {import('../types.js').Options} Options + */ - function continuationCommentInside(code) { - if (code === 45) { - effects.consume(code); - return continuationDeclarationInside - } +/** + * @param {Context} context + * @returns {Exclude} + */ +function checkBulletOther(context) { + const bullet = checkBullet(context); + const bulletOther = context.options.bulletOther; - return continuation(code) + if (!bulletOther) { + return bullet === '*' ? '-' : '*' } - /** @type {State} */ - function continuationRawTagOpen(code) { - if (code === 47) { - effects.consume(code); - buffer = ''; - return continuationRawEndTag - } + if (bulletOther !== '*' && bulletOther !== '+' && bulletOther !== '-') { + throw new Error( + 'Cannot serialize items with `' + + bulletOther + + '` for `options.bulletOther`, expected `*`, `+`, or `-`' + ) + } - return continuation(code) + if (bulletOther === bullet) { + throw new Error( + 'Expected `bullet` (`' + + bullet + + '`) and `bulletOther` (`' + + bulletOther + + '`) to be different' + ) } - /** @type {State} */ - function continuationRawEndTag(code) { - if (code === 62 && htmlRawNames.includes(buffer.toLowerCase())) { - effects.consume(code); - return continuationClose - } + return bulletOther +} - if (asciiAlpha(code) && buffer.length < 8) { - effects.consume(code); - buffer += String.fromCharCode(code); - return continuationRawEndTag - } +/** + * @typedef {import('../types.js').Context} Context + * @typedef {import('../types.js').Options} Options + */ - return continuation(code) +/** + * @param {Context} context + * @returns {Exclude} + */ +function checkBulletOrdered(context) { + const marker = context.options.bulletOrdered || '.'; + + if (marker !== '.' && marker !== ')') { + throw new Error( + 'Cannot serialize items with `' + + marker + + '` for `options.bulletOrdered`, expected `.` or `)`' + ) } - /** @type {State} */ - function continuationCharacterDataInside(code) { - if (code === 93) { - effects.consume(code); - return continuationDeclarationInside - } + return marker +} - return continuation(code) - } - /** @type {State} */ +/** + * @typedef {import('../types.js').Context} Context + * @typedef {import('../types.js').Options} Options + */ - function continuationDeclarationInside(code) { - if (code === 62) { - effects.consume(code); - return continuationClose - } +/** + * @param {Context} context + * @returns {Exclude} + */ +function checkBulletOrderedOther(context) { + const bulletOrdered = checkBulletOrdered(context); + const bulletOrderedOther = context.options.bulletOrderedOther; - return continuation(code) + if (!bulletOrderedOther) { + return bulletOrdered === '.' ? ')' : '.' } - /** @type {State} */ - function continuationClose(code) { - if (code === null || markdownLineEnding(code)) { - effects.exit('htmlFlowData'); - return done(code) - } - - effects.consume(code); - return continuationClose + if (bulletOrderedOther !== '.' && bulletOrderedOther !== ')') { + throw new Error( + 'Cannot serialize items with `' + + bulletOrderedOther + + '` for `options.bulletOrderedOther`, expected `*`, `+`, or `-`' + ) } - /** @type {State} */ - function done(code) { - effects.exit('htmlFlow'); - return ok(code) + if (bulletOrderedOther === bulletOrdered) { + throw new Error( + 'Expected `bulletOrdered` (`' + + bulletOrdered + + '`) and `bulletOrderedOther` (`' + + bulletOrderedOther + + '`) to be different' + ) } + + return bulletOrderedOther } -/** @type {Tokenizer} */ -function tokenizeNextBlank(effects, ok, nok) { - return start - /** @type {State} */ +/** + * @typedef {import('../types.js').Context} Context + * @typedef {import('../types.js').Options} Options + */ - function start(code) { - effects.exit('htmlFlowData'); - effects.enter('lineEndingBlank'); - effects.consume(code); - effects.exit('lineEndingBlank'); - return effects.attempt(blankLine, ok, nok) +/** + * @param {Context} context + * @returns {Exclude} + */ +function checkRule(context) { + const marker = context.options.rule || '*'; + + if (marker !== '*' && marker !== '-' && marker !== '_') { + throw new Error( + 'Cannot serialize rules with `' + + marker + + '` for `options.rule`, expected `*`, `-`, or `_`' + ) } + + return marker } /** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State - * @typedef {import('micromark-util-types').Code} Code + * @typedef {import('mdast').List} List + * @typedef {import('../types.js').Handle} Handle */ -/** @type {Construct} */ -const htmlText = { - name: 'htmlText', - tokenize: tokenizeHtmlText -}; -/** @type {Tokenizer} */ +/** + * @type {Handle} + * @param {List} node + */ +function list(node, parent, context) { + const exit = context.enter('list'); + const bulletCurrent = context.bulletCurrent; + /** @type {string} */ + let bullet = node.ordered ? checkBulletOrdered(context) : checkBullet(context); + /** @type {string} */ + const bulletOther = node.ordered + ? checkBulletOrderedOther(context) + : checkBulletOther(context); + const bulletLastUsed = context.bulletLastUsed; + let useDifferentMarker = false; -function tokenizeHtmlText(effects, ok, nok) { - const self = this; - /** @type {NonNullable|undefined} */ + if ( + parent && + // Explicit `other` set. + (node.ordered + ? context.options.bulletOrderedOther + : context.options.bulletOther) && + bulletLastUsed && + bullet === bulletLastUsed + ) { + useDifferentMarker = true; + } - let marker; - /** @type {string} */ + if (!node.ordered) { + const firstListItem = node.children ? node.children[0] : undefined; - let buffer; - /** @type {number} */ + // If there’s an empty first list item directly in two list items, + // we have to use a different bullet: + // + // ```markdown + // * - * + // ``` + // + // …because otherwise it would become one big thematic break. + if ( + // Bullet could be used as a thematic break marker: + (bullet === '*' || bullet === '-') && + // Empty first list item: + firstListItem && + (!firstListItem.children || !firstListItem.children[0]) && + // Directly in two other list items: + context.stack[context.stack.length - 1] === 'list' && + context.stack[context.stack.length - 2] === 'listItem' && + context.stack[context.stack.length - 3] === 'list' && + context.stack[context.stack.length - 4] === 'listItem' && + // That are each the first child. + context.indexStack[context.indexStack.length - 1] === 0 && + context.indexStack[context.indexStack.length - 2] === 0 && + context.indexStack[context.indexStack.length - 3] === 0 && + context.indexStack[context.indexStack.length - 4] === 0 + ) { + useDifferentMarker = true; + } - let index; - /** @type {State} */ + // If there’s a thematic break at the start of the first list item, + // we have to use a different bullet: + // + // ```markdown + // * --- + // ``` + // + // …because otherwise it would become one big thematic break. + if (checkRule(context) === bullet && firstListItem) { + let index = -1; - let returnState; - return start - /** @type {State} */ + while (++index < node.children.length) { + const item = node.children[index]; - function start(code) { - effects.enter('htmlText'); - effects.enter('htmlTextData'); - effects.consume(code); - return open + if ( + item && + item.type === 'listItem' && + item.children && + item.children[0] && + item.children[0].type === 'thematicBreak' + ) { + useDifferentMarker = true; + break + } + } + } } - /** @type {State} */ - function open(code) { - if (code === 33) { - effects.consume(code); - return declarationOpen - } + if (useDifferentMarker) { + bullet = bulletOther; + } - if (code === 47) { - effects.consume(code); - return tagCloseStart - } + context.bulletCurrent = bullet; + const value = containerFlow(node, context); + context.bulletLastUsed = bullet; + context.bulletCurrent = bulletCurrent; + exit(); + return value +} - if (code === 63) { - effects.consume(code); - return instruction - } +/** + * @typedef {import('../types.js').Context} Context + * @typedef {import('../types.js').Options} Options + */ - if (asciiAlpha(code)) { - effects.consume(code); - return tagOpen - } +/** + * @param {Context} context + * @returns {Exclude} + */ +function checkListItemIndent(context) { + const style = context.options.listItemIndent || 'tab'; - return nok(code) + // To do: remove in a major. + // @ts-expect-error: deprecated. + if (style === 1 || style === '1') { + return 'one' } - /** @type {State} */ - function declarationOpen(code) { - if (code === 45) { - effects.consume(code); - return commentOpen - } + if (style !== 'tab' && style !== 'one' && style !== 'mixed') { + throw new Error( + 'Cannot serialize items with `' + + style + + '` for `options.listItemIndent`, expected `tab`, `one`, or `mixed`' + ) + } - if (code === 91) { - effects.consume(code); - buffer = 'CDATA['; - index = 0; - return cdataOpen - } + return style +} - if (asciiAlpha(code)) { - effects.consume(code); - return declaration - } +/** + * @typedef {import('mdast').ListItem} ListItem + * @typedef {import('mdast').List} List + * @typedef {import('../util/indent-lines.js').Map} Map + * @typedef {import('../types.js').Options} Options + * @typedef {import('../types.js').Handle} Handle + */ - return nok(code) +/** + * @type {Handle} + * @param {ListItem} node + */ +function listItem(node, parent, context) { + const listItemIndent = checkListItemIndent(context); + let bullet = context.bulletCurrent || checkBullet(context); + + // Add the marker value for ordered lists. + if (parent && parent.type === 'list' && parent.ordered) { + bullet = + (typeof parent.start === 'number' && parent.start > -1 + ? parent.start + : 1) + + (context.options.incrementListMarker === false + ? 0 + : parent.children.indexOf(node)) + + bullet; } - /** @type {State} */ - function commentOpen(code) { - if (code === 45) { - effects.consume(code); - return commentStart - } + let size = bullet.length + 1; - return nok(code) + if ( + listItemIndent === 'tab' || + (listItemIndent === 'mixed' && + ((parent && parent.type === 'list' && parent.spread) || node.spread)) + ) { + size = Math.ceil(size / 4) * 4; } - /** @type {State} */ - - function commentStart(code) { - if (code === null || code === 62) { - return nok(code) - } - if (code === 45) { - effects.consume(code); - return commentStartDash - } + const exit = context.enter('listItem'); + const value = indentLines(containerFlow(node, context), map); + exit(); - return comment(code) - } - /** @type {State} */ + return value - function commentStartDash(code) { - if (code === null || code === 62) { - return nok(code) + /** @type {Map} */ + function map(line, index, blank) { + if (index) { + return (blank ? '' : ' '.repeat(size)) + line } - return comment(code) + return (blank ? bullet : bullet + ' '.repeat(size - bullet.length)) + line } - /** @type {State} */ - - function comment(code) { - if (code === null) { - return nok(code) - } +} - if (code === 45) { - effects.consume(code); - return commentClose - } +/** + * @typedef {import('mdast').Paragraph} Paragraph + * @typedef {import('../types.js').Handle} Handle + */ - if (markdownLineEnding(code)) { - returnState = comment; - return atLineEnding(code) - } +/** + * @type {Handle} + * @param {Paragraph} node + */ +function paragraph(node, _, context) { + const exit = context.enter('paragraph'); + const subexit = context.enter('phrasing'); + const value = containerPhrasing(node, context, {before: '\n', after: '\n'}); + subexit(); + exit(); + return value +} - effects.consume(code); - return comment - } - /** @type {State} */ +/** + * @typedef {import('mdast').Root} Root + * @typedef {import('../types.js').Handle} Handle + */ - function commentClose(code) { - if (code === 45) { - effects.consume(code); - return end - } +/** + * @type {Handle} + * @param {Root} node + */ +function root(node, _, context) { + return containerFlow(node, context) +} - return comment(code) - } - /** @type {State} */ +/** + * @typedef {import('../types.js').Context} Context + * @typedef {import('../types.js').Options} Options + */ - function cdataOpen(code) { - if (code === buffer.charCodeAt(index++)) { - effects.consume(code); - return index === buffer.length ? cdata : cdataOpen - } +/** + * @param {Context} context + * @returns {Exclude} + */ +function checkStrong(context) { + const marker = context.options.strong || '*'; - return nok(code) + if (marker !== '*' && marker !== '_') { + throw new Error( + 'Cannot serialize strong with `' + + marker + + '` for `options.strong`, expected `*`, or `_`' + ) } - /** @type {State} */ - function cdata(code) { - if (code === null) { - return nok(code) - } + return marker +} - if (code === 93) { - effects.consume(code); - return cdataClose - } +/** + * @typedef {import('mdast').Strong} Strong + * @typedef {import('../types.js').Handle} Handle + */ - if (markdownLineEnding(code)) { - returnState = cdata; - return atLineEnding(code) - } +strong.peek = strongPeek; - effects.consume(code); - return cdata - } - /** @type {State} */ +// To do: there are cases where emphasis cannot “form” depending on the +// previous or next character of sequences. +// There’s no way around that though, except for injecting zero-width stuff. +// Do we need to safeguard against that? +/** + * @type {Handle} + * @param {Strong} node + */ +function strong(node, _, context) { + const marker = checkStrong(context); + const exit = context.enter('strong'); + const value = containerPhrasing(node, context, { + before: marker, + after: marker + }); + exit(); + return marker + marker + value + marker + marker +} - function cdataClose(code) { - if (code === 93) { - effects.consume(code); - return cdataEnd - } +/** + * @type {Handle} + * @param {Strong} _ + */ +function strongPeek(_, _1, context) { + return context.options.strong || '*' +} - return cdata(code) - } - /** @type {State} */ +/** + * @typedef {import('mdast').Text} Text + * @typedef {import('../types.js').Handle} Handle + */ - function cdataEnd(code) { - if (code === 62) { - return end(code) - } +/** + * @type {Handle} + * @param {Text} node + */ +function text$1(node, _, context, safeOptions) { + return safe(context, node.value, safeOptions) +} - if (code === 93) { - effects.consume(code); - return cdataEnd - } +/** + * @typedef {import('../types.js').Context} Context + * @typedef {import('../types.js').Options} Options + */ - return cdata(code) +/** + * @param {Context} context + * @returns {Exclude} + */ +function checkRuleRepetition(context) { + const repetition = context.options.ruleRepetition || 3; + + if (repetition < 3) { + throw new Error( + 'Cannot serialize rules with repetition `' + + repetition + + '` for `options.ruleRepetition`, expected `3` or more' + ) } - /** @type {State} */ - function declaration(code) { - if (code === null || code === 62) { - return end(code) - } + return repetition +} - if (markdownLineEnding(code)) { - returnState = declaration; - return atLineEnding(code) - } +/** + * @typedef {import('../types.js').Handle} Handle + * @typedef {import('mdast').ThematicBreak} ThematicBreak + */ - effects.consume(code); - return declaration - } - /** @type {State} */ +/** + * @type {Handle} + * @param {ThematicBreak} _ + */ +function thematicBreak(_, _1, context) { + const value = ( + checkRule(context) + (context.options.ruleSpaces ? ' ' : '') + ).repeat(checkRuleRepetition(context)); - function instruction(code) { - if (code === null) { - return nok(code) - } + return context.options.ruleSpaces ? value.slice(0, -1) : value +} - if (code === 63) { - effects.consume(code); - return instructionClose - } +const handle = { + blockquote, + break: hardBreak, + code: code$1, + definition, + emphasis, + hardBreak, + heading, + html, + image, + imageReference, + inlineCode, + link, + linkReference, + list, + listItem, + paragraph, + root, + strong, + text: text$1, + thematicBreak +}; - if (markdownLineEnding(code)) { - returnState = instruction; - return atLineEnding(code) - } +/** + * @typedef {import('./types.js').Join} Join + */ - effects.consume(code); - return instruction - } - /** @type {State} */ +/** @type {Array.} */ +const join = [joinDefaults]; - function instructionClose(code) { - return code === 62 ? end(code) : instruction(code) +/** @type {Join} */ +function joinDefaults(left, right, parent, context) { + // Indented code after list or another indented code. + if ( + right.type === 'code' && + formatCodeAsIndented(right, context) && + (left.type === 'list' || + (left.type === right.type && formatCodeAsIndented(left, context))) + ) { + return false } - /** @type {State} */ - - function tagCloseStart(code) { - if (asciiAlpha(code)) { - effects.consume(code); - return tagClose - } - return nok(code) + // Two lists with the same marker. + if ( + left.type === 'list' && + left.type === right.type && + Boolean(left.ordered) === Boolean(right.ordered) && + !(left.ordered + ? context.options.bulletOrderedOther + : context.options.bulletOther) + ) { + return false } - /** @type {State} */ - function tagClose(code) { - if (code === 45 || asciiAlphanumeric(code)) { - effects.consume(code); - return tagClose + // Join children of a list or an item. + // In which case, `parent` has a `spread` field. + if ('spread' in parent && typeof parent.spread === 'boolean') { + if ( + left.type === 'paragraph' && + // Two paragraphs. + (left.type === right.type || + right.type === 'definition' || + // Paragraph followed by a setext heading. + (right.type === 'heading' && formatHeadingAsSetext(right, context))) + ) { + return } - return tagCloseBetween(code) + return parent.spread ? 1 : 0 } - /** @type {State} */ +} - function tagCloseBetween(code) { - if (markdownLineEnding(code)) { - returnState = tagCloseBetween; - return atLineEnding(code) - } +/** + * @typedef {import('./types.js').Unsafe} Unsafe + */ - if (markdownSpace(code)) { - effects.consume(code); - return tagCloseBetween - } +/** @type {Array.} */ +const unsafe = [ + {character: '\t', after: '[\\r\\n]', inConstruct: 'phrasing'}, + {character: '\t', before: '[\\r\\n]', inConstruct: 'phrasing'}, + { + character: '\t', + inConstruct: ['codeFencedLangGraveAccent', 'codeFencedLangTilde'] + }, + { + character: '\r', + inConstruct: [ + 'codeFencedLangGraveAccent', + 'codeFencedLangTilde', + 'codeFencedMetaGraveAccent', + 'codeFencedMetaTilde', + 'destinationLiteral', + 'headingAtx' + ] + }, + { + character: '\n', + inConstruct: [ + 'codeFencedLangGraveAccent', + 'codeFencedLangTilde', + 'codeFencedMetaGraveAccent', + 'codeFencedMetaTilde', + 'destinationLiteral', + 'headingAtx' + ] + }, + {character: ' ', after: '[\\r\\n]', inConstruct: 'phrasing'}, + {character: ' ', before: '[\\r\\n]', inConstruct: 'phrasing'}, + { + character: ' ', + inConstruct: ['codeFencedLangGraveAccent', 'codeFencedLangTilde'] + }, + // An exclamation mark can start an image, if it is followed by a link or + // a link reference. + {character: '!', after: '\\[', inConstruct: 'phrasing'}, + // A quote can break out of a title. + {character: '"', inConstruct: 'titleQuote'}, + // A number sign could start an ATX heading if it starts a line. + {atBreak: true, character: '#'}, + {character: '#', inConstruct: 'headingAtx', after: '(?:[\r\n]|$)'}, + // Dollar sign and percentage are not used in markdown. + // An ampersand could start a character reference. + {character: '&', after: '[#A-Za-z]', inConstruct: 'phrasing'}, + // An apostrophe can break out of a title. + {character: "'", inConstruct: 'titleApostrophe'}, + // A left paren could break out of a destination raw. + {character: '(', inConstruct: 'destinationRaw'}, + {before: '\\]', character: '(', inConstruct: 'phrasing'}, + // A right paren could start a list item or break out of a destination + // raw. + {atBreak: true, before: '\\d+', character: ')'}, + {character: ')', inConstruct: 'destinationRaw'}, + // An asterisk can start thematic breaks, list items, emphasis, strong. + {atBreak: true, character: '*'}, + {character: '*', inConstruct: 'phrasing'}, + // A plus sign could start a list item. + {atBreak: true, character: '+'}, + // A dash can start thematic breaks, list items, and setext heading + // underlines. + {atBreak: true, character: '-'}, + // A dot could start a list item. + {atBreak: true, before: '\\d+', character: '.', after: '(?:[ \t\r\n]|$)'}, + // Slash, colon, and semicolon are not used in markdown for constructs. + // A less than can start html (flow or text) or an autolink. + // HTML could start with an exclamation mark (declaration, cdata, comment), + // slash (closing tag), question mark (instruction), or a letter (tag). + // An autolink also starts with a letter. + // Finally, it could break out of a destination literal. + {atBreak: true, character: '<', after: '[!/?A-Za-z]'}, + {character: '<', after: '[!/?A-Za-z]', inConstruct: 'phrasing'}, + {character: '<', inConstruct: 'destinationLiteral'}, + // An equals to can start setext heading underlines. + {atBreak: true, character: '='}, + // A greater than can start block quotes and it can break out of a + // destination literal. + {atBreak: true, character: '>'}, + {character: '>', inConstruct: 'destinationLiteral'}, + // Question mark and at sign are not used in markdown for constructs. + // A left bracket can start definitions, references, labels, + {atBreak: true, character: '['}, + {character: '[', inConstruct: ['phrasing', 'label', 'reference']}, + // A backslash can start an escape (when followed by punctuation) or a + // hard break (when followed by an eol). + // Note: typical escapes are handled in `safe`! + {character: '\\', after: '[\\r\\n]', inConstruct: 'phrasing'}, + // A right bracket can exit labels. + {character: ']', inConstruct: ['label', 'reference']}, + // Caret is not used in markdown for constructs. + // An underscore can start emphasis, strong, or a thematic break. + {atBreak: true, character: '_'}, + {character: '_', inConstruct: 'phrasing'}, + // A grave accent can start code (fenced or text), or it can break out of + // a grave accent code fence. + {atBreak: true, character: '`'}, + { + character: '`', + inConstruct: [ + 'codeFencedLangGraveAccent', + 'codeFencedMetaGraveAccent', + 'phrasing' + ] + }, + // Left brace, vertical bar, right brace are not used in markdown for + // constructs. + // A tilde can start code (fenced). + {atBreak: true, character: '~'} +]; - return end(code) - } - /** @type {State} */ +/** + * @typedef {import('./types.js').Node} Node + * @typedef {import('./types.js').Options} Options + * @typedef {import('./types.js').Context} Context + * @typedef {import('./types.js').Handle} Handle + * @typedef {import('./types.js').Join} Join + * @typedef {import('./types.js').Unsafe} Unsafe + */ - function tagOpen(code) { - if (code === 45 || asciiAlphanumeric(code)) { - effects.consume(code); - return tagOpen - } +/** + * @param {Node} tree + * @param {Options} [options] + * @returns {string} + */ +function toMarkdown(tree, options = {}) { + /** @type {Context} */ + // @ts-expect-error: we’ll add `handle` later. + const context = { + enter, + stack: [], + unsafe: [], + join: [], + handlers: {}, + options: {}, + indexStack: [] + }; - if (code === 47 || code === 62 || markdownLineEndingOrSpace(code)) { - return tagOpenBetween(code) - } + configure(context, {unsafe, join, handlers: handle}); + configure(context, options); - return nok(code) + if (context.options.tightDefinitions) { + configure(context, {join: [joinDefinition]}); } - /** @type {State} */ - - function tagOpenBetween(code) { - if (code === 47) { - effects.consume(code); - return end - } - - if (code === 58 || code === 95 || asciiAlpha(code)) { - effects.consume(code); - return tagOpenAttributeName - } - if (markdownLineEnding(code)) { - returnState = tagOpenBetween; - return atLineEnding(code) - } + /** @type {Handle} */ + context.handle = zwitch('type', { + invalid, + // @ts-expect-error: hush. + unknown, + // @ts-expect-error: hush. + handlers: context.handlers + }); - if (markdownSpace(code)) { - effects.consume(code); - return tagOpenBetween - } + let result = context.handle(tree, null, context, {before: '\n', after: '\n'}); - return end(code) + if ( + result && + result.charCodeAt(result.length - 1) !== 10 && + result.charCodeAt(result.length - 1) !== 13 + ) { + result += '\n'; } - /** @type {State} */ - function tagOpenAttributeName(code) { - if ( - code === 45 || - code === 46 || - code === 58 || - code === 95 || - asciiAlphanumeric(code) - ) { - effects.consume(code); - return tagOpenAttributeName - } + return result - return tagOpenAttributeNameAfter(code) - } - /** @type {State} */ + /** @type {Context['enter']} */ + function enter(name) { + context.stack.push(name); + return exit - function tagOpenAttributeNameAfter(code) { - if (code === 61) { - effects.consume(code); - return tagOpenAttributeValueBefore + function exit() { + context.stack.pop(); } + } +} - if (markdownLineEnding(code)) { - returnState = tagOpenAttributeNameAfter; - return atLineEnding(code) - } +/** + * @type {Handle} + * @param {unknown} value + */ +function invalid(value) { + throw new Error('Cannot handle value `' + value + '`, expected node') +} - if (markdownSpace(code)) { - effects.consume(code); - return tagOpenAttributeNameAfter - } +/** + * @type {Handle} + * @param {Node} node + */ +function unknown(node) { + throw new Error('Cannot handle unknown node `' + node.type + '`') +} - return tagOpenBetween(code) +/** @type {Join} */ +function joinDefinition(left, right) { + // No blank line between adjacent definitions. + if (left.type === 'definition' && left.type === right.type) { + return 0 } - /** @type {State} */ - - function tagOpenAttributeValueBefore(code) { - if ( - code === null || - code === 60 || - code === 61 || - code === 62 || - code === 96 - ) { - return nok(code) - } - - if (code === 34 || code === 39) { - effects.consume(code); - marker = code; - return tagOpenAttributeValueQuoted - } +} - if (markdownLineEnding(code)) { - returnState = tagOpenAttributeValueBefore; - return atLineEnding(code) - } +/** + * @typedef {import('mdast').Root|import('mdast').Content} Node + * @typedef {import('mdast-util-to-markdown').Options} Options + */ - if (markdownSpace(code)) { - effects.consume(code); - return tagOpenAttributeValueBefore - } +/** @type {import('unified').Plugin<[Options]|void[], Node, string>} */ +function remarkStringify(options) { + /** @type {import('unified').CompilerFunction} */ + const compiler = (tree) => { + // Assume options. + const settings = /** @type {Options} */ (this.data('settings')); - effects.consume(code); - marker = undefined; - return tagOpenAttributeValueUnquoted - } - /** @type {State} */ + return toMarkdown( + tree, + Object.assign({}, settings, options, { + // Note: this option is not in the readme. + // The goal is for it to be set by plugins on `data` instead of being + // passed by users. + extensions: this.data('toMarkdownExtensions') || [] + }) + ) + }; - function tagOpenAttributeValueQuoted(code) { - if (code === marker) { - effects.consume(code); - return tagOpenAttributeValueQuotedAfter - } + Object.assign(this, {Compiler: compiler}); +} - if (code === null) { - return nok(code) - } +/** + * @typedef {import('unist').Point} Point + * @typedef {import('vfile').VFile} VFile + * + * @typedef {Pick} PositionalPoint + * @typedef {Required} FullPoint + * @typedef {NonNullable} Offset + */ - if (markdownLineEnding(code)) { - returnState = tagOpenAttributeValueQuoted; - return atLineEnding(code) - } +/** + * Get transform functions for the given `document`. + * + * @param {string|Uint8Array|VFile} file + */ +function location(file) { + var value = String(file); + /** @type {Array.} */ + var indices = []; + var search = /\r?\n|\r/g; - effects.consume(code); - return tagOpenAttributeValueQuoted + while (search.test(value)) { + indices.push(search.lastIndex); } - /** @type {State} */ - function tagOpenAttributeValueQuotedAfter(code) { - if (code === 62 || code === 47 || markdownLineEndingOrSpace(code)) { - return tagOpenBetween(code) - } + indices.push(value.length + 1); - return nok(code) - } - /** @type {State} */ + return {toPoint, toOffset} - function tagOpenAttributeValueUnquoted(code) { - if ( - code === null || - code === 34 || - code === 39 || - code === 60 || - code === 61 || - code === 96 - ) { - return nok(code) - } + /** + * Get the line and column-based `point` for `offset` in the bound indices. + * Returns a point with `undefined` values when given invalid or out of bounds + * input. + * + * @param {Offset} offset + * @returns {FullPoint} + */ + function toPoint(offset) { + var index = -1; - if (code === 62 || markdownLineEndingOrSpace(code)) { - return tagOpenBetween(code) + if (offset > -1 && offset < indices[indices.length - 1]) { + while (++index < indices.length) { + if (indices[index] > offset) { + return { + line: index + 1, + column: offset - (indices[index - 1] || 0) + 1, + offset + } + } + } } - effects.consume(code); - return tagOpenAttributeValueUnquoted - } // We can’t have blank lines in content, so no need to worry about empty - // tokens. - - /** @type {State} */ - - function atLineEnding(code) { - effects.exit('htmlTextData'); - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - return factorySpace( - effects, - afterPrefix, - 'linePrefix', - self.parser.constructs.disable.null.includes('codeIndented') - ? undefined - : 4 - ) + return {line: undefined, column: undefined, offset: undefined} } - /** @type {State} */ - function afterPrefix(code) { - effects.enter('htmlTextData'); - return returnState(code) - } - /** @type {State} */ + /** + * Get the `offset` for a line and column-based `point` in the bound indices. + * Returns `-1` when given invalid or out of bounds input. + * + * @param {PositionalPoint} point + * @returns {Offset} + */ + function toOffset(point) { + var line = point && point.line; + var column = point && point.column; + /** @type {number} */ + var offset; - function end(code) { - if (code === 62) { - effects.consume(code); - effects.exit('htmlTextData'); - effects.exit('htmlText'); - return ok + if ( + typeof line === 'number' && + typeof column === 'number' && + !Number.isNaN(line) && + !Number.isNaN(column) && + line - 1 in indices + ) { + offset = (indices[line - 2] || 0) + column - 1 || 0; } - return nok(code) + return offset > -1 && offset < indices[indices.length - 1] ? offset : -1 } } /** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Resolver} Resolver - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').Event} Event - * @typedef {import('micromark-util-types').Token} Token - * @typedef {import('micromark-util-types').State} State - * @typedef {import('micromark-util-types').Code} Code + * @param {string} d + * @returns {string} */ +function color(d) { + return '\u001B[33m' + d + '\u001B[39m' +} -/** @type {Construct} */ -const labelEnd = { - name: 'labelEnd', - tokenize: tokenizeLabelEnd, - resolveTo: resolveToLabelEnd, - resolveAll: resolveAllLabelEnd -}; -/** @type {Construct} */ - -const resourceConstruct = { - tokenize: tokenizeResource -}; -/** @type {Construct} */ +/** + * @typedef {import('unist').Node} Node + * @typedef {import('unist').Parent} Parent + * @typedef {import('unist-util-is').Test} Test + */ -const fullReferenceConstruct = { - tokenize: tokenizeFullReference -}; -/** @type {Construct} */ +/** + * Continue traversing as normal + */ +const CONTINUE = true; +/** + * Do not traverse this node’s children + */ +const SKIP = 'skip'; +/** + * Stop traversing immediately + */ +const EXIT = false; -const collapsedReferenceConstruct = { - tokenize: tokenizeCollapsedReference -}; -/** @type {Resolver} */ +const visitParents = + /** + * @type {( + * ((tree: Node, test: T['type']|Partial|import('unist-util-is').TestFunctionPredicate|Array.|import('unist-util-is').TestFunctionPredicate>, visitor: Visitor, reverse?: boolean) => void) & + * ((tree: Node, test: Test, visitor: Visitor, reverse?: boolean) => void) & + * ((tree: Node, visitor: Visitor, reverse?: boolean) => void) + * )} + */ + ( + /** + * Visit children of tree which pass a test + * + * @param {Node} tree Abstract syntax tree to walk + * @param {Test} test test Test node + * @param {Visitor} visitor Function to run for each node + * @param {boolean} [reverse] Fisit the tree in reverse, defaults to false + */ + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + // @ts-ignore no visitor given, so `visitor` is test. + visitor = test; + test = null; + } -function resolveAllLabelEnd(events) { - let index = -1; - /** @type {Token} */ + var is = convert(test); + var step = reverse ? -1 : 1; - let token; + factory(tree, null, [])(); - while (++index < events.length) { - token = events[index][1]; + /** + * @param {Node} node + * @param {number?} index + * @param {Array.} parents + */ + function factory(node, index, parents) { + /** @type {Object.} */ + var value = typeof node === 'object' && node !== null ? node : {}; + /** @type {string} */ + var name; - if ( - token.type === 'labelImage' || - token.type === 'labelLink' || - token.type === 'labelEnd' - ) { - // Remove the marker. - events.splice(index + 1, token.type === 'labelImage' ? 4 : 2); - token.type = 'data'; - index++; - } - } + if (typeof value.type === 'string') { + name = + typeof value.tagName === 'string' + ? value.tagName + : typeof value.name === 'string' + ? value.name + : undefined; - return events -} -/** @type {Resolver} */ + Object.defineProperty(visit, 'name', { + value: + 'node (' + + color(value.type + (name ? '<' + name + '>' : '')) + + ')' + }); + } -function resolveToLabelEnd(events, context) { - let index = events.length; - let offset = 0; - /** @type {Token} */ + return visit - let token; - /** @type {number|undefined} */ + function visit() { + /** @type {ActionTuple} */ + var result = []; + /** @type {ActionTuple} */ + var subresult; + /** @type {number} */ + var offset; + /** @type {Array.} */ + var grandparents; - let open; - /** @type {number|undefined} */ + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult(visitor(node, parents)); - let close; - /** @type {Event[]} */ + if (result[0] === EXIT) { + return result + } + } - let media; // Find an opening. + if (node.children && result[0] !== SKIP) { + // @ts-ignore looks like a parent. + offset = (reverse ? node.children.length : -1) + step; + // @ts-ignore looks like a parent. + grandparents = parents.concat(node); - while (index--) { - token = events[index][1]; + // @ts-ignore looks like a parent. + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); - if (open) { - // If we see another link, or inactive link label, we’ve been here before. - if ( - token.type === 'link' || - (token.type === 'labelLink' && token._inactive) - ) { - break - } // Mark other link openings as inactive, as we can’t have links in - // links. + if (subresult[0] === EXIT) { + return subresult + } - if (events[index][0] === 'enter' && token.type === 'labelLink') { - token._inactive = true; - } - } else if (close) { - if ( - events[index][0] === 'enter' && - (token.type === 'labelImage' || token.type === 'labelLink') && - !token._balanced - ) { - open = index; + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } - if (token.type !== 'labelLink') { - offset = 2; - break + return result } } - } else if (token.type === 'labelEnd') { - close = index; } - } - - const group = { - type: events[open][1].type === 'labelLink' ? 'link' : 'image', - start: Object.assign({}, events[open][1].start), - end: Object.assign({}, events[events.length - 1][1].end) - }; - const label = { - type: 'label', - start: Object.assign({}, events[open][1].start), - end: Object.assign({}, events[close][1].end) - }; - const text = { - type: 'labelText', - start: Object.assign({}, events[open + offset + 2][1].end), - end: Object.assign({}, events[close - 2][1].start) - }; - media = [ - ['enter', group, context], - ['enter', label, context] - ]; // Opening marker. - - media = push(media, events.slice(open + 1, open + offset + 3)); // Text open. - - media = push(media, [['enter', text, context]]); // Between. - - media = push( - media, - resolveAll( - context.parser.constructs.insideSpan.null, - events.slice(open + offset + 4, close - 3), - context - ) - ); // Text close, marker close, label close. + ); - media = push(media, [ - ['exit', text, context], - events[close - 2], - events[close - 1], - ['exit', label, context] - ]); // Reference, resource, or so. +/** + * @param {VisitorResult} value + * @returns {ActionTuple} + */ +function toResult(value) { + if (Array.isArray(value)) { + return value + } - media = push(media, events.slice(close + 1)); // Media close. + if (typeof value === 'number') { + return [CONTINUE, value] + } - media = push(media, [['exit', group, context]]); - splice(events, open, events.length, media); - return events + return [value] } -/** @type {Tokenizer} */ -function tokenizeLabelEnd(effects, ok, nok) { - const self = this; - let index = self.events.length; - /** @type {Token} */ +/** + * @typedef {import('unist').Node} Node + * @typedef {import('unist').Parent} Parent + * @typedef {import('unist-util-is').Test} Test + * @typedef {import('unist-util-visit-parents').VisitorResult} VisitorResult + */ - let labelStart; - /** @type {boolean} */ +const visit = + /** + * @type {( + * ((tree: Node, test: T['type']|Partial|import('unist-util-is').TestFunctionPredicate|Array.|import('unist-util-is').TestFunctionPredicate>, visitor: Visitor, reverse?: boolean) => void) & + * ((tree: Node, test: Test, visitor: Visitor, reverse?: boolean) => void) & + * ((tree: Node, visitor: Visitor, reverse?: boolean) => void) + * )} + */ + ( + /** + * Visit children of tree which pass a test + * + * @param {Node} tree Abstract syntax tree to walk + * @param {Test} test test Test node + * @param {Visitor} visitor Function to run for each node + * @param {boolean} [reverse] Fisit the tree in reverse, defaults to false + */ + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } - let defined; // Find an opening. + visitParents(tree, test, overload, reverse); - while (index--) { - if ( - (self.events[index][1].type === 'labelImage' || - self.events[index][1].type === 'labelLink') && - !self.events[index][1]._balanced - ) { - labelStart = self.events[index][1]; - break + /** + * @param {Node} node + * @param {Array.} parents + */ + function overload(node, parents) { + var parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } } - } + ); - return start - /** @type {State} */ +/** + * @typedef {import('unist').Node} Node + * @typedef {import('unist').Parent} Parent + * @typedef {import('unist').Point} Point + * @typedef {import('unist-util-is').Test} Test + * @typedef {import('vfile').VFile} VFile + * @typedef {import('vfile-message').VFileMessage} VFileMessage + * + * @typedef {OptionsWithoutReset|OptionsWithReset} Options + * @typedef {OptionsBaseFields & OptionsWithoutResetFields} OptionsWithoutReset + * @typedef {OptionsBaseFields & OptionsWithResetFields} OptionsWithReset + * + * @typedef OptionsWithoutResetFields + * @property {false} [reset] + * Whether to treat all messages as turned off initially. + * @property {string[]} [disable] + * List of `ruleId`s to turn off. + * + * @typedef OptionsWithResetFields + * @property {true} reset + * Whether to treat all messages as turned off initially. + * @property {string[]} [enable] + * List of `ruleId`s to initially turn on. + * + * @typedef OptionsBaseFields + * @property {string} name + * Name of markers that can control the message sources. + * + * For example, `{name: 'alpha'}` controls `alpha` markers: + * + * ```html + * + * ``` + * @property {MarkerParser} marker + * Parse a possible marker to a comment marker object (Marker). + * If the marker isn't a marker, should return `null`. + * @property {Test} [test] + * Test for possible markers + * @property {string[]} [known] + * List of allowed `ruleId`s. When given a warning is shown + * when someone tries to control an unknown rule. + * + * For example, `{name: 'alpha', known: ['bravo']}` results in a warning if + * `charlie` is configured: + * + * ```html + * + * ``` + * @property {string|string[]} [source] + * Sources that can be controlled with `name` markers. + * Defaults to `name`. + * + * @callback MarkerParser + * Parse a possible comment marker node to a Marker. + * @param {Node} node + * Node to parse + * + * @typedef Marker + * A comment marker. + * @property {string} name + * Name of marker. + * @property {string} attributes + * Value after name. + * @property {Record} parameters + * Parsed attributes. + * @property {Node} node + * Reference to given node. + * + * @typedef Mark + * @property {Point|undefined} point + * @property {boolean} state + */ - function start(code) { - if (!labelStart) { - return nok(code) - } // It’s a balanced bracket, but contains a link. +const own$3 = {}.hasOwnProperty; - if (labelStart._inactive) return balanced(code) - defined = self.parser.defined.includes( - normalizeIdentifier( - self.sliceSerialize({ - start: labelStart.end, - end: self.now() - }) - ) - ); - effects.enter('labelEnd'); - effects.enter('labelMarker'); - effects.consume(code); - effects.exit('labelMarker'); - effects.exit('labelEnd'); - return afterLabelEnd +/** + * @type {import('unified').Plugin<[Options]>} + * @returns {(tree: Node, file: VFile) => void} + */ +function messageControl(options) { + if (!options || typeof options !== 'object' || !options.name) { + throw new Error( + 'Expected `name` in `options`, got `' + (options || {}).name + '`' + ) } - /** @type {State} */ - - function afterLabelEnd(code) { - // Resource: `[asd](fgh)`. - if (code === 40) { - return effects.attempt( - resourceConstruct, - ok, - defined ? ok : balanced - )(code) - } // Collapsed (`[asd][]`) or full (`[asd][fgh]`) reference? - - if (code === 91) { - return effects.attempt( - fullReferenceConstruct, - ok, - defined - ? effects.attempt(collapsedReferenceConstruct, ok, balanced) - : balanced - )(code) - } // Shortcut reference: `[asd]`? - return defined ? ok(code) : balanced(code) + if (!options.marker) { + throw new Error( + 'Expected `marker` in `options`, got `' + options.marker + '`' + ) } - /** @type {State} */ - function balanced(code) { - labelStart._balanced = true; - return nok(code) - } -} -/** @type {Tokenizer} */ + const enable = 'enable' in options && options.enable ? options.enable : []; + const disable = 'disable' in options && options.disable ? options.disable : []; + let reset = options.reset; + const sources = + typeof options.source === 'string' + ? [options.source] + : options.source || [options.name]; -function tokenizeResource(effects, ok, nok) { - return start - /** @type {State} */ + return transformer - function start(code) { - effects.enter('resource'); - effects.enter('resourceMarker'); - effects.consume(code); - effects.exit('resourceMarker'); - return factoryWhitespace(effects, open) - } - /** @type {State} */ + /** + * @param {Node} tree + * @param {VFile} file + */ + function transformer(tree, file) { + const toOffset = location(file).toOffset; + const initial = !reset; + const gaps = detectGaps(tree, file); + /** @type {Record} */ + const scope = {}; + /** @type {Mark[]} */ + const globals = []; - function open(code) { - if (code === 41) { - return end(code) - } + visit(tree, options.test, visitor); - return factoryDestination( - effects, - destinationAfter, - nok, - 'resourceDestination', - 'resourceDestinationLiteral', - 'resourceDestinationLiteralMarker', - 'resourceDestinationRaw', - 'resourceDestinationString', - 3 - )(code) - } - /** @type {State} */ + file.messages = file.messages.filter((m) => filter(m)); - function destinationAfter(code) { - return markdownLineEndingOrSpace(code) - ? factoryWhitespace(effects, between)(code) - : end(code) - } - /** @type {State} */ + /** + * @param {Node} node + * @param {number|null} position + * @param {Parent|null} parent + */ + function visitor(node, position, parent) { + /** @type {Marker|null} */ + const mark = options.marker(node); - function between(code) { - if (code === 34 || code === 39 || code === 40) { - return factoryTitle( - effects, - factoryWhitespace(effects, end), - nok, - 'resourceTitle', - 'resourceTitleMarker', - 'resourceTitleString' - )(code) - } + if (!mark || mark.name !== options.name) { + return + } - return end(code) - } - /** @type {State} */ + const ruleIds = mark.attributes.split(/\s/g); + const point = mark.node.position && mark.node.position.start; + const next = + (parent && position !== null && parent.children[position + 1]) || + undefined; + const tail = (next && next.position && next.position.end) || undefined; + let index = -1; - function end(code) { - if (code === 41) { - effects.enter('resourceMarker'); - effects.consume(code); - effects.exit('resourceMarker'); - effects.exit('resource'); - return ok - } + /** @type {string} */ + // @ts-expect-error: we’ll check for unknown values next. + const verb = ruleIds.shift(); - return nok(code) - } -} -/** @type {Tokenizer} */ + if (verb !== 'enable' && verb !== 'disable' && verb !== 'ignore') { + file.fail( + 'Unknown keyword `' + + verb + + '`: expected ' + + "`'enable'`, `'disable'`, or `'ignore'`", + mark.node + ); + } -function tokenizeFullReference(effects, ok, nok) { - const self = this; - return start - /** @type {State} */ + // Apply to all rules. + if (ruleIds.length > 0) { + while (++index < ruleIds.length) { + const ruleId = ruleIds[index]; - function start(code) { - return factoryLabel.call( - self, - effects, - afterLabel, - nok, - 'reference', - 'referenceMarker', - 'referenceString' - )(code) - } - /** @type {State} */ + if (isKnown(ruleId, verb, mark.node)) { + toggle(point, verb === 'enable', ruleId); - function afterLabel(code) { - return self.parser.defined.includes( - normalizeIdentifier( - self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1) - ) - ) - ? ok(code) - : nok(code) - } -} -/** @type {Tokenizer} */ + if (verb === 'ignore') { + toggle(tail, true, ruleId); + } + } + } + } else if (verb === 'ignore') { + toggle(point, false); + toggle(tail, true); + } else { + toggle(point, verb === 'enable'); + reset = verb !== 'enable'; + } + } -function tokenizeCollapsedReference(effects, ok, nok) { - return start - /** @type {State} */ + /** + * @param {VFileMessage} message + * @returns {boolean} + */ + function filter(message) { + let gapIndex = gaps.length; - function start(code) { - effects.enter('reference'); - effects.enter('referenceMarker'); - effects.consume(code); - effects.exit('referenceMarker'); - return open - } - /** @type {State} */ + // Keep messages from a different source. + if (!message.source || !sources.includes(message.source)) { + return true + } - function open(code) { - if (code === 93) { - effects.enter('referenceMarker'); - effects.consume(code); - effects.exit('referenceMarker'); - effects.exit('reference'); - return ok - } + // We only ignore messages if they‘re disabled, *not* when they’re not in + // the document. + if (!message.line) { + message.line = 1; + } - return nok(code) - } -} + if (!message.column) { + message.column = 1; + } -/** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State - */ -/** @type {Construct} */ + // Check whether the warning is inside a gap. + // @ts-expect-error: we just normalized `null` to `number`s. + const offset = toOffset(message); -const labelStartImage = { - name: 'labelStartImage', - tokenize: tokenizeLabelStartImage, - resolveAll: labelEnd.resolveAll -}; -/** @type {Tokenizer} */ + while (gapIndex--) { + if (gaps[gapIndex][0] <= offset && gaps[gapIndex][1] > offset) { + return false + } + } -function tokenizeLabelStartImage(effects, ok, nok) { - const self = this; - return start - /** @type {State} */ + // Check whether allowed by specific and global states. + return ( + (!message.ruleId || + check(message, scope[message.ruleId], message.ruleId)) && + check(message, globals) + ) + } - function start(code) { - effects.enter('labelImage'); - effects.enter('labelImageMarker'); - effects.consume(code); - effects.exit('labelImageMarker'); - return open - } - /** @type {State} */ + /** + * Helper to check (and possibly warn) if a `ruleId` is unknown. + * + * @param {string} ruleId + * @param {string} verb + * @param {Node} node + * @returns {boolean} + */ + function isKnown(ruleId, verb, node) { + const result = options.known ? options.known.includes(ruleId) : true; + + if (!result) { + file.message( + 'Unknown rule: cannot ' + verb + " `'" + ruleId + "'`", + node + ); + } - function open(code) { - if (code === 91) { - effects.enter('labelMarker'); - effects.consume(code); - effects.exit('labelMarker'); - effects.exit('labelImage'); - return after + return result } - return nok(code) - } - /** @type {State} */ + /** + * Get the latest state of a rule. + * When without `ruleId`, gets global state. + * + * @param {string|undefined} ruleId + * @returns {boolean} + */ + function getState(ruleId) { + const ranges = ruleId ? scope[ruleId] : globals; - function after(code) { - /* Hidden footnotes hook */ + if (ranges && ranges.length > 0) { + return ranges[ranges.length - 1].state + } - /* c8 ignore next 3 */ - return code === 94 && '_hiddenFootnoteSupport' in self.parser.constructs - ? nok(code) - : ok(code) - } -} + if (!ruleId) { + return !reset + } -/** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State - */ -/** @type {Construct} */ + return reset ? enable.includes(ruleId) : !disable.includes(ruleId) + } -const labelStartLink = { - name: 'labelStartLink', - tokenize: tokenizeLabelStartLink, - resolveAll: labelEnd.resolveAll -}; -/** @type {Tokenizer} */ + /** + * Handle a rule. + * + * @param {Point|undefined} point + * @param {boolean} state + * @param {string|undefined} [ruleId] + * @returns {void} + */ + function toggle(point, state, ruleId) { + let markers = ruleId ? scope[ruleId] : globals; -function tokenizeLabelStartLink(effects, ok, nok) { - const self = this; - return start - /** @type {State} */ + if (!markers) { + markers = []; + scope[String(ruleId)] = markers; + } - function start(code) { - effects.enter('labelLink'); - effects.enter('labelMarker'); - effects.consume(code); - effects.exit('labelMarker'); - effects.exit('labelLink'); - return after - } - /** @type {State} */ + const previousState = getState(ruleId); - function after(code) { - /* Hidden footnotes hook. */ + if (state !== previousState) { + markers.push({state, point}); + } - /* c8 ignore next 3 */ - return code === 94 && '_hiddenFootnoteSupport' in self.parser.constructs - ? nok(code) - : ok(code) - } -} + // Toggle all known rules. + if (!ruleId) { + for (ruleId in scope) { + if (own$3.call(scope, ruleId)) { + toggle(point, state, ruleId); + } + } + } + } -/** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State - */ + /** + * Check all `ranges` for `message`. + * + * @param {VFileMessage} message + * @param {Mark[]|undefined} ranges + * @param {string|undefined} [ruleId] + * @returns {boolean} + */ + function check(message, ranges, ruleId) { + if (ranges && ranges.length > 0) { + // Check the state at the message’s position. + let index = ranges.length; -/** @type {Construct} */ -const lineEnding = { - name: 'lineEnding', - tokenize: tokenizeLineEnding -}; -/** @type {Tokenizer} */ + while (index--) { + const range = ranges[index]; -function tokenizeLineEnding(effects, ok) { - return start - /** @type {State} */ + if ( + message.line && + message.column && + range.point && + range.point.line && + range.point.column && + (range.point.line < message.line || + (range.point.line === message.line && + range.point.column <= message.column)) + ) { + return range.state === true + } + } + } - function start(code) { - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - return factorySpace(effects, ok, 'linePrefix') + // The first marker ocurred after the first message, so we check the + // initial state. + if (!ruleId) { + return Boolean(initial || reset) + } + + return reset ? enable.includes(ruleId) : !disable.includes(ruleId) + } } } /** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State - * @typedef {import('micromark-util-types').Code} Code + * Detect gaps in `tree`. + * + * @param {Node} tree + * @param {VFile} file */ +function detectGaps(tree, file) { + /** @type {Node[]} */ + // @ts-expect-error: fine. + const children = tree.children || []; + const lastNode = children[children.length - 1]; + /** @type {[number, number][]} */ + const gaps = []; + let offset = 0; + /** @type {boolean|undefined} */ + let gap; -/** @type {Construct} */ -const thematicBreak$1 = { - name: 'thematicBreak', - tokenize: tokenizeThematicBreak -}; -/** @type {Tokenizer} */ - -function tokenizeThematicBreak(effects, ok, nok) { - let size = 0; - /** @type {NonNullable} */ + // Find all gaps. + visit(tree, one); - let marker; - return start - /** @type {State} */ + // Get the end of the document. + // This detects if the last node was the last node. + // If not, there’s an extra gap between the last node and the end of the + // document. + if ( + lastNode && + lastNode.position && + lastNode.position.end && + offset === lastNode.position.end.offset && + file.toString().slice(offset).trim() !== '' + ) { + update(); - function start(code) { - effects.enter('thematicBreak'); - marker = code; - return atBreak(code) + update( + tree && + tree.position && + tree.position.end && + tree.position.end.offset && + tree.position.end.offset - 1 + ); } - /** @type {State} */ - function atBreak(code) { - if (code === marker) { - effects.enter('thematicBreakSequence'); - return sequence(code) - } + return gaps - if (markdownSpace(code)) { - return factorySpace(effects, atBreak, 'whitespace')(code) - } + /** + * @param {Node} node + */ + function one(node) { + update(node.position && node.position.start && node.position.start.offset); - if (size < 3 || (code !== null && !markdownLineEnding(code))) { - return nok(code) + if (!('children' in node)) { + update(node.position && node.position.end && node.position.end.offset); } - - effects.exit('thematicBreak'); - return ok(code) } - /** @type {State} */ - function sequence(code) { - if (code === marker) { - effects.consume(code); - size++; - return sequence - } + /** + * Detect a new position. + * + * @param {number|undefined} [latest] + * @returns {void} + */ + function update(latest) { + if (latest === null || latest === undefined) { + gap = true; + } else if (offset < latest) { + if (gap) { + gaps.push([offset, latest]); + gap = undefined; + } - effects.exit('thematicBreakSequence'); - return atBreak(code) + offset = latest; + } } } /** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext - * @typedef {import('micromark-util-types').Exiter} Exiter - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State - * @typedef {import('micromark-util-types').Code} Code + * @typedef {string|number|boolean} MarkerParameterValue + * @typedef {Object.} MarkerParameters + * + * @typedef HtmlNode + * @property {'html'} type + * @property {string} value + * + * @typedef CommentNode + * @property {'comment'} type + * @property {string} value + * + * @typedef Marker + * @property {string} name + * @property {string} attributes + * @property {MarkerParameters|null} parameters + * @property {HtmlNode|CommentNode} node */ -/** @type {Construct} */ -const list$1 = { - name: 'list', - tokenize: tokenizeListStart, - continuation: { - tokenize: tokenizeListContinuation - }, - exit: tokenizeListEnd -}; -/** @type {Construct} */ +var commentExpression = /\s*([a-zA-Z\d-]+)(\s+([\s\S]*))?\s*/; -const listItemPrefixWhitespaceConstruct = { - tokenize: tokenizeListItemPrefixWhitespace, - partial: true -}; -/** @type {Construct} */ +var markerExpression = new RegExp( + '(\\s*\\s*)' +); -const indentConstruct = { - tokenize: tokenizeIndent, - partial: true -}; /** - * @type {Tokenizer} - * @this {TokenizeContextWithState} + * Parse a comment marker. + * @param {unknown} node + * @returns {Marker|null} */ +function commentMarker(node) { + /** @type {RegExpMatchArray} */ + var match; + /** @type {number} */ + var offset; + /** @type {MarkerParameters} */ + var parameters; -function tokenizeListStart(effects, ok, nok) { - const self = this; - const tail = self.events[self.events.length - 1]; - let initialSize = - tail && tail[1].type === 'linePrefix' - ? tail[2].sliceSerialize(tail[1], true).length - : 0; - let size = 0; - return start - /** @type {State} */ - - function start(code) { - const kind = - self.containerState.type || - (code === 42 || code === 43 || code === 45 - ? 'listUnordered' - : 'listOrdered'); - - if ( - kind === 'listUnordered' - ? !self.containerState.marker || code === self.containerState.marker - : asciiDigit(code) - ) { - if (!self.containerState.type) { - self.containerState.type = kind; - effects.enter(kind, { - _container: true - }); - } + if ( + node && + typeof node === 'object' && + // @ts-ignore hush + (node.type === 'html' || node.type === 'comment') + ) { + // @ts-ignore hush + match = node.value.match( + // @ts-ignore hush + node.type === 'comment' ? commentExpression : markerExpression + ); - if (kind === 'listUnordered') { - effects.enter('listItemPrefix'); - return code === 42 || code === 45 - ? effects.check(thematicBreak$1, nok, atMarker)(code) - : atMarker(code) - } + // @ts-ignore hush + if (match && match[0].length === node.value.length) { + // @ts-ignore hush + offset = node.type === 'comment' ? 1 : 2; + parameters = parseParameters(match[offset + 1] || ''); - if (!self.interrupt || code === 49) { - effects.enter('listItemPrefix'); - effects.enter('listItemValue'); - return inside(code) + if (parameters) { + return { + name: match[offset], + attributes: match[offset + 2] || '', + parameters, + // @ts-ignore hush + node + } } } - - return nok(code) - } - /** @type {State} */ - - function inside(code) { - if (asciiDigit(code) && ++size < 10) { - effects.consume(code); - return inside - } - - if ( - (!self.interrupt || size < 2) && - (self.containerState.marker - ? code === self.containerState.marker - : code === 41 || code === 46) - ) { - effects.exit('listItemValue'); - return atMarker(code) - } - - return nok(code) - } - /** - * @type {State} - **/ - - function atMarker(code) { - effects.enter('listItemMarker'); - effects.consume(code); - effects.exit('listItemMarker'); - self.containerState.marker = self.containerState.marker || code; - return effects.check( - blankLine, // Can’t be empty when interrupting. - self.interrupt ? nok : onBlank, - effects.attempt( - listItemPrefixWhitespaceConstruct, - endOfPrefix, - otherPrefix - ) - ) - } - /** @type {State} */ - - function onBlank(code) { - self.containerState.initialBlankLine = true; - initialSize++; - return endOfPrefix(code) - } - /** @type {State} */ - - function otherPrefix(code) { - if (markdownSpace(code)) { - effects.enter('listItemPrefixWhitespace'); - effects.consume(code); - effects.exit('listItemPrefixWhitespace'); - return endOfPrefix - } - - return nok(code) } - /** @type {State} */ - function endOfPrefix(code) { - self.containerState.size = - initialSize + - self.sliceSerialize(effects.exit('listItemPrefix'), true).length; - return ok(code) - } + return null } + /** - * @type {Tokenizer} - * @this {TokenizeContextWithState} + * Parse `value` into an object. + * + * @param {string} value + * @returns {MarkerParameters|null} */ +function parseParameters(value) { + /** @type {MarkerParameters} */ + var parameters = {}; -function tokenizeListContinuation(effects, ok, nok) { - const self = this; - self.containerState._closeFlow = undefined; - return effects.check(blankLine, onBlank, notBlank) - /** @type {State} */ - - function onBlank(code) { - self.containerState.furtherBlankLines = - self.containerState.furtherBlankLines || - self.containerState.initialBlankLine; // We have a blank line. - // Still, try to consume at most the items size. + return value + .replace( + /\s+([-\w]+)(?:=(?:"((?:\\[\s\S]|[^"])+)"|'((?:\\[\s\S]|[^'])+)'|((?:\\[\s\S]|[^"'\s])+)))?/gi, + replacer + ) + .replace(/\s+/g, '') + ? null + : parameters - return factorySpace( - effects, - ok, - 'listItemIndent', - self.containerState.size + 1 - )(code) - } - /** @type {State} */ + /** + * @param {string} _ + * @param {string} $1 + * @param {string} $2 + * @param {string} $3 + * @param {string} $4 + */ + // eslint-disable-next-line max-params + function replacer(_, $1, $2, $3, $4) { + /** @type {MarkerParameterValue} */ + var value = $2 || $3 || $4 || ''; - function notBlank(code) { - if (self.containerState.furtherBlankLines || !markdownSpace(code)) { - self.containerState.furtherBlankLines = undefined; - self.containerState.initialBlankLine = undefined; - return notInCurrentItem(code) + if (value === 'true' || value === '') { + value = true; + } else if (value === 'false') { + value = false; + } else if (!Number.isNaN(Number(value))) { + value = Number(value); } - self.containerState.furtherBlankLines = undefined; - self.containerState.initialBlankLine = undefined; - return effects.attempt(indentConstruct, ok, notInCurrentItem)(code) - } - /** @type {State} */ - - function notInCurrentItem(code) { - // While we do continue, we signal that the flow should be closed. - self.containerState._closeFlow = true; // As we’re closing flow, we’re no longer interrupting. + parameters[$1] = value; - self.interrupt = undefined; - return factorySpace( - effects, - effects.attempt(list$1, ok, nok), - 'linePrefix', - self.parser.constructs.disable.null.includes('codeIndented') - ? undefined - : 4 - )(code) + return '' } } + /** - * @type {Tokenizer} - * @this {TokenizeContextWithState} + * @typedef {import('mdast').Root} Root + * @typedef {import('vfile').VFile} VFile + * @typedef {import('unified-message-control')} MessageControl + * @typedef {Omit|Omit} Options */ -function tokenizeIndent(effects, ok, nok) { - const self = this; - return factorySpace( - effects, - afterPrefix, - 'listItemIndent', - self.containerState.size + 1 - ) - /** @type {State} */ +const test = [ + 'html', // Comments are `html` nodes in mdast. + 'comment' // In MDX, comments have their own node. +]; - function afterPrefix(code) { - const tail = self.events[self.events.length - 1]; - return tail && - tail[1].type === 'listItemIndent' && - tail[2].sliceSerialize(tail[1], true).length === self.containerState.size - ? ok(code) - : nok(code) - } +/** + * Plugin to enable, disable, and ignore messages. + * + * @type {import('unified').Plugin<[Options], Root>} + * @returns {(node: Root, file: VFile) => void} + */ +function remarkMessageControl(options) { + return messageControl( + Object.assign({marker: commentMarker, test}, options) + ) } + /** - * @type {Exiter} - * @this {TokenizeContextWithState} + * @typedef {import('mdast').Root} Root */ -function tokenizeListEnd(effects) { - effects.exit(this.containerState.type); +/** + * The core plugin for `remark-lint`. + * This adds support for ignoring stuff from messages (``). + * All rules are in their own packages and presets. + * + * @type {import('unified').Plugin} + */ +function remarkLint() { + this.use(lintMessageControl); +} + +/** @type {import('unified').Plugin} */ +function lintMessageControl() { + return remarkMessageControl({name: 'lint', source: 'remark-lint'}) } + /** - * @type {Tokenizer} - * @this {TokenizeContextWithState} + * @typedef {import('unist').Node} Node + * @typedef {import('vfile').VFile} VFile + * + * @typedef {0|1|2} Severity + * @typedef {'warn'|'on'|'off'|'error'} Label + * @typedef {[Severity, ...unknown[]]} SeverityTuple + * + * @typedef RuleMeta + * @property {string} origin name of the lint rule + * @property {string} [url] link to documentation + * + * @callback Rule + * @param {Node} tree + * @param {VFile} file + * @param {unknown} options + * @returns {void} */ -function tokenizeListItemPrefixWhitespace(effects, ok, nok) { - const self = this; - return factorySpace( - effects, - afterPrefix, - 'listItemPrefixWhitespace', - self.parser.constructs.disable.null.includes('codeIndented') - ? undefined - : 4 + 1 - ) - /** @type {State} */ +const primitives = new Set(['string', 'number', 'boolean']); - function afterPrefix(code) { - const tail = self.events[self.events.length - 1]; - return !markdownSpace(code) && - tail && - tail[1].type === 'listItemPrefixWhitespace' - ? ok(code) - : nok(code) +/** + * @param {string|RuleMeta} meta + * @param {Rule} rule + */ +function lintRule(meta, rule) { + const id = typeof meta === 'string' ? meta : meta.origin; + const url = typeof meta === 'string' ? undefined : meta.url; + const parts = id.split(':'); + // Possibly useful if externalised later. + /* c8 ignore next */ + const source = parts[1] ? parts[0] : undefined; + const ruleId = parts[1]; + + Object.defineProperty(plugin, 'name', {value: id}); + + return plugin + + /** @type {import('unified').Plugin<[unknown]|void[]>} */ + function plugin(raw) { + const [severity, options] = coerce$1(ruleId, raw); + + if (!severity) return + + const fatal = severity === 2; + + return (tree, file, next) => { + let index = file.messages.length - 1; + + wrap(rule, (error) => { + const messages = file.messages; + + // Add the error, if not already properly added. + // Only happens for incorrect plugins. + /* c8 ignore next 6 */ + // @ts-expect-error: errors could be `messages`. + if (error && !messages.includes(error)) { + try { + file.fail(error); + } catch {} + } + + while (++index < messages.length) { + Object.assign(messages[index], {ruleId, source, fatal, url}); + } + + next(); + })(tree, file, options); + } } } /** - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').Resolver} Resolver - * @typedef {import('micromark-util-types').Tokenizer} Tokenizer - * @typedef {import('micromark-util-types').State} State - * @typedef {import('micromark-util-types').Code} Code + * Coerce a value to a severity--options tuple. + * + * @param {string} name + * @param {unknown} value + * @returns {SeverityTuple} */ +function coerce$1(name, value) { + /** @type {unknown[]} */ + let result; -/** @type {Construct} */ -const setextUnderline = { - name: 'setextUnderline', - tokenize: tokenizeSetextUnderline, - resolveTo: resolveToSetextUnderline -}; -/** @type {Resolver} */ + if (typeof value === 'boolean') { + result = [value]; + } else if (value === null || value === undefined) { + result = [1]; + } else if ( + Array.isArray(value) && + // `isArray(unknown)` is turned into `any[]`: + // type-coverage:ignore-next-line + primitives.has(typeof value[0]) + ) { + // `isArray(unknown)` is turned into `any[]`: + // type-coverage:ignore-next-line + result = [...value]; + } else { + result = [1, value]; + } -function resolveToSetextUnderline(events, context) { - let index = events.length; - /** @type {number|undefined} */ + let level = result[0]; - let content; - /** @type {number|undefined} */ + if (typeof level === 'boolean') { + level = level ? 1 : 0; + } else if (typeof level === 'string') { + if (level === 'off') { + level = 0; + } else if (level === 'on' || level === 'warn') { + level = 1; + } else if (level === 'error') { + level = 2; + } else { + level = 1; + result = [level, result]; + } + } - let text; - /** @type {number|undefined} */ + if (typeof level !== 'number' || level < 0 || level > 2) { + throw new Error( + 'Incorrect severity `' + + level + + '` for `' + + name + + '`, ' + + 'expected 0, 1, or 2' + ) + } - let definition; // Find the opening of the content. - // It’ll always exist: we don’t tokenize if it isn’t there. + result[0] = level; - while (index--) { - if (events[index][0] === 'enter') { - if (events[index][1].type === 'content') { - content = index; - break - } + // @ts-expect-error: it’s now a valid tuple. + return result +} - if (events[index][1].type === 'paragraph') { - text = index; - } - } // Exit - else { - if (events[index][1].type === 'content') { - // Remove the content end (if needed we’ll add it later) - events.splice(index, 1); - } +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module final-newline + * @fileoverview + * Warn when a line feed at the end of a file is missing. + * Empty files are allowed. + * + * See [StackExchange](https://unix.stackexchange.com/questions/18743) for why. + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) + * always adds a final line feed to files. + * + * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) + * on how to automatically fix warnings for this rule. + * + * ## Example + * + * ##### `ok.md` + * + * ###### In + * + * Note: `␊` represents LF. + * + * ```markdown + * Alpha␊ + * ``` + * + * ###### Out + * + * No messages. + * + * ##### `not-ok.md` + * + * ###### In + * + * Note: The below file does not have a final newline. + * + * ```markdown + * Bravo + * ``` + * + * ###### Out + * + * ```text + * 1:1: Missing newline character at end of file + * ``` + */ - if (!definition && events[index][1].type === 'definition') { - definition = index; - } +const remarkLintFinalNewline = lintRule( + { + origin: 'remark-lint:final-newline', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-newline#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (_, file) => { + const value = String(file); + const last = value.length - 1; + + if (last > -1 && value.charAt(last) !== '\n') { + file.message('Missing newline character at end of file'); } } +); - const heading = { - type: 'setextHeading', - start: Object.assign({}, events[text][1].start), - end: Object.assign({}, events[events.length - 1][1].end) - }; // Change the paragraph to setext heading text. +var remarkLintFinalNewline$1 = remarkLintFinalNewline; - events[text][1].type = 'setextHeadingText'; // If we have definitions in the content, we’ll keep on having content, - // but we need move it. +var pluralize = {exports: {}}; - if (definition) { - events.splice(text, 0, ['enter', heading, context]); - events.splice(definition + 1, 0, ['exit', events[content][1], context]); - events[content][1].end = Object.assign({}, events[definition][1].end); +/* global define */ + +(function (module, exports) { +(function (root, pluralize) { + /* istanbul ignore else */ + if (typeof commonjsRequire === 'function' && 'object' === 'object' && 'object' === 'object') { + // Node. + module.exports = pluralize(); } else { - events[content][1] = heading; - } // Add the heading exit at the end. + // Browser global. + root.pluralize = pluralize(); + } +})(commonjsGlobal, function () { + // Rule storage - pluralize and singularize need to be run sequentially, + // while other rules can be optimized using an object for instant lookups. + var pluralRules = []; + var singularRules = []; + var uncountables = {}; + var irregularPlurals = {}; + var irregularSingles = {}; - events.push(['exit', heading, context]); - return events -} -/** @type {Tokenizer} */ + /** + * Sanitize a pluralization rule to a usable regular expression. + * + * @param {(RegExp|string)} rule + * @return {RegExp} + */ + function sanitizeRule (rule) { + if (typeof rule === 'string') { + return new RegExp('^' + rule + '$', 'i'); + } -function tokenizeSetextUnderline(effects, ok, nok) { - const self = this; - let index = self.events.length; - /** @type {NonNullable} */ + return rule; + } - let marker; - /** @type {boolean} */ + /** + * Pass in a word token to produce a function that can replicate the case on + * another word. + * + * @param {string} word + * @param {string} token + * @return {Function} + */ + function restoreCase (word, token) { + // Tokens are an exact match. + if (word === token) return token; - let paragraph; // Find an opening. + // Lower cased words. E.g. "hello". + if (word === word.toLowerCase()) return token.toLowerCase(); - while (index--) { - // Skip enter/exit of line ending, line prefix, and content. - // We can now either have a definition or a paragraph. - if ( - self.events[index][1].type !== 'lineEnding' && - self.events[index][1].type !== 'linePrefix' && - self.events[index][1].type !== 'content' - ) { - paragraph = self.events[index][1].type === 'paragraph'; - break + // Upper cased words. E.g. "WHISKY". + if (word === word.toUpperCase()) return token.toUpperCase(); + + // Title cased words. E.g. "Title". + if (word[0] === word[0].toUpperCase()) { + return token.charAt(0).toUpperCase() + token.substr(1).toLowerCase(); } + + // Lower cased words. E.g. "test". + return token.toLowerCase(); } - return start - /** @type {State} */ + /** + * Interpolate a regexp string. + * + * @param {string} str + * @param {Array} args + * @return {string} + */ + function interpolate (str, args) { + return str.replace(/\$(\d{1,2})/g, function (match, index) { + return args[index] || ''; + }); + } - function start(code) { - if (!self.parser.lazy[self.now().line] && (self.interrupt || paragraph)) { - effects.enter('setextHeadingLine'); - effects.enter('setextHeadingLineSequence'); - marker = code; - return closingSequence(code) - } + /** + * Replace a word using a rule. + * + * @param {string} word + * @param {Array} rule + * @return {string} + */ + function replace (word, rule) { + return word.replace(rule[0], function (match, index) { + var result = interpolate(rule[1], arguments); - return nok(code) + if (match === '') { + return restoreCase(word[index - 1], result); + } + + return restoreCase(match, result); + }); } - /** @type {State} */ - function closingSequence(code) { - if (code === marker) { - effects.consume(code); - return closingSequence + /** + * Sanitize a word by passing in the word and sanitization rules. + * + * @param {string} token + * @param {string} word + * @param {Array} rules + * @return {string} + */ + function sanitizeWord (token, word, rules) { + // Empty string or doesn't need fixing. + if (!token.length || uncountables.hasOwnProperty(token)) { + return word; } - effects.exit('setextHeadingLineSequence'); - return factorySpace(effects, closingSequenceEnd, 'lineSuffix')(code) - } - /** @type {State} */ + var len = rules.length; - function closingSequenceEnd(code) { - if (code === null || markdownLineEnding(code)) { - effects.exit('setextHeadingLine'); - return ok(code) + // Iterate over the sanitization rules and use the first one to match. + while (len--) { + var rule = rules[len]; + + if (rule[0].test(word)) return replace(word, rule); } - return nok(code) + return word; } -} - -/** - * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct - * @typedef {import('micromark-util-types').Initializer} Initializer - * @typedef {import('micromark-util-types').State} State - */ - -/** @type {InitialConstruct} */ -const flow$1 = { - tokenize: initializeFlow -}; -/** @type {Initializer} */ -function initializeFlow(effects) { - const self = this; - const initial = effects.attempt( - // Try to parse a blank line. - blankLine, - atBlankEnding, // Try to parse initial flow (essentially, only code). - effects.attempt( - this.parser.constructs.flowInitial, - afterConstruct, - factorySpace( - effects, - effects.attempt( - this.parser.constructs.flow, - afterConstruct, - effects.attempt(content, afterConstruct) - ), - 'linePrefix' - ) - ) - ); - return initial - /** @type {State} */ + /** + * Replace a word with the updated word. + * + * @param {Object} replaceMap + * @param {Object} keepMap + * @param {Array} rules + * @return {Function} + */ + function replaceWord (replaceMap, keepMap, rules) { + return function (word) { + // Get the correct token and case restoration functions. + var token = word.toLowerCase(); - function atBlankEnding(code) { - if (code === null) { - effects.consume(code); - return - } + // Check against the keep object map. + if (keepMap.hasOwnProperty(token)) { + return restoreCase(word, token); + } - effects.enter('lineEndingBlank'); - effects.consume(code); - effects.exit('lineEndingBlank'); - self.currentConstruct = undefined; - return initial + // Check against the replacement map for a direct word replacement. + if (replaceMap.hasOwnProperty(token)) { + return restoreCase(word, replaceMap[token]); + } + + // Run all the rules against the word. + return sanitizeWord(token, word, rules); + }; } - /** @type {State} */ - function afterConstruct(code) { - if (code === null) { - effects.consume(code); - return - } + /** + * Check if a word is part of the map. + */ + function checkWord (replaceMap, keepMap, rules, bool) { + return function (word) { + var token = word.toLowerCase(); - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - self.currentConstruct = undefined; - return initial + if (keepMap.hasOwnProperty(token)) return true; + if (replaceMap.hasOwnProperty(token)) return false; + + return sanitizeWord(token, token, rules) === token; + }; } -} -/** - * @typedef {import('micromark-util-types').Resolver} Resolver - * @typedef {import('micromark-util-types').Initializer} Initializer - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct - * @typedef {import('micromark-util-types').State} State - * @typedef {import('micromark-util-types').Code} Code - */ -const resolver = { - resolveAll: createResolver() -}; -const string$1 = initializeFactory('string'); -const text$3 = initializeFactory('text'); -/** - * @param {'string'|'text'} field - * @returns {InitialConstruct} - */ + /** + * Pluralize or singularize a word based on the passed in count. + * + * @param {string} word The word to pluralize + * @param {number} count How many of the word exist + * @param {boolean} inclusive Whether to prefix with the number (e.g. 3 ducks) + * @return {string} + */ + function pluralize (word, count, inclusive) { + var pluralized = count === 1 + ? pluralize.singular(word) : pluralize.plural(word); -function initializeFactory(field) { - return { - tokenize: initializeText, - resolveAll: createResolver( - field === 'text' ? resolveAllLineSuffixes : undefined - ) + return (inclusive ? count + ' ' : '') + pluralized; } - /** @type {Initializer} */ - function initializeText(effects) { - const self = this; - const constructs = this.parser.constructs[field]; - const text = effects.attempt(constructs, start, notText); - return start - /** @type {State} */ + /** + * Pluralize a word. + * + * @type {Function} + */ + pluralize.plural = replaceWord( + irregularSingles, irregularPlurals, pluralRules + ); - function start(code) { - return atBreak(code) ? text(code) : notText(code) - } - /** @type {State} */ + /** + * Check if a word is plural. + * + * @type {Function} + */ + pluralize.isPlural = checkWord( + irregularSingles, irregularPlurals, pluralRules + ); - function notText(code) { - if (code === null) { - effects.consume(code); - return - } + /** + * Singularize a word. + * + * @type {Function} + */ + pluralize.singular = replaceWord( + irregularPlurals, irregularSingles, singularRules + ); - effects.enter('data'); - effects.consume(code); - return data - } - /** @type {State} */ + /** + * Check if a word is singular. + * + * @type {Function} + */ + pluralize.isSingular = checkWord( + irregularPlurals, irregularSingles, singularRules + ); - function data(code) { - if (atBreak(code)) { - effects.exit('data'); - return text(code) - } // Data. + /** + * Add a pluralization rule to the collection. + * + * @param {(string|RegExp)} rule + * @param {string} replacement + */ + pluralize.addPluralRule = function (rule, replacement) { + pluralRules.push([sanitizeRule(rule), replacement]); + }; - effects.consume(code); - return data - } - /** - * @param {Code} code - * @returns {boolean} - */ + /** + * Add a singularization rule to the collection. + * + * @param {(string|RegExp)} rule + * @param {string} replacement + */ + pluralize.addSingularRule = function (rule, replacement) { + singularRules.push([sanitizeRule(rule), replacement]); + }; - function atBreak(code) { - if (code === null) { - return true - } + /** + * Add an uncountable word rule. + * + * @param {(string|RegExp)} word + */ + pluralize.addUncountableRule = function (word) { + if (typeof word === 'string') { + uncountables[word.toLowerCase()] = true; + return; + } - const list = constructs[code]; - let index = -1; + // Set singular and plural references for the word. + pluralize.addPluralRule(word, '$0'); + pluralize.addSingularRule(word, '$0'); + }; - if (list) { - while (++index < list.length) { - const item = list[index]; + /** + * Add an irregular word definition. + * + * @param {string} single + * @param {string} plural + */ + pluralize.addIrregularRule = function (single, plural) { + plural = plural.toLowerCase(); + single = single.toLowerCase(); - if (!item.previous || item.previous.call(self, self.previous)) { - return true - } - } - } + irregularSingles[single] = plural; + irregularPlurals[plural] = single; + }; - return false - } - } -} -/** - * @param {Resolver} [extraResolver] - * @returns {Resolver} - */ + /** + * Irregular rules. + */ + [ + // Pronouns. + ['I', 'we'], + ['me', 'us'], + ['he', 'they'], + ['she', 'they'], + ['them', 'them'], + ['myself', 'ourselves'], + ['yourself', 'yourselves'], + ['itself', 'themselves'], + ['herself', 'themselves'], + ['himself', 'themselves'], + ['themself', 'themselves'], + ['is', 'are'], + ['was', 'were'], + ['has', 'have'], + ['this', 'these'], + ['that', 'those'], + // Words ending in with a consonant and `o`. + ['echo', 'echoes'], + ['dingo', 'dingoes'], + ['volcano', 'volcanoes'], + ['tornado', 'tornadoes'], + ['torpedo', 'torpedoes'], + // Ends with `us`. + ['genus', 'genera'], + ['viscus', 'viscera'], + // Ends with `ma`. + ['stigma', 'stigmata'], + ['stoma', 'stomata'], + ['dogma', 'dogmata'], + ['lemma', 'lemmata'], + ['schema', 'schemata'], + ['anathema', 'anathemata'], + // Other irregular rules. + ['ox', 'oxen'], + ['axe', 'axes'], + ['die', 'dice'], + ['yes', 'yeses'], + ['foot', 'feet'], + ['eave', 'eaves'], + ['goose', 'geese'], + ['tooth', 'teeth'], + ['quiz', 'quizzes'], + ['human', 'humans'], + ['proof', 'proofs'], + ['carve', 'carves'], + ['valve', 'valves'], + ['looey', 'looies'], + ['thief', 'thieves'], + ['groove', 'grooves'], + ['pickaxe', 'pickaxes'], + ['passerby', 'passersby'] + ].forEach(function (rule) { + return pluralize.addIrregularRule(rule[0], rule[1]); + }); -function createResolver(extraResolver) { - return resolveAllText - /** @type {Resolver} */ + /** + * Pluralization rules. + */ + [ + [/s?$/i, 's'], + [/[^\u0000-\u007F]$/i, '$0'], + [/([^aeiou]ese)$/i, '$1'], + [/(ax|test)is$/i, '$1es'], + [/(alias|[^aou]us|t[lm]as|gas|ris)$/i, '$1es'], + [/(e[mn]u)s?$/i, '$1s'], + [/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i, '$1'], + [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1i'], + [/(alumn|alg|vertebr)(?:a|ae)$/i, '$1ae'], + [/(seraph|cherub)(?:im)?$/i, '$1im'], + [/(her|at|gr)o$/i, '$1oes'], + [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i, '$1a'], + [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i, '$1a'], + [/sis$/i, 'ses'], + [/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, '$1$2ves'], + [/([^aeiouy]|qu)y$/i, '$1ies'], + [/([^ch][ieo][ln])ey$/i, '$1ies'], + [/(x|ch|ss|sh|zz)$/i, '$1es'], + [/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, '$1ices'], + [/\b((?:tit)?m|l)(?:ice|ouse)$/i, '$1ice'], + [/(pe)(?:rson|ople)$/i, '$1ople'], + [/(child)(?:ren)?$/i, '$1ren'], + [/eaux$/i, '$0'], + [/m[ae]n$/i, 'men'], + ['thou', 'you'] + ].forEach(function (rule) { + return pluralize.addPluralRule(rule[0], rule[1]); + }); - function resolveAllText(events, context) { - let index = -1; - /** @type {number|undefined} */ + /** + * Singularization rules. + */ + [ + [/s$/i, ''], + [/(ss)$/i, '$1'], + [/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, '$1fe'], + [/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'], + [/ies$/i, 'y'], + [/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i, '$1ie'], + [/\b(mon|smil)ies$/i, '$1ey'], + [/\b((?:tit)?m|l)ice$/i, '$1ouse'], + [/(seraph|cherub)im$/i, '$1'], + [/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i, '$1'], + [/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i, '$1sis'], + [/(movie|twelve|abuse|e[mn]u)s$/i, '$1'], + [/(test)(?:is|es)$/i, '$1is'], + [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1us'], + [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i, '$1um'], + [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i, '$1on'], + [/(alumn|alg|vertebr)ae$/i, '$1a'], + [/(cod|mur|sil|vert|ind)ices$/i, '$1ex'], + [/(matr|append)ices$/i, '$1ix'], + [/(pe)(rson|ople)$/i, '$1rson'], + [/(child)ren$/i, '$1'], + [/(eau)x?$/i, '$1'], + [/men$/i, 'man'] + ].forEach(function (rule) { + return pluralize.addSingularRule(rule[0], rule[1]); + }); - let enter; // A rather boring computation (to merge adjacent `data` events) which - // improves mm performance by 29%. + /** + * Uncountable rules. + */ + [ + // Singular words with no plurals. + 'adulthood', + 'advice', + 'agenda', + 'aid', + 'aircraft', + 'alcohol', + 'ammo', + 'analytics', + 'anime', + 'athletics', + 'audio', + 'bison', + 'blood', + 'bream', + 'buffalo', + 'butter', + 'carp', + 'cash', + 'chassis', + 'chess', + 'clothing', + 'cod', + 'commerce', + 'cooperation', + 'corps', + 'debris', + 'diabetes', + 'digestion', + 'elk', + 'energy', + 'equipment', + 'excretion', + 'expertise', + 'firmware', + 'flounder', + 'fun', + 'gallows', + 'garbage', + 'graffiti', + 'hardware', + 'headquarters', + 'health', + 'herpes', + 'highjinks', + 'homework', + 'housework', + 'information', + 'jeans', + 'justice', + 'kudos', + 'labour', + 'literature', + 'machinery', + 'mackerel', + 'mail', + 'media', + 'mews', + 'moose', + 'music', + 'mud', + 'manga', + 'news', + 'only', + 'personnel', + 'pike', + 'plankton', + 'pliers', + 'police', + 'pollution', + 'premises', + 'rain', + 'research', + 'rice', + 'salmon', + 'scissors', + 'series', + 'sewage', + 'shambles', + 'shrimp', + 'software', + 'species', + 'staff', + 'swine', + 'tennis', + 'traffic', + 'transportation', + 'trout', + 'tuna', + 'wealth', + 'welfare', + 'whiting', + 'wildebeest', + 'wildlife', + 'you', + /pok[eé]mon$/i, + // Regexes. + /[^aeiou]ese$/i, // "chinese", "japanese" + /deer$/i, // "deer", "reindeer" + /fish$/i, // "fish", "blowfish", "angelfish" + /measles$/i, + /o[iu]s$/i, // "carnivorous" + /pox$/i, // "chickpox", "smallpox" + /sheep$/i + ].forEach(pluralize.addUncountableRule); - while (++index <= events.length) { - if (enter === undefined) { - if (events[index] && events[index][1].type === 'data') { - enter = index; - index++; - } - } else if (!events[index] || events[index][1].type !== 'data') { - // Don’t do anything if there is one data token. - if (index !== enter + 2) { - events[enter][1].end = events[index - 1][1].end; - events.splice(enter + 2, index - enter - 2); - index = enter + 2; - } + return pluralize; +}); +}(pluralize)); - enter = undefined; - } - } +var plural = pluralize.exports; - return extraResolver ? extraResolver(events, context) : events - } -} /** - * A rather ugly set of instructions which again looks at chunks in the input - * stream. - * The reason to do this here is that it is *much* faster to parse in reverse. - * And that we can’t hook into `null` to split the line suffix before an EOF. - * To do: figure out if we can make this into a clean utility, or even in core. - * As it will be useful for GFMs literal autolink extension (and maybe even - * tables?) + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module list-item-bullet-indent + * @fileoverview + * Warn when list item bullets are indented. + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) + * removes all indentation before bullets. + * + * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) + * on how to automatically fix warnings for this rule. + * + * @example + * {"name": "ok.md"} + * + * Paragraph. + * + * * List item + * * List item + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * Paragraph. + * + * ·* List item + * ·* List item * - * @type {Resolver} + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 3:2: Incorrect indentation before bullet: remove 1 space + * 4:2: Incorrect indentation before bullet: remove 1 space */ -function resolveAllLineSuffixes(events, context) { - let eventIndex = -1; - - while (++eventIndex <= events.length) { - if ( - (eventIndex === events.length || - events[eventIndex][1].type === 'lineEnding') && - events[eventIndex - 1][1].type === 'data' - ) { - const data = events[eventIndex - 1][1]; - const chunks = context.sliceStream(data); - let index = chunks.length; - let bufferIndex = -1; - let size = 0; - /** @type {boolean|undefined} */ - - let tabs; +const remarkLintListItemBulletIndent = lintRule( + { + origin: 'remark-lint:list-item-bullet-indent', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-bullet-indent#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + visit$1(tree, 'list', (list, _, grandparent) => { + let index = -1; - while (index--) { - const chunk = chunks[index]; + while (++index < list.children.length) { + const item = list.children[index]; - if (typeof chunk === 'string') { - bufferIndex = chunk.length; + if ( + grandparent && + grandparent.type === 'root' && + grandparent.position && + typeof grandparent.position.start.column === 'number' && + item.position && + typeof item.position.start.column === 'number' + ) { + const indent = + item.position.start.column - grandparent.position.start.column; - while (chunk.charCodeAt(bufferIndex - 1) === 32) { - size++; - bufferIndex--; + if (indent) { + file.message( + 'Incorrect indentation before bullet: remove ' + + indent + + ' ' + + plural('space', indent), + item.position.start + ); } - - if (bufferIndex) break - bufferIndex = -1; - } // Number - else if (chunk === -2) { - tabs = true; - size++; - } else if (chunk === -1) ; else { - // Replacement character, exit. - index++; - break - } - } - - if (size) { - const token = { - type: - eventIndex === events.length || tabs || size < 2 - ? 'lineSuffix' - : 'hardBreakTrailing', - start: { - line: data.end.line, - column: data.end.column - size, - offset: data.end.offset - size, - _index: data.start._index + index, - _bufferIndex: index - ? bufferIndex - : data.start._bufferIndex + bufferIndex - }, - end: Object.assign({}, data.end) - }; - data.end = Object.assign({}, token.start); - - if (data.start.offset === data.end.offset) { - Object.assign(data, token); - } else { - events.splice( - eventIndex, - 0, - ['enter', token, context], - ['exit', token, context] - ); - eventIndex += 2; } } - - eventIndex++; - } + }); } +); - return events -} +var remarkLintListItemBulletIndent$1 = remarkLintListItemBulletIndent; /** - * @typedef {import('micromark-util-types').Code} Code - * @typedef {import('micromark-util-types').Chunk} Chunk - * @typedef {import('micromark-util-types').Point} Point - * @typedef {import('micromark-util-types').Token} Token - * @typedef {import('micromark-util-types').Effects} Effects - * @typedef {import('micromark-util-types').State} State - * @typedef {import('micromark-util-types').Construct} Construct - * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct - * @typedef {import('micromark-util-types').ConstructRecord} ConstructRecord - * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext - * @typedef {import('micromark-util-types').ParseContext} ParseContext + * @typedef {import('unist').Position} Position + * @typedef {import('unist').Point} Point + * + * @typedef {Partial} PointLike + * + * @typedef {Object} PositionLike + * @property {PointLike} [start] + * @property {PointLike} [end] + * + * @typedef {Object} NodeLike + * @property {PositionLike} [position] */ +var pointStart = point('start'); +var pointEnd = point('end'); + /** - * Create a tokenizer. - * Tokenizers deal with one type of data (e.g., containers, flow, text). - * The parser is the object dealing with it all. - * `initialize` works like other constructs, except that only its `tokenize` - * function is used, in which case it doesn’t receive an `ok` or `nok`. - * `from` can be given to set the point before the first character, although - * when further lines are indented, they must be set with `defineSkip`. + * Get the positional info of `node`. * - * @param {ParseContext} parser - * @param {InitialConstruct} initialize - * @param {Omit} [from] - * @returns {TokenizeContext} + * @param {'start'|'end'} type */ -function createTokenizer(parser, initialize, from) { - /** @type {Point} */ - let point = Object.assign( - from - ? Object.assign({}, from) - : { - line: 1, - column: 1, - offset: 0 - }, - { - _index: 0, - _bufferIndex: -1 - } - ); - /** @type {Record} */ - - const columnStart = {}; - /** @type {Construct[]} */ - - const resolveAllConstructs = []; - /** @type {Chunk[]} */ - - let chunks = []; - /** @type {Token[]} */ - - let stack = []; - /** - * Tools used for tokenizing. - * - * @type {Effects} - */ - - const effects = { - consume, - enter, - exit, - attempt: constructFactory(onsuccessfulconstruct), - check: constructFactory(onsuccessfulcheck), - interrupt: constructFactory(onsuccessfulcheck, { - interrupt: true - }) - }; - /** - * State and tools for resolving and serializing. - * - * @type {TokenizeContext} - */ - - const context = { - previous: null, - code: null, - containerState: {}, - events: [], - parser, - sliceStream, - sliceSerialize, - now, - defineSkip, - write - }; - /** - * The state function. - * - * @type {State|void} - */ - - let state = initialize.tokenize.call(context, effects); - - if (initialize.resolveAll) { - resolveAllConstructs.push(initialize); - } - - return context - /** @type {TokenizeContext['write']} */ - - function write(slice) { - chunks = push(chunks, slice); - main(); // Exit if we’re not done, resolve might change stuff. - - if (chunks[chunks.length - 1] !== null) { - return [] - } - - addResult(initialize, 0); // Otherwise, resolve, and exit. - - context.events = resolveAll(resolveAllConstructs, context.events, context); - return context.events - } // - // Tools. - // - - /** @type {TokenizeContext['sliceSerialize']} */ - - function sliceSerialize(token, expandTabs) { - return serializeChunks(sliceStream(token), expandTabs) - } - /** @type {TokenizeContext['sliceStream']} */ - - function sliceStream(token) { - return sliceChunks(chunks, token) - } - /** @type {TokenizeContext['now']} */ - - function now() { - return Object.assign({}, point) - } - /** @type {TokenizeContext['defineSkip']} */ - - function defineSkip(value) { - columnStart[value.line] = value.column; - accountForPotentialSkip(); - } // - // State management. - // +function point(type) { + return point /** - * Main loop (note that `_index` and `_bufferIndex` in `point` are modified by - * `consume`). - * Here is where we walk through the chunks, which either include strings of - * several characters, or numerical character codes. - * The reason to do this in a loop instead of a call is so the stack can - * drain. + * Get the positional info of `node`. * - * @returns {void} + * @param {NodeLike} [node] + * @returns {Point} */ + function point(node) { + /** @type {Point} */ + // @ts-ignore looks like a point + var point = (node && node.position && node.position[type]) || {}; - function main() { - /** @type {number} */ - let chunkIndex; - - while (point._index < chunks.length) { - const chunk = chunks[point._index]; // If we’re in a buffer chunk, loop through it. - - if (typeof chunk === 'string') { - chunkIndex = point._index; - - if (point._bufferIndex < 0) { - point._bufferIndex = 0; - } - - while ( - point._index === chunkIndex && - point._bufferIndex < chunk.length - ) { - go(chunk.charCodeAt(point._bufferIndex)); - } - } else { - go(chunk); - } + return { + line: point.line || null, + column: point.column || null, + offset: point.offset > -1 ? point.offset : null } } - /** - * Deal with one code. - * - * @param {Code} code - * @returns {void} - */ - - function go(code) { - state = state(code); - } - /** @type {Effects['consume']} */ - - function consume(code) { - if (markdownLineEnding(code)) { - point.line++; - point.column = 1; - point.offset += code === -3 ? 2 : 1; - accountForPotentialSkip(); - } else if (code !== -1) { - point.column++; - point.offset++; - } // Not in a string chunk. - - if (point._bufferIndex < 0) { - point._index++; - } else { - point._bufferIndex++; // At end of string chunk. - // @ts-expect-error Points w/ non-negative `_bufferIndex` reference - // strings. - - if (point._bufferIndex === chunks[point._index].length) { - point._bufferIndex = -1; - point._index++; - } - } // Expose the previous character. +} - context.previous = code; // Mark as consumed. - } - /** @type {Effects['enter']} */ +/** + * @typedef {Object} PointLike + * @property {number} [line] + * @property {number} [column] + * @property {number} [offset] + * + * @typedef {Object} PositionLike + * @property {PointLike} [start] + * @property {PointLike} [end] + * + * @typedef {Object} NodeLike + * @property {PositionLike} [position] + */ - function enter(type, fields) { - /** @type {Token} */ - // @ts-expect-error Patch instead of assign required fields to help GC. - const token = fields || {}; - token.type = type; - token.start = now(); - context.events.push(['enter', token, context]); - stack.push(token); - return token - } - /** @type {Effects['exit']} */ +/** + * Check if `node` is *generated*. + * + * @param {NodeLike} [node] + * @returns {boolean} + */ +function generated(node) { + return ( + !node || + !node.position || + !node.position.start || + !node.position.start.line || + !node.position.start.column || + !node.position.end || + !node.position.end.line || + !node.position.end.column + ) +} - function exit(type) { - const token = stack.pop(); - token.end = now(); - context.events.push(['exit', token, context]); - return token - } - /** - * Use results. - * - * @type {ReturnHandle} - */ +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module list-item-indent + * @fileoverview + * Warn when the spacing between a list item’s bullet and its content violates + * a given style. + * + * Options: `'tab-size'`, `'mixed'`, or `'space'`, default: `'tab-size'`. + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) + * uses `'tab-size'` (named `'tab'` there) by default to ensure Markdown is + * seen the same way across vendors. + * This can be configured with the + * [`listItemIndent`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify#optionslistitemindent) + * option. + * This rule’s `'space'` option is named `'1'` there. + * + * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) + * on how to automatically fix warnings for this rule. + * + * @example + * {"name": "ok.md"} + * + * *···List + * ····item. + * + * Paragraph. + * + * 11.·List + * ····item. + * + * Paragraph. + * + * *···List + * ····item. + * + * *···List + * ····item. + * + * @example + * {"name": "ok.md", "setting": "mixed"} + * + * *·List item. + * + * Paragraph. + * + * 11.·List item + * + * Paragraph. + * + * *···List + * ····item. + * + * *···List + * ····item. + * + * @example + * {"name": "ok.md", "setting": "space"} + * + * *·List item. + * + * Paragraph. + * + * 11.·List item + * + * Paragraph. + * + * *·List + * ··item. + * + * *·List + * ··item. + * + * @example + * {"name": "not-ok.md", "setting": "space", "label": "input"} + * + * *···List + * ····item. + * + * @example + * {"name": "not-ok.md", "setting": "space", "label": "output"} + * + * 1:5: Incorrect list-item indent: remove 2 spaces + * + * @example + * {"name": "not-ok.md", "setting": "tab-size", "label": "input"} + * + * *·List + * ··item. + * + * @example + * {"name": "not-ok.md", "setting": "tab-size", "label": "output"} + * + * 1:3: Incorrect list-item indent: add 2 spaces + * + * @example + * {"name": "not-ok.md", "setting": "mixed", "label": "input"} + * + * *···List item. + * + * @example + * {"name": "not-ok.md", "setting": "mixed", "label": "output"} + * + * 1:5: Incorrect list-item indent: remove 2 spaces + * + * @example + * {"name": "not-ok.md", "setting": "💩", "label": "output", "positionless": true} + * + * 1:1: Incorrect list-item indent style `💩`: use either `'tab-size'`, `'space'`, or `'mixed'` + */ - function onsuccessfulconstruct(construct, info) { - addResult(construct, info.from); - } - /** - * Discard results. - * - * @type {ReturnHandle} - */ +const remarkLintListItemIndent = lintRule( + { + origin: 'remark-lint:list-item-indent', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-indent#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file, option = 'tab-size') => { + const value = String(file); - function onsuccessfulcheck(_, info) { - info.restore(); - } - /** - * Factory to attempt/check/interrupt. - * - * @param {ReturnHandle} onreturn - * @param {Record} [fields] - */ + if (option !== 'tab-size' && option !== 'space' && option !== 'mixed') { + file.fail( + 'Incorrect list-item indent style `' + + option + + "`: use either `'tab-size'`, `'space'`, or `'mixed'`" + ); + } - function constructFactory(onreturn, fields) { - return hook - /** - * Handle either an object mapping codes to constructs, a list of - * constructs, or a single construct. - * - * @param {Construct|Construct[]|ConstructRecord} constructs - * @param {State} returnState - * @param {State} [bogusState] - * @returns {State} - */ + visit$1(tree, 'list', (node) => { + if (generated(node)) return - function hook(constructs, returnState, bogusState) { - /** @type {Construct[]} */ - let listOfConstructs; - /** @type {number} */ + const spread = node.spread; + let index = -1; - let constructIndex; - /** @type {Construct} */ + while (++index < node.children.length) { + const item = node.children[index]; + const head = item.children[0]; + const final = pointStart(head); - let currentConstruct; - /** @type {Info} */ + const marker = value + .slice(pointStart(item).offset, final.offset) + .replace(/\[[x ]?]\s*$/i, ''); - let info; - return Array.isArray(constructs) - ? /* c8 ignore next 1 */ - handleListOfConstructs(constructs) - : 'tokenize' in constructs // @ts-expect-error Looks like a construct. - ? handleListOfConstructs([constructs]) - : handleMapOfConstructs(constructs) - /** - * Handle a list of construct. - * - * @param {ConstructRecord} map - * @returns {State} - */ + const bulletSize = marker.replace(/\s+$/, '').length; - function handleMapOfConstructs(map) { - return start - /** @type {State} */ + const style = + option === 'tab-size' || (option === 'mixed' && spread) + ? Math.ceil(bulletSize / 4) * 4 + : bulletSize + 1; - function start(code) { - const def = code !== null && map[code]; - const all = code !== null && map.null; - const list = [ - // To do: add more extension tests. + if (marker.length !== style) { + const diff = style - marker.length; + const abs = Math.abs(diff); - /* c8 ignore next 2 */ - ...(Array.isArray(def) ? def : def ? [def] : []), - ...(Array.isArray(all) ? all : all ? [all] : []) - ]; - return handleListOfConstructs(list)(code) + file.message( + 'Incorrect list-item indent: ' + + (diff > 0 ? 'add' : 'remove') + + ' ' + + abs + + ' ' + + plural('space', abs), + final + ); } } - /** - * Handle a list of construct. - * - * @param {Construct[]} list - * @returns {State} - */ + }); + } +); - function handleListOfConstructs(list) { - listOfConstructs = list; - constructIndex = 0; +var remarkLintListItemIndent$1 = remarkLintListItemIndent; - if (list.length === 0) { - return bogusState - } +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module no-auto-link-without-protocol + * @fileoverview + * Warn for autolinks without protocol. + * Autolinks are URLs enclosed in `<` (less than) and `>` (greater than) + * characters. + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) + * adds a protocol where needed. + * + * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) + * on how to automatically fix warnings for this rule. + * + * @example + * {"name": "ok.md"} + * + * + * + * + * Most Markdown vendors don’t recognize the following as a link: + * + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 1:1-1:14: All automatic links must start with a protocol + */ - return handleConstruct(list[constructIndex]) +// Protocol expression. +// See: . +const protocol = /^[a-z][a-z+.-]+:\/?/i; + +const remarkLintNoAutoLinkWithoutProtocol = lintRule( + { + origin: 'remark-lint:no-auto-link-without-protocol', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-auto-link-without-protocol#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + visit$1(tree, 'link', (node) => { + if ( + !generated(node) && + pointStart(node).column === pointStart(node.children[0]).column - 1 && + pointEnd(node).column === + pointEnd(node.children[node.children.length - 1]).column + 1 && + !protocol.test(toString(node)) + ) { + file.message('All automatic links must start with a protocol', node); } - /** - * Handle a single construct. - * - * @param {Construct} construct - * @returns {State} - */ + }); + } +); - function handleConstruct(construct) { - return start - /** @type {State} */ +var remarkLintNoAutoLinkWithoutProtocol$1 = remarkLintNoAutoLinkWithoutProtocol; - function start(code) { - // To do: not needed to store if there is no bogus state, probably? - // Currently doesn’t work because `inspect` in document does a check - // w/o a bogus, which doesn’t make sense. But it does seem to help perf - // by not storing. - info = store(); - currentConstruct = construct; +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module no-blockquote-without-marker + * @fileoverview + * Warn when blank lines without `>` (greater than) markers are found in a + * block quote. + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) + * adds markers to every line in a block quote. + * + * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) + * on how to automatically fix warnings for this rule. + * + * @example + * {"name": "ok.md"} + * + * > Foo… + * > …bar… + * > …baz. + * + * @example + * {"name": "ok-tabs.md"} + * + * >»Foo… + * >»…bar… + * >»…baz. + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * > Foo… + * …bar… + * > …baz. + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 2:1: Missing marker in block quote + * + * @example + * {"name": "not-ok-tabs.md", "label": "input"} + * + * >»Foo… + * »…bar… + * …baz. + * + * @example + * {"name": "not-ok-tabs.md", "label": "output"} + * + * 2:1: Missing marker in block quote + * 3:1: Missing marker in block quote + */ - if (!construct.partial) { - context.currentConstruct = construct; - } +const remarkLintNoBlockquoteWithoutMarker = lintRule( + { + origin: 'remark-lint:no-blockquote-without-marker', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-blockquote-without-marker#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + const value = String(file); + const loc = location(file); - if ( - construct.name && - context.parser.constructs.disable.null.includes(construct.name) - ) { - return nok() - } + visit$1(tree, 'blockquote', (node) => { + let index = -1; - return construct.tokenize.call( - // If we do have fields, create an object w/ `context` as its - // prototype. - // This allows a “live binding”, which is needed for `interrupt`. - fields ? Object.assign(Object.create(context), fields) : context, - effects, - ok, - nok - )(code) + while (++index < node.children.length) { + const child = node.children[index]; + + if (child.type === 'paragraph' && !generated(child)) { + const end = pointEnd(child).line; + const column = pointStart(child).column; + let line = pointStart(child).line; + + // Skip past the first line. + while (++line <= end) { + const offset = loc.toOffset({line, column}); + + if (/>[\t ]+$/.test(value.slice(offset - 5, offset))) { + continue + } + + // Roughly here. + file.message('Missing marker in block quote', { + line, + column: column - 2 + }); + } } } - /** @type {State} */ + }); + } +); - function ok(code) { - onreturn(currentConstruct, info); - return returnState - } - /** @type {State} */ +var remarkLintNoBlockquoteWithoutMarker$1 = remarkLintNoBlockquoteWithoutMarker; - function nok(code) { - info.restore(); +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module no-literal-urls + * @fileoverview + * Warn for literal URLs in text. + * URLs are treated as links in some Markdown vendors, but not in others. + * To make sure they are always linked, wrap them in `<` (less than) and `>` + * (greater than). + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) + * never creates literal URLs and always uses `<` (less than) and `>` + * (greater than). + * + * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) + * on how to automatically fix warnings for this rule. + * + * @example + * {"name": "ok.md"} + * + * + * + * @example + * {"name": "not-ok.md", "label": "input", "gfm": true} + * + * http://foo.bar/baz + * + * @example + * {"name": "not-ok.md", "label": "output", "gfm": true} + * + * 1:1-1:19: Don’t use literal URLs without angle brackets + */ - if (++constructIndex < listOfConstructs.length) { - return handleConstruct(listOfConstructs[constructIndex]) - } +const remarkLintNoLiteralUrls = lintRule( + { + origin: 'remark-lint:no-literal-urls', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-literal-urls#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + visit$1(tree, 'link', (node) => { + const value = toString(node); - return bogusState + if ( + !generated(node) && + pointStart(node).column === pointStart(node.children[0]).column && + pointEnd(node).column === + pointEnd(node.children[node.children.length - 1]).column && + (node.url === 'mailto:' + value || node.url === value) + ) { + file.message('Don’t use literal URLs without angle brackets', node); } - } + }); } - /** - * @param {Construct} construct - * @param {number} from - * @returns {void} - */ +); - function addResult(construct, from) { - if (construct.resolveAll && !resolveAllConstructs.includes(construct)) { - resolveAllConstructs.push(construct); - } +var remarkLintNoLiteralUrls$1 = remarkLintNoLiteralUrls; - if (construct.resolve) { - splice( - context.events, - from, - context.events.length - from, - construct.resolve(context.events.slice(from), context) +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module ordered-list-marker-style + * @fileoverview + * Warn when the list item marker style of ordered lists violate a given style. + * + * Options: `'consistent'`, `'.'`, or `')'`, default: `'consistent'`. + * + * `'consistent'` detects the first used list style and warns when subsequent + * lists use different styles. + * + * @example + * {"name": "ok.md"} + * + * 1. Foo + * + * + * 1. Bar + * + * Unordered lists are not affected by this rule. + * + * * Foo + * + * @example + * {"name": "ok.md", "setting": "."} + * + * 1. Foo + * + * 2. Bar + * + * @example + * {"name": "ok.md", "setting": ")"} + * + * 1) Foo + * + * 2) Bar + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * 1. Foo + * + * 2) Bar + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 3:1-3:8: Marker style should be `.` + * + * @example + * {"name": "not-ok.md", "label": "output", "setting": "💩", "positionless": true} + * + * 1:1: Incorrect ordered list item marker style `💩`: use either `'.'` or `')'` + */ + +const remarkLintOrderedListMarkerStyle = lintRule( + { + origin: 'remark-lint:ordered-list-marker-style', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-ordered-list-marker-style#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file, option = 'consistent') => { + const value = String(file); + + if (option !== 'consistent' && option !== '.' && option !== ')') { + file.fail( + 'Incorrect ordered list item marker style `' + + option + + "`: use either `'.'` or `')'`" ); } - if (construct.resolveTo) { - context.events = construct.resolveTo(context.events, context); - } - } - /** - * Store state. - * - * @returns {Info} - */ + visit$1(tree, 'list', (node) => { + let index = -1; - function store() { - const startPoint = now(); - const startPrevious = context.previous; - const startCurrentConstruct = context.currentConstruct; - const startEventsIndex = context.events.length; - const startStack = Array.from(stack); - return { - restore, - from: startEventsIndex - } - /** - * Restore state. - * - * @returns {void} - */ + if (!node.ordered) return - function restore() { - point = startPoint; - context.previous = startPrevious; - context.currentConstruct = startCurrentConstruct; - context.events.length = startEventsIndex; - stack = startStack; - accountForPotentialSkip(); - } - } - /** - * Move the current point a bit forward in the line when it’s on a column - * skip. - * - * @returns {void} - */ + while (++index < node.children.length) { + const child = node.children[index]; + + if (!generated(child)) { + const marker = /** @type {Marker} */ ( + value + .slice( + pointStart(child).offset, + pointStart(child.children[0]).offset + ) + .replace(/\s|\d/g, '') + .replace(/\[[x ]?]\s*$/i, '') + ); - function accountForPotentialSkip() { - if (point.line in columnStart && point.column < 2) { - point.column = columnStart[point.line]; - point.offset += columnStart[point.line] - 1; - } + if (option === 'consistent') { + option = marker; + } else if (marker !== option) { + file.message('Marker style should be `' + option + '`', child); + } + } + } + }); } -} +); + +var remarkLintOrderedListMarkerStyle$1 = remarkLintOrderedListMarkerStyle; + /** - * Get the chunks from a slice of chunks in the range of a token. + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module hard-break-spaces + * @fileoverview + * Warn when too many spaces are used to create a hard break. * - * @param {Chunk[]} chunks - * @param {Pick} token - * @returns {Chunk[]} + * @example + * {"name": "ok.md"} + * + * Lorem ipsum·· + * dolor sit amet + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * Lorem ipsum··· + * dolor sit amet. + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 1:12-2:1: Use two spaces for hard line breaks */ -function sliceChunks(chunks, token) { - const startIndex = token.start._index; - const startBufferIndex = token.start._bufferIndex; - const endIndex = token.end._index; - const endBufferIndex = token.end._bufferIndex; - /** @type {Chunk[]} */ - - let view; - - if (startIndex === endIndex) { - // @ts-expect-error `_bufferIndex` is used on string chunks. - view = [chunks[startIndex].slice(startBufferIndex, endBufferIndex)]; - } else { - view = chunks.slice(startIndex, endIndex); +const remarkLintHardBreakSpaces = lintRule( + { + origin: 'remark-lint:hard-break-spaces', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-hard-break-spaces#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + const value = String(file); - if (startBufferIndex > -1) { - // @ts-expect-error `_bufferIndex` is used on string chunks. - view[0] = view[0].slice(startBufferIndex); - } + visit$1(tree, 'break', (node) => { + if (!generated(node)) { + const slice = value + .slice(pointStart(node).offset, pointEnd(node).offset) + .split('\n', 1)[0] + .replace(/\r$/, ''); - if (endBufferIndex > 0) { - // @ts-expect-error `_bufferIndex` is used on string chunks. - view.push(chunks[endIndex].slice(0, endBufferIndex)); - } + if (slice.length > 2) { + file.message('Use two spaces for hard line breaks', node); + } + } + }); } +); + +var remarkLintHardBreakSpaces$1 = remarkLintHardBreakSpaces; - return view -} /** - * Get the string value of a slice of chunks. + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module no-duplicate-definitions + * @fileoverview + * Warn when duplicate definitions are found. * - * @param {Chunk[]} chunks - * @param {boolean} [expandTabs=false] - * @returns {string} + * @example + * {"name": "ok.md"} + * + * [foo]: bar + * [baz]: qux + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * [foo]: bar + * [foo]: qux + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 2:1-2:11: Do not use definitions with the same identifier (1:1) */ -function serializeChunks(chunks, expandTabs) { - let index = -1; - /** @type {string[]} */ +const remarkLintNoDuplicateDefinitions = lintRule( + { + origin: 'remark-lint:no-duplicate-definitions', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-duplicate-definitions#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + /** @type {Record} */ + const map = Object.create(null); - const result = []; - /** @type {boolean|undefined} */ + visit$1(tree, (node) => { + if ( + (node.type === 'definition' || node.type === 'footnoteDefinition') && + !generated(node) + ) { + const identifier = node.identifier; + const duplicate = map[identifier]; - let atTab; + if (duplicate) { + file.message( + 'Do not use definitions with the same identifier (' + + duplicate + + ')', + node + ); + } - while (++index < chunks.length) { - const chunk = chunks[index]; - /** @type {string} */ + map[identifier] = stringifyPosition(pointStart(node)); + } + }); + } +); - let value; +var remarkLintNoDuplicateDefinitions$1 = remarkLintNoDuplicateDefinitions; - if (typeof chunk === 'string') { - value = chunk; - } else - switch (chunk) { - case -5: { - value = '\r'; - break - } +/** + * @typedef {import('mdast').Heading} Heading + * @typedef {'atx'|'atx-closed'|'setext'} Style + */ - case -4: { - value = '\n'; - break - } +/** + * @param {Heading} node + * @param {Style} [relative] + * @returns {Style|null} + */ +function headingStyle(node, relative) { + var last = node.children[node.children.length - 1]; + var depth = node.depth; + var pos = node && node.position && node.position.end; + var final = last && last.position && last.position.end; - case -3: { - value = '\r' + '\n'; - break - } + if (!pos) { + return null + } - case -2: { - value = expandTabs ? ' ' : '\t'; - break - } + // This can only occur for `'atx'` and `'atx-closed'` headings. + // This might incorrectly match `'atx'` headings with lots of trailing white + // space as an `'atx-closed'` heading. + if (!last) { + if (pos.column - 1 <= depth * 2) { + return consolidate(depth, relative) + } - case -1: { - if (!expandTabs && atTab) continue - value = ' '; - break - } + return 'atx-closed' + } - default: { - // Currently only replacement character. - value = String.fromCharCode(chunk); - } - } + if (final.line + 1 === pos.line) { + return 'setext' + } - atTab = chunk === -2; - result.push(value); + if (final.column + depth < pos.column) { + return 'atx-closed' } - return result.join('') + return consolidate(depth, relative) } /** - * @typedef {import('micromark-util-types').Extension} Extension + * Get the probable style of an atx-heading, depending on preferred style. + * + * @param {number} depth + * @param {Style} relative + * @returns {Style|null} */ -/** @type {Extension['document']} */ +function consolidate(depth, relative) { + return depth < 3 + ? 'atx' + : relative === 'atx' || relative === 'setext' + ? relative + : null +} -const document$1 = { - [42]: list$1, - [43]: list$1, - [45]: list$1, - [48]: list$1, - [49]: list$1, - [50]: list$1, - [51]: list$1, - [52]: list$1, - [53]: list$1, - [54]: list$1, - [55]: list$1, - [56]: list$1, - [57]: list$1, - [62]: blockQuote -}; -/** @type {Extension['contentInitial']} */ +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module no-heading-content-indent + * @fileoverview + * Warn when content of headings is indented. + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) + * removes all unneeded padding around content in headings. + * + * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) + * on how to automatically fix warnings for this rule. + * + * @example + * {"name": "ok.md"} + * + * #·Foo + * + * ## Bar·## + * + * ##·Baz + * + * Setext headings are not affected. + * + * Baz + * === + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * #··Foo + * + * ## Bar··## + * + * ##··Baz + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 1:4: Remove 1 space before this heading’s content + * 3:7: Remove 1 space after this heading’s content + * 5:7: Remove 1 space before this heading’s content + * + * @example + * {"name": "empty-heading.md"} + * + * #·· + */ -const contentInitial = { - [91]: definition$1 -}; -/** @type {Extension['flowInitial']} */ +const remarkLintNoHeadingContentIndent = lintRule( + { + origin: 'remark-lint:no-heading-content-indent', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-heading-content-indent#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + visit$1(tree, 'heading', (node) => { + if (generated(node)) { + return + } -const flowInitial = { - [-2]: codeIndented, - [-1]: codeIndented, - [32]: codeIndented -}; -/** @type {Extension['flow']} */ + const type = headingStyle(node, 'atx'); -const flow = { - [35]: headingAtx, - [42]: thematicBreak$1, - [45]: [setextUnderline, thematicBreak$1], - [60]: htmlFlow, - [61]: setextUnderline, - [95]: thematicBreak$1, - [96]: codeFenced, - [126]: codeFenced -}; -/** @type {Extension['string']} */ + if (type === 'atx' || type === 'atx-closed') { + const head = pointStart(node.children[0]).column; -const string = { - [38]: characterReference, - [92]: characterEscape -}; -/** @type {Extension['text']} */ + // Ignore empty headings. + if (!head) { + return + } -const text$2 = { - [-5]: lineEnding, - [-4]: lineEnding, - [-3]: lineEnding, - [33]: labelStartImage, - [38]: characterReference, - [42]: attention, - [60]: [autolink, htmlText], - [91]: labelStartLink, - [92]: [hardBreakEscape, characterEscape], - [93]: labelEnd, - [95]: attention, - [96]: codeText -}; -/** @type {Extension['insideSpan']} */ + const diff = head - pointStart(node).column - 1 - node.depth; -const insideSpan = { - null: [attention, resolver] -}; -/** @type {Extension['attentionMarkers']} */ + if (diff) { + file.message( + 'Remove ' + + Math.abs(diff) + + ' ' + + plural('space', Math.abs(diff)) + + ' before this heading’s content', + pointStart(node.children[0]) + ); + } + } -const attentionMarkers = { - null: [42, 95] -}; -/** @type {Extension['disable']} */ + // Closed ATX headings always must have a space between their content and + // the final hashes, thus, there is no `add x spaces`. + if (type === 'atx-closed') { + const final = pointEnd(node.children[node.children.length - 1]); + const diff = pointEnd(node).column - final.column - 1 - node.depth; -const disable = { - null: [] -}; + if (diff) { + file.message( + 'Remove ' + + diff + + ' ' + + plural('space', diff) + + ' after this heading’s content', + final + ); + } + } + }); + } +); -var defaultConstructs = /*#__PURE__*/Object.freeze({ - __proto__: null, - document: document$1, - contentInitial: contentInitial, - flowInitial: flowInitial, - flow: flow, - string: string, - text: text$2, - insideSpan: insideSpan, - attentionMarkers: attentionMarkers, - disable: disable -}); +var remarkLintNoHeadingContentIndent$1 = remarkLintNoHeadingContentIndent; /** - * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct - * @typedef {import('micromark-util-types').FullNormalizedExtension} FullNormalizedExtension - * @typedef {import('micromark-util-types').ParseOptions} ParseOptions - * @typedef {import('micromark-util-types').ParseContext} ParseContext - * @typedef {import('micromark-util-types').Create} Create - */ -/** - * @param {ParseOptions} [options] - * @returns {ParseContext} + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module no-inline-padding + * @fileoverview + * Warn when phrasing content is padded with spaces between their markers and + * content. + * + * Warns for emphasis, strong, delete, image, and link. + * + * @example + * {"name": "ok.md"} + * + * Alpha [bravo](http://echo.fox/trot) + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * Alpha [ bravo ](http://echo.fox/trot) + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 1:7-1:38: Don’t pad `link` with inner spaces */ -function parse(options = {}) { - /** @type {FullNormalizedExtension} */ - // @ts-expect-error `defaultConstructs` is full, so the result will be too. - const constructs = combineExtensions( - // @ts-expect-error Same as above. - [defaultConstructs].concat(options.extensions || []) - ); - /** @type {ParseContext} */ +const remarkLintNoInlinePadding = lintRule( + { + origin: 'remark-lint:no-inline-padding', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-inline-padding#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + // Note: `emphasis`, `strong`, `delete` (GFM) can’t have padding anymore + // since CM. + visit$1(tree, (node) => { + if ( + (node.type === 'link' || node.type === 'linkReference') && + !generated(node) + ) { + const value = toString(node); - const parser = { - defined: [], - lazy: {}, - constructs, - content: create(content$1), - document: create(document$2), - flow: create(flow$1), - string: create(string$1), - text: create(text$3) - }; - return parser - /** - * @param {InitialConstruct} initial - */ + if (value.charAt(0) === ' ' || value.charAt(value.length - 1) === ' ') { + file.message('Don’t pad `' + node.type + '` with inner spaces', node); + } + } + }); + } +); - function create(initial) { - return creator - /** @type {Create} */ +var remarkLintNoInlinePadding$1 = remarkLintNoInlinePadding; + +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module no-shortcut-reference-image + * @fileoverview + * Warn when shortcut reference images are used. + * + * Shortcut references render as images when a definition is found, and as + * plain text without definition. + * Sometimes, you don’t intend to create an image from the reference, but this + * rule still warns anyway. + * In that case, you can escape the reference like so: `!\[foo]`. + * + * @example + * {"name": "ok.md"} + * + * ![foo][] + * + * [foo]: http://foo.bar/baz.png + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * ![foo] + * + * [foo]: http://foo.bar/baz.png + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 1:1-1:7: Use the trailing [] on reference images + */ - function creator(from) { - return createTokenizer(parser, initial, from) - } +const remarkLintNoShortcutReferenceImage = lintRule( + { + origin: 'remark-lint:no-shortcut-reference-image', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-shortcut-reference-image#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + visit$1(tree, 'imageReference', (node) => { + if (!generated(node) && node.referenceType === 'shortcut') { + file.message('Use the trailing [] on reference images', node); + } + }); } -} +); -/** - * @typedef {import('micromark-util-types').Encoding} Encoding - * @typedef {import('micromark-util-types').Value} Value - * @typedef {import('micromark-util-types').Chunk} Chunk - * @typedef {import('micromark-util-types').Code} Code - */ +var remarkLintNoShortcutReferenceImage$1 = remarkLintNoShortcutReferenceImage; /** - * @callback Preprocessor - * @param {Value} value - * @param {Encoding} [encoding] - * @param {boolean} [end=false] - * @returns {Chunk[]} - */ -const search = /[\0\t\n\r]/g; -/** - * @returns {Preprocessor} + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module no-shortcut-reference-link + * @fileoverview + * Warn when shortcut reference links are used. + * + * Shortcut references render as links when a definition is found, and as + * plain text without definition. + * Sometimes, you don’t intend to create a link from the reference, but this + * rule still warns anyway. + * In that case, you can escape the reference like so: `\[foo]`. + * + * @example + * {"name": "ok.md"} + * + * [foo][] + * + * [foo]: http://foo.bar/baz + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * [foo] + * + * [foo]: http://foo.bar/baz + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 1:1-1:6: Use the trailing `[]` on reference links */ -function preprocess() { - let column = 1; - let buffer = ''; - /** @type {boolean|undefined} */ - - let start = true; - /** @type {boolean|undefined} */ - - let atCarriageReturn; - return preprocessor - /** @type {Preprocessor} */ - - function preprocessor(value, encoding, end) { - /** @type {Chunk[]} */ - const chunks = []; - /** @type {RegExpMatchArray|null} */ - - let match; - /** @type {number} */ - - let next; - /** @type {number} */ - - let startPosition; - /** @type {number} */ +const remarkLintNoShortcutReferenceLink = lintRule( + { + origin: 'remark-lint:no-shortcut-reference-link', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-shortcut-reference-link#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + visit$1(tree, 'linkReference', (node) => { + if (!generated(node) && node.referenceType === 'shortcut') { + file.message('Use the trailing `[]` on reference links', node); + } + }); + } +); - let endPosition; - /** @type {Code} */ +var remarkLintNoShortcutReferenceLink$1 = remarkLintNoShortcutReferenceLink; - let code; // @ts-expect-error `Buffer` does allow an encoding. +/** + * @author Titus Wormer + * @copyright 2016 Titus Wormer + * @license MIT + * @module no-undefined-references + * @fileoverview + * Warn when references to undefined definitions are found. + * + * Options: `Object`, optional. + * + * The object can have an `allow` field, set to an array of strings that may + * appear between `[` and `]`, but that should not be treated as link + * identifiers. + * + * @example + * {"name": "ok.md"} + * + * [foo][] + * + * Just a [ bracket. + * + * Typically, you’d want to use escapes (with a backslash: \\) to escape what + * could turn into a \[reference otherwise]. + * + * Just two braces can’t link: []. + * + * [foo]: https://example.com + * + * @example + * {"name": "ok-allow.md", "setting": {"allow": ["...", "…"]}} + * + * > Eliding a portion of a quoted passage […] is acceptable. + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * [bar] + * + * [baz][] + * + * [text][qux] + * + * Spread [over + * lines][] + * + * > in [a + * > block quote][] + * + * [asd][a + * + * Can include [*emphasis*]. + * + * Multiple pairs: [a][b][c]. + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 1:1-1:6: Found reference to undefined definition + * 3:1-3:8: Found reference to undefined definition + * 5:1-5:12: Found reference to undefined definition + * 7:8-8:9: Found reference to undefined definition + * 10:6-11:17: Found reference to undefined definition + * 13:1-13:6: Found reference to undefined definition + * 15:13-15:25: Found reference to undefined definition + * 17:17-17:23: Found reference to undefined definition + * 17:23-17:26: Found reference to undefined definition + */ - value = buffer + value.toString(encoding); - startPosition = 0; - buffer = ''; +const remarkLintNoUndefinedReferences = lintRule( + { + origin: 'remark-lint:no-undefined-references', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-undefined-references#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file, option = {}) => { + const contents = String(file); + const loc = location(file); + const lineEnding = /(\r?\n|\r)[\t ]*(>[\t ]*)*/g; + const allow = new Set( + (option.allow || []).map((d) => normalizeIdentifier(d)) + ); + /** @type {Record} */ + const map = Object.create(null); - if (start) { - if (value.charCodeAt(0) === 65279) { - startPosition++; + visit$1(tree, (node) => { + if ( + (node.type === 'definition' || node.type === 'footnoteDefinition') && + !generated(node) + ) { + map[normalizeIdentifier(node.identifier)] = true; } + }); - start = undefined; - } - - while (startPosition < value.length) { - search.lastIndex = startPosition; - match = search.exec(value); - endPosition = - match && match.index !== undefined ? match.index : value.length; - code = value.charCodeAt(endPosition); + visit$1(tree, (node) => { + // CM specifiers that references only form when defined. + // Still, they could be added by plugins, so let’s keep it. + /* c8 ignore next 10 */ + if ( + (node.type === 'imageReference' || + node.type === 'linkReference' || + node.type === 'footnoteReference') && + !generated(node) && + !(normalizeIdentifier(node.identifier) in map) && + !allow.has(normalizeIdentifier(node.identifier)) + ) { + file.message('Found reference to undefined definition', node); + } - if (!match) { - buffer = value.slice(startPosition); - break + if (node.type === 'paragraph' || node.type === 'heading') { + findInPhrasing(node); } + }); - if (code === 10 && startPosition === endPosition && atCarriageReturn) { - chunks.push(-3); - atCarriageReturn = undefined; - } else { - if (atCarriageReturn) { - chunks.push(-5); - atCarriageReturn = undefined; - } + /** + * @param {Heading|Paragraph} node + */ + function findInPhrasing(node) { + /** @type {Range[]} */ + let ranges = []; - if (startPosition < endPosition) { - chunks.push(value.slice(startPosition, endPosition)); - column += endPosition - startPosition; + visit$1(node, (child) => { + // Ignore the node itself. + if (child === node) return + + // Can’t have links in links, so reset ranges. + if (child.type === 'link' || child.type === 'linkReference') { + ranges = []; + return SKIP$1 } - switch (code) { - case 0: { - chunks.push(65533); - column++; - break - } + // Enter non-text. + if (child.type !== 'text') return - case 9: { - next = Math.ceil(column / 4) * 4; - chunks.push(-2); + const start = pointStart(child).offset; + const end = pointEnd(child).offset; - while (column++ < next) chunks.push(-1); + // Bail if there’s no positional info. + if (typeof start !== 'number' || typeof end !== 'number') { + return EXIT$1 + } - break - } + const source = contents.slice(start, end); + /** @type {Array.<[number, string]>} */ + const lines = [[start, '']]; + let last = 0; - case 10: { - chunks.push(-4); - column = 1; - break - } + lineEnding.lastIndex = 0; + let match = lineEnding.exec(source); - default: { - atCarriageReturn = true; - column = 1; - } + while (match) { + const index = match.index; + lines[lines.length - 1][1] = source.slice(last, index); + last = index + match[0].length; + lines.push([start + last, '']); + match = lineEnding.exec(source); } - } - - startPosition = endPosition + 1; - } - if (end) { - if (atCarriageReturn) chunks.push(-5); - if (buffer) chunks.push(buffer); - chunks.push(null); - } + lines[lines.length - 1][1] = source.slice(last); + let lineIndex = -1; - return chunks - } -} + while (++lineIndex < lines.length) { + const line = lines[lineIndex][1]; + let index = 0; -/** - * @typedef {import('micromark-util-types').Event} Event - */ -/** - * @param {Event[]} events - * @returns {Event[]} - */ + while (index < line.length) { + const code = line.charCodeAt(index); -function postprocess(events) { - while (!subtokenize(events)) { - // Empty - } + // Skip past escaped brackets. + if (code === 92) { + const next = line.charCodeAt(index + 1); + index++; - return events -} + if (next === 91 || next === 93) { + index++; + } + } + // Opening bracket. + else if (code === 91) { + ranges.push([lines[lineIndex][0] + index]); + index++; + } + // Close bracket. + else if (code === 93) { + // No opening. + if (ranges.length === 0) { + index++; + } else if (line.charCodeAt(index + 1) === 91) { + index++; -/** - * Turn the number (in string form as either hexa- or plain decimal) coming from - * a numeric character reference into a character. - * - * @param {string} value - * Value to decode. - * @param {number} base - * Numeric base. - * @returns {string} - */ -function decodeNumericCharacterReference(value, base) { - const code = Number.parseInt(value, base); + // Collapsed or full. + let range = ranges.pop(); - if ( - // C0 except for HT, LF, FF, CR, space - code < 9 || - code === 11 || - (code > 13 && code < 32) || // Control character (DEL) of the basic block and C1 controls. - (code > 126 && code < 160) || // Lone high surrogates and low surrogates. - (code > 55295 && code < 57344) || // Noncharacters. - (code > 64975 && code < 65008) || - (code & 65535) === 65535 || - (code & 65535) === 65534 || // Out of range - code > 1114111 - ) { - return '\uFFFD' - } + // Range should always exist. + // eslint-disable-next-line max-depth + if (range) { + range.push(lines[lineIndex][0] + index); - return String.fromCharCode(code) -} + // This is the end of a reference already. + // eslint-disable-next-line max-depth + if (range.length === 4) { + handleRange(range); + range = []; + } -const characterEscapeOrReference = - /\\([!-/:-@[-`{-~])|&(#(?:\d{1,7}|x[\da-f]{1,6})|[\da-z]{1,31});/gi; -/** - * Utility to decode markdown strings (which occur in places such as fenced - * code info strings, destinations, labels, and titles). - * The “string” content type allows character escapes and -references. - * This decodes those. - * - * @param {string} value - * @returns {string} - */ + range.push(lines[lineIndex][0] + index); + ranges.push(range); + index++; + } + } else { + index++; -function decodeString(value) { - return value.replace(characterEscapeOrReference, decode) -} -/** - * @param {string} $0 - * @param {string} $1 - * @param {string} $2 - * @returns {string} - */ + // Shortcut or typical end of a reference. + const range = ranges.pop(); -function decode($0, $1, $2) { - if ($1) { - // Escape. - return $1 - } // Reference. + // Range should always exist. + // eslint-disable-next-line max-depth + if (range) { + range.push(lines[lineIndex][0] + index); + handleRange(range); + } + } + } + // Anything else. + else { + index++; + } + } + } + }); - const head = $2.charCodeAt(0); + let index = -1; - if (head === 35) { - const head = $2.charCodeAt(1); - const hex = head === 120 || head === 88; - return decodeNumericCharacterReference($2.slice(hex ? 2 : 1), hex ? 16 : 10) - } + while (++index < ranges.length) { + handleRange(ranges[index]); + } - return decodeEntity($2) || $0 -} + return SKIP$1 -/** - * @typedef {import('micromark-util-types').Encoding} Encoding - * @typedef {import('micromark-util-types').Event} Event - * @typedef {import('micromark-util-types').ParseOptions} ParseOptions - * @typedef {import('micromark-util-types').Token} Token - * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext - * @typedef {import('micromark-util-types').Value} Value - * @typedef {import('unist').Parent} UnistParent - * @typedef {import('unist').Point} Point - * @typedef {import('mdast').PhrasingContent} PhrasingContent - * @typedef {import('mdast').Content} Content - * @typedef {Root|Content} Node - * @typedef {Extract} Parent - * @typedef {import('mdast').Break} Break - * @typedef {import('mdast').Blockquote} Blockquote - * @typedef {import('mdast').Code} Code - * @typedef {import('mdast').Definition} Definition - * @typedef {import('mdast').Emphasis} Emphasis - * @typedef {import('mdast').Heading} Heading - * @typedef {import('mdast').HTML} HTML - * @typedef {import('mdast').Image} Image - * @typedef {import('mdast').ImageReference} ImageReference - * @typedef {import('mdast').InlineCode} InlineCode - * @typedef {import('mdast').Link} Link - * @typedef {import('mdast').LinkReference} LinkReference - * @typedef {import('mdast').List} List - * @typedef {import('mdast').ListItem} ListItem - * @typedef {import('mdast').Paragraph} Paragraph - * @typedef {import('mdast').Root} Root - * @typedef {import('mdast').Strong} Strong - * @typedef {import('mdast').Text} Text - * @typedef {import('mdast').ThematicBreak} ThematicBreak - * - * @typedef {UnistParent & {type: 'fragment', children: PhrasingContent[]}} Fragment - */ -const own$4 = {}.hasOwnProperty; -/** - * @param value Markdown to parse (`string` or `Buffer`). - * @param [encoding] Character encoding to understand `value` as when it’s a `Buffer` (`string`, default: `'utf8'`). - * @param [options] Configuration - */ + /** + * @param {Range} range + */ + function handleRange(range) { + if (range.length === 1) return + if (range.length === 3) range.length = 2; -const fromMarkdown = - /** - * @param {Value} value - * @param {Encoding} [encoding] - * @param {Options} [options] - * @returns {Root} - */ - function (value, encoding, options) { - if (typeof encoding !== 'string') { - options = encoding; - encoding = undefined; + // No need to warn for just `[]`. + if (range.length === 2 && range[0] + 2 === range[1]) return + + const offset = range.length === 4 && range[2] + 2 !== range[3] ? 2 : 0; + const id = contents + .slice(range[0 + offset] + 1, range[1 + offset] - 1) + .replace(lineEnding, ' '); + const pos = { + start: loc.toPoint(range[0]), + end: loc.toPoint(range[range.length - 1]) + }; + + if ( + !generated({position: pos}) && + !(normalizeIdentifier(id) in map) && + !allow.has(normalizeIdentifier(id)) + ) { + file.message('Found reference to undefined definition', pos); + } + } } + } +); + +var remarkLintNoUndefinedReferences$1 = remarkLintNoUndefinedReferences; - return compiler(options)( - postprocess( - parse(options).document().write(preprocess()(value, encoding, true)) - ) - ) - }; /** - * Note this compiler only understand complete buffering, not streaming. + * @author Titus Wormer + * @copyright 2016 Titus Wormer + * @license MIT + * @module no-unused-definitions + * @fileoverview + * Warn when unused definitions are found. * - * @param {Options} [options] + * @example + * {"name": "ok.md"} + * + * [foo][] + * + * [foo]: https://example.com + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * [bar]: https://example.com + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 1:1-1:27: Found unused definition */ -function compiler(options = {}) { - /** @type {NormalizedExtension} */ - // @ts-expect-error: our base has all required fields, so the result will too. - const config = configure$1( - { - transforms: [], - canContainEols: [ - 'emphasis', - 'fragment', - 'heading', - 'paragraph', - 'strong' - ], - enter: { - autolink: opener(link), - autolinkProtocol: onenterdata, - autolinkEmail: onenterdata, - atxHeading: opener(heading), - blockQuote: opener(blockQuote), - characterEscape: onenterdata, - characterReference: onenterdata, - codeFenced: opener(codeFlow), - codeFencedFenceInfo: buffer, - codeFencedFenceMeta: buffer, - codeIndented: opener(codeFlow, buffer), - codeText: opener(codeText, buffer), - codeTextData: onenterdata, - data: onenterdata, - codeFlowValue: onenterdata, - definition: opener(definition), - definitionDestinationString: buffer, - definitionLabelString: buffer, - definitionTitleString: buffer, - emphasis: opener(emphasis), - hardBreakEscape: opener(hardBreak), - hardBreakTrailing: opener(hardBreak), - htmlFlow: opener(html, buffer), - htmlFlowData: onenterdata, - htmlText: opener(html, buffer), - htmlTextData: onenterdata, - image: opener(image), - label: buffer, - link: opener(link), - listItem: opener(listItem), - listItemValue: onenterlistitemvalue, - listOrdered: opener(list, onenterlistordered), - listUnordered: opener(list), - paragraph: opener(paragraph), - reference: onenterreference, - referenceString: buffer, - resourceDestinationString: buffer, - resourceTitleString: buffer, - setextHeading: opener(heading), - strong: opener(strong), - thematicBreak: opener(thematicBreak) - }, - exit: { - atxHeading: closer(), - atxHeadingSequence: onexitatxheadingsequence, - autolink: closer(), - autolinkEmail: onexitautolinkemail, - autolinkProtocol: onexitautolinkprotocol, - blockQuote: closer(), - characterEscapeValue: onexitdata, - characterReferenceMarkerHexadecimal: onexitcharacterreferencemarker, - characterReferenceMarkerNumeric: onexitcharacterreferencemarker, - characterReferenceValue: onexitcharacterreferencevalue, - codeFenced: closer(onexitcodefenced), - codeFencedFence: onexitcodefencedfence, - codeFencedFenceInfo: onexitcodefencedfenceinfo, - codeFencedFenceMeta: onexitcodefencedfencemeta, - codeFlowValue: onexitdata, - codeIndented: closer(onexitcodeindented), - codeText: closer(onexitcodetext), - codeTextData: onexitdata, - data: onexitdata, - definition: closer(), - definitionDestinationString: onexitdefinitiondestinationstring, - definitionLabelString: onexitdefinitionlabelstring, - definitionTitleString: onexitdefinitiontitlestring, - emphasis: closer(), - hardBreakEscape: closer(onexithardbreak), - hardBreakTrailing: closer(onexithardbreak), - htmlFlow: closer(onexithtmlflow), - htmlFlowData: onexitdata, - htmlText: closer(onexithtmltext), - htmlTextData: onexitdata, - image: closer(onexitimage), - label: onexitlabel, - labelText: onexitlabeltext, - lineEnding: onexitlineending, - link: closer(onexitlink), - listItem: closer(), - listOrdered: closer(), - listUnordered: closer(), - paragraph: closer(), - referenceString: onexitreferencestring, - resourceDestinationString: onexitresourcedestinationstring, - resourceTitleString: onexitresourcetitlestring, - resource: onexitresource, - setextHeading: closer(onexitsetextheading), - setextHeadingLineSequence: onexitsetextheadinglinesequence, - setextHeadingText: onexitsetextheadingtext, - strong: closer(), - thematicBreak: closer() - } - }, - options.mdastExtensions || [] - ); - /** @type {CompileData} */ +const own$2 = {}.hasOwnProperty; - const data = {}; - return compile - /** - * @param {Array.} events - * @returns {Root} - */ +const remarkLintNoUnusedDefinitions = lintRule( + { + origin: 'remark-lint:no-unused-definitions', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-unused-definitions#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + /** @type {Record} */ + const map = Object.create(null); - function compile(events) { - /** @type {Root} */ - let tree = { - type: 'root', - children: [] - }; - /** @type {CompileContext['stack']} */ + visit$1(tree, (node) => { + if ( + (node.type === 'definition' || node.type === 'footnoteDefinition') && + !generated(node) + ) { + map[node.identifier.toUpperCase()] = {node, used: false}; + } + }); - const stack = [tree]; - /** @type {CompileContext['tokenStack']} */ + visit$1(tree, (node) => { + if ( + node.type === 'imageReference' || + node.type === 'linkReference' || + node.type === 'footnoteReference' + ) { + const info = map[node.identifier.toUpperCase()]; - const tokenStack = []; - /** @type {Array.} */ + if (!generated(node) && info) { + info.used = true; + } + } + }); - const listStack = []; - /** @type {Omit} */ + /** @type {string} */ + let identifier; - const context = { - stack, - tokenStack, - config, - enter, - exit, - buffer, - resume, - setData, - getData - }; - let index = -1; + for (identifier in map) { + if (own$2.call(map, identifier)) { + const entry = map[identifier]; - while (++index < events.length) { - // We preprocess lists to add `listItem` tokens, and to infer whether - // items the list itself are spread out. - if ( - events[index][1].type === 'listOrdered' || - events[index][1].type === 'listUnordered' - ) { - if (events[index][0] === 'enter') { - listStack.push(index); - } else { - const tail = listStack.pop(); - index = prepareList(events, tail, index); + if (!entry.used) { + file.message('Found unused definition', entry.node); } } } + } +); - index = -1; +var remarkLintNoUnusedDefinitions$1 = remarkLintNoUnusedDefinitions; - while (++index < events.length) { - const handler = config[events[index][0]]; +/** + * @fileoverview + * remark preset to configure `remark-lint` with settings that prevent + * mistakes or stuff that fails across vendors. + */ - if (own$4.call(handler, events[index][1].type)) { - handler[events[index][1].type].call( - Object.assign( - { - sliceSerialize: events[index][2].sliceSerialize - }, - context - ), - events[index][1] - ); - } - } +/** @type {Preset} */ +const remarkPresetLintRecommended = { + plugins: [ + remarkLint, + // Unix compatibility. + remarkLintFinalNewline$1, + // Rendering across vendors differs greatly if using other styles. + remarkLintListItemBulletIndent$1, + [remarkLintListItemIndent$1, 'tab-size'], + // Differs or unsupported across vendors. + remarkLintNoAutoLinkWithoutProtocol$1, + remarkLintNoBlockquoteWithoutMarker$1, + remarkLintNoLiteralUrls$1, + [remarkLintOrderedListMarkerStyle$1, '.'], + // Mistakes. + remarkLintHardBreakSpaces$1, + remarkLintNoDuplicateDefinitions$1, + remarkLintNoHeadingContentIndent$1, + remarkLintNoInlinePadding$1, + remarkLintNoShortcutReferenceImage$1, + remarkLintNoShortcutReferenceLink$1, + remarkLintNoUndefinedReferences$1, + remarkLintNoUnusedDefinitions$1 + ] +}; - if (tokenStack.length > 0) { - throw new Error( - 'Cannot close document, a token (`' + - tokenStack[tokenStack.length - 1].type + - '`, ' + - stringifyPosition$1({ - start: tokenStack[tokenStack.length - 1].start, - end: tokenStack[tokenStack.length - 1].end - }) + - ') is still open' - ) - } // Figure out `root` position. +var remarkPresetLintRecommended$1 = remarkPresetLintRecommended; - tree.position = { - start: point( - events.length > 0 - ? events[0][1].start - : { - line: 1, - column: 1, - offset: 0 - } - ), - end: point( - events.length > 0 - ? events[events.length - 2][1].end - : { - line: 1, - column: 1, - offset: 0 - } - ) - }; - index = -1; +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module blockquote-indentation + * @fileoverview + * Warn when block quotes are indented too much or too little. + * + * Options: `number` or `'consistent'`, default: `'consistent'`. + * + * `'consistent'` detects the first used indentation and will warn when + * other block quotes use a different indentation. + * + * @example + * {"name": "ok.md", "setting": 4} + * + * > Hello + * + * Paragraph. + * + * > World + * @example + * {"name": "ok.md", "setting": 2} + * + * > Hello + * + * Paragraph. + * + * > World + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * > Hello + * + * Paragraph. + * + * > World + * + * Paragraph. + * + * > World + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 5:5: Remove 1 space between block quote and content + * 9:3: Add 1 space between block quote and content + */ - while (++index < config.transforms.length) { - tree = config.transforms[index](tree) || tree; - } +const remarkLintBlockquoteIndentation = lintRule( + { + origin: 'remark-lint:blockquote-indentation', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-blockquote-indentation#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file, option = 'consistent') => { + visit$1(tree, 'blockquote', (node) => { + if (generated(node) || node.children.length === 0) { + return + } - return tree + if (option === 'consistent') { + option = check$1(node); + } else { + const diff = option - check$1(node); + + if (diff !== 0) { + const abs = Math.abs(diff); + + file.message( + (diff > 0 ? 'Add' : 'Remove') + + ' ' + + abs + + ' ' + + plural('space', abs) + + ' between block quote and content', + pointStart(node.children[0]) + ); + } + } + }); } - /** - * @param {Array.} events - * @param {number} start - * @param {number} length - * @returns {number} - */ +); - function prepareList(events, start, length) { - let index = start - 1; - let containerBalance = -1; - let listSpread = false; - /** @type {Token|undefined} */ +var remarkLintBlockquoteIndentation$1 = remarkLintBlockquoteIndentation; + +/** + * @param {Blockquote} node + * @returns {number} + */ +function check$1(node) { + return pointStart(node.children[0]).column - pointStart(node).column +} + +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module checkbox-character-style + * @fileoverview + * Warn when list item checkboxes violate a given style. + * + * Options: `Object` or `'consistent'`, default: `'consistent'`. + * + * `'consistent'` detects the first used checked and unchecked checkbox + * styles and warns when subsequent checkboxes use different styles. + * + * Styles can also be passed in like so: + * + * ```js + * {checked: 'x', unchecked: ' '} + * ``` + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) + * formats checked checkboxes using `x` (lowercase X) and unchecked checkboxes + * as `·` (a single space). + * + * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) + * on how to automatically fix warnings for this rule. + * + * @example + * {"name": "ok.md", "setting": {"checked": "x"}, "gfm": true} + * + * - [x] List item + * - [x] List item + * + * @example + * {"name": "ok.md", "setting": {"checked": "X"}, "gfm": true} + * + * - [X] List item + * - [X] List item + * + * @example + * {"name": "ok.md", "setting": {"unchecked": " "}, "gfm": true} + * + * - [ ] List item + * - [ ] List item + * - [ ]·· + * - [ ] + * + * @example + * {"name": "ok.md", "setting": {"unchecked": "\t"}, "gfm": true} + * + * - [»] List item + * - [»] List item + * + * @example + * {"name": "not-ok.md", "label": "input", "gfm": true} + * + * - [x] List item + * - [X] List item + * - [ ] List item + * - [»] List item + * + * @example + * {"name": "not-ok.md", "label": "output", "gfm": true} + * + * 2:5: Checked checkboxes should use `x` as a marker + * 4:5: Unchecked checkboxes should use ` ` as a marker + * + * @example + * {"setting": {"unchecked": "💩"}, "name": "not-ok.md", "label": "output", "positionless": true, "gfm": true} + * + * 1:1: Incorrect unchecked checkbox marker `💩`: use either `'\t'`, or `' '` + * + * @example + * {"setting": {"checked": "💩"}, "name": "not-ok.md", "label": "output", "positionless": true, "gfm": true} + * + * 1:1: Incorrect checked checkbox marker `💩`: use either `'x'`, or `'X'` + */ - let listItem; - /** @type {number|undefined} */ +const remarkLintCheckboxCharacterStyle = lintRule( + { + origin: 'remark-lint:checkbox-character-style', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-checkbox-character-style#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file, option = 'consistent') => { + const value = String(file); + /** @type {'x'|'X'|'consistent'} */ + let checked = 'consistent'; + /** @type {' '|'\x09'|'consistent'} */ + let unchecked = 'consistent'; - let lineIndex; - /** @type {number|undefined} */ + if (typeof option === 'object') { + checked = option.checked || 'consistent'; + unchecked = option.unchecked || 'consistent'; + } - let firstBlankLineIndex; - /** @type {boolean|undefined} */ + if (unchecked !== 'consistent' && unchecked !== ' ' && unchecked !== '\t') { + file.fail( + 'Incorrect unchecked checkbox marker `' + + unchecked + + "`: use either `'\\t'`, or `' '`" + ); + } - let atMarker; + if (checked !== 'consistent' && checked !== 'x' && checked !== 'X') { + file.fail( + 'Incorrect checked checkbox marker `' + + checked + + "`: use either `'x'`, or `'X'`" + ); + } - while (++index <= length) { - const event = events[index]; + visit$1(tree, 'listItem', (node) => { + const head = node.children[0]; + const point = pointStart(head); + // Exit early for items without checkbox. + // A list item cannot be checked and empty, according to GFM. if ( - event[1].type === 'listUnordered' || - event[1].type === 'listOrdered' || - event[1].type === 'blockQuote' + typeof node.checked !== 'boolean' || + !head || + typeof point.offset !== 'number' ) { - if (event[0] === 'enter') { - containerBalance++; - } else { - containerBalance--; - } - - atMarker = undefined; - } else if (event[1].type === 'lineEndingBlank') { - if (event[0] === 'enter') { - if ( - listItem && - !atMarker && - !containerBalance && - !firstBlankLineIndex - ) { - firstBlankLineIndex = index; - } - - atMarker = undefined; - } - } else if ( - event[1].type === 'linePrefix' || - event[1].type === 'listItemValue' || - event[1].type === 'listItemMarker' || - event[1].type === 'listItemPrefix' || - event[1].type === 'listItemPrefixWhitespace' - ) ; else { - atMarker = undefined; + return } - if ( - (!containerBalance && - event[0] === 'enter' && - event[1].type === 'listItemPrefix') || - (containerBalance === -1 && - event[0] === 'exit' && - (event[1].type === 'listUnordered' || - event[1].type === 'listOrdered')) - ) { - if (listItem) { - let tailIndex = index; - lineIndex = undefined; - - while (tailIndex--) { - const tailEvent = events[tailIndex]; - - if ( - tailEvent[1].type === 'lineEnding' || - tailEvent[1].type === 'lineEndingBlank' - ) { - if (tailEvent[0] === 'exit') continue - - if (lineIndex) { - events[lineIndex][1].type = 'lineEndingBlank'; - listSpread = true; - } - - tailEvent[1].type = 'lineEnding'; - lineIndex = tailIndex; - } else if ( - tailEvent[1].type === 'linePrefix' || - tailEvent[1].type === 'blockQuotePrefix' || - tailEvent[1].type === 'blockQuotePrefixWhitespace' || - tailEvent[1].type === 'blockQuoteMarker' || - tailEvent[1].type === 'listItemIndent' - ) ; else { - break - } - } + // Move back to before `] `. + point.offset -= 2; + point.column -= 2; - if ( - firstBlankLineIndex && - (!lineIndex || firstBlankLineIndex < lineIndex) - ) { - // @ts-expect-error Patched. - listItem._spread = true; - } // Fix position. + // Assume we start with a checkbox, because well, `checked` is set. + const match = /\[([\t Xx])]/.exec( + value.slice(point.offset - 2, point.offset + 1) + ); - listItem.end = Object.assign( - {}, - lineIndex ? events[lineIndex][1].start : event[1].end - ); - events.splice(lineIndex || index, 0, ['exit', listItem, event[2]]); - index++; - length++; - } // Create a new list item. + // Failsafe to make sure we don‘t crash if there actually isn’t a checkbox. + /* c8 ignore next */ + if (!match) return - if (event[1].type === 'listItemPrefix') { - listItem = { - type: 'listItem', - // @ts-expect-error Patched - _spread: false, - start: Object.assign({}, event[1].start) - }; // @ts-expect-error: `listItem` is most definitely defined, TS... + const style = node.checked ? checked : unchecked; - events.splice(index, 0, ['enter', listItem, event[2]]); - index++; - length++; - firstBlankLineIndex = undefined; - atMarker = true; + if (style === 'consistent') { + if (node.checked) { + // @ts-expect-error: valid marker. + checked = match[1]; + } else { + // @ts-expect-error: valid marker. + unchecked = match[1]; } + } else if (match[1] !== style) { + file.message( + (node.checked ? 'Checked' : 'Unchecked') + + ' checkboxes should use `' + + style + + '` as a marker', + point + ); } - } // @ts-expect-error Patched. - - events[start][1]._spread = listSpread; - return length + }); } - /** - * @type {CompileContext['setData']} - * @param [value] - */ +); - function setData(key, value) { - data[key] = value; - } - /** - * @type {CompileContext['getData']} - * @template {string} K - * @param {K} key - * @returns {CompileData[K]} - */ +var remarkLintCheckboxCharacterStyle$1 = remarkLintCheckboxCharacterStyle; - function getData(key) { - return data[key] - } - /** - * @param {Point} d - * @returns {Point} - */ +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module checkbox-content-indent + * @fileoverview + * Warn when list item checkboxes are followed by too much whitespace. + * + * @example + * {"name": "ok.md", "gfm": true} + * + * - [ ] List item + * + [x] List Item + * * [X] List item + * - [ ] List item + * + * @example + * {"name": "not-ok.md", "label": "input", "gfm": true} + * + * - [ ] List item + * + [x] List item + * * [X] List item + * - [ ] List item + * + * @example + * {"name": "not-ok.md", "label": "output", "gfm": true} + * + * 2:7-2:8: Checkboxes should be followed by a single character + * 3:7-3:9: Checkboxes should be followed by a single character + * 4:7-4:10: Checkboxes should be followed by a single character + */ - function point(d) { - return { - line: d.line, - column: d.column, - offset: d.offset - } - } - /** - * @param {(token: Token) => Node} create - * @param {Handle} [and] - * @returns {Handle} - */ +const remarkLintCheckboxContentIndent = lintRule( + { + origin: 'remark-lint:checkbox-content-indent', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-checkbox-content-indent#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + const value = String(file); + const loc = location(file); - function opener(create, and) { - return open - /** - * @this {CompileContext} - * @param {Token} token - * @returns {void} - */ + visit$1(tree, 'listItem', (node) => { + const head = node.children[0]; + const point = pointStart(head); - function open(token) { - enter.call(this, create(token), token); - if (and) and.call(this, token); - } - } - /** @type {CompileContext['buffer']} */ + // Exit early for items without checkbox. + // A list item cannot be checked and empty, according to GFM. + if ( + typeof node.checked !== 'boolean' || + !head || + typeof point.offset !== 'number' + ) { + return + } - function buffer() { - this.stack.push({ - type: 'fragment', - children: [] - }); - } - /** - * @type {CompileContext['enter']} - * @template {Node} N - * @this {CompileContext} - * @param {N} node - * @param {Token} token - * @returns {N} - */ + // Assume we start with a checkbox, because well, `checked` is set. + const match = /\[([\t xX])]/.exec( + value.slice(point.offset - 4, point.offset + 1) + ); - function enter(node, token) { - const parent = this.stack[this.stack.length - 1]; - // @ts-expect-error: Assume `Node` can exist as a child of `parent`. - parent.children.push(node); - this.stack.push(node); - this.tokenStack.push(token); // @ts-expect-error: `end` will be patched later. + // Failsafe to make sure we don‘t crash if there actually isn’t a checkbox. + /* c8 ignore next */ + if (!match) return - node.position = { - start: point(token.start) - }; - return node - } - /** - * @param {Handle} [and] - * @returns {Handle} - */ + // Move past checkbox. + const initial = point.offset; + let final = initial; - function closer(and) { - return close - /** - * @this {CompileContext} - * @param {Token} token - * @returns {void} - */ + while (/[\t ]/.test(value.charAt(final))) final++; - function close(token) { - if (and) and.call(this, token); - exit.call(this, token); - } + if (final - initial > 0) { + file.message('Checkboxes should be followed by a single character', { + start: loc.toPoint(initial), + end: loc.toPoint(final) + }); + } + }); } - /** @type {CompileContext['exit']} */ +); - function exit(token) { - const node = this.stack.pop(); - const open = this.tokenStack.pop(); +var remarkLintCheckboxContentIndent$1 = remarkLintCheckboxContentIndent; - if (!open) { - throw new Error( - 'Cannot close `' + - token.type + - '` (' + - stringifyPosition$1({ - start: token.start, - end: token.end - }) + - '): it’s not open' - ) - } else if (open.type !== token.type) { - throw new Error( - 'Cannot close `' + - token.type + - '` (' + - stringifyPosition$1({ - start: token.start, - end: token.end - }) + - '): a different token (`' + - open.type + - '`, ' + - stringifyPosition$1({ - start: open.start, - end: open.end - }) + - ') is open' - ) +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module code-block-style + * @fileoverview + * Warn when code blocks do not adhere to a given style. + * + * Options: `'consistent'`, `'fenced'`, or `'indented'`, default: `'consistent'`. + * + * `'consistent'` detects the first used code block style and warns when + * subsequent code blocks uses different styles. + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) + * formats code blocks using a fence if they have a language flag and + * indentation if not. + * Pass + * [`fences: true`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify#optionsfences) + * to always use fences for code blocks. + * + * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) + * on how to automatically fix warnings for this rule. + * + * @example + * {"setting": "indented", "name": "ok.md"} + * + * alpha() + * + * Paragraph. + * + * bravo() + * + * @example + * {"setting": "indented", "name": "not-ok.md", "label": "input"} + * + * ``` + * alpha() + * ``` + * + * Paragraph. + * + * ``` + * bravo() + * ``` + * + * @example + * {"setting": "indented", "name": "not-ok.md", "label": "output"} + * + * 1:1-3:4: Code blocks should be indented + * 7:1-9:4: Code blocks should be indented + * + * @example + * {"setting": "fenced", "name": "ok.md"} + * + * ``` + * alpha() + * ``` + * + * Paragraph. + * + * ``` + * bravo() + * ``` + * + * @example + * {"setting": "fenced", "name": "not-ok-fenced.md", "label": "input"} + * + * alpha() + * + * Paragraph. + * + * bravo() + * + * @example + * {"setting": "fenced", "name": "not-ok-fenced.md", "label": "output"} + * + * 1:1-1:12: Code blocks should be fenced + * 5:1-5:12: Code blocks should be fenced + * + * @example + * {"name": "not-ok-consistent.md", "label": "input"} + * + * alpha() + * + * Paragraph. + * + * ``` + * bravo() + * ``` + * + * @example + * {"name": "not-ok-consistent.md", "label": "output"} + * + * 5:1-7:4: Code blocks should be indented + * + * @example + * {"setting": "💩", "name": "not-ok-incorrect.md", "label": "output", "positionless": true} + * + * 1:1: Incorrect code block style `💩`: use either `'consistent'`, `'fenced'`, or `'indented'` + */ + +const remarkLintCodeBlockStyle = lintRule( + { + origin: 'remark-lint:code-block-style', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-code-block-style#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file, option = 'consistent') => { + const value = String(file); + + if ( + option !== 'consistent' && + option !== 'fenced' && + option !== 'indented' + ) { + file.fail( + 'Incorrect code block style `' + + option + + "`: use either `'consistent'`, `'fenced'`, or `'indented'`" + ); } - node.position.end = point(token.end); - return node - } - /** - * @this {CompileContext} - * @returns {string} - */ + visit$1(tree, 'code', (node) => { + if (generated(node)) { + return + } - function resume() { - return toString(this.stack.pop()) - } // - // Handlers. - // + const initial = pointStart(node).offset; + const final = pointEnd(node).offset; - /** @type {Handle} */ + const current = + node.lang || /^\s*([~`])\1{2,}/.test(value.slice(initial, final)) + ? 'fenced' + : 'indented'; - function onenterlistordered() { - setData('expectingFirstListItemValue', true); + if (option === 'consistent') { + option = current; + } else if (option !== current) { + file.message('Code blocks should be ' + option, node); + } + }); } - /** @type {Handle} */ +); - function onenterlistitemvalue(token) { - if (getData('expectingFirstListItemValue')) { - const ancestor = this.stack[this.stack.length - 2]; - ancestor.start = Number.parseInt(this.sliceSerialize(token), 10); - setData('expectingFirstListItemValue'); - } - } - /** @type {Handle} */ +var remarkLintCodeBlockStyle$1 = remarkLintCodeBlockStyle; - function onexitcodefencedfenceinfo() { - const data = this.resume(); - const node = this.stack[this.stack.length - 1]; - node.lang = data; - } - /** @type {Handle} */ +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module definition-spacing + * @fileoverview + * Warn when consecutive whitespace is used in a definition. + * + * @example + * {"name": "ok.md"} + * + * [example domain]: http://example.com "Example Domain" + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * [example····domain]: http://example.com "Example Domain" + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 1:1-1:57: Do not use consecutive whitespace in definition labels + */ - function onexitcodefencedfencemeta() { - const data = this.resume(); - const node = this.stack[this.stack.length - 1]; - node.meta = data; - } - /** @type {Handle} */ +const label = /^\s*\[((?:\\[\s\S]|[^[\]])+)]/; - function onexitcodefencedfence() { - // Exit if this is the closing fence. - if (getData('flowCodeInside')) return - this.buffer(); - setData('flowCodeInside', true); - } - /** @type {Handle} */ +const remarkLintDefinitionSpacing = lintRule( + { + origin: 'remark-lint:definition-spacing', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-definition-spacing#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + const value = String(file); - function onexitcodefenced() { - const data = this.resume(); - const node = this.stack[this.stack.length - 1]; - node.value = data.replace(/^(\r?\n|\r)|(\r?\n|\r)$/g, ''); - setData('flowCodeInside'); - } - /** @type {Handle} */ + visit$1(tree, (node) => { + if (node.type === 'definition' || node.type === 'footnoteDefinition') { + const start = pointStart(node).offset; + const end = pointEnd(node).offset; - function onexitcodeindented() { - const data = this.resume(); - const node = this.stack[this.stack.length - 1]; - node.value = data.replace(/(\r?\n|\r)$/g, ''); - } - /** @type {Handle} */ + if (typeof start === 'number' && typeof end === 'number') { + const match = value.slice(start, end).match(label); - function onexitdefinitionlabelstring(token) { - // Discard label, use the source content instead. - const label = this.resume(); - const node = this.stack[this.stack.length - 1]; - node.label = label; - node.identifier = normalizeIdentifier( - this.sliceSerialize(token) - ).toLowerCase(); + if (match && /[ \t\n]{2,}/.test(match[1])) { + file.message( + 'Do not use consecutive whitespace in definition labels', + node + ); + } + } + } + }); } - /** @type {Handle} */ +); - function onexitdefinitiontitlestring() { - const data = this.resume(); - const node = this.stack[this.stack.length - 1]; - node.title = data; - } - /** @type {Handle} */ +var remarkLintDefinitionSpacing$1 = remarkLintDefinitionSpacing; - function onexitdefinitiondestinationstring() { - const data = this.resume(); - const node = this.stack[this.stack.length - 1]; - node.url = data; - } - /** @type {Handle} */ +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module fenced-code-flag + * @fileoverview + * Check fenced code block flags. + * + * Options: `Array.` or `Object`, optional. + * + * Providing an array is as passing `{flags: Array}`. + * + * The object can have an array of `'flags'` which are allowed: other flags + * will not be allowed. + * An `allowEmpty` field (`boolean`, default: `false`) can be set to allow + * code blocks without language flags. + * + * @example + * {"name": "ok.md"} + * + * ```alpha + * bravo() + * ``` + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * ``` + * alpha() + * ``` + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 1:1-3:4: Missing code language flag + * + * @example + * {"name": "ok.md", "setting": {"allowEmpty": true}} + * + * ``` + * alpha() + * ``` + * + * @example + * {"name": "not-ok.md", "setting": {"allowEmpty": false}, "label": "input"} + * + * ``` + * alpha() + * ``` + * + * @example + * {"name": "not-ok.md", "setting": {"allowEmpty": false}, "label": "output"} + * + * 1:1-3:4: Missing code language flag + * + * @example + * {"name": "ok.md", "setting": ["alpha"]} + * + * ```alpha + * bravo() + * ``` + * + * @example + * {"name": "ok.md", "setting": {"flags":["alpha"]}} + * + * ```alpha + * bravo() + * ``` + * + * @example + * {"name": "not-ok.md", "setting": ["charlie"], "label": "input"} + * + * ```alpha + * bravo() + * ``` + * + * @example + * {"name": "not-ok.md", "setting": ["charlie"], "label": "output"} + * + * 1:1-3:4: Incorrect code language flag + */ - function onexitatxheadingsequence(token) { - const node = this.stack[this.stack.length - 1]; +const fence = /^ {0,3}([~`])\1{2,}/; - if (!node.depth) { - const depth = this.sliceSerialize(token).length; - node.depth = depth; +const remarkLintFencedCodeFlag = lintRule( + { + origin: 'remark-lint:fenced-code-flag', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-fenced-code-flag#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file, option) => { + const value = String(file); + let allowEmpty = false; + /** @type {string[]} */ + let allowed = []; + + if (typeof option === 'object') { + if (Array.isArray(option)) { + allowed = option; + } else { + allowEmpty = Boolean(option.allowEmpty); + + if (option.flags) { + allowed = option.flags; + } + } } - } - /** @type {Handle} */ - function onexitsetextheadingtext() { - setData('setextHeadingSlurpLineEnding', true); - } - /** @type {Handle} */ + visit$1(tree, 'code', (node) => { + if (!generated(node)) { + if (node.lang) { + if (allowed.length > 0 && !allowed.includes(node.lang)) { + file.message('Incorrect code language flag', node); + } + } else { + const slice = value.slice( + pointStart(node).offset, + pointEnd(node).offset + ); - function onexitsetextheadinglinesequence(token) { - const node = this.stack[this.stack.length - 1]; - node.depth = this.sliceSerialize(token).charCodeAt(0) === 61 ? 1 : 2; + if (!allowEmpty && fence.test(slice)) { + file.message('Missing code language flag', node); + } + } + } + }); } - /** @type {Handle} */ +); - function onexitsetextheading() { - setData('setextHeadingSlurpLineEnding'); - } - /** @type {Handle} */ +var remarkLintFencedCodeFlag$1 = remarkLintFencedCodeFlag; - function onenterdata(token) { - const parent = this.stack[this.stack.length - 1]; - /** @type {Node} */ +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module fenced-code-marker + * @fileoverview + * Warn for violating fenced code markers. + * + * Options: `` '`' ``, `'~'`, or `'consistent'`, default: `'consistent'`. + * + * `'consistent'` detects the first used fenced code marker style and warns + * when subsequent fenced code blocks use different styles. + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) + * formats fences using ``'`'`` (grave accent) by default. + * Pass + * [`fence: '~'`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify#optionsfence) + * to use `~` (tilde) instead. + * + * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) + * on how to automatically fix warnings for this rule. + * + * @example + * {"name": "ok.md"} + * + * Indented code blocks are not affected by this rule: + * + * bravo() + * + * @example + * {"name": "ok.md", "setting": "`"} + * + * ```alpha + * bravo() + * ``` + * + * ``` + * charlie() + * ``` + * + * @example + * {"name": "ok.md", "setting": "~"} + * + * ~~~alpha + * bravo() + * ~~~ + * + * ~~~ + * charlie() + * ~~~ + * + * @example + * {"name": "not-ok-consistent-tick.md", "label": "input"} + * + * ```alpha + * bravo() + * ``` + * + * ~~~ + * charlie() + * ~~~ + * + * @example + * {"name": "not-ok-consistent-tick.md", "label": "output"} + * + * 5:1-7:4: Fenced code should use `` ` `` as a marker + * + * @example + * {"name": "not-ok-consistent-tilde.md", "label": "input"} + * + * ~~~alpha + * bravo() + * ~~~ + * + * ``` + * charlie() + * ``` + * + * @example + * {"name": "not-ok-consistent-tilde.md", "label": "output"} + * + * 5:1-7:4: Fenced code should use `~` as a marker + * + * @example + * {"name": "not-ok-incorrect.md", "setting": "💩", "label": "output", "positionless": true} + * + * 1:1: Incorrect fenced code marker `💩`: use either `'consistent'`, `` '`' ``, or `'~'` + */ - let tail = parent.children[parent.children.length - 1]; +const remarkLintFencedCodeMarker = lintRule( + { + origin: 'remark-lint:fenced-code-marker', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-fenced-code-marker#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file, option = 'consistent') => { + const contents = String(file); - if (!tail || tail.type !== 'text') { - // Add a new text node. - tail = text(); // @ts-expect-error: we’ll add `end` later. + if (option !== 'consistent' && option !== '~' && option !== '`') { + file.fail( + 'Incorrect fenced code marker `' + + option + + "`: use either `'consistent'`, `` '`' ``, or `'~'`" + ); + } - tail.position = { - start: point(token.start) - }; // @ts-expect-error: Assume `parent` accepts `text`. + visit$1(tree, 'code', (node) => { + const start = pointStart(node).offset; - parent.children.push(tail); - } + if (typeof start === 'number') { + const marker = contents + .slice(start, start + 4) + .replace(/^\s+/, '') + .charAt(0); - this.stack.push(tail); + // Ignore unfenced code blocks. + if (marker === '~' || marker === '`') { + if (option === 'consistent') { + option = marker; + } else if (marker !== option) { + file.message( + 'Fenced code should use `' + + (option === '~' ? option : '` ` `') + + '` as a marker', + node + ); + } + } + } + }); } - /** @type {Handle} */ +); - function onexitdata(token) { - const tail = this.stack.pop(); - tail.value += this.sliceSerialize(token); - tail.position.end = point(token.end); - } - /** @type {Handle} */ +var remarkLintFencedCodeMarker$1 = remarkLintFencedCodeMarker; - function onexitlineending(token) { - const context = this.stack[this.stack.length - 1]; +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module file-extension + * @fileoverview + * Warn when the file extension differ from the preferred extension. + * + * Does not warn when given documents have no file extensions (such as + * `AUTHORS` or `LICENSE`). + * + * Options: `string`, default: `'md'` — Expected file extension. + * + * @example + * {"name": "readme.md"} + * + * @example + * {"name": "readme"} + * + * @example + * {"name": "readme.mkd", "label": "output", "positionless": true} + * + * 1:1: Incorrect extension: use `md` + * + * @example + * {"name": "readme.mkd", "setting": "mkd"} + */ - // If we’re at a hard break, include the line ending in there. - if (getData('atHardBreak')) { - const tail = context.children[context.children.length - 1]; - tail.position.end = point(token.end); - setData('atHardBreak'); - return - } +const remarkLintFileExtension = lintRule( + { + origin: 'remark-lint:file-extension', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-file-extension#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (_, file, option = 'md') => { + const ext = file.extname; - if ( - !getData('setextHeadingSlurpLineEnding') && - config.canContainEols.includes(context.type) - ) { - onenterdata.call(this, token); - onexitdata.call(this, token); + if (ext && ext.slice(1) !== option) { + file.message('Incorrect extension: use `' + option + '`'); } } - /** @type {Handle} */ +); + +var remarkLintFileExtension$1 = remarkLintFileExtension; + +/** + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module final-definition + * @fileoverview + * Warn when definitions are placed somewhere other than at the end of + * the file. + * + * @example + * {"name": "ok.md"} + * + * Paragraph. + * + * [example]: http://example.com "Example Domain" + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * Paragraph. + * + * [example]: http://example.com "Example Domain" + * + * Another paragraph. + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 3:1-3:47: Move definitions to the end of the file (after the node at line `5`) + * + * @example + * {"name": "ok-comments.md"} + * + * Paragraph. + * + * [example-1]: http://example.com/one/ + * + * + * + * [example-2]: http://example.com/two/ + */ + +const remarkLintFinalDefinition = lintRule( + { + origin: 'remark-lint:final-definition', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-definition#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (tree, file) => { + let last = 0; - function onexithardbreak() { - setData('atHardBreak', true); - } - /** @type {Handle} */ + visit$1( + tree, + (node) => { + // Ignore generated and HTML comment nodes. + if ( + node.type === 'root' || + generated(node) || + (node.type === 'html' && /^\s*\n\n' + line++; } - } - return '\n\n' + return SKIP$1 + }); } -} +); + +var remarkLintNoTableIndentation$1 = remarkLintNoTableIndentation; /** - * @callback Map - * @param {string} value - * @param {number} line - * @param {boolean} blank - * @returns {string} + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @module no-tabs + * @fileoverview + * Warn when hard tabs (`\t`) are used instead of spaces. + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) + * uses spaces where tabs are used for indentation, but retains tabs used in + * content. + * + * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) + * on how to automatically fix warnings for this rule. + * + * @example + * {"name": "ok.md"} + * + * Foo Bar + * + * ····Foo + * + * @example + * {"name": "not-ok.md", "label": "input", "positionless": true} + * + * »Here's one before a code block. + * + * Here's a tab:», and here is another:». + * + * And this is in `inline»code`. + * + * >»This is in a block quote. + * + * *»And… + * + * »1.»in a list. + * + * And this is a tab as the last character.» + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 1:1: Use spaces instead of tabs + * 3:14: Use spaces instead of tabs + * 3:37: Use spaces instead of tabs + * 5:23: Use spaces instead of tabs + * 7:2: Use spaces instead of tabs + * 9:2: Use spaces instead of tabs + * 11:1: Use spaces instead of tabs + * 11:4: Use spaces instead of tabs + * 13:41: Use spaces instead of tabs */ -const eol = /\r?\n|\r/g; +const remarkLintNoTabs = lintRule( + { + origin: 'remark-lint:no-tabs', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-tabs#readme' + }, + /** @type {import('unified-lint-rule').Rule} */ + (_, file) => { + const value = String(file); + const toPoint = location(file).toPoint; + let index = value.indexOf('\t'); + + while (index !== -1) { + file.message('Use spaces instead of tabs', toPoint(index)); + index = value.indexOf('\t', index + 1); + } + } +); + +var remarkLintNoTabs$1 = remarkLintNoTabs; /** - * @param {string} value - * @param {Map} map - * @returns {string} - */ -function indentLines(value, map) { - /** @type {Array.} */ - const result = []; - let start = 0; - let line = 0; - /** @type {RegExpExecArray|null} */ - let match; + * An Array.prototype.slice.call(arguments) alternative + * + * @param {Object} args something with a length + * @param {Number} slice + * @param {Number} sliceEnd + * @api public + */ - while ((match = eol.exec(value))) { - one(value.slice(start, match.index)); - result.push(match[0]); - start = match.index + match[0].length; - line++; - } +var sliced$1 = function (args, slice, sliceEnd) { + var ret = []; + var len = args.length; - one(value.slice(start)); + if (0 === len) return ret; - return result.join('') + var start = slice < 0 + ? Math.max(0, slice + len) + : slice || 0; - /** - * @param {string} value - */ - function one(value) { - result.push(map(value, line, !value)); + if (sliceEnd !== undefined) { + len = sliceEnd < 0 + ? sliceEnd + len + : sliceEnd; } -} -/** - * @typedef {import('mdast').Blockquote} Blockquote - * @typedef {import('../types.js').Handle} Handle - * @typedef {import('../util/indent-lines.js').Map} Map - */ + while (len-- > start) { + ret[len - start] = args[len]; + } + + return ret; +}; /** - * @type {Handle} - * @param {Blockquote} node + * slice() reference. */ -function blockquote(node, _, context) { - const exit = context.enter('blockquote'); - const value = indentLines(containerFlow(node, context), map$1); - exit(); - return value -} -/** @type {Map} */ -function map$1(line, _, blank) { - return '>' + (blank ? '' : ' ') + line -} +var slice = Array.prototype.slice; /** - * @typedef {import('../types.js').Unsafe} Unsafe + * Expose `co`. */ -/** - * @param {Array.} stack - * @param {Unsafe} pattern - * @returns {boolean} - */ -function patternInScope(stack, pattern) { - return ( - listInScope(stack, pattern.inConstruct, true) && - !listInScope(stack, pattern.notInConstruct, false) - ) -} +var co_1 = co$1; /** - * @param {Array.} stack - * @param {Unsafe['inConstruct']} list - * @param {boolean} none - * @returns {boolean} + * Wrap the given generator `fn` and + * return a thunk. + * + * @param {Function} fn + * @return {Function} + * @api public */ -function listInScope(stack, list, none) { - if (!list) { - return none - } - if (typeof list === 'string') { - list = [list]; - } - - let index = -1; +function co$1(fn) { + var isGenFun = isGeneratorFunction(fn); - while (++index < list.length) { - if (stack.includes(list[index])) { - return true - } - } + return function (done) { + var ctx = this; - return false -} + // in toThunk() below we invoke co() + // with a generator, so optimize for + // this case + var gen = fn; -/** - * @typedef {import('../types.js').Handle} Handle - * @typedef {import('mdast').Break} Break - */ + // we only need to parse the arguments + // if gen is a generator function. + if (isGenFun) { + var args = slice.call(arguments), len = args.length; + var hasCallback = len && 'function' == typeof args[len - 1]; + done = hasCallback ? args.pop() : error; + gen = fn.apply(this, args); + } else { + done = done || error; + } -/** - * @type {Handle} - * @param {Break} _ - */ -function hardBreak(_, _1, context, safe) { - let index = -1; + next(); - while (++index < context.unsafe.length) { - // If we can’t put eols in this construct (setext headings, tables), use a - // space instead. - if ( - context.unsafe[index].character === '\n' && - patternInScope(context.stack, context.unsafe[index]) - ) { - return /[ \t]/.test(safe.before) ? '' : ' ' + // #92 + // wrap the callback in a setImmediate + // so that any of its errors aren't caught by `co` + function exit(err, res) { + setImmediate(function(){ + done.call(ctx, err, res); + }); } - } - return '\\\n' -} + function next(err, res) { + var ret; -/** - * Get the count of the longest repeating streak of `character` in `value`. - * - * @param {string} value Content. - * @param {string} character Single character to look for - * @returns {number} Count of most frequent adjacent `character`s in `value` - */ -function longestStreak(value, character) { - var source = String(value); - var index = source.indexOf(character); - var expected = index; - var count = 0; - var max = 0; + // multiple args + if (arguments.length > 2) res = slice.call(arguments, 1); - if (typeof character !== 'string' || character.length !== 1) { - throw new Error('Expected character') - } + // error + if (err) { + try { + ret = gen.throw(err); + } catch (e) { + return exit(e); + } + } - while (index !== -1) { - if (index === expected) { - if (++count > max) { - max = count; + // ok + if (!err) { + try { + ret = gen.next(res); + } catch (e) { + return exit(e); + } } - } else { - count = 1; - } - expected = index + 1; - index = source.indexOf(character, expected); - } + // done + if (ret.done) return exit(null, ret.value); - return max -} + // normalize + ret.value = toThunk(ret.value, ctx); -/** - * @typedef {import('mdast').Code} Code - * @typedef {import('../types.js').Context} Context - */ + // run + if ('function' == typeof ret.value) { + var called = false; + try { + ret.value.call(ctx, function(){ + if (called) return; + called = true; + next.apply(ctx, arguments); + }); + } catch (e) { + setImmediate(function(){ + if (called) return; + called = true; + next(e); + }); + } + return; + } -/** - * @param {Code} node - * @param {Context} context - * @returns {boolean} - */ -function formatCodeAsIndented(node, context) { - return Boolean( - !context.options.fences && - node.value && - // If there’s no info… - !node.lang && - // And there’s a non-whitespace character… - /[^ \r\n]/.test(node.value) && - // And the value doesn’t start or end in a blank… - !/^[\t ]*(?:[\r\n]|$)|(?:^|[\r\n])[\t ]*$/.test(node.value) - ) + // invalid + next(new TypeError('You may only yield a function, promise, generator, array, or object, ' + + 'but the following was passed: "' + String(ret.value) + '"')); + } + } } /** - * @typedef {import('../types.js').Context} Context - * @typedef {import('../types.js').Options} Options + * Convert `obj` into a normalized thunk. + * + * @param {Mixed} obj + * @param {Mixed} ctx + * @return {Function} + * @api private */ -/** - * @param {Context} context - * @returns {Exclude} - */ -function checkFence(context) { - const marker = context.options.fence || '`'; +function toThunk(obj, ctx) { - if (marker !== '`' && marker !== '~') { - throw new Error( - 'Cannot serialize code with `' + - marker + - '` for `options.fence`, expected `` ` `` or `~`' - ) + if (isGeneratorFunction(obj)) { + return co$1(obj.call(ctx)); } - return marker -} + if (isGenerator(obj)) { + return co$1(obj); + } -/** - * @typedef {import('../types.js').Unsafe} Unsafe - */ + if (isPromise(obj)) { + return promiseToThunk(obj); + } -/** - * @param {Unsafe} pattern - * @returns {RegExp} - */ -function patternCompile(pattern) { - if (!pattern._compiled) { - const before = - (pattern.atBreak ? '[\\r\\n][\\t ]*' : '') + - (pattern.before ? '(?:' + pattern.before + ')' : ''); + if ('function' == typeof obj) { + return obj; + } - pattern._compiled = new RegExp( - (before ? '(' + before + ')' : '') + - (/[|\\{}()[\]^$+*?.-]/.test(pattern.character) ? '\\' : '') + - pattern.character + - (pattern.after ? '(?:' + pattern.after + ')' : ''), - 'g' - ); + if (isObject$1(obj) || Array.isArray(obj)) { + return objectToThunk.call(ctx, obj); } - return pattern._compiled + return obj; } /** - * @typedef {import('../types.js').Context} Context - * @typedef {import('../types.js').SafeOptions} SafeOptions + * Convert an object of yieldables to a thunk. + * + * @param {Object} obj + * @return {Function} + * @api private */ -/** - * @param {Context} context - * @param {string|null|undefined} input - * @param {SafeOptions & {encode?: Array.}} config - * @returns {string} - */ -function safe(context, input, config) { - const value = (config.before || '') + (input || '') + (config.after || ''); - /** @type {Array.} */ - const positions = []; - /** @type {Array.} */ - const result = []; - /** @type {Record} */ - const infos = {}; - let index = -1; +function objectToThunk(obj){ + var ctx = this; + var isArray = Array.isArray(obj); - while (++index < context.unsafe.length) { - const pattern = context.unsafe[index]; + return function(done){ + var keys = Object.keys(obj); + var pending = keys.length; + var results = isArray + ? new Array(pending) // predefine the array length + : new obj.constructor(); + var finished; - if (!patternInScope(context.stack, pattern)) { - continue + if (!pending) { + setImmediate(function(){ + done(null, results); + }); + return; } - const expression = patternCompile(pattern); - /** @type {RegExpExecArray|null} */ - let match; - - while ((match = expression.exec(value))) { - const before = 'before' in pattern || Boolean(pattern.atBreak); - const after = 'after' in pattern; - const position = match.index + (before ? match[1].length : 0); - - if (positions.includes(position)) { - if (infos[position].before && !before) { - infos[position].before = false; - } - - if (infos[position].after && !after) { - infos[position].after = false; - } - } else { - positions.push(position); - infos[position] = {before, after}; + // prepopulate object keys to preserve key ordering + if (!isArray) { + for (var i = 0; i < pending; i++) { + results[keys[i]] = undefined; } } - } - positions.sort(numerical); + for (var i = 0; i < keys.length; i++) { + run(obj[keys[i]], keys[i]); + } - let start = config.before ? config.before.length : 0; - const end = value.length - (config.after ? config.after.length : 0); - index = -1; + function run(fn, key) { + if (finished) return; + try { + fn = toThunk(fn, ctx); - while (++index < positions.length) { - const position = positions[index]; + if ('function' != typeof fn) { + results[key] = fn; + return --pending || done(null, results); + } - // Character before or after matched: - if (position < start || position >= end) { - continue - } + fn.call(ctx, function(err, res){ + if (finished) return; - // If this character is supposed to be escaped because it has a condition on - // the next character, and the next character is definitly being escaped, - // then skip this escape. - if ( - (position + 1 < end && - positions[index + 1] === position + 1 && - infos[position].after && - !infos[position + 1].before && - !infos[position + 1].after) || - (positions[index - 1] === position - 1 && - infos[position].before && - !infos[position - 1].before && - !infos[position - 1].after) - ) { - continue - } + if (err) { + finished = true; + return done(err); + } - if (start !== position) { - // If we have to use a character reference, an ampersand would be more - // correct, but as backslashes only care about punctuation, either will - // do the trick - result.push(escapeBackslashes(value.slice(start, position), '\\')); + results[key] = res; + --pending || done(null, results); + }); + } catch (err) { + finished = true; + done(err); + } } + } +} - start = position; +/** + * Convert `promise` to a thunk. + * + * @param {Object} promise + * @return {Function} + * @api private + */ - if ( - /[!-/:-@[-`{-~]/.test(value.charAt(position)) && - (!config.encode || !config.encode.includes(value.charAt(position))) - ) { - // Character escape. - result.push('\\'); - } else { - // Character reference. - result.push( - '&#x' + value.charCodeAt(position).toString(16).toUpperCase() + ';' - ); - start++; - } +function promiseToThunk(promise) { + return function(fn){ + promise.then(function(res) { + fn(null, res); + }, fn); } +} - result.push(escapeBackslashes(value.slice(start, end), config.after)); +/** + * Check if `obj` is a promise. + * + * @param {Object} obj + * @return {Boolean} + * @api private + */ - return result.join('') +function isPromise(obj) { + return obj && 'function' == typeof obj.then; } /** - * @param {number} a - * @param {number} b - * @returns {number} + * Check if `obj` is a generator. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private */ -function numerical(a, b) { - return a - b + +function isGenerator(obj) { + return obj && 'function' == typeof obj.next && 'function' == typeof obj.throw; } /** - * @param {string} value - * @param {string} after - * @returns {string} + * Check if `obj` is a generator function. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private */ -function escapeBackslashes(value, after) { - const expression = /\\(?=[!-/:-@[-`{-~])/g; - /** @type {Array.} */ - const positions = []; - /** @type {Array.} */ - const results = []; - const whole = value + after; - let index = -1; - let start = 0; - /** @type {RegExpExecArray|null} */ - let match; - while ((match = expression.exec(whole))) { - positions.push(match.index); - } +function isGeneratorFunction(obj) { + return obj && obj.constructor && 'GeneratorFunction' == obj.constructor.name; +} - while (++index < positions.length) { - if (start !== positions[index]) { - results.push(value.slice(start, positions[index])); - } +/** + * Check for plain object. + * + * @param {Mixed} val + * @return {Boolean} + * @api private + */ + +function isObject$1(val) { + return val && Object == val.constructor; +} + +/** + * Throw `err` in a new stack. + * + * This is used when co() is invoked + * without supplying a callback, which + * should only be for demonstrational + * purposes. + * + * @param {Error} err + * @api private + */ - results.push('\\'); - start = positions[index]; - } +function error(err) { + if (!err) return; + setImmediate(function(){ + throw err; + }); +} - results.push(value.slice(start)); +/** + * Module Dependencies + */ - return results.join('') -} +var sliced = sliced$1; +var noop = function(){}; +var co = co_1; /** - * @typedef {import('mdast').Code} Code - * @typedef {import('../types.js').Handle} Handle - * @typedef {import('../types.js').Exit} Exit - * @typedef {import('../util/indent-lines.js').Map} Map + * Export `wrapped` */ +var wrapped_1 = wrapped$1; + /** - * @type {Handle} - * @param {Code} node + * Wrap a function to support + * sync, async, and gen functions. + * + * @param {Function} fn + * @return {Function} + * @api public */ -function code$1(node, _, context) { - const marker = checkFence(context); - const raw = node.value || ''; - const suffix = marker === '`' ? 'GraveAccent' : 'Tilde'; - /** @type {string} */ - let value; - /** @type {Exit} */ - let exit; - if (formatCodeAsIndented(node, context)) { - exit = context.enter('codeIndented'); - value = indentLines(raw, map); - } else { - const sequence = marker.repeat(Math.max(longestStreak(raw, marker) + 1, 3)); - /** @type {Exit} */ - let subexit; - exit = context.enter('codeFenced'); - value = sequence; +function wrapped$1(fn) { + function wrap() { + var args = sliced(arguments); + var last = args[args.length - 1]; + var ctx = this; - if (node.lang) { - subexit = context.enter('codeFencedLang' + suffix); - value += safe(context, node.lang, { - before: '`', - after: ' ', - encode: ['`'] - }); - subexit(); - } + // done + var done = typeof last == 'function' ? args.pop() : noop; - if (node.lang && node.meta) { - subexit = context.enter('codeFencedMeta' + suffix); - value += - ' ' + - safe(context, node.meta, { - before: ' ', - after: '\n', - encode: ['`'] - }); - subexit(); + // nothing + if (!fn) { + return done.apply(ctx, [null].concat(args)); } - value += '\n'; + // generator + if (generator(fn)) { + return co(fn).apply(ctx, args.concat(done)); + } - if (raw) { - value += raw + '\n'; + // async + if (fn.length > args.length) { + // NOTE: this only handles uncaught synchronous errors + try { + return fn.apply(ctx, args.concat(done)); + } catch (e) { + return done(e); + } } - value += sequence; + // sync + return sync(fn, done).apply(ctx, args); } - exit(); - return value -} - -/** @type {Map} */ -function map(line, _, blank) { - return (blank ? '' : ' ') + line + return wrap; } /** - * @typedef {import('mdast').Association} Association + * Wrap a synchronous function execution. + * + * @param {Function} fn + * @param {Function} done + * @return {Function} + * @api private */ +function sync(fn, done) { + return function () { + var ret; + + try { + ret = fn.apply(this, arguments); + } catch (err) { + return done(err); + } + + if (promise(ret)) { + ret.then(function (value) { done(null, value); }, done); + } else { + ret instanceof Error ? done(ret) : done(null, ret); + } + } +} + /** - * The `label` of an association is the string value: character escapes and - * references work, and casing is intact. - * The `identifier` is used to match one association to another: controversially, - * character escapes and references don’t work in this matching: `©` does - * not match `©`, and `\+` does not match `+`. - * But casing is ignored (and whitespace) is trimmed and collapsed: ` A\nb` - * matches `a b`. - * So, we do prefer the label when figuring out how we’re going to serialize: - * it has whitespace, casing, and we can ignore most useless character escapes - * and all character references. + * Is `value` a generator? * - * @param {Association} node - * @returns {string} + * @param {Mixed} value + * @return {Boolean} + * @api private */ -function association(node) { - if (node.label || !node.identifier) { - return node.label || '' - } - return decodeString(node.identifier) +function generator(value) { + return value + && value.constructor + && 'GeneratorFunction' == value.constructor.name; } -/** - * @typedef {import('../types.js').Context} Context - * @typedef {import('../types.js').Options} Options - */ /** - * @param {Context} context - * @returns {Exclude} + * Is `value` a promise? + * + * @param {Mixed} value + * @return {Boolean} + * @api private */ -function checkQuote(context) { - const marker = context.options.quote || '"'; - - if (marker !== '"' && marker !== "'") { - throw new Error( - 'Cannot serialize title with `' + - marker + - '` for `options.quote`, expected `"`, or `\'`' - ) - } - return marker +function promise(value) { + return value && 'function' == typeof value.then; } -/** - * @typedef {import('mdast').Definition} Definition - * @typedef {import('../types.js').Handle} Handle - */ +var wrapped = wrapped_1; -/** - * @type {Handle} - * @param {Definition} node - */ -function definition(node, _, context) { - const marker = checkQuote(context); - const suffix = marker === '"' ? 'Quote' : 'Apostrophe'; - const exit = context.enter('definition'); - let subexit = context.enter('label'); - let value = - '[' + safe(context, association(node), {before: '[', after: ']'}) + ']: '; +var unifiedLintRule = factory; - subexit(); +function factory(id, rule) { + var parts = id.split(':'); + var source = parts[0]; + var ruleId = parts[1]; + var fn = wrapped(rule); - if ( - // If there’s no url, or… - !node.url || - // If there’s whitespace, enclosed is prettier. - /[ \t\r\n]/.test(node.url) - ) { - subexit = context.enter('destinationLiteral'); - value += '<' + safe(context, node.url, {before: '<', after: '>'}) + '>'; - } else { - // No whitespace, raw is prettier. - subexit = context.enter('destinationRaw'); - value += safe(context, node.url, {before: ' ', after: ' '}); + /* istanbul ignore if - possibly useful if externalised later. */ + if (!ruleId) { + ruleId = source; + source = null; } - subexit(); + attacher.displayName = id; - if (node.title) { - subexit = context.enter('title' + suffix); - value += - ' ' + - marker + - safe(context, node.title, {before: marker, after: marker}) + - marker; - subexit(); - } + return attacher - exit(); + function attacher(raw) { + var config = coerce(ruleId, raw); + var severity = config[0]; + var options = config[1]; + var fatal = severity === 2; - return value -} + return severity ? transformer : undefined -/** - * @typedef {import('../types.js').Context} Context - * @typedef {import('../types.js').Options} Options - */ + function transformer(tree, file, next) { + var index = file.messages.length; -/** - * @param {Context} context - * @returns {Exclude} - */ -function checkEmphasis(context) { - const marker = context.options.emphasis || '*'; + fn(tree, file, options, done); - if (marker !== '*' && marker !== '_') { - throw new Error( - 'Cannot serialize emphasis with `' + - marker + - '` for `options.emphasis`, expected `*`, or `_`' - ) - } + function done(err) { + var messages = file.messages; + var message; - return marker -} + // Add the error, if not already properly added. + /* istanbul ignore if - only happens for incorrect plugins */ + if (err && messages.indexOf(err) === -1) { + try { + file.fail(err); + } catch (_) {} + } -/** - * @typedef {import('../types.js').Node} Node - * @typedef {import('../types.js').Parent} Parent - * @typedef {import('../types.js').SafeOptions} SafeOptions - * @typedef {import('../types.js').Context} Context - */ + while (index < messages.length) { + message = messages[index]; + message.ruleId = ruleId; + message.source = source; + message.fatal = fatal; -/** - * @param {Parent} parent - * @param {Context} context - * @param {SafeOptions} safeOptions - * @returns {string} - */ -function containerPhrasing(parent, context, safeOptions) { - const indexStack = context.indexStack; - const children = parent.children || []; - /** @type {Array.} */ - const results = []; - let index = -1; - let before = safeOptions.before; + index++; + } - indexStack.push(-1); + next(); + } + } + } +} - while (++index < children.length) { - const child = children[index]; - /** @type {string} */ - let after; +// Coerce a value to a severity--options tuple. +function coerce(name, value) { + var def = 1; + var result; + var level; - indexStack[indexStack.length - 1] = index; + /* istanbul ignore if - Handled by unified in v6.0.0 */ + if (typeof value === 'boolean') { + result = [value]; + } else if (value == null) { + result = [def]; + } else if ( + typeof value === 'object' && + (typeof value[0] === 'number' || + typeof value[0] === 'boolean' || + typeof value[0] === 'string') + ) { + result = value.concat(); + } else { + result = [1, value]; + } - if (index + 1 < children.length) { - // @ts-expect-error: hush, it’s actually a `zwitch`. - let handle = context.handle.handlers[children[index + 1].type]; - if (handle && handle.peek) handle = handle.peek; - after = handle - ? handle(children[index + 1], parent, context, { - before: '', - after: '' - }).charAt(0) - : ''; - } else { - after = safeOptions.after; - } + level = result[0]; - // In some cases, html (text) can be found in phrasing right after an eol. - // When we’d serialize that, in most cases that would be seen as html - // (flow). - // As we can’t escape or so to prevent it from happening, we take a somewhat - // reasonable approach: replace that eol with a space. - // See: - if ( - results.length > 0 && - (before === '\r' || before === '\n') && - child.type === 'html' - ) { - results[results.length - 1] = results[results.length - 1].replace( - /(\r?\n|\r)$/, - ' ' - ); - before = ' '; + if (typeof level === 'boolean') { + level = level ? 1 : 0; + } else if (typeof level === 'string') { + if (level === 'off') { + level = 0; + } else if (level === 'on' || level === 'warn') { + level = 1; + } else if (level === 'error') { + level = 2; + } else { + level = 1; + result = [level, result]; } + } - results.push(context.handle(child, parent, context, {before, after})); - - before = results[results.length - 1].slice(-1); + if (level < 0 || level > 2) { + throw new Error( + 'Incorrect severity `' + + level + + '` for `' + + name + + '`, ' + + 'expected 0, 1, or 2' + ) } - indexStack.pop(); + result[0] = level; - return results.join('') + return result } -/** - * @typedef {import('mdast').Emphasis} Emphasis - * @typedef {import('../types.js').Handle} Handle - */ +var rule = unifiedLintRule; -emphasis.peek = emphasisPeek; +var remarkLintNoTrailingSpaces = rule('remark-lint:no-trailing-spaces', noTrailingSpaces); -// To do: there are cases where emphasis cannot “form” depending on the -// previous or next character of sequences. -// There’s no way around that though, except for injecting zero-width stuff. -// Do we need to safeguard against that? /** - * @type {Handle} - * @param {Emphasis} node + * Lines that are just space characters are not present in + * the AST, which is why we loop through lines manually. */ -function emphasis(node, _, context) { - const marker = checkEmphasis(context); - const exit = context.enter('emphasis'); - const value = containerPhrasing(node, context, { - before: marker, - after: marker - }); - exit(); - return marker + value + marker -} -/** - * @type {Handle} - * @param {Emphasis} _ - */ -function emphasisPeek(_, _1, context) { - return context.options.emphasis || '*' +function noTrailingSpaces(ast, file) { + var lines = file.toString().split(/\r?\n/); + for (var i = 0; i < lines.length; i++) { + var currentLine = lines[i]; + var lineIndex = i + 1; + if (/\s$/.test(currentLine)) { + file.message('Remove trailing whitespace', { + position: { + start: { line: lineIndex, column: currentLine.length + 1 }, + end: { line: lineIndex } + } + }); + } + } } -/** - * @typedef {import('unist').Node} Node - * @typedef {import('unist').Parent} Parent - * - * @typedef {string} Type - * @typedef {Object} Props - * - * @typedef {null|undefined|Type|Props|TestFunctionAnything|Array.} Test - */ +function* getLinksRecursively(node) { + if (node.url) { + yield node; + } + for (const child of node.children || []) { + yield* getLinksRecursively(child); + } +} -const convert = - /** - * @type {( - * ((test: T['type']|Partial|TestFunctionPredicate) => AssertPredicate) & - * ((test?: Test) => AssertAnything) - * )} - */ - ( - /** - * Generate an assertion from a check. - * @param {Test} [test] - * When nullish, checks if `node` is a `Node`. - * When `string`, works like passing `function (node) {return node.type === test}`. - * When `function` checks if function passed the node is true. - * When `object`, checks that all keys in test are in node, and that they have (strictly) equal values. - * When `array`, checks any one of the subtests pass. - * @returns {AssertAnything} - */ - function (test) { - if (test === undefined || test === null) { - return ok +function validateLinks(tree, vfile) { + const currentFileURL = pathToFileURL(path$1.join(vfile.cwd, vfile.path)); + let previousDefinitionLabel; + for (const node of getLinksRecursively(tree)) { + if (node.url[0] !== "#") { + const targetURL = new URL(node.url, currentFileURL); + if (targetURL.protocol === "file:" && !fs.existsSync(targetURL)) { + vfile.message("Broken link", node); + } else if (targetURL.pathname === currentFileURL.pathname) { + const expected = node.url.includes("#") + ? node.url.slice(node.url.indexOf("#")) + : "#"; + vfile.message( + `Self-reference must start with hash (expected "${expected}", got "${node.url}")`, + node + ); + } + } + if (node.type === "definition") { + if (previousDefinitionLabel && previousDefinitionLabel > node.label) { + vfile.message( + `Unordered reference ("${node.label}" should be before "${previousDefinitionLabel}")`, + node + ); } + previousDefinitionLabel = node.label; + } + } +} + +const remarkLintNodejsLinks = lintRule( + "remark-lint:nodejs-links", + validateLinks +); + +/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */ +function isNothing(subject) { + return (typeof subject === 'undefined') || (subject === null); +} + + +function isObject(subject) { + return (typeof subject === 'object') && (subject !== null); +} + + +function toArray(sequence) { + if (Array.isArray(sequence)) return sequence; + else if (isNothing(sequence)) return []; - if (typeof test === 'string') { - return typeFactory(test) - } + return [ sequence ]; +} - if (typeof test === 'object') { - return Array.isArray(test) ? anyFactory(test) : propsFactory(test) - } - if (typeof test === 'function') { - return castFactory(test) - } +function extend(target, source) { + var index, length, key, sourceKeys; - throw new Error('Expected function, string, or object as test') - } - ); -/** - * @param {Array.} tests - * @returns {AssertAnything} - */ -function anyFactory(tests) { - /** @type {Array.} */ - const checks = []; - let index = -1; + if (source) { + sourceKeys = Object.keys(source); - while (++index < tests.length) { - checks[index] = convert(tests[index]); + for (index = 0, length = sourceKeys.length; index < length; index += 1) { + key = sourceKeys[index]; + target[key] = source[key]; + } } - return castFactory(any) + return target; +} - /** - * @this {unknown} - * @param {unknown[]} parameters - * @returns {boolean} - */ - function any(...parameters) { - let index = -1; - while (++index < checks.length) { - if (checks[index].call(this, ...parameters)) return true - } +function repeat(string, count) { + var result = '', cycle; - return false + for (cycle = 0; cycle < count; cycle += 1) { + result += string; } + + return result; } -/** - * Utility to assert each property in `test` is represented in `node`, and each - * values are strictly equal. - * - * @param {Props} check - * @returns {AssertAnything} - */ -function propsFactory(check) { - return castFactory(all) - /** - * @param {Node} node - * @returns {boolean} - */ - function all(node) { - /** @type {string} */ - let key; +function isNegativeZero(number) { + return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number); +} - for (key in check) { - // @ts-expect-error: hush, it sure works as an index. - if (node[key] !== check[key]) return false - } - return true +var isNothing_1 = isNothing; +var isObject_1 = isObject; +var toArray_1 = toArray; +var repeat_1 = repeat; +var isNegativeZero_1 = isNegativeZero; +var extend_1 = extend; + +var common = { + isNothing: isNothing_1, + isObject: isObject_1, + toArray: toArray_1, + repeat: repeat_1, + isNegativeZero: isNegativeZero_1, + extend: extend_1 +}; + +// YAML error class. http://stackoverflow.com/questions/8458984 + + +function formatError(exception, compact) { + var where = '', message = exception.reason || '(unknown reason)'; + + if (!exception.mark) return message; + + if (exception.mark.name) { + where += 'in "' + exception.mark.name + '" '; } -} -/** - * Utility to convert a string into a function which checks a given node’s type - * for said string. - * - * @param {Type} check - * @returns {AssertAnything} - */ -function typeFactory(check) { - return castFactory(type) + where += '(' + (exception.mark.line + 1) + ':' + (exception.mark.column + 1) + ')'; - /** - * @param {Node} node - */ - function type(node) { - return node && node.type === check + if (!compact && exception.mark.snippet) { + where += '\n\n' + exception.mark.snippet; } + + return message + ' ' + where; } -/** - * Utility to convert a string into a function which checks a given node’s type - * for said string. - * @param {TestFunctionAnything} check - * @returns {AssertAnything} - */ -function castFactory(check) { - return assertion - /** - * @this {unknown} - * @param {Array.} parameters - * @returns {boolean} - */ - function assertion(...parameters) { - // @ts-expect-error: spreading is fine. - return Boolean(check.call(this, ...parameters)) +function YAMLException$1(reason, mark) { + // Super constructor + Error.call(this); + + this.name = 'YAMLException'; + this.reason = reason; + this.mark = mark; + this.message = formatError(this, false); + + // 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 || ''; } } -// Utility to return true. -function ok() { - return true -} -/** - * @param {string} d - * @returns {string} - */ -function color$1(d) { - return '\u001B[33m' + d + '\u001B[39m' -} +// Inherit from Error +YAMLException$1.prototype = Object.create(Error.prototype); +YAMLException$1.prototype.constructor = YAMLException$1; -/** - * @typedef {import('unist').Node} Node - * @typedef {import('unist').Parent} Parent - * @typedef {import('unist-util-is').Test} Test - */ -/** - * Continue traversing as normal - */ -const CONTINUE$1 = true; -/** - * Do not traverse this node’s children - */ -const SKIP$1 = 'skip'; -/** - * Stop traversing immediately - */ -const EXIT$1 = false; +YAMLException$1.prototype.toString = function toString(compact) { + return this.name + ': ' + formatError(this, compact); +}; -/** - * Visit children of tree which pass a test - * - * @param tree Abstract syntax tree to walk - * @param test Test node, optional - * @param visitor Function to run for each node - * @param reverse Visit the tree in reverse order, defaults to false - */ -const visitParents$1 = - /** - * @type {( - * ((tree: Tree, test: Check, visitor: Visitor, Check>>, reverse?: boolean) => void) & - * ((tree: Tree, visitor: Visitor>, reverse?: boolean) => void) - * )} - */ - ( - /** - * @param {Node} tree - * @param {Test} test - * @param {Visitor} visitor - * @param {boolean} [reverse] - */ - function (tree, test, visitor, reverse) { - if (typeof test === 'function' && typeof visitor !== 'function') { - reverse = visitor; - // @ts-expect-error no visitor given, so `visitor` is test. - visitor = test; - test = null; - } - const is = convert(test); - const step = reverse ? -1 : 1; +var exception = YAMLException$1; - factory(tree, null, [])(); +// get snippet for a single line, respecting maxLength +function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { + var head = ''; + var tail = ''; + var maxHalfLength = Math.floor(maxLineLength / 2) - 1; - /** - * @param {Node} node - * @param {number?} index - * @param {Array.} parents - */ - function factory(node, index, parents) { - /** @type {Object.} */ - // @ts-expect-error: hush - const value = typeof node === 'object' && node !== null ? node : {}; - /** @type {string|undefined} */ - let name; + if (position - lineStart > maxHalfLength) { + head = ' ... '; + lineStart = position - maxHalfLength + head.length; + } - if (typeof value.type === 'string') { - name = - typeof value.tagName === 'string' - ? value.tagName - : typeof value.name === 'string' - ? value.name - : undefined; + if (lineEnd - position > maxHalfLength) { + tail = ' ...'; + lineEnd = position + maxHalfLength - tail.length; + } - Object.defineProperty(visit, 'name', { - value: - 'node (' + - color$1(value.type + (name ? '<' + name + '>' : '')) + - ')' - }); - } + return { + str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, '→') + tail, + pos: position - lineStart + head.length // relative position + }; +} - return visit - function visit() { - /** @type {ActionTuple} */ - let result = []; - /** @type {ActionTuple} */ - let subresult; - /** @type {number} */ - let offset; - /** @type {Array.} */ - let grandparents; +function padStart(string, max) { + return common.repeat(' ', max - string.length) + string; +} - if (!test || is(node, index, parents[parents.length - 1] || null)) { - result = toResult$1(visitor(node, parents)); - if (result[0] === EXIT$1) { - return result - } - } +function makeSnippet(mark, options) { + options = Object.create(options || null); - // @ts-expect-error looks like a parent. - if (node.children && result[0] !== SKIP$1) { - // @ts-expect-error looks like a parent. - offset = (reverse ? node.children.length : -1) + step; - // @ts-expect-error looks like a parent. - grandparents = parents.concat(node); + if (!mark.buffer) return null; - // @ts-expect-error looks like a parent. - while (offset > -1 && offset < node.children.length) { - // @ts-expect-error looks like a parent. - subresult = factory(node.children[offset], offset, grandparents)(); + if (!options.maxLength) options.maxLength = 79; + if (typeof options.indent !== 'number') options.indent = 1; + if (typeof options.linesBefore !== 'number') options.linesBefore = 3; + if (typeof options.linesAfter !== 'number') options.linesAfter = 2; - if (subresult[0] === EXIT$1) { - return subresult - } + var re = /\r?\n|\r|\0/g; + var lineStarts = [ 0 ]; + var lineEnds = []; + var match; + var foundLineNo = -1; - offset = - typeof subresult[1] === 'number' ? subresult[1] : offset + step; - } - } + while ((match = re.exec(mark.buffer))) { + lineEnds.push(match.index); + lineStarts.push(match.index + match[0].length); - return result - } - } + if (mark.position <= match.index && foundLineNo < 0) { + foundLineNo = lineStarts.length - 2; } - ); + } -/** - * @param {VisitorResult} value - * @returns {ActionTuple} - */ -function toResult$1(value) { - if (Array.isArray(value)) { - return value + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; + + var result = '', i, line; + var lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length; + var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3); + + for (i = 1; i <= options.linesBefore; i++) { + if (foundLineNo - i < 0) break; + line = getLine( + mark.buffer, + lineStarts[foundLineNo - i], + lineEnds[foundLineNo - i], + mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), + maxLineLength + ); + result = common.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) + + ' | ' + line.str + '\n' + result; } - if (typeof value === 'number') { - return [CONTINUE$1, value] + line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); + result += common.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) + + ' | ' + line.str + '\n'; + result += common.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\n'; + + for (i = 1; i <= options.linesAfter; i++) { + if (foundLineNo + i >= lineEnds.length) break; + line = getLine( + mark.buffer, + lineStarts[foundLineNo + i], + lineEnds[foundLineNo + i], + mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), + maxLineLength + ); + result += common.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) + + ' | ' + line.str + '\n'; } - return [value] + return result.replace(/\n$/, ''); } -/** - * @typedef {import('unist').Node} Node - * @typedef {import('unist').Parent} Parent - * @typedef {import('unist-util-is').Test} Test - * @typedef {import('unist-util-visit-parents').VisitorResult} VisitorResult - */ - -/** - * Visit children of tree which pass a test - * - * @param tree Abstract syntax tree to walk - * @param test Test, optional - * @param visitor Function to run for each node - * @param reverse Fisit the tree in reverse, defaults to false - */ -const visit$1 = - /** - * @type {( - * ((tree: Tree, test: Check, visitor: Visitor, Check>>, reverse?: boolean) => void) & - * ((tree: Tree, visitor: Visitor>, reverse?: boolean) => void) - * )} - */ - ( - /** - * @param {Node} tree - * @param {Test} test - * @param {Visitor} visitor - * @param {boolean} [reverse] - */ - function (tree, test, visitor, reverse) { - if (typeof test === 'function' && typeof visitor !== 'function') { - reverse = visitor; - visitor = test; - test = null; - } - visitParents$1(tree, test, overload, reverse); +var snippet = makeSnippet; - /** - * @param {Node} node - * @param {Array.} parents - */ - function overload(node, parents) { - const parent = parents[parents.length - 1]; - return visitor( - node, - parent ? parent.children.indexOf(node) : null, - parent - ) - } - } - ); +var TYPE_CONSTRUCTOR_OPTIONS = [ + 'kind', + 'multi', + 'resolve', + 'construct', + 'instanceOf', + 'predicate', + 'represent', + 'representName', + 'defaultStyle', + 'styleAliases' +]; -/** - * @typedef {import('mdast').Heading} Heading - * @typedef {import('../types.js').Context} Context - */ +var YAML_NODE_KINDS = [ + 'scalar', + 'sequence', + 'mapping' +]; -/** - * @param {Heading} node - * @param {Context} context - * @returns {boolean} - */ -function formatHeadingAsSetext(node, context) { - let literalWithBreak = false; +function compileStyleAliases(map) { + var result = {}; - // Look for literals with a line break. - // Note that this also - visit$1(node, (node) => { - if ( - ('value' in node && /\r?\n|\r/.test(node.value)) || - node.type === 'break' - ) { - literalWithBreak = true; - return EXIT$1 - } - }); + if (map !== null) { + Object.keys(map).forEach(function (style) { + map[style].forEach(function (alias) { + result[String(alias)] = style; + }); + }); + } - return Boolean( - (!node.depth || node.depth < 3) && - toString(node) && - (context.options.setext || literalWithBreak) - ) + return result; } -/** - * @typedef {import('mdast').Heading} Heading - * @typedef {import('../types.js').Handle} Handle - * @typedef {import('../types.js').Exit} Exit - */ +function Type$1(tag, options) { + options = options || {}; -/** - * @type {Handle} - * @param {Heading} node - */ -function heading(node, _, context) { - const rank = Math.max(Math.min(6, node.depth || 1), 1); + Object.keys(options).forEach(function (name) { + if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) { + throw new exception('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.'); + } + }); - if (formatHeadingAsSetext(node, context)) { - const exit = context.enter('headingSetext'); - const subexit = context.enter('phrasing'); - const value = containerPhrasing(node, context, {before: '\n', after: '\n'}); - subexit(); - exit(); + // TODO: Add tag format check. + this.options = options; // keep original options in case user wants to extend this type later + 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.representName = options['representName'] || null; + this.defaultStyle = options['defaultStyle'] || null; + this.multi = options['multi'] || false; + this.styleAliases = compileStyleAliases(options['styleAliases'] || null); - return ( - value + - '\n' + - (rank === 1 ? '=' : '-').repeat( - // The whole size… - value.length - - // Minus the position of the character after the last EOL (or - // 0 if there is none)… - (Math.max(value.lastIndexOf('\r'), value.lastIndexOf('\n')) + 1) - ) - ) + if (YAML_NODE_KINDS.indexOf(this.kind) === -1) { + throw new exception('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.'); } +} - const sequence = '#'.repeat(rank); - const exit = context.enter('headingAtx'); - const subexit = context.enter('phrasing'); - let value = containerPhrasing(node, context, {before: '# ', after: '\n'}); +var type = Type$1; - if (/^[\t ]/.test(value)) { - value = - '&#x' + - value.charCodeAt(0).toString(16).toUpperCase() + - ';' + - value.slice(1); - } +/*eslint-disable max-len*/ - value = value ? sequence + ' ' + value : sequence; - if (context.options.closeAtx) { - value += ' ' + sequence; - } - subexit(); - exit(); - return value -} -/** - * @typedef {import('mdast').HTML} HTML - * @typedef {import('../types.js').Handle} Handle - */ +function compileList(schema, name) { + var result = []; -html.peek = htmlPeek; + schema[name].forEach(function (currentType) { + var newIndex = result.length; -/** - * @type {Handle} - * @param {HTML} node - */ -function html(node) { - return node.value || '' -} + result.forEach(function (previousType, previousIndex) { + if (previousType.tag === currentType.tag && + previousType.kind === currentType.kind && + previousType.multi === currentType.multi) { -/** - * @type {Handle} - */ -function htmlPeek() { - return '<' -} + newIndex = previousIndex; + } + }); -/** - * @typedef {import('mdast').Image} Image - * @typedef {import('../types.js').Handle} Handle - */ + result[newIndex] = currentType; + }); -image.peek = imagePeek; + return result; +} -/** - * @type {Handle} - * @param {Image} node - */ -function image(node, _, context) { - const quote = checkQuote(context); - const suffix = quote === '"' ? 'Quote' : 'Apostrophe'; - const exit = context.enter('image'); - let subexit = context.enter('label'); - let value = '![' + safe(context, node.alt, {before: '[', after: ']'}) + ']('; - subexit(); +function compileMap(/* lists... */) { + var result = { + scalar: {}, + sequence: {}, + mapping: {}, + fallback: {}, + multi: { + scalar: [], + sequence: [], + mapping: [], + fallback: [] + } + }, index, length; - if ( - // If there’s no url but there is a title… - (!node.url && node.title) || - // Or if there’s markdown whitespace or an eol, enclose. - /[ \t\r\n]/.test(node.url) - ) { - subexit = context.enter('destinationLiteral'); - value += '<' + safe(context, node.url, {before: '<', after: '>'}) + '>'; - } else { - // No whitespace, raw is prettier. - subexit = context.enter('destinationRaw'); - value += safe(context, node.url, { - before: '(', - after: node.title ? ' ' : ')' - }); + function collectType(type) { + if (type.multi) { + result.multi[type.kind].push(type); + result.multi['fallback'].push(type); + } else { + result[type.kind][type.tag] = result['fallback'][type.tag] = type; + } } - subexit(); - - if (node.title) { - subexit = context.enter('title' + suffix); - value += - ' ' + - quote + - safe(context, node.title, {before: quote, after: quote}) + - quote; - subexit(); + for (index = 0, length = arguments.length; index < length; index += 1) { + arguments[index].forEach(collectType); } + return result; +} - value += ')'; - exit(); - return value +function Schema$1(definition) { + return this.extend(definition); } -/** - * @type {Handle} - */ -function imagePeek() { - return '!' -} -/** - * @typedef {import('mdast').ImageReference} ImageReference - * @typedef {import('../types.js').Handle} Handle - */ +Schema$1.prototype.extend = function extend(definition) { + var implicit = []; + var explicit = []; -imageReference.peek = imageReferencePeek; + if (definition instanceof type) { + // Schema.extend(type) + explicit.push(definition); -/** - * @type {Handle} - * @param {ImageReference} node - */ -function imageReference(node, _, context) { - const type = node.referenceType; - const exit = context.enter('imageReference'); - let subexit = context.enter('label'); - const alt = safe(context, node.alt, {before: '[', after: ']'}); - let value = '![' + alt + ']'; + } else if (Array.isArray(definition)) { + // Schema.extend([ type1, type2, ... ]) + explicit = explicit.concat(definition); - subexit(); - // Hide the fact that we’re in phrasing, because escapes don’t work. - const stack = context.stack; - context.stack = []; - subexit = context.enter('reference'); - const reference = safe(context, association(node), {before: '[', after: ']'}); - subexit(); - context.stack = stack; - exit(); + } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) { + // Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] }) + if (definition.implicit) implicit = implicit.concat(definition.implicit); + if (definition.explicit) explicit = explicit.concat(definition.explicit); - if (type === 'full' || !alt || alt !== reference) { - value += '[' + reference + ']'; - } else if (type !== 'shortcut') { - value += '[]'; + } else { + throw new exception('Schema.extend argument should be a Type, [ Type ], ' + + 'or a schema definition ({ implicit: [...], explicit: [...] })'); } - return value -} + implicit.forEach(function (type$1) { + if (!(type$1 instanceof type)) { + throw new exception('Specified list of YAML types (or a single Type object) contains a non-Type object.'); + } -/** - * @type {Handle} - */ -function imageReferencePeek() { - return '!' -} + if (type$1.loadKind && type$1.loadKind !== 'scalar') { + throw new exception('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.'); + } -/** - * @typedef {import('mdast').InlineCode} InlineCode - * @typedef {import('../types.js').Handle} Handle - */ + if (type$1.multi) { + throw new exception('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.'); + } + }); -inlineCode.peek = inlineCodePeek; + explicit.forEach(function (type$1) { + if (!(type$1 instanceof type)) { + throw new exception('Specified list of YAML types (or a single Type object) contains a non-Type object.'); + } + }); -/** - * @type {Handle} - * @param {InlineCode} node - */ -function inlineCode(node, _, context) { - let value = node.value || ''; - let sequence = '`'; - let index = -1; + var result = Object.create(Schema$1.prototype); - // If there is a single grave accent on its own in the code, use a fence of - // two. - // If there are two in a row, use one. - while (new RegExp('(^|[^`])' + sequence + '([^`]|$)').test(value)) { - sequence += '`'; - } + result.implicit = (this.implicit || []).concat(implicit); + result.explicit = (this.explicit || []).concat(explicit); - // If this is not just spaces or eols (tabs don’t count), and either the - // first or last character are a space, eol, or tick, then pad with spaces. - if ( - /[^ \r\n]/.test(value) && - ((/^[ \r\n]/.test(value) && /[ \r\n]$/.test(value)) || /^`|`$/.test(value)) - ) { - value = ' ' + value + ' '; - } + result.compiledImplicit = compileList(result, 'implicit'); + result.compiledExplicit = compileList(result, 'explicit'); + result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit); - // We have a potential problem: certain characters after eols could result in - // blocks being seen. - // For example, if someone injected the string `'\n# b'`, then that would - // result in an ATX heading. - // We can’t escape characters in `inlineCode`, but because eols are - // transformed to spaces when going from markdown to HTML anyway, we can swap - // them out. - while (++index < context.unsafe.length) { - const pattern = context.unsafe[index]; - const expression = patternCompile(pattern); - /** @type {RegExpExecArray|null} */ - let match; + return result; +}; - // Only look for `atBreak`s. - // Btw: note that `atBreak` patterns will always start the regex at LF or - // CR. - if (!pattern.atBreak) continue - while ((match = expression.exec(value))) { - let position = match.index; +var schema = Schema$1; - // Support CRLF (patterns only look for one of the characters). - if ( - value.charCodeAt(position) === 10 /* `\n` */ && - value.charCodeAt(position - 1) === 13 /* `\r` */ - ) { - position--; - } +var str = new type('tag:yaml.org,2002:str', { + kind: 'scalar', + construct: function (data) { return data !== null ? data : ''; } +}); - value = value.slice(0, position) + ' ' + value.slice(match.index + 1); - } - } +var seq = new type('tag:yaml.org,2002:seq', { + kind: 'sequence', + construct: function (data) { return data !== null ? data : []; } +}); - return sequence + value + sequence -} +var map = new type('tag:yaml.org,2002:map', { + kind: 'mapping', + construct: function (data) { return data !== null ? data : {}; } +}); -/** - * @type {Handle} - */ -function inlineCodePeek() { - return '`' -} +var failsafe = new schema({ + explicit: [ + str, + seq, + map + ] +}); -/** - * @typedef {import('mdast').Link} Link - * @typedef {import('../types.js').Context} Context - */ +function resolveYamlNull(data) { + if (data === null) return true; -/** - * @param {Link} node - * @param {Context} context - * @returns {boolean} - */ -function formatLinkAsAutolink(node, context) { - const raw = toString(node); + var max = data.length; - return Boolean( - !context.options.resourceLink && - // If there’s a url… - node.url && - // And there’s a no title… - !node.title && - // And the content of `node` is a single text node… - node.children && - node.children.length === 1 && - node.children[0].type === 'text' && - // And if the url is the same as the content… - (raw === node.url || 'mailto:' + raw === node.url) && - // And that starts w/ a protocol… - /^[a-z][a-z+.-]+:/i.test(node.url) && - // And that doesn’t contain ASCII control codes (character escapes and - // references don’t work) or angle brackets… - !/[\0- <>\u007F]/.test(node.url) - ) + return (max === 1 && data === '~') || + (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL')); } -/** - * @typedef {import('mdast').Link} Link - * @typedef {import('../types.js').Handle} Handle - * @typedef {import('../types.js').Exit} Exit - */ +function constructYamlNull() { + return null; +} -link.peek = linkPeek; +function isNull(object) { + return object === null; +} -/** - * @type {Handle} - * @param {Link} node - */ -function link(node, _, context) { - const quote = checkQuote(context); - const suffix = quote === '"' ? 'Quote' : 'Apostrophe'; - /** @type {Exit} */ - let exit; - /** @type {Exit} */ - let subexit; - /** @type {string} */ - let value; +var _null = new type('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'; }, + empty: function () { return ''; } + }, + defaultStyle: 'lowercase' +}); - if (formatLinkAsAutolink(node, context)) { - // Hide the fact that we’re in phrasing, because escapes don’t work. - const stack = context.stack; - context.stack = []; - exit = context.enter('autolink'); - value = - '<' + containerPhrasing(node, context, {before: '<', after: '>'}) + '>'; - exit(); - context.stack = stack; - return value - } +function resolveYamlBoolean(data) { + if (data === null) return false; - exit = context.enter('link'); - subexit = context.enter('label'); - value = - '[' + containerPhrasing(node, context, {before: '[', after: ']'}) + ']('; - subexit(); + var max = data.length; - if ( - // If there’s no url but there is a title… - (!node.url && node.title) || - // Or if there’s markdown whitespace or an eol, enclose. - /[ \t\r\n]/.test(node.url) - ) { - subexit = context.enter('destinationLiteral'); - value += '<' + safe(context, node.url, {before: '<', after: '>'}) + '>'; - } else { - // No whitespace, raw is prettier. - subexit = context.enter('destinationRaw'); - value += safe(context, node.url, { - before: '(', - after: node.title ? ' ' : ')' - }); - } + return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) || + (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE')); +} - subexit(); +function constructYamlBoolean(data) { + return data === 'true' || + data === 'True' || + data === 'TRUE'; +} - if (node.title) { - subexit = context.enter('title' + suffix); - value += - ' ' + - quote + - safe(context, node.title, {before: quote, after: quote}) + - quote; - subexit(); - } +function isBoolean(object) { + return Object.prototype.toString.call(object) === '[object Boolean]'; +} - value += ')'; +var bool = new type('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' +}); - exit(); - return value +function isHexCode(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) || + ((0x41/* A */ <= c) && (c <= 0x46/* F */)) || + ((0x61/* a */ <= c) && (c <= 0x66/* f */)); } -/** - * @type {Handle} - * @param {Link} node - */ -function linkPeek(node, _, context) { - return formatLinkAsAutolink(node, context) ? '<' : '[' +function isOctCode(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */)); } -/** - * @typedef {import('mdast').LinkReference} LinkReference - * @typedef {import('../types.js').Handle} Handle - */ +function isDecCode(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)); +} -linkReference.peek = linkReferencePeek; +function resolveYamlInteger(data) { + if (data === null) return false; -/** - * @type {Handle} - * @param {LinkReference} node - */ -function linkReference(node, _, context) { - const type = node.referenceType; - const exit = context.enter('linkReference'); - let subexit = context.enter('label'); - const text = containerPhrasing(node, context, {before: '[', after: ']'}); - let value = '[' + text + ']'; + var max = data.length, + index = 0, + hasDigits = false, + ch; - subexit(); - // Hide the fact that we’re in phrasing, because escapes don’t work. - const stack = context.stack; - context.stack = []; - subexit = context.enter('reference'); - const reference = safe(context, association(node), {before: '[', after: ']'}); - subexit(); - context.stack = stack; - exit(); + if (!max) return false; - if (type === 'full' || !text || text !== reference) { - value += '[' + reference + ']'; - } else if (type !== 'shortcut') { - value += '[]'; - } + ch = data[index]; - return value -} + // sign + if (ch === '-' || ch === '+') { + ch = data[++index]; + } -/** - * @type {Handle} - */ -function linkReferencePeek() { - return '[' -} + if (ch === '0') { + // 0 + if (index + 1 === max) return true; + ch = data[++index]; -/** - * @typedef {import('../types.js').Context} Context - * @typedef {import('../types.js').Options} Options - */ + // base 2, base 8, base 16 -/** - * @param {Context} context - * @returns {Exclude} - */ -function checkBullet(context) { - const marker = context.options.bullet || '*'; + if (ch === 'b') { + // base 2 + index++; - if (marker !== '*' && marker !== '+' && marker !== '-') { - throw new Error( - 'Cannot serialize items with `' + - marker + - '` for `options.bullet`, expected `*`, `+`, or `-`' - ) - } + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (ch !== '0' && ch !== '1') return false; + hasDigits = true; + } + return hasDigits && ch !== '_'; + } - return marker -} -/** - * @typedef {import('../types.js').Context} Context - * @typedef {import('../types.js').Options} Options - */ + if (ch === 'x') { + // base 16 + index++; -/** - * @param {Context} context - * @returns {Exclude} - */ -function checkBulletOther(context) { - const bullet = checkBullet(context); - const bulletOther = context.options.bulletOther; + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (!isHexCode(data.charCodeAt(index))) return false; + hasDigits = true; + } + return hasDigits && ch !== '_'; + } - if (!bulletOther) { - return bullet === '*' ? '-' : '*' - } - if (bulletOther !== '*' && bulletOther !== '+' && bulletOther !== '-') { - throw new Error( - 'Cannot serialize items with `' + - bulletOther + - '` for `options.bulletOther`, expected `*`, `+`, or `-`' - ) - } + if (ch === 'o') { + // base 8 + index++; - if (bulletOther === bullet) { - throw new Error( - 'Expected `bullet` (`' + - bullet + - '`) and `bulletOther` (`' + - bulletOther + - '`) to be different' - ) + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (!isOctCode(data.charCodeAt(index))) return false; + hasDigits = true; + } + return hasDigits && ch !== '_'; + } } - return bulletOther -} - -/** - * @typedef {import('../types.js').Context} Context - * @typedef {import('../types.js').Options} Options - */ + // base 10 (except 0) -/** - * @param {Context} context - * @returns {Exclude} - */ -function checkBulletOrdered(context) { - const marker = context.options.bulletOrdered || '.'; + // value should not start with `_`; + if (ch === '_') return false; - if (marker !== '.' && marker !== ')') { - throw new Error( - 'Cannot serialize items with `' + - marker + - '` for `options.bulletOrdered`, expected `.` or `)`' - ) + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') continue; + if (!isDecCode(data.charCodeAt(index))) { + return false; + } + hasDigits = true; } - return marker -} + // Should have digits and should not end with `_` + if (!hasDigits || ch === '_') return false; -/** - * @typedef {import('../types.js').Context} Context - * @typedef {import('../types.js').Options} Options - */ + return true; +} -/** - * @param {Context} context - * @returns {Exclude} - */ -function checkBulletOrderedOther(context) { - const bulletOrdered = checkBulletOrdered(context); - const bulletOrderedOther = context.options.bulletOrderedOther; +function constructYamlInteger(data) { + var value = data, sign = 1, ch; - if (!bulletOrderedOther) { - return bulletOrdered === '.' ? ')' : '.' + if (value.indexOf('_') !== -1) { + value = value.replace(/_/g, ''); } - if (bulletOrderedOther !== '.' && bulletOrderedOther !== ')') { - throw new Error( - 'Cannot serialize items with `' + - bulletOrderedOther + - '` for `options.bulletOrderedOther`, expected `*`, `+`, or `-`' - ) + ch = value[0]; + + if (ch === '-' || ch === '+') { + if (ch === '-') sign = -1; + value = value.slice(1); + ch = value[0]; } - if (bulletOrderedOther === bulletOrdered) { - throw new Error( - 'Expected `bulletOrdered` (`' + - bulletOrdered + - '`) and `bulletOrderedOther` (`' + - bulletOrderedOther + - '`) to be different' - ) + 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.slice(2), 16); + if (value[1] === 'o') return sign * parseInt(value.slice(2), 8); } - return bulletOrderedOther + return sign * parseInt(value, 10); } -/** - * @typedef {import('../types.js').Context} Context - * @typedef {import('../types.js').Options} Options - */ - -/** - * @param {Context} context - * @returns {Exclude} - */ -function checkRule(context) { - const marker = context.options.rule || '*'; +function isInteger(object) { + return (Object.prototype.toString.call(object)) === '[object Number]' && + (object % 1 === 0 && !common.isNegativeZero(object)); +} - if (marker !== '*' && marker !== '-' && marker !== '_') { - throw new Error( - 'Cannot serialize rules with `' + - marker + - '` for `options.rule`, expected `*`, `-`, or `_`' - ) +var int = new type('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 ? '0o' + obj.toString(8) : '-0o' + 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' ] } +}); - return marker -} - -/** - * @typedef {import('mdast').List} List - * @typedef {import('../types.js').Handle} Handle - */ +var YAML_FLOAT_PATTERN = new RegExp( + // 2.5e4, 2.5 and integers + '^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?' + + // .2e4, .2 + // special case, seems not from spec + '|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?' + + // .inf + '|[-+]?\\.(?:inf|Inf|INF)' + + // .nan + '|\\.(?:nan|NaN|NAN))$'); -/** - * @type {Handle} - * @param {List} node - */ -function list(node, parent, context) { - const exit = context.enter('list'); - const bulletCurrent = context.bulletCurrent; - /** @type {string} */ - let bullet = node.ordered ? checkBulletOrdered(context) : checkBullet(context); - /** @type {string} */ - const bulletOther = node.ordered - ? checkBulletOrderedOther(context) - : checkBulletOther(context); - const bulletLastUsed = context.bulletLastUsed; - let useDifferentMarker = false; +function resolveYamlFloat(data) { + if (data === null) return false; - if ( - parent && - // Explicit `other` set. - (node.ordered - ? context.options.bulletOrderedOther - : context.options.bulletOther) && - bulletLastUsed && - bullet === bulletLastUsed - ) { - useDifferentMarker = true; + 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; } - if (!node.ordered) { - const firstListItem = node.children ? node.children[0] : undefined; - - // If there’s an empty first list item directly in two list items, - // we have to use a different bullet: - // - // ```markdown - // * - * - // ``` - // - // …because otherwise it would become one big thematic break. - if ( - // Bullet could be used as a thematic break marker: - (bullet === '*' || bullet === '-') && - // Empty first list item: - firstListItem && - (!firstListItem.children || !firstListItem.children[0]) && - // Directly in two other list items: - context.stack[context.stack.length - 1] === 'list' && - context.stack[context.stack.length - 2] === 'listItem' && - context.stack[context.stack.length - 3] === 'list' && - context.stack[context.stack.length - 4] === 'listItem' && - // That are each the first child. - context.indexStack[context.indexStack.length - 1] === 0 && - context.indexStack[context.indexStack.length - 2] === 0 && - context.indexStack[context.indexStack.length - 3] === 0 && - context.indexStack[context.indexStack.length - 4] === 0 - ) { - useDifferentMarker = true; - } + return true; +} - // If there’s a thematic break at the start of the first list item, - // we have to use a different bullet: - // - // ```markdown - // * --- - // ``` - // - // …because otherwise it would become one big thematic break. - if (checkRule(context) === bullet && firstListItem) { - let index = -1; +function constructYamlFloat(data) { + var value, sign; - while (++index < node.children.length) { - const item = node.children[index]; + value = data.replace(/_/g, '').toLowerCase(); + sign = value[0] === '-' ? -1 : 1; - if ( - item && - item.type === 'listItem' && - item.children && - item.children[0] && - item.children[0].type === 'thematicBreak' - ) { - useDifferentMarker = true; - break - } - } - } + if ('+-'.indexOf(value[0]) >= 0) { + value = value.slice(1); } - if (useDifferentMarker) { - bullet = bulletOther; - } + if (value === '.inf') { + return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; - context.bulletCurrent = bullet; - const value = containerFlow(node, context); - context.bulletLastUsed = bullet; - context.bulletCurrent = bulletCurrent; - exit(); - return value + } else if (value === '.nan') { + return NaN; + } + return sign * parseFloat(value, 10); } -/** - * @typedef {import('../types.js').Context} Context - * @typedef {import('../types.js').Options} Options - */ -/** - * @param {Context} context - * @returns {Exclude} - */ -function checkListItemIndent(context) { - const style = context.options.listItemIndent || 'tab'; +var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/; - // To do: remove in a major. - // @ts-expect-error: deprecated. - if (style === 1 || style === '1') { - return 'one' - } +function representYamlFloat(object, style) { + var res; - if (style !== 'tab' && style !== 'one' && style !== 'mixed') { - throw new Error( - 'Cannot serialize items with `' + - style + - '` for `options.listItemIndent`, expected `tab`, `one`, or `mixed`' - ) + 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.isNegativeZero(object)) { + return '-0.0'; } - return style -} + res = object.toString(10); -/** - * @typedef {import('mdast').ListItem} ListItem - * @typedef {import('mdast').List} List - * @typedef {import('../util/indent-lines.js').Map} Map - * @typedef {import('../types.js').Options} Options - * @typedef {import('../types.js').Handle} Handle - */ + // JS stringifier can build scientific format without dots: 5e-100, + // while YAML requres dot: 5.e-100. Fix it with simple hack -/** - * @type {Handle} - * @param {ListItem} node - */ -function listItem(node, parent, context) { - const listItemIndent = checkListItemIndent(context); - let bullet = context.bulletCurrent || checkBullet(context); + return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res; +} - // Add the marker value for ordered lists. - if (parent && parent.type === 'list' && parent.ordered) { - bullet = - (typeof parent.start === 'number' && parent.start > -1 - ? parent.start - : 1) + - (context.options.incrementListMarker === false - ? 0 - : parent.children.indexOf(node)) + - bullet; - } +function isFloat(object) { + return (Object.prototype.toString.call(object) === '[object Number]') && + (object % 1 !== 0 || common.isNegativeZero(object)); +} - let size = bullet.length + 1; +var float = new type('tag:yaml.org,2002:float', { + kind: 'scalar', + resolve: resolveYamlFloat, + construct: constructYamlFloat, + predicate: isFloat, + represent: representYamlFloat, + defaultStyle: 'lowercase' +}); - if ( - listItemIndent === 'tab' || - (listItemIndent === 'mixed' && - ((parent && parent.type === 'list' && parent.spread) || node.spread)) - ) { - size = Math.ceil(size / 4) * 4; - } +var json = failsafe.extend({ + implicit: [ + _null, + bool, + int, + float + ] +}); - const exit = context.enter('listItem'); - const value = indentLines(containerFlow(node, context), map); - exit(); +var core = json; - return value +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 - /** @type {Map} */ - function map(line, index, blank) { - if (index) { - return (blank ? '' : ' '.repeat(size)) + line - } +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 - return (blank ? bullet : bullet + ' '.repeat(size - bullet.length)) + line - } +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; } -/** - * @typedef {import('mdast').Paragraph} Paragraph - * @typedef {import('../types.js').Handle} Handle - */ +function constructYamlTimestamp(data) { + var match, year, month, day, hour, minute, second, fraction = 0, + delta = null, tz_hour, tz_minute, date; -/** - * @type {Handle} - * @param {Paragraph} node - */ -function paragraph(node, _, context) { - const exit = context.enter('paragraph'); - const subexit = context.enter('phrasing'); - const value = containerPhrasing(node, context, {before: '\n', after: '\n'}); - subexit(); - exit(); - return value -} + match = YAML_DATE_REGEXP.exec(data); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data); -/** - * @typedef {import('mdast').Root} Root - * @typedef {import('../types.js').Handle} Handle - */ + if (match === null) throw new Error('Date resolve error'); -/** - * @type {Handle} - * @param {Root} node - */ -function root(node, _, context) { - return containerFlow(node, context) -} + // match: [1] year [2] month [3] day -/** - * @typedef {import('../types.js').Context} Context - * @typedef {import('../types.js').Options} Options - */ + year = +(match[1]); + month = +(match[2]) - 1; // JS month starts with 0 + day = +(match[3]); -/** - * @param {Context} context - * @returns {Exclude} - */ -function checkStrong(context) { - const marker = context.options.strong || '*'; + if (!match[4]) { // no hour + return new Date(Date.UTC(year, month, day)); + } - if (marker !== '*' && marker !== '_') { - throw new Error( - 'Cannot serialize strong with `' + - marker + - '` for `options.strong`, expected `*`, or `_`' - ) + // 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; } - return marker -} + // 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; + } -/** - * @typedef {import('mdast').Strong} Strong - * @typedef {import('../types.js').Handle} Handle - */ + date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); -strong.peek = strongPeek; + if (delta) date.setTime(date.getTime() - delta); -// To do: there are cases where emphasis cannot “form” depending on the -// previous or next character of sequences. -// There’s no way around that though, except for injecting zero-width stuff. -// Do we need to safeguard against that? -/** - * @type {Handle} - * @param {Strong} node - */ -function strong(node, _, context) { - const marker = checkStrong(context); - const exit = context.enter('strong'); - const value = containerPhrasing(node, context, { - before: marker, - after: marker - }); - exit(); - return marker + marker + value + marker + marker + return date; } -/** - * @type {Handle} - * @param {Strong} _ - */ -function strongPeek(_, _1, context) { - return context.options.strong || '*' +function representYamlTimestamp(object /*, style*/) { + return object.toISOString(); } -/** - * @typedef {import('mdast').Text} Text - * @typedef {import('../types.js').Handle} Handle - */ +var timestamp = new type('tag:yaml.org,2002:timestamp', { + kind: 'scalar', + resolve: resolveYamlTimestamp, + construct: constructYamlTimestamp, + instanceOf: Date, + represent: representYamlTimestamp +}); -/** - * @type {Handle} - * @param {Text} node - */ -function text$1(node, _, context, safeOptions) { - return safe(context, node.value, safeOptions) +function resolveYamlMerge(data) { + return data === '<<' || data === null; } -/** - * @typedef {import('../types.js').Context} Context - * @typedef {import('../types.js').Options} Options - */ +var merge = new type('tag:yaml.org,2002:merge', { + kind: 'scalar', + resolve: resolveYamlMerge +}); -/** - * @param {Context} context - * @returns {Exclude} - */ -function checkRuleRepetition(context) { - const repetition = context.options.ruleRepetition || 3; +/*eslint-disable no-bitwise*/ - if (repetition < 3) { - throw new Error( - 'Cannot serialize rules with repetition `' + - repetition + - '` for `options.ruleRepetition`, expected `3` or more' - ) - } - return repetition -} -/** - * @typedef {import('../types.js').Handle} Handle - * @typedef {import('mdast').ThematicBreak} ThematicBreak - */ -/** - * @type {Handle} - * @param {ThematicBreak} _ - */ -function thematicBreak(_, _1, context) { - const value = ( - checkRule(context) + (context.options.ruleSpaces ? ' ' : '') - ).repeat(checkRuleRepetition(context)); - return context.options.ruleSpaces ? value.slice(0, -1) : value -} +// [ 64, 65, 66 ] -> [ padding, CR, LF ] +var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r'; -const handle = { - blockquote, - break: hardBreak, - code: code$1, - definition, - emphasis, - hardBreak, - heading, - html, - image, - imageReference, - inlineCode, - link, - linkReference, - list, - listItem, - paragraph, - root, - strong, - text: text$1, - thematicBreak -}; -/** - * @typedef {import('./types.js').Join} Join - */ +function resolveYamlBinary(data) { + if (data === null) return false; -/** @type {Array.} */ -const join = [joinDefaults]; + var code, idx, bitlen = 0, max = data.length, map = BASE64_MAP; -/** @type {Join} */ -function joinDefaults(left, right, parent, context) { - // Indented code after list or another indented code. - if ( - right.type === 'code' && - formatCodeAsIndented(right, context) && - (left.type === 'list' || - (left.type === right.type && formatCodeAsIndented(left, context))) - ) { - return false - } + // Convert one by one. + for (idx = 0; idx < max; idx++) { + code = map.indexOf(data.charAt(idx)); - // Two lists with the same marker. - if ( - left.type === 'list' && - left.type === right.type && - Boolean(left.ordered) === Boolean(right.ordered) && - !(left.ordered - ? context.options.bulletOrderedOther - : context.options.bulletOther) - ) { - return false - } + // Skip CR/LF + if (code > 64) continue; - // Join children of a list or an item. - // In which case, `parent` has a `spread` field. - if ('spread' in parent && typeof parent.spread === 'boolean') { - if ( - left.type === 'paragraph' && - // Two paragraphs. - (left.type === right.type || - right.type === 'definition' || - // Paragraph followed by a setext heading. - (right.type === 'heading' && formatHeadingAsSetext(right, context))) - ) { - return - } + // Fail on illegal characters + if (code < 0) return false; - return parent.spread ? 1 : 0 + bitlen += 6; } + + // If there are any bits left, source was corrupted + return (bitlen % 8) === 0; } -/** - * @typedef {import('./types.js').Unsafe} Unsafe - */ +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 = []; -/** @type {Array.} */ -const unsafe = [ - {character: '\t', after: '[\\r\\n]', inConstruct: 'phrasing'}, - {character: '\t', before: '[\\r\\n]', inConstruct: 'phrasing'}, - { - character: '\t', - inConstruct: ['codeFencedLangGraveAccent', 'codeFencedLangTilde'] - }, - { - character: '\r', - inConstruct: [ - 'codeFencedLangGraveAccent', - 'codeFencedLangTilde', - 'codeFencedMetaGraveAccent', - 'codeFencedMetaTilde', - 'destinationLiteral', - 'headingAtx' - ] - }, - { - character: '\n', - inConstruct: [ - 'codeFencedLangGraveAccent', - 'codeFencedLangTilde', - 'codeFencedMetaGraveAccent', - 'codeFencedMetaTilde', - 'destinationLiteral', - 'headingAtx' - ] - }, - {character: ' ', after: '[\\r\\n]', inConstruct: 'phrasing'}, - {character: ' ', before: '[\\r\\n]', inConstruct: 'phrasing'}, - { - character: ' ', - inConstruct: ['codeFencedLangGraveAccent', 'codeFencedLangTilde'] - }, - // An exclamation mark can start an image, if it is followed by a link or - // a link reference. - {character: '!', after: '\\[', inConstruct: 'phrasing'}, - // A quote can break out of a title. - {character: '"', inConstruct: 'titleQuote'}, - // A number sign could start an ATX heading if it starts a line. - {atBreak: true, character: '#'}, - {character: '#', inConstruct: 'headingAtx', after: '(?:[\r\n]|$)'}, - // Dollar sign and percentage are not used in markdown. - // An ampersand could start a character reference. - {character: '&', after: '[#A-Za-z]', inConstruct: 'phrasing'}, - // An apostrophe can break out of a title. - {character: "'", inConstruct: 'titleApostrophe'}, - // A left paren could break out of a destination raw. - {character: '(', inConstruct: 'destinationRaw'}, - {before: '\\]', character: '(', inConstruct: 'phrasing'}, - // A right paren could start a list item or break out of a destination - // raw. - {atBreak: true, before: '\\d+', character: ')'}, - {character: ')', inConstruct: 'destinationRaw'}, - // An asterisk can start thematic breaks, list items, emphasis, strong. - {atBreak: true, character: '*'}, - {character: '*', inConstruct: 'phrasing'}, - // A plus sign could start a list item. - {atBreak: true, character: '+'}, - // A dash can start thematic breaks, list items, and setext heading - // underlines. - {atBreak: true, character: '-'}, - // A dot could start a list item. - {atBreak: true, before: '\\d+', character: '.', after: '(?:[ \t\r\n]|$)'}, - // Slash, colon, and semicolon are not used in markdown for constructs. - // A less than can start html (flow or text) or an autolink. - // HTML could start with an exclamation mark (declaration, cdata, comment), - // slash (closing tag), question mark (instruction), or a letter (tag). - // An autolink also starts with a letter. - // Finally, it could break out of a destination literal. - {atBreak: true, character: '<', after: '[!/?A-Za-z]'}, - {character: '<', after: '[!/?A-Za-z]', inConstruct: 'phrasing'}, - {character: '<', inConstruct: 'destinationLiteral'}, - // An equals to can start setext heading underlines. - {atBreak: true, character: '='}, - // A greater than can start block quotes and it can break out of a - // destination literal. - {atBreak: true, character: '>'}, - {character: '>', inConstruct: 'destinationLiteral'}, - // Question mark and at sign are not used in markdown for constructs. - // A left bracket can start definitions, references, labels, - {atBreak: true, character: '['}, - {character: '[', inConstruct: ['phrasing', 'label', 'reference']}, - // A backslash can start an escape (when followed by punctuation) or a - // hard break (when followed by an eol). - // Note: typical escapes are handled in `safe`! - {character: '\\', after: '[\\r\\n]', inConstruct: 'phrasing'}, - // A right bracket can exit labels. - {character: ']', inConstruct: ['label', 'reference']}, - // Caret is not used in markdown for constructs. - // An underscore can start emphasis, strong, or a thematic break. - {atBreak: true, character: '_'}, - {character: '_', inConstruct: 'phrasing'}, - // A grave accent can start code (fenced or text), or it can break out of - // a grave accent code fence. - {atBreak: true, character: '`'}, - { - character: '`', - inConstruct: [ - 'codeFencedLangGraveAccent', - 'codeFencedMetaGraveAccent', - 'phrasing' - ] - }, - // Left brace, vertical bar, right brace are not used in markdown for - // constructs. - // A tilde can start code (fenced). - {atBreak: true, character: '~'} -]; + // Collect by 6*4 bits (3 bytes) -/** - * @typedef {import('./types.js').Node} Node - * @typedef {import('./types.js').Options} Options - * @typedef {import('./types.js').Context} Context - * @typedef {import('./types.js').Handle} Handle - * @typedef {import('./types.js').Join} Join - * @typedef {import('./types.js').Unsafe} Unsafe - */ + 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); + } -/** - * @param {Node} tree - * @param {Options} [options] - * @returns {string} - */ -function toMarkdown(tree, options = {}) { - /** @type {Context} */ - // @ts-expect-error: we’ll add `handle` later. - const context = { - enter, - stack: [], - unsafe: [], - join: [], - handlers: {}, - options: {}, - indexStack: [] - }; + bits = (bits << 6) | map.indexOf(input.charAt(idx)); + } - configure(context, {unsafe, join, handlers: handle}); - configure(context, options); + // Dump tail - if (context.options.tightDefinitions) { - configure(context, {join: [joinDefinition]}); + 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); } - /** @type {Handle} */ - context.handle = zwitch('type', { - invalid, - // @ts-expect-error: hush. - unknown, - // @ts-expect-error: hush. - handlers: context.handlers - }); + return new Uint8Array(result); +} - let result = context.handle(tree, null, context, {before: '\n', after: '\n'}); +function representYamlBinary(object /*, style*/) { + var result = '', bits = 0, idx, tail, + max = object.length, + map = BASE64_MAP; - if ( - result && - result.charCodeAt(result.length - 1) !== 10 && - result.charCodeAt(result.length - 1) !== 13 - ) { - result += '\n'; + // 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]; } - return result + // Dump tail - /** @type {Context['enter']} */ - function enter(name) { - context.stack.push(name); - return exit + tail = max % 3; - function exit() { - context.stack.pop(); - } + 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]; } -} -/** - * @type {Handle} - * @param {unknown} value - */ -function invalid(value) { - throw new Error('Cannot handle value `' + value + '`, expected node') + return result; } -/** - * @type {Handle} - * @param {Node} node - */ -function unknown(node) { - throw new Error('Cannot handle unknown node `' + node.type + '`') +function isBinary(obj) { + return Object.prototype.toString.call(obj) === '[object Uint8Array]'; } -/** @type {Join} */ -function joinDefinition(left, right) { - // No blank line between adjacent definitions. - if (left.type === 'definition' && left.type === right.type) { - return 0 - } -} +var binary = new type('tag:yaml.org,2002:binary', { + kind: 'scalar', + resolve: resolveYamlBinary, + construct: constructYamlBinary, + predicate: isBinary, + represent: representYamlBinary +}); -/** - * @typedef {import('mdast').Root|import('mdast').Content} Node - * @typedef {import('mdast-util-to-markdown').Options} Options - */ +var _hasOwnProperty$3 = Object.prototype.hasOwnProperty; +var _toString$2 = Object.prototype.toString; -/** @type {import('unified').Plugin<[Options]|void[], Node, string>} */ -function remarkStringify(options) { - /** @type {import('unified').CompilerFunction} */ - const compiler = (tree) => { - // Assume options. - const settings = /** @type {Options} */ (this.data('settings')); +function resolveYamlOmap(data) { + if (data === null) return true; - return toMarkdown( - tree, - Object.assign({}, settings, options, { - // Note: this option is not in the readme. - // The goal is for it to be set by plugins on `data` instead of being - // passed by users. - extensions: this.data('toMarkdownExtensions') || [] - }) - ) - }; + var objectKeys = [], index, length, pair, pairKey, pairHasKey, + object = data; - Object.assign(this, {Compiler: compiler}); + 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$3.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; } -const remark = unified().use(remarkParse).use(remarkStringify).freeze(); - -const name$1 = "remark"; -const version$1 = "14.0.1"; -const description$1 = "Markdown processor powered by plugins part of the unified collective"; -const license = "MIT"; -const keywords = [ - "unified", - "remark", - "markdown", - "mdast", - "abstract", - "syntax", - "tree", - "ast", - "parse", - "stringify", - "serialize", - "compile", - "process" -]; -const homepage = "https://remark.js.org"; -const repository = "https://github.com/remarkjs/remark/tree/main/packages/remark"; -const bugs = "https://github.com/remarkjs/remark/issues"; -const funding = { - type: "opencollective", - url: "https://opencollective.com/unified" -}; -const author = "Titus Wormer (https://wooorm.com)"; -const contributors = [ - "Titus Wormer (https://wooorm.com)" -]; -const sideEffects = false; -const type = "module"; -const main$1 = "index.js"; -const types = "index.d.ts"; -const files = [ - "index.d.ts", - "index.js" -]; -const dependencies$1 = { - "@types/mdast": "^3.0.0", - "remark-parse": "^10.0.0", - "remark-stringify": "^10.0.0", - unified: "^10.0.0" -}; -const scripts$1 = { - test: "node --conditions development test.js", - build: "rimraf \"*.d.ts\" && tsc && type-coverage" -}; -const xo = false; -const typeCoverage = { - atLeast: 100, - detail: true, - strict: true, - ignoreCatch: true -}; -var proc = { - name: name$1, - version: version$1, - description: description$1, - license: license, - keywords: keywords, - homepage: homepage, - repository: repository, - bugs: bugs, - funding: funding, - author: author, - contributors: contributors, - sideEffects: sideEffects, - type: type, - main: main$1, - types: types, - files: files, - dependencies: dependencies$1, - scripts: scripts$1, - xo: xo, - typeCoverage: typeCoverage -}; +function constructYamlOmap(data) { + return data !== null ? data : []; +} -const name = "node-lint-md-cli-rollup"; -const description = "remark packaged for Node.js Markdown linting"; -const version = "2.0.2"; -const devDependencies = { - "@rollup/plugin-commonjs": "^20.0.0", - "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^13.0.4", - rollup: "^2.56.3", - shx: "^0.3.3" -}; -const dependencies = { - "markdown-extensions": "^1.1.1", - remark: "^14.0.1", - "remark-gfm": "^2.0.0", - "remark-preset-lint-node": "^3.0.1", - "unified-args": "^9.0.2" -}; -const main = "dist/index.js"; -const scripts = { - build: "npx rollup -c", - "build-node": "npm run build && npx shx cp dist/index.mjs ../lint-md.mjs" -}; -var cli = { - name: name, - description: description, - version: version, - devDependencies: devDependencies, - dependencies: dependencies, - main: main, - scripts: scripts -}; +var omap = new type('tag:yaml.org,2002:omap', { + kind: 'sequence', + resolve: resolveYamlOmap, + construct: constructYamlOmap +}); -/** - * @typedef {import('unist').Point} Point - * @typedef {import('vfile').VFile} VFile - * - * @typedef {Pick} PositionalPoint - * @typedef {Required} FullPoint - * @typedef {NonNullable} Offset - */ +var _toString$1 = Object.prototype.toString; -/** - * Get transform functions for the given `document`. - * - * @param {string|Uint8Array|VFile} file - */ -function location(file) { - var value = String(file); - /** @type {Array.} */ - var indices = []; - var search = /\r?\n|\r/g; +function resolveYamlPairs(data) { + if (data === null) return true; - while (search.test(value)) { - indices.push(search.lastIndex); - } + var index, length, pair, keys, result, + object = data; - indices.push(value.length + 1); + result = new Array(object.length); - return {toPoint, toOffset} + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; - /** - * Get the line and column-based `point` for `offset` in the bound indices. - * Returns a point with `undefined` values when given invalid or out of bounds - * input. - * - * @param {Offset} offset - * @returns {FullPoint} - */ - function toPoint(offset) { - var index = -1; + if (_toString$1.call(pair) !== '[object Object]') return false; - if (offset > -1 && offset < indices[indices.length - 1]) { - while (++index < indices.length) { - if (indices[index] > offset) { - return { - line: index + 1, - column: offset - (indices[index - 1] || 0) + 1, - offset - } - } - } - } + keys = Object.keys(pair); - return {line: undefined, column: undefined, offset: undefined} + if (keys.length !== 1) return false; + + result[index] = [ keys[0], pair[keys[0]] ]; } - /** - * Get the `offset` for a line and column-based `point` in the bound indices. - * Returns `-1` when given invalid or out of bounds input. - * - * @param {PositionalPoint} point - * @returns {Offset} - */ - function toOffset(point) { - var line = point && point.line; - var column = point && point.column; - /** @type {number} */ - var offset; + return true; +} - if ( - typeof line === 'number' && - typeof column === 'number' && - !Number.isNaN(line) && - !Number.isNaN(column) && - line - 1 in indices - ) { - offset = (indices[line - 2] || 0) + column - 1 || 0; - } +function constructYamlPairs(data) { + if (data === null) return []; - return offset > -1 && offset < indices[indices.length - 1] ? offset : -1 + 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]] ]; } -} -/** - * @param {string} d - * @returns {string} - */ -function color(d) { - return '\u001B[33m' + d + '\u001B[39m' + return result; } -/** - * @typedef {import('unist').Node} Node - * @typedef {import('unist').Parent} Parent - * @typedef {import('unist-util-is').Test} Test - */ +var pairs = new type('tag:yaml.org,2002:pairs', { + kind: 'sequence', + resolve: resolveYamlPairs, + construct: constructYamlPairs +}); -/** - * Continue traversing as normal - */ -const CONTINUE = true; -/** - * Do not traverse this node’s children - */ -const SKIP = 'skip'; -/** - * Stop traversing immediately - */ -const EXIT = false; +var _hasOwnProperty$2 = Object.prototype.hasOwnProperty; -const visitParents = - /** - * @type {( - * ((tree: Node, test: T['type']|Partial|import('unist-util-is').TestFunctionPredicate|Array.|import('unist-util-is').TestFunctionPredicate>, visitor: Visitor, reverse?: boolean) => void) & - * ((tree: Node, test: Test, visitor: Visitor, reverse?: boolean) => void) & - * ((tree: Node, visitor: Visitor, reverse?: boolean) => void) - * )} - */ - ( - /** - * Visit children of tree which pass a test - * - * @param {Node} tree Abstract syntax tree to walk - * @param {Test} test test Test node - * @param {Visitor} visitor Function to run for each node - * @param {boolean} [reverse] Fisit the tree in reverse, defaults to false - */ - function (tree, test, visitor, reverse) { - if (typeof test === 'function' && typeof visitor !== 'function') { - reverse = visitor; - // @ts-ignore no visitor given, so `visitor` is test. - visitor = test; - test = null; - } +function resolveYamlSet(data) { + if (data === null) return true; - var is = convert(test); - var step = reverse ? -1 : 1; + var key, object = data; - factory(tree, null, [])(); + for (key in object) { + if (_hasOwnProperty$2.call(object, key)) { + if (object[key] !== null) return false; + } + } - /** - * @param {Node} node - * @param {number?} index - * @param {Array.} parents - */ - function factory(node, index, parents) { - /** @type {Object.} */ - var value = typeof node === 'object' && node !== null ? node : {}; - /** @type {string} */ - var name; + return true; +} - if (typeof value.type === 'string') { - name = - typeof value.tagName === 'string' - ? value.tagName - : typeof value.name === 'string' - ? value.name - : undefined; +function constructYamlSet(data) { + return data !== null ? data : {}; +} - Object.defineProperty(visit, 'name', { - value: - 'node (' + - color(value.type + (name ? '<' + name + '>' : '')) + - ')' - }); - } +var set = new type('tag:yaml.org,2002:set', { + kind: 'mapping', + resolve: resolveYamlSet, + construct: constructYamlSet +}); - return visit +var _default = core.extend({ + implicit: [ + timestamp, + merge + ], + explicit: [ + binary, + omap, + pairs, + set + ] +}); - function visit() { - /** @type {ActionTuple} */ - var result = []; - /** @type {ActionTuple} */ - var subresult; - /** @type {number} */ - var offset; - /** @type {Array.} */ - var grandparents; +/*eslint-disable max-len,no-use-before-define*/ - if (!test || is(node, index, parents[parents.length - 1] || null)) { - result = toResult(visitor(node, parents)); - if (result[0] === EXIT) { - return result - } - } - if (node.children && result[0] !== SKIP) { - // @ts-ignore looks like a parent. - offset = (reverse ? node.children.length : -1) + step; - // @ts-ignore looks like a parent. - grandparents = parents.concat(node); - // @ts-ignore looks like a parent. - while (offset > -1 && offset < node.children.length) { - subresult = factory(node.children[offset], offset, grandparents)(); - if (subresult[0] === EXIT) { - return subresult - } - offset = - typeof subresult[1] === 'number' ? subresult[1] : offset + step; - } - } - return result - } - } - } - ); +var _hasOwnProperty$1 = Object.prototype.hasOwnProperty; -/** - * @param {VisitorResult} value - * @returns {ActionTuple} - */ -function toResult(value) { - if (Array.isArray(value)) { - return value - } - if (typeof value === 'number') { - return [CONTINUE, value] - } +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; - return [value] -} -/** - * @typedef {import('unist').Node} Node - * @typedef {import('unist').Parent} Parent - * @typedef {import('unist-util-is').Test} Test - * @typedef {import('unist-util-visit-parents').VisitorResult} VisitorResult - */ +var CHOMPING_CLIP = 1; +var CHOMPING_STRIP = 2; +var CHOMPING_KEEP = 3; -const visit = - /** - * @type {( - * ((tree: Node, test: T['type']|Partial|import('unist-util-is').TestFunctionPredicate|Array.|import('unist-util-is').TestFunctionPredicate>, visitor: Visitor, reverse?: boolean) => void) & - * ((tree: Node, test: Test, visitor: Visitor, reverse?: boolean) => void) & - * ((tree: Node, visitor: Visitor, reverse?: boolean) => void) - * )} - */ - ( - /** - * Visit children of tree which pass a test - * - * @param {Node} tree Abstract syntax tree to walk - * @param {Test} test test Test node - * @param {Visitor} visitor Function to run for each node - * @param {boolean} [reverse] Fisit the tree in reverse, defaults to false - */ - function (tree, test, visitor, reverse) { - if (typeof test === 'function' && typeof visitor !== 'function') { - reverse = visitor; - visitor = test; - test = null; - } - visitParents(tree, test, overload, reverse); +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; - /** - * @param {Node} node - * @param {Array.} parents - */ - function overload(node, parents) { - var parent = parents[parents.length - 1]; - return visitor( - node, - parent ? parent.children.indexOf(node) : null, - parent - ) - } - } - ); -/** - * @typedef {import('unist').Node} Node - * @typedef {import('unist').Parent} Parent - * @typedef {import('unist').Point} Point - * @typedef {import('unist-util-is').Test} Test - * @typedef {import('vfile').VFile} VFile - * @typedef {import('vfile-message').VFileMessage} VFileMessage - * - * @typedef {OptionsWithoutReset|OptionsWithReset} Options - * @typedef {OptionsBaseFields & OptionsWithoutResetFields} OptionsWithoutReset - * @typedef {OptionsBaseFields & OptionsWithResetFields} OptionsWithReset - * - * @typedef OptionsWithoutResetFields - * @property {false} [reset] - * Whether to treat all messages as turned off initially. - * @property {string[]} [disable] - * List of `ruleId`s to turn off. - * - * @typedef OptionsWithResetFields - * @property {true} reset - * Whether to treat all messages as turned off initially. - * @property {string[]} [enable] - * List of `ruleId`s to initially turn on. - * - * @typedef OptionsBaseFields - * @property {string} name - * Name of markers that can control the message sources. - * - * For example, `{name: 'alpha'}` controls `alpha` markers: - * - * ```html - * - * ``` - * @property {MarkerParser} marker - * Parse a possible marker to a comment marker object (Marker). - * If the marker isn't a marker, should return `null`. - * @property {Test} [test] - * Test for possible markers - * @property {string[]} [known] - * List of allowed `ruleId`s. When given a warning is shown - * when someone tries to control an unknown rule. - * - * For example, `{name: 'alpha', known: ['bravo']}` results in a warning if - * `charlie` is configured: - * - * ```html - * - * ``` - * @property {string|string[]} [source] - * Sources that can be controlled with `name` markers. - * Defaults to `name`. - * - * @callback MarkerParser - * Parse a possible comment marker node to a Marker. - * @param {Node} node - * Node to parse - * - * @typedef Marker - * A comment marker. - * @property {string} name - * Name of marker. - * @property {string} attributes - * Value after name. - * @property {Record} parameters - * Parsed attributes. - * @property {Node} node - * Reference to given node. - * - * @typedef Mark - * @property {Point|undefined} point - * @property {boolean} state - */ +function _class(obj) { return Object.prototype.toString.call(obj); } -const own$2 = {}.hasOwnProperty; +function is_EOL(c) { + return (c === 0x0A/* LF */) || (c === 0x0D/* CR */); +} -/** - * @type {import('unified').Plugin<[Options]>} - * @returns {(tree: Node, file: VFile) => void} - */ -function messageControl(options) { - if (!options || typeof options !== 'object' || !options.name) { - throw new Error( - 'Expected `name` in `options`, got `' + (options || {}).name + '`' - ) - } +function is_WHITE_SPACE(c) { + return (c === 0x09/* Tab */) || (c === 0x20/* Space */); +} - if (!options.marker) { - throw new Error( - 'Expected `marker` in `options`, got `' + options.marker + '`' - ) - } +function is_WS_OR_EOL(c) { + return (c === 0x09/* Tab */) || + (c === 0x20/* Space */) || + (c === 0x0A/* LF */) || + (c === 0x0D/* CR */); +} - const enable = 'enable' in options && options.enable ? options.enable : []; - const disable = 'disable' in options && options.disable ? options.disable : []; - let reset = options.reset; - const sources = - typeof options.source === 'string' - ? [options.source] - : options.source || [options.name]; +function is_FLOW_INDICATOR(c) { + return c === 0x2C/* , */ || + c === 0x5B/* [ */ || + c === 0x5D/* ] */ || + c === 0x7B/* { */ || + c === 0x7D/* } */; +} - return transformer +function fromHexCode(c) { + var lc; - /** - * @param {Node} tree - * @param {VFile} file - */ - function transformer(tree, file) { - const toOffset = location(file).toOffset; - const initial = !reset; - const gaps = detectGaps(tree, file); - /** @type {Record} */ - const scope = {}; - /** @type {Mark[]} */ - const globals = []; + if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) { + return c - 0x30; + } - visit(tree, options.test, visitor); + /*eslint-disable no-bitwise*/ + lc = c | 0x20; - file.messages = file.messages.filter((m) => filter(m)); + if ((0x61/* a */ <= lc) && (lc <= 0x66/* f */)) { + return lc - 0x61 + 10; + } - /** - * @param {Node} node - * @param {number|null} position - * @param {Parent|null} parent - */ - function visitor(node, position, parent) { - /** @type {Marker|null} */ - const mark = options.marker(node); + return -1; +} - if (!mark || mark.name !== options.name) { - return - } +function escapedHexLen(c) { + if (c === 0x78/* x */) { return 2; } + if (c === 0x75/* u */) { return 4; } + if (c === 0x55/* U */) { return 8; } + return 0; +} - const ruleIds = mark.attributes.split(/\s/g); - const point = mark.node.position && mark.node.position.start; - const next = - (parent && position !== null && parent.children[position + 1]) || - undefined; - const tail = (next && next.position && next.position.end) || undefined; - let index = -1; +function fromDecimalCode(c) { + if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) { + return c - 0x30; + } - /** @type {string} */ - // @ts-expect-error: we’ll check for unknown values next. - const verb = ruleIds.shift(); + return -1; +} - if (verb !== 'enable' && verb !== 'disable' && verb !== 'ignore') { - file.fail( - 'Unknown keyword `' + - verb + - '`: expected ' + - "`'enable'`, `'disable'`, or `'ignore'`", - mark.node - ); - } +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' : ''; +} - // Apply to all rules. - if (ruleIds.length > 0) { - while (++index < ruleIds.length) { - const ruleId = ruleIds[index]; +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 = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} - if (isKnown(ruleId, verb, mark.node)) { - toggle(point, verb === 'enable', ruleId); - if (verb === 'ignore') { - toggle(tail, true, ruleId); - } - } - } - } else if (verb === 'ignore') { - toggle(point, false); - toggle(tail, true); - } else { - toggle(point, verb === 'enable'); - reset = verb !== 'enable'; - } - } +function State$1(input, options) { + this.input = input; - /** - * @param {VFileMessage} message - * @returns {boolean} - */ - function filter(message) { - let gapIndex = gaps.length; + this.filename = options['filename'] || null; + this.schema = options['schema'] || _default; + this.onWarning = options['onWarning'] || null; + // (Hidden) Remove? makes the loader to expect YAML 1.1 documents + // if such documents have no explicit %YAML directive + this.legacy = options['legacy'] || false; - // Keep messages from a different source. - if (!message.source || !sources.includes(message.source)) { - return true - } + this.json = options['json'] || false; + this.listener = options['listener'] || null; - // We only ignore messages if they‘re disabled, *not* when they’re not in - // the document. - if (!message.line) { - message.line = 1; - } + this.implicitTypes = this.schema.compiledImplicit; + this.typeMap = this.schema.compiledTypeMap; - if (!message.column) { - message.column = 1; - } + this.length = input.length; + this.position = 0; + this.line = 0; + this.lineStart = 0; + this.lineIndent = 0; - // Check whether the warning is inside a gap. - // @ts-expect-error: we just normalized `null` to `number`s. - const offset = toOffset(message); + // position of first leading tab in the current line, + // used to make sure there are no tabs in the indentation + this.firstTabInLine = -1; - while (gapIndex--) { - if (gaps[gapIndex][0] <= offset && gaps[gapIndex][1] > offset) { - return false - } - } + this.documents = []; - // Check whether allowed by specific and global states. - return ( - (!message.ruleId || - check(message, scope[message.ruleId], message.ruleId)) && - check(message, globals) - ) - } + /* + this.version; + this.checkLineBreaks; + this.tagMap; + this.anchorMap; + this.tag; + this.anchor; + this.kind; + this.result;*/ - /** - * Helper to check (and possibly warn) if a `ruleId` is unknown. - * - * @param {string} ruleId - * @param {string} verb - * @param {Node} node - * @returns {boolean} - */ - function isKnown(ruleId, verb, node) { - const result = options.known ? options.known.includes(ruleId) : true; +} - if (!result) { - file.message( - 'Unknown rule: cannot ' + verb + " `'" + ruleId + "'`", - node - ); - } - return result - } +function generateError(state, message) { + var mark = { + name: state.filename, + buffer: state.input.slice(0, -1), // omit trailing \0 + position: state.position, + line: state.line, + column: state.position - state.lineStart + }; - /** - * Get the latest state of a rule. - * When without `ruleId`, gets global state. - * - * @param {string|undefined} ruleId - * @returns {boolean} - */ - function getState(ruleId) { - const ranges = ruleId ? scope[ruleId] : globals; + mark.snippet = snippet(mark); - if (ranges && ranges.length > 0) { - return ranges[ranges.length - 1].state - } + return new exception(message, mark); +} - if (!ruleId) { - return !reset - } +function throwError(state, message) { + throw generateError(state, message); +} - return reset ? enable.includes(ruleId) : !disable.includes(ruleId) - } +function throwWarning(state, message) { + if (state.onWarning) { + state.onWarning.call(null, generateError(state, message)); + } +} - /** - * Handle a rule. - * - * @param {Point|undefined} point - * @param {boolean} state - * @param {string|undefined} [ruleId] - * @returns {void} - */ - function toggle(point, state, ruleId) { - let markers = ruleId ? scope[ruleId] : globals; - if (!markers) { - markers = []; - scope[String(ruleId)] = markers; - } +var directiveHandlers = { - const previousState = getState(ruleId); + YAML: function handleYamlDirective(state, name, args) { - if (state !== previousState) { - markers.push({state, point}); - } + var match, major, minor; - // Toggle all known rules. - if (!ruleId) { - for (ruleId in scope) { - if (own$2.call(scope, ruleId)) { - toggle(point, state, ruleId); - } - } - } + if (state.version !== null) { + throwError(state, 'duplication of %YAML directive'); } - /** - * Check all `ranges` for `message`. - * - * @param {VFileMessage} message - * @param {Mark[]|undefined} ranges - * @param {string|undefined} [ruleId] - * @returns {boolean} - */ - function check(message, ranges, ruleId) { - if (ranges && ranges.length > 0) { - // Check the state at the message’s position. - let index = ranges.length; + if (args.length !== 1) { + throwError(state, 'YAML directive accepts exactly one argument'); + } - while (index--) { - const range = ranges[index]; + match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); - if ( - message.line && - message.column && - range.point && - range.point.line && - range.point.column && - (range.point.line < message.line || - (range.point.line === message.line && - range.point.column <= message.column)) - ) { - return range.state === true - } - } - } + if (match === null) { + throwError(state, 'ill-formed argument of the YAML directive'); + } - // The first marker ocurred after the first message, so we check the - // initial state. - if (!ruleId) { - return Boolean(initial || reset) - } + major = parseInt(match[1], 10); + minor = parseInt(match[2], 10); - return reset ? enable.includes(ruleId) : !disable.includes(ruleId) + if (major !== 1) { + throwError(state, 'unacceptable YAML version of the document'); } - } -} -/** - * Detect gaps in `tree`. - * - * @param {Node} tree - * @param {VFile} file - */ -function detectGaps(tree, file) { - /** @type {Node[]} */ - // @ts-expect-error: fine. - const children = tree.children || []; - const lastNode = children[children.length - 1]; - /** @type {[number, number][]} */ - const gaps = []; - let offset = 0; - /** @type {boolean|undefined} */ - let gap; + state.version = args[0]; + state.checkLineBreaks = (minor < 2); - // Find all gaps. - visit(tree, one); + if (minor !== 1 && minor !== 2) { + throwWarning(state, 'unsupported YAML version of the document'); + } + }, - // Get the end of the document. - // This detects if the last node was the last node. - // If not, there’s an extra gap between the last node and the end of the - // document. - if ( - lastNode && - lastNode.position && - lastNode.position.end && - offset === lastNode.position.end.offset && - file.toString().slice(offset).trim() !== '' - ) { - update(); + TAG: function handleTagDirective(state, name, args) { - update( - tree && - tree.position && - tree.position.end && - tree.position.end.offset && - tree.position.end.offset - 1 - ); - } + var handle, prefix; - return gaps + if (args.length !== 2) { + throwError(state, 'TAG directive accepts exactly two arguments'); + } - /** - * @param {Node} node - */ - function one(node) { - update(node.position && node.position.start && node.position.start.offset); + handle = args[0]; + prefix = args[1]; - if (!('children' in node)) { - update(node.position && node.position.end && node.position.end.offset); + if (!PATTERN_TAG_HANDLE.test(handle)) { + throwError(state, 'ill-formed tag handle (first argument) of the TAG directive'); } - } - - /** - * Detect a new position. - * - * @param {number|undefined} [latest] - * @returns {void} - */ - function update(latest) { - if (latest === null || latest === undefined) { - gap = true; - } else if (offset < latest) { - if (gap) { - gaps.push([offset, latest]); - gap = undefined; - } - offset = latest; + if (_hasOwnProperty$1.call(state.tagMap, handle)) { + throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle'); } - } -} -/** - * @typedef {string|number|boolean} MarkerParameterValue - * @typedef {Object.} MarkerParameters - * - * @typedef HtmlNode - * @property {'html'} type - * @property {string} value - * - * @typedef CommentNode - * @property {'comment'} type - * @property {string} value - * - * @typedef Marker - * @property {string} name - * @property {string} attributes - * @property {MarkerParameters|null} parameters - * @property {HtmlNode|CommentNode} node - */ + if (!PATTERN_TAG_URI.test(prefix)) { + throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive'); + } -var commentExpression = /\s*([a-zA-Z\d-]+)(\s+([\s\S]*))?\s*/; + try { + prefix = decodeURIComponent(prefix); + } catch (err) { + throwError(state, 'tag prefix is malformed: ' + prefix); + } -var markerExpression = new RegExp( - '(\\s*\\s*)' -); + state.tagMap[handle] = prefix; + } +}; -/** - * Parse a comment marker. - * @param {unknown} node - * @returns {Marker|null} - */ -function commentMarker(node) { - /** @type {RegExpMatchArray} */ - var match; - /** @type {number} */ - var offset; - /** @type {MarkerParameters} */ - var parameters; - if ( - node && - typeof node === 'object' && - // @ts-ignore hush - (node.type === 'html' || node.type === 'comment') - ) { - // @ts-ignore hush - match = node.value.match( - // @ts-ignore hush - node.type === 'comment' ? commentExpression : markerExpression - ); +function captureSegment(state, start, end, checkJson) { + var _position, _length, _character, _result; - // @ts-ignore hush - if (match && match[0].length === node.value.length) { - // @ts-ignore hush - offset = node.type === 'comment' ? 1 : 2; - parameters = parseParameters(match[offset + 1] || ''); + if (start < end) { + _result = state.input.slice(start, end); - if (parameters) { - return { - name: match[offset], - attributes: match[offset + 2] || '', - parameters, - // @ts-ignore hush - node + 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'); } - } - return null + state.result += _result; + } } -/** - * Parse `value` into an object. - * - * @param {string} value - * @returns {MarkerParameters|null} - */ -function parseParameters(value) { - /** @type {MarkerParameters} */ - var parameters = {}; - - return value - .replace( - /\s+([-\w]+)(?:=(?:"((?:\\[\s\S]|[^"])+)"|'((?:\\[\s\S]|[^'])+)'|((?:\\[\s\S]|[^"'\s])+)))?/gi, - replacer - ) - .replace(/\s+/g, '') - ? null - : parameters - - /** - * @param {string} _ - * @param {string} $1 - * @param {string} $2 - * @param {string} $3 - * @param {string} $4 - */ - // eslint-disable-next-line max-params - function replacer(_, $1, $2, $3, $4) { - /** @type {MarkerParameterValue} */ - var value = $2 || $3 || $4 || ''; - - if (value === 'true' || value === '') { - value = true; - } else if (value === 'false') { - value = false; - } else if (!Number.isNaN(Number(value))) { - value = Number(value); - } - - parameters[$1] = value; +function mergeMappings(state, destination, source, overridableKeys) { + var sourceKeys, key, index, quantity; - return '' + if (!common.isObject(source)) { + throwError(state, 'cannot merge mappings; the provided source object is unacceptable'); } -} -/** - * @typedef {import('mdast').Root} Root - * @typedef {import('vfile').VFile} VFile - * @typedef {import('unified-message-control')} MessageControl - * @typedef {Omit|Omit} Options - */ + sourceKeys = Object.keys(source); -const test = [ - 'html', // Comments are `html` nodes in mdast. - 'comment' // In MDX, comments have their own node. -]; + for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) { + key = sourceKeys[index]; -/** - * Plugin to enable, disable, and ignore messages. - * - * @type {import('unified').Plugin<[Options], Root>} - * @returns {(node: Root, file: VFile) => void} - */ -function remarkMessageControl(options) { - return messageControl( - Object.assign({marker: commentMarker, test}, options) - ) + if (!_hasOwnProperty$1.call(destination, key)) { + destination[key] = source[key]; + overridableKeys[key] = true; + } + } } -/** - * @typedef {import('mdast').Root} Root - */ - -/** - * The core plugin for `remark-lint`. - * This adds support for ignoring stuff from messages (``). - * All rules are in their own packages and presets. - * - * @type {import('unified').Plugin} - */ -function remarkLint() { - this.use(lintMessageControl); -} +function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, + startLine, startLineStart, startPos) { -/** @type {import('unified').Plugin} */ -function lintMessageControl() { - return remarkMessageControl({name: 'lint', source: 'remark-lint'}) -} + var index, quantity; -/** - * @typedef {import('unist').Node} Node - * @typedef {import('vfile').VFile} VFile - * - * @typedef {0|1|2} Severity - * @typedef {'warn'|'on'|'off'|'error'} Label - * @typedef {[Severity, ...unknown[]]} SeverityTuple - * - * @typedef RuleMeta - * @property {string} origin name of the lint rule - * @property {string} [url] link to documentation - * - * @callback Rule - * @param {Node} tree - * @param {VFile} file - * @param {unknown} options - * @returns {void} - */ + // 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); -const primitives = new Set(['string', 'number', 'boolean']); + for (index = 0, quantity = keyNode.length; index < quantity; index += 1) { + if (Array.isArray(keyNode[index])) { + throwError(state, 'nested arrays are not supported inside keys'); + } -/** - * @param {string|RuleMeta} meta - * @param {Rule} rule - */ -function lintRule(meta, rule) { - const id = typeof meta === 'string' ? meta : meta.origin; - const url = typeof meta === 'string' ? undefined : meta.url; - const parts = id.split(':'); - // Possibly useful if externalised later. - /* c8 ignore next */ - const source = parts[1] ? parts[0] : undefined; - const ruleId = parts[1]; + if (typeof keyNode === 'object' && _class(keyNode[index]) === '[object Object]') { + keyNode[index] = '[object Object]'; + } + } + } - Object.defineProperty(plugin, 'name', {value: id}); + // 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(keyNode) === '[object Object]') { + keyNode = '[object Object]'; + } - return plugin - /** @type {import('unified').Plugin<[unknown]|void[]>} */ - function plugin(raw) { - const [severity, options] = coerce$1(ruleId, raw); + keyNode = String(keyNode); - if (!severity) return + if (_result === null) { + _result = {}; + } - const fatal = severity === 2; + 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$1.call(overridableKeys, keyNode) && + _hasOwnProperty$1.call(_result, keyNode)) { + state.line = startLine || state.line; + state.lineStart = startLineStart || state.lineStart; + state.position = startPos || state.position; + throwError(state, 'duplicated mapping key'); + } - return (tree, file, next) => { - let index = file.messages.length - 1; + // used for this specific key only because Object.defineProperty is slow + if (keyNode === '__proto__') { + Object.defineProperty(_result, keyNode, { + configurable: true, + enumerable: true, + writable: true, + value: valueNode + }); + } else { + _result[keyNode] = valueNode; + } + delete overridableKeys[keyNode]; + } - wrap(rule, (error) => { - const messages = file.messages; + return _result; +} - // Add the error, if not already properly added. - // Only happens for incorrect plugins. - /* c8 ignore next 6 */ - // @ts-expect-error: errors could be `messages`. - if (error && !messages.includes(error)) { - try { - file.fail(error); - } catch {} - } +function readLineBreak(state) { + var ch; - while (++index < messages.length) { - Object.assign(messages[index], {ruleId, source, fatal, url}); - } + ch = state.input.charCodeAt(state.position); - next(); - })(tree, file, options); + 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; + state.firstTabInLine = -1; } -/** - * Coerce a value to a severity--options tuple. - * - * @param {string} name - * @param {unknown} value - * @returns {SeverityTuple} - */ -function coerce$1(name, value) { - /** @type {unknown[]} */ - let result; +function skipSeparationSpace(state, allowComments, checkIndent) { + var lineBreaks = 0, + ch = state.input.charCodeAt(state.position); - if (typeof value === 'boolean') { - result = [value]; - } else if (value === null || value === undefined) { - result = [1]; - } else if ( - Array.isArray(value) && - // `isArray(unknown)` is turned into `any[]`: - // type-coverage:ignore-next-line - primitives.has(typeof value[0]) - ) { - // `isArray(unknown)` is turned into `any[]`: - // type-coverage:ignore-next-line - result = [...value]; - } else { - result = [1, value]; - } + while (ch !== 0) { + while (is_WHITE_SPACE(ch)) { + if (ch === 0x09/* Tab */ && state.firstTabInLine === -1) { + state.firstTabInLine = state.position; + } + ch = state.input.charCodeAt(++state.position); + } - let level = result[0]; + if (allowComments && ch === 0x23/* # */) { + do { + ch = state.input.charCodeAt(++state.position); + } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0); + } - if (typeof level === 'boolean') { - level = level ? 1 : 0; - } else if (typeof level === 'string') { - if (level === 'off') { - level = 0; - } else if (level === 'on' || level === 'warn') { - level = 1; - } else if (level === 'error') { - level = 2; + 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 { - level = 1; - result = [level, result]; + break; } } - if (typeof level !== 'number' || level < 0 || level > 2) { - throw new Error( - 'Incorrect severity `' + - level + - '` for `' + - name + - '`, ' + - 'expected 0, 1, or 2' - ) + if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) { + throwWarning(state, 'deficient indentation'); } - result[0] = level; - - // @ts-expect-error: it’s now a valid tuple. - return result + return lineBreaks; } -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module final-newline - * @fileoverview - * Warn when a line feed at the end of a file is missing. - * Empty files are allowed. - * - * See [StackExchange](https://unix.stackexchange.com/questions/18743) for why. - * - * ## Fix - * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) - * always adds a final line feed to files. - * - * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) - * on how to automatically fix warnings for this rule. - * - * ## Example - * - * ##### `ok.md` - * - * ###### In - * - * Note: `␊` represents LF. - * - * ```markdown - * Alpha␊ - * ``` - * - * ###### Out - * - * No messages. - * - * ##### `not-ok.md` - * - * ###### In - * - * Note: The below file does not have a final newline. - * - * ```markdown - * Bravo - * ``` - * - * ###### Out - * - * ```text - * 1:1: Missing newline character at end of file - * ``` - */ - -const remarkLintFinalNewline = lintRule( - { - origin: 'remark-lint:final-newline', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-newline#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (_, file) => { - const value = String(file); - const last = value.length - 1; +function testDocumentSeparator(state) { + var _position = state.position, + ch; - if (last > -1 && value.charAt(last) !== '\n') { - file.message('Missing newline character at end of file'); - } - } -); + ch = state.input.charCodeAt(_position); -var remarkLintFinalNewline$1 = remarkLintFinalNewline; + // 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)) { -var pluralize = {exports: {}}; + _position += 3; -/* global define */ + ch = state.input.charCodeAt(_position); -(function (module, exports) { -(function (root, pluralize) { - /* istanbul ignore else */ - if (typeof commonjsRequire === 'function' && 'object' === 'object' && 'object' === 'object') { - // Node. - module.exports = pluralize(); - } else { - // Browser global. - root.pluralize = pluralize(); + if (ch === 0 || is_WS_OR_EOL(ch)) { + return true; + } } -})(commonjsGlobal, function () { - // Rule storage - pluralize and singularize need to be run sequentially, - // while other rules can be optimized using an object for instant lookups. - var pluralRules = []; - var singularRules = []; - var uncountables = {}; - var irregularPlurals = {}; - var irregularSingles = {}; - /** - * Sanitize a pluralization rule to a usable regular expression. - * - * @param {(RegExp|string)} rule - * @return {RegExp} - */ - function sanitizeRule (rule) { - if (typeof rule === 'string') { - return new RegExp('^' + rule + '$', 'i'); - } + return false; +} - return rule; +function writeFoldedLines(state, count) { + if (count === 1) { + state.result += ' '; + } else if (count > 1) { + state.result += common.repeat('\n', count - 1); } +} - /** - * Pass in a word token to produce a function that can replicate the case on - * another word. - * - * @param {string} word - * @param {string} token - * @return {Function} - */ - function restoreCase (word, token) { - // Tokens are an exact match. - if (word === token) return token; - - // Lower cased words. E.g. "hello". - if (word === word.toLowerCase()) return token.toLowerCase(); - // Upper cased words. E.g. "WHISKY". - if (word === word.toUpperCase()) return token.toUpperCase(); +function readPlainScalar(state, nodeIndent, withinFlowCollection) { + var preceding, + following, + captureStart, + captureEnd, + hasPendingContent, + _line, + _lineStart, + _lineIndent, + _kind = state.kind, + _result = state.result, + ch; - // Title cased words. E.g. "Title". - if (word[0] === word[0].toUpperCase()) { - return token.charAt(0).toUpperCase() + token.substr(1).toLowerCase(); - } + ch = state.input.charCodeAt(state.position); - // Lower cased words. E.g. "test". - return token.toLowerCase(); + 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; } - /** - * Interpolate a regexp string. - * - * @param {string} str - * @param {Array} args - * @return {string} - */ - function interpolate (str, args) { - return str.replace(/\$(\d{1,2})/g, function (match, index) { - return args[index] || ''; - }); + 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; + } } - /** - * Replace a word using a rule. - * - * @param {string} word - * @param {Array} rule - * @return {string} - */ - function replace (word, rule) { - return word.replace(rule[0], function (match, index) { - var result = interpolate(rule[1], arguments); + state.kind = 'scalar'; + state.result = ''; + captureStart = captureEnd = state.position; + hasPendingContent = false; - if (match === '') { - return restoreCase(word[index - 1], result); + 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; } - return restoreCase(match, result); - }); - } + } else if (ch === 0x23/* # */) { + preceding = state.input.charCodeAt(state.position - 1); - /** - * Sanitize a word by passing in the word and sanitization rules. - * - * @param {string} token - * @param {string} word - * @param {Array} rules - * @return {string} - */ - function sanitizeWord (token, word, rules) { - // Empty string or doesn't need fixing. - if (!token.length || uncountables.hasOwnProperty(token)) { - return word; - } + if (is_WS_OR_EOL(preceding)) { + break; + } - var len = rules.length; + } else if ((state.position === state.lineStart && testDocumentSeparator(state)) || + withinFlowCollection && is_FLOW_INDICATOR(ch)) { + break; - // Iterate over the sanitization rules and use the first one to match. - while (len--) { - var rule = rules[len]; + } else if (is_EOL(ch)) { + _line = state.line; + _lineStart = state.lineStart; + _lineIndent = state.lineIndent; + skipSeparationSpace(state, false, -1); - if (rule[0].test(word)) return replace(word, rule); + 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; + } } - return word; - } + if (hasPendingContent) { + captureSegment(state, captureStart, captureEnd, false); + writeFoldedLines(state, state.line - _line); + captureStart = captureEnd = state.position; + hasPendingContent = false; + } - /** - * Replace a word with the updated word. - * - * @param {Object} replaceMap - * @param {Object} keepMap - * @param {Array} rules - * @return {Function} - */ - function replaceWord (replaceMap, keepMap, rules) { - return function (word) { - // Get the correct token and case restoration functions. - var token = word.toLowerCase(); + if (!is_WHITE_SPACE(ch)) { + captureEnd = state.position + 1; + } - // Check against the keep object map. - if (keepMap.hasOwnProperty(token)) { - return restoreCase(word, token); - } + ch = state.input.charCodeAt(++state.position); + } - // Check against the replacement map for a direct word replacement. - if (replaceMap.hasOwnProperty(token)) { - return restoreCase(word, replaceMap[token]); - } + captureSegment(state, captureStart, captureEnd, false); - // Run all the rules against the word. - return sanitizeWord(token, word, rules); - }; + if (state.result) { + return true; } - /** - * Check if a word is part of the map. - */ - function checkWord (replaceMap, keepMap, rules, bool) { - return function (word) { - var token = word.toLowerCase(); - - if (keepMap.hasOwnProperty(token)) return true; - if (replaceMap.hasOwnProperty(token)) return false; + state.kind = _kind; + state.result = _result; + return false; +} - return sanitizeWord(token, token, rules) === token; - }; - } +function readSingleQuotedScalar(state, nodeIndent) { + var ch, + captureStart, captureEnd; - /** - * Pluralize or singularize a word based on the passed in count. - * - * @param {string} word The word to pluralize - * @param {number} count How many of the word exist - * @param {boolean} inclusive Whether to prefix with the number (e.g. 3 ducks) - * @return {string} - */ - function pluralize (word, count, inclusive) { - var pluralized = count === 1 - ? pluralize.singular(word) : pluralize.plural(word); + ch = state.input.charCodeAt(state.position); - return (inclusive ? count + ' ' : '') + pluralized; + if (ch !== 0x27/* ' */) { + return false; } - /** - * Pluralize a word. - * - * @type {Function} - */ - pluralize.plural = replaceWord( - irregularSingles, irregularPlurals, pluralRules - ); - - /** - * Check if a word is plural. - * - * @type {Function} - */ - pluralize.isPlural = checkWord( - irregularSingles, irregularPlurals, pluralRules - ); + state.kind = 'scalar'; + state.result = ''; + state.position++; + captureStart = captureEnd = state.position; - /** - * Singularize a word. - * - * @type {Function} - */ - pluralize.singular = replaceWord( - irregularPlurals, irregularSingles, singularRules - ); + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + if (ch === 0x27/* ' */) { + captureSegment(state, captureStart, state.position, true); + ch = state.input.charCodeAt(++state.position); - /** - * Check if a word is singular. - * - * @type {Function} - */ - pluralize.isSingular = checkWord( - irregularPlurals, irregularSingles, singularRules - ); + if (ch === 0x27/* ' */) { + captureStart = state.position; + state.position++; + captureEnd = state.position; + } else { + return true; + } - /** - * Add a pluralization rule to the collection. - * - * @param {(string|RegExp)} rule - * @param {string} replacement - */ - pluralize.addPluralRule = function (rule, replacement) { - pluralRules.push([sanitizeRule(rule), replacement]); - }; + } else if (is_EOL(ch)) { + captureSegment(state, captureStart, captureEnd, true); + writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent)); + captureStart = captureEnd = state.position; - /** - * Add a singularization rule to the collection. - * - * @param {(string|RegExp)} rule - * @param {string} replacement - */ - pluralize.addSingularRule = function (rule, replacement) { - singularRules.push([sanitizeRule(rule), replacement]); - }; + } else if (state.position === state.lineStart && testDocumentSeparator(state)) { + throwError(state, 'unexpected end of the document within a single quoted scalar'); - /** - * Add an uncountable word rule. - * - * @param {(string|RegExp)} word - */ - pluralize.addUncountableRule = function (word) { - if (typeof word === 'string') { - uncountables[word.toLowerCase()] = true; - return; + } else { + state.position++; + captureEnd = state.position; } + } - // Set singular and plural references for the word. - pluralize.addPluralRule(word, '$0'); - pluralize.addSingularRule(word, '$0'); - }; - - /** - * Add an irregular word definition. - * - * @param {string} single - * @param {string} plural - */ - pluralize.addIrregularRule = function (single, plural) { - plural = plural.toLowerCase(); - single = single.toLowerCase(); + throwError(state, 'unexpected end of the stream within a single quoted scalar'); +} - irregularSingles[single] = plural; - irregularPlurals[plural] = single; - }; +function readDoubleQuotedScalar(state, nodeIndent) { + var captureStart, + captureEnd, + hexLength, + hexResult, + tmp, + ch; - /** - * Irregular rules. - */ - [ - // Pronouns. - ['I', 'we'], - ['me', 'us'], - ['he', 'they'], - ['she', 'they'], - ['them', 'them'], - ['myself', 'ourselves'], - ['yourself', 'yourselves'], - ['itself', 'themselves'], - ['herself', 'themselves'], - ['himself', 'themselves'], - ['themself', 'themselves'], - ['is', 'are'], - ['was', 'were'], - ['has', 'have'], - ['this', 'these'], - ['that', 'those'], - // Words ending in with a consonant and `o`. - ['echo', 'echoes'], - ['dingo', 'dingoes'], - ['volcano', 'volcanoes'], - ['tornado', 'tornadoes'], - ['torpedo', 'torpedoes'], - // Ends with `us`. - ['genus', 'genera'], - ['viscus', 'viscera'], - // Ends with `ma`. - ['stigma', 'stigmata'], - ['stoma', 'stomata'], - ['dogma', 'dogmata'], - ['lemma', 'lemmata'], - ['schema', 'schemata'], - ['anathema', 'anathemata'], - // Other irregular rules. - ['ox', 'oxen'], - ['axe', 'axes'], - ['die', 'dice'], - ['yes', 'yeses'], - ['foot', 'feet'], - ['eave', 'eaves'], - ['goose', 'geese'], - ['tooth', 'teeth'], - ['quiz', 'quizzes'], - ['human', 'humans'], - ['proof', 'proofs'], - ['carve', 'carves'], - ['valve', 'valves'], - ['looey', 'looies'], - ['thief', 'thieves'], - ['groove', 'grooves'], - ['pickaxe', 'pickaxes'], - ['passerby', 'passersby'] - ].forEach(function (rule) { - return pluralize.addIrregularRule(rule[0], rule[1]); - }); + ch = state.input.charCodeAt(state.position); - /** - * Pluralization rules. - */ - [ - [/s?$/i, 's'], - [/[^\u0000-\u007F]$/i, '$0'], - [/([^aeiou]ese)$/i, '$1'], - [/(ax|test)is$/i, '$1es'], - [/(alias|[^aou]us|t[lm]as|gas|ris)$/i, '$1es'], - [/(e[mn]u)s?$/i, '$1s'], - [/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i, '$1'], - [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1i'], - [/(alumn|alg|vertebr)(?:a|ae)$/i, '$1ae'], - [/(seraph|cherub)(?:im)?$/i, '$1im'], - [/(her|at|gr)o$/i, '$1oes'], - [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i, '$1a'], - [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i, '$1a'], - [/sis$/i, 'ses'], - [/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, '$1$2ves'], - [/([^aeiouy]|qu)y$/i, '$1ies'], - [/([^ch][ieo][ln])ey$/i, '$1ies'], - [/(x|ch|ss|sh|zz)$/i, '$1es'], - [/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, '$1ices'], - [/\b((?:tit)?m|l)(?:ice|ouse)$/i, '$1ice'], - [/(pe)(?:rson|ople)$/i, '$1ople'], - [/(child)(?:ren)?$/i, '$1ren'], - [/eaux$/i, '$0'], - [/m[ae]n$/i, 'men'], - ['thou', 'you'] - ].forEach(function (rule) { - return pluralize.addPluralRule(rule[0], rule[1]); - }); + if (ch !== 0x22/* " */) { + return false; + } - /** - * Singularization rules. - */ - [ - [/s$/i, ''], - [/(ss)$/i, '$1'], - [/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, '$1fe'], - [/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'], - [/ies$/i, 'y'], - [/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i, '$1ie'], - [/\b(mon|smil)ies$/i, '$1ey'], - [/\b((?:tit)?m|l)ice$/i, '$1ouse'], - [/(seraph|cherub)im$/i, '$1'], - [/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i, '$1'], - [/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i, '$1sis'], - [/(movie|twelve|abuse|e[mn]u)s$/i, '$1'], - [/(test)(?:is|es)$/i, '$1is'], - [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1us'], - [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i, '$1um'], - [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i, '$1on'], - [/(alumn|alg|vertebr)ae$/i, '$1a'], - [/(cod|mur|sil|vert|ind)ices$/i, '$1ex'], - [/(matr|append)ices$/i, '$1ix'], - [/(pe)(rson|ople)$/i, '$1rson'], - [/(child)ren$/i, '$1'], - [/(eau)x?$/i, '$1'], - [/men$/i, 'man'] - ].forEach(function (rule) { - return pluralize.addSingularRule(rule[0], rule[1]); - }); + state.kind = 'scalar'; + state.result = ''; + state.position++; + captureStart = captureEnd = state.position; - /** - * Uncountable rules. - */ - [ - // Singular words with no plurals. - 'adulthood', - 'advice', - 'agenda', - 'aid', - 'aircraft', - 'alcohol', - 'ammo', - 'analytics', - 'anime', - 'athletics', - 'audio', - 'bison', - 'blood', - 'bream', - 'buffalo', - 'butter', - 'carp', - 'cash', - 'chassis', - 'chess', - 'clothing', - 'cod', - 'commerce', - 'cooperation', - 'corps', - 'debris', - 'diabetes', - 'digestion', - 'elk', - 'energy', - 'equipment', - 'excretion', - 'expertise', - 'firmware', - 'flounder', - 'fun', - 'gallows', - 'garbage', - 'graffiti', - 'hardware', - 'headquarters', - 'health', - 'herpes', - 'highjinks', - 'homework', - 'housework', - 'information', - 'jeans', - 'justice', - 'kudos', - 'labour', - 'literature', - 'machinery', - 'mackerel', - 'mail', - 'media', - 'mews', - 'moose', - 'music', - 'mud', - 'manga', - 'news', - 'only', - 'personnel', - 'pike', - 'plankton', - 'pliers', - 'police', - 'pollution', - 'premises', - 'rain', - 'research', - 'rice', - 'salmon', - 'scissors', - 'series', - 'sewage', - 'shambles', - 'shrimp', - 'software', - 'species', - 'staff', - 'swine', - 'tennis', - 'traffic', - 'transportation', - 'trout', - 'tuna', - 'wealth', - 'welfare', - 'whiting', - 'wildebeest', - 'wildlife', - 'you', - /pok[eé]mon$/i, - // Regexes. - /[^aeiou]ese$/i, // "chinese", "japanese" - /deer$/i, // "deer", "reindeer" - /fish$/i, // "fish", "blowfish", "angelfish" - /measles$/i, - /o[iu]s$/i, // "carnivorous" - /pox$/i, // "chickpox", "smallpox" - /sheep$/i - ].forEach(pluralize.addUncountableRule); + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + if (ch === 0x22/* " */) { + captureSegment(state, captureStart, state.position, true); + state.position++; + return true; - return pluralize; -}); -}(pluralize)); + } else if (ch === 0x5C/* \ */) { + captureSegment(state, captureStart, state.position, true); + ch = state.input.charCodeAt(++state.position); -var plural = pluralize.exports; + if (is_EOL(ch)) { + skipSeparationSpace(state, false, nodeIndent); -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module list-item-bullet-indent - * @fileoverview - * Warn when list item bullets are indented. - * - * ## Fix - * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) - * removes all indentation before bullets. - * - * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) - * on how to automatically fix warnings for this rule. - * - * @example - * {"name": "ok.md"} - * - * Paragraph. - * - * * List item - * * List item - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * Paragraph. - * - * ·* List item - * ·* List item - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 3:2: Incorrect indentation before bullet: remove 1 space - * 4:2: Incorrect indentation before bullet: remove 1 space - */ + // TODO: rework to inline fn with no type cast? + } else if (ch < 256 && simpleEscapeCheck[ch]) { + state.result += simpleEscapeMap[ch]; + state.position++; -const remarkLintListItemBulletIndent = lintRule( - { - origin: 'remark-lint:list-item-bullet-indent', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-bullet-indent#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - visit$1(tree, 'list', (list, _, grandparent) => { - let index = -1; + } else if ((tmp = escapedHexLen(ch)) > 0) { + hexLength = tmp; + hexResult = 0; - while (++index < list.children.length) { - const item = list.children[index]; + for (; hexLength > 0; hexLength--) { + ch = state.input.charCodeAt(++state.position); - if ( - grandparent && - grandparent.type === 'root' && - grandparent.position && - typeof grandparent.position.start.column === 'number' && - item.position && - typeof item.position.start.column === 'number' - ) { - const indent = - item.position.start.column - grandparent.position.start.column; + if ((tmp = fromHexCode(ch)) >= 0) { + hexResult = (hexResult << 4) + tmp; - if (indent) { - file.message( - 'Incorrect indentation before bullet: remove ' + - indent + - ' ' + - plural('space', indent), - item.position.start - ); + } 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; + } } -); -var remarkLintListItemBulletIndent$1 = remarkLintListItemBulletIndent; + throwError(state, 'unexpected end of the stream within a double quoted scalar'); +} -/** - * @typedef {import('unist').Position} Position - * @typedef {import('unist').Point} Point - * - * @typedef {Partial} PointLike - * - * @typedef {Object} PositionLike - * @property {PointLike} [start] - * @property {PointLike} [end] - * - * @typedef {Object} NodeLike - * @property {PositionLike} [position] - */ +function readFlowCollection(state, nodeIndent) { + var readNext = true, + _line, + _lineStart, + _pos, + _tag = state.tag, + _result, + _anchor = state.anchor, + following, + terminator, + isPair, + isExplicitPair, + isMapping, + overridableKeys = Object.create(null), + keyNode, + keyTag, + valueNode, + ch; -var pointStart = point('start'); -var pointEnd = point('end'); + ch = state.input.charCodeAt(state.position); -/** - * Get the positional info of `node`. - * - * @param {'start'|'end'} type - */ -function point(type) { - return point + if (ch === 0x5B/* [ */) { + terminator = 0x5D;/* ] */ + isMapping = false; + _result = []; + } else if (ch === 0x7B/* { */) { + terminator = 0x7D;/* } */ + isMapping = true; + _result = {}; + } else { + return false; + } - /** - * Get the positional info of `node`. - * - * @param {NodeLike} [node] - * @returns {Point} - */ - function point(node) { - /** @type {Point} */ - // @ts-ignore looks like a point - var point = (node && node.position && node.position[type]) || {}; + if (state.anchor !== null) { + state.anchorMap[state.anchor] = _result; + } - return { - line: point.line || null, - column: point.column || null, - offset: point.offset > -1 ? point.offset : null + 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'); + } else if (ch === 0x2C/* , */) { + // "flow collection entries can never be completely empty", as per YAML 1.2, section 7.4 + throwError(state, "expected the node content, but found ','"); } - } -} -/** - * @typedef {Object} PointLike - * @property {number} [line] - * @property {number} [column] - * @property {number} [offset] - * - * @typedef {Object} PositionLike - * @property {PointLike} [start] - * @property {PointLike} [end] - * - * @typedef {Object} NodeLike - * @property {PositionLike} [position] - */ + keyTag = keyNode = valueNode = null; + isPair = isExplicitPair = false; -/** - * Check if `node` is *generated*. - * - * @param {NodeLike} [node] - * @returns {boolean} - */ -function generated(node) { - return ( - !node || - !node.position || - !node.position.start || - !node.position.start.line || - !node.position.start.column || - !node.position.end || - !node.position.end.line || - !node.position.end.column - ) -} + if (ch === 0x3F/* ? */) { + following = state.input.charCodeAt(state.position + 1); -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module list-item-indent - * @fileoverview - * Warn when the spacing between a list item’s bullet and its content violates - * a given style. - * - * Options: `'tab-size'`, `'mixed'`, or `'space'`, default: `'tab-size'`. - * - * ## Fix - * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) - * uses `'tab-size'` (named `'tab'` there) by default to ensure Markdown is - * seen the same way across vendors. - * This can be configured with the - * [`listItemIndent`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify#optionslistitemindent) - * option. - * This rule’s `'space'` option is named `'1'` there. - * - * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) - * on how to automatically fix warnings for this rule. - * - * @example - * {"name": "ok.md"} - * - * *···List - * ····item. - * - * Paragraph. - * - * 11.·List - * ····item. - * - * Paragraph. - * - * *···List - * ····item. - * - * *···List - * ····item. - * - * @example - * {"name": "ok.md", "setting": "mixed"} - * - * *·List item. - * - * Paragraph. - * - * 11.·List item - * - * Paragraph. - * - * *···List - * ····item. - * - * *···List - * ····item. - * - * @example - * {"name": "ok.md", "setting": "space"} - * - * *·List item. - * - * Paragraph. - * - * 11.·List item - * - * Paragraph. - * - * *·List - * ··item. - * - * *·List - * ··item. - * - * @example - * {"name": "not-ok.md", "setting": "space", "label": "input"} - * - * *···List - * ····item. - * - * @example - * {"name": "not-ok.md", "setting": "space", "label": "output"} - * - * 1:5: Incorrect list-item indent: remove 2 spaces - * - * @example - * {"name": "not-ok.md", "setting": "tab-size", "label": "input"} - * - * *·List - * ··item. - * - * @example - * {"name": "not-ok.md", "setting": "tab-size", "label": "output"} - * - * 1:3: Incorrect list-item indent: add 2 spaces - * - * @example - * {"name": "not-ok.md", "setting": "mixed", "label": "input"} - * - * *···List item. - * - * @example - * {"name": "not-ok.md", "setting": "mixed", "label": "output"} - * - * 1:5: Incorrect list-item indent: remove 2 spaces - * - * @example - * {"name": "not-ok.md", "setting": "💩", "label": "output", "positionless": true} - * - * 1:1: Incorrect list-item indent style `💩`: use either `'tab-size'`, `'space'`, or `'mixed'` - */ + if (is_WS_OR_EOL(following)) { + isPair = isExplicitPair = true; + state.position++; + skipSeparationSpace(state, true, nodeIndent); + } + } -const remarkLintListItemIndent = lintRule( - { - origin: 'remark-lint:list-item-indent', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-indent#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file, option = 'tab-size') => { - const value = String(file); + _line = state.line; // Save the current line. + _lineStart = state.lineStart; + _pos = state.position; + composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + keyTag = state.tag; + keyNode = state.result; + skipSeparationSpace(state, true, nodeIndent); - if (option !== 'tab-size' && option !== 'space' && option !== 'mixed') { - file.fail( - 'Incorrect list-item indent style `' + - option + - "`: use either `'tab-size'`, `'space'`, or `'mixed'`" - ); + 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; } - visit$1(tree, 'list', (node) => { - if (generated(node)) return + if (isMapping) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos); + } else if (isPair) { + _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos)); + } else { + _result.push(keyNode); + } - const spread = node.spread; - let index = -1; + skipSeparationSpace(state, true, nodeIndent); - while (++index < node.children.length) { - const item = node.children[index]; - const head = item.children[0]; - const final = pointStart(head); + ch = state.input.charCodeAt(state.position); - const marker = value - .slice(pointStart(item).offset, final.offset) - .replace(/\[[x ]?]\s*$/i, ''); + if (ch === 0x2C/* , */) { + readNext = true; + ch = state.input.charCodeAt(++state.position); + } else { + readNext = false; + } + } - const bulletSize = marker.replace(/\s+$/, '').length; + throwError(state, 'unexpected end of the stream within a flow collection'); +} - const style = - option === 'tab-size' || (option === 'mixed' && spread) - ? Math.ceil(bulletSize / 4) * 4 - : bulletSize + 1; +function readBlockScalar(state, nodeIndent) { + var captureStart, + folding, + chomping = CHOMPING_CLIP, + didReadContent = false, + detectedIndent = false, + textIndent = nodeIndent, + emptyLines = 0, + atMoreIndented = false, + tmp, + ch; - if (marker.length !== style) { - const diff = style - marker.length; - const abs = Math.abs(diff); + ch = state.input.charCodeAt(state.position); - file.message( - 'Incorrect list-item indent: ' + - (diff > 0 ? 'add' : 'remove') + - ' ' + - abs + - ' ' + - plural('space', abs), - final - ); - } - } - }); + if (ch === 0x7C/* | */) { + folding = false; + } else if (ch === 0x3E/* > */) { + folding = true; + } else { + return false; } -); -var remarkLintListItemIndent$1 = remarkLintListItemIndent; + state.kind = 'scalar'; + state.result = ''; -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module no-auto-link-without-protocol - * @fileoverview - * Warn for autolinks without protocol. - * Autolinks are URLs enclosed in `<` (less than) and `>` (greater than) - * characters. - * - * ## Fix - * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) - * adds a protocol where needed. - * - * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) - * on how to automatically fix warnings for this rule. - * - * @example - * {"name": "ok.md"} - * - * - * - * - * Most Markdown vendors don’t recognize the following as a link: - * - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 1:1-1:14: All automatic links must start with a protocol - */ + while (ch !== 0) { + ch = state.input.charCodeAt(++state.position); -// Protocol expression. -// See: . -const protocol = /^[a-z][a-z+.-]+:\/?/i; + 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'); + } -const remarkLintNoAutoLinkWithoutProtocol = lintRule( - { - origin: 'remark-lint:no-auto-link-without-protocol', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-auto-link-without-protocol#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - visit$1(tree, 'link', (node) => { - if ( - !generated(node) && - pointStart(node).column === pointStart(node.children[0]).column - 1 && - pointEnd(node).column === - pointEnd(node.children[node.children.length - 1]).column + 1 && - !protocol.test(toString(node)) - ) { - file.message('All automatic links must start with a protocol', node); + } 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; + } } -); -var remarkLintNoAutoLinkWithoutProtocol$1 = remarkLintNoAutoLinkWithoutProtocol; + if (is_WHITE_SPACE(ch)) { + do { ch = state.input.charCodeAt(++state.position); } + while (is_WHITE_SPACE(ch)); -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module no-blockquote-without-marker - * @fileoverview - * Warn when blank lines without `>` (greater than) markers are found in a - * block quote. - * - * ## Fix - * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) - * adds markers to every line in a block quote. - * - * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) - * on how to automatically fix warnings for this rule. - * - * @example - * {"name": "ok.md"} - * - * > Foo… - * > …bar… - * > …baz. - * - * @example - * {"name": "ok-tabs.md"} - * - * >»Foo… - * >»…bar… - * >»…baz. - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * > Foo… - * …bar… - * > …baz. - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 2:1: Missing marker in block quote - * - * @example - * {"name": "not-ok-tabs.md", "label": "input"} - * - * >»Foo… - * »…bar… - * …baz. - * - * @example - * {"name": "not-ok-tabs.md", "label": "output"} - * - * 2:1: Missing marker in block quote - * 3:1: Missing marker in block quote - */ + if (ch === 0x23/* # */) { + do { ch = state.input.charCodeAt(++state.position); } + while (!is_EOL(ch) && (ch !== 0)); + } + } -const remarkLintNoBlockquoteWithoutMarker = lintRule( - { - origin: 'remark-lint:no-blockquote-without-marker', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-blockquote-without-marker#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - const value = String(file); - const loc = location(file); + while (ch !== 0) { + readLineBreak(state); + state.lineIndent = 0; - visit$1(tree, 'blockquote', (node) => { - let index = -1; + ch = state.input.charCodeAt(state.position); - while (++index < node.children.length) { - const child = node.children[index]; + while ((!detectedIndent || state.lineIndent < textIndent) && + (ch === 0x20/* Space */)) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } - if (child.type === 'paragraph' && !generated(child)) { - const end = pointEnd(child).line; - const column = pointStart(child).column; - let line = pointStart(child).line; + if (!detectedIndent && state.lineIndent > textIndent) { + textIndent = state.lineIndent; + } - // Skip past the first line. - while (++line <= end) { - const offset = loc.toOffset({line, column}); + if (is_EOL(ch)) { + emptyLines++; + continue; + } - if (/>[\t ]+$/.test(value.slice(offset - 5, offset))) { - continue - } + // End of the scalar. + if (state.lineIndent < textIndent) { - // Roughly here. - file.message('Missing marker in block quote', { - line, - column: column - 2 - }); - } + // Perform the chomping. + if (chomping === CHOMPING_KEEP) { + state.result += common.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'; } } - }); - } -); -var remarkLintNoBlockquoteWithoutMarker$1 = remarkLintNoBlockquoteWithoutMarker; + // Break this `while` cycle and go to the funciton's epilogue. + break; + } -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module no-literal-urls - * @fileoverview - * Warn for literal URLs in text. - * URLs are treated as links in some Markdown vendors, but not in others. - * To make sure they are always linked, wrap them in `<` (less than) and `>` - * (greater than). - * - * ## Fix - * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) - * never creates literal URLs and always uses `<` (less than) and `>` - * (greater than). - * - * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) - * on how to automatically fix warnings for this rule. - * - * @example - * {"name": "ok.md"} - * - * - * - * @example - * {"name": "not-ok.md", "label": "input", "gfm": true} - * - * http://foo.bar/baz - * - * @example - * {"name": "not-ok.md", "label": "output", "gfm": true} - * - * 1:1-1:19: Don’t use literal URLs without angle brackets - */ + // Folded style: use fancy rules to handle line breaks. + if (folding) { -const remarkLintNoLiteralUrls = lintRule( - { - origin: 'remark-lint:no-literal-urls', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-literal-urls#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - visit$1(tree, 'link', (node) => { - const value = toString(node); + // 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.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines); + + // End of more-indented block. + } else if (atMoreIndented) { + atMoreIndented = false; + state.result += common.repeat('\n', emptyLines + 1); - if ( - !generated(node) && - pointStart(node).column === pointStart(node.children[0]).column && - pointEnd(node).column === - pointEnd(node.children[node.children.length - 1]).column && - (node.url === 'mailto:' + value || node.url === value) - ) { - file.message('Don’t use literal URLs without angle brackets', node); + // 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.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.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); } -); -var remarkLintNoLiteralUrls$1 = remarkLintNoLiteralUrls; + return true; +} -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module ordered-list-marker-style - * @fileoverview - * Warn when the list item marker style of ordered lists violate a given style. - * - * Options: `'consistent'`, `'.'`, or `')'`, default: `'consistent'`. - * - * `'consistent'` detects the first used list style and warns when subsequent - * lists use different styles. - * - * @example - * {"name": "ok.md"} - * - * 1. Foo - * - * - * 1. Bar - * - * Unordered lists are not affected by this rule. - * - * * Foo - * - * @example - * {"name": "ok.md", "setting": "."} - * - * 1. Foo - * - * 2. Bar - * - * @example - * {"name": "ok.md", "setting": ")"} - * - * 1) Foo - * - * 2) Bar - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * 1. Foo - * - * 2) Bar - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 3:1-3:8: Marker style should be `.` - * - * @example - * {"name": "not-ok.md", "label": "output", "setting": "💩", "positionless": true} - * - * 1:1: Incorrect ordered list item marker style `💩`: use either `'.'` or `')'` - */ +function readBlockSequence(state, nodeIndent) { + var _line, + _tag = state.tag, + _anchor = state.anchor, + _result = [], + following, + detected = false, + ch; -const remarkLintOrderedListMarkerStyle = lintRule( - { - origin: 'remark-lint:ordered-list-marker-style', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-ordered-list-marker-style#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file, option = 'consistent') => { - const value = String(file); + // there is a leading tab before this token, so it can't be a block sequence/mapping; + // it can still be flow sequence/mapping or a scalar + if (state.firstTabInLine !== -1) return false; - if (option !== 'consistent' && option !== '.' && option !== ')') { - file.fail( - 'Incorrect ordered list item marker style `' + - option + - "`: use either `'.'` or `')'`" - ); + if (state.anchor !== null) { + state.anchorMap[state.anchor] = _result; + } + + ch = state.input.charCodeAt(state.position); + + while (ch !== 0) { + if (state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, 'tab characters must not be used in indentation'); } - visit$1(tree, 'list', (node) => { - let index = -1; + if (ch !== 0x2D/* - */) { + break; + } - if (!node.ordered) return + following = state.input.charCodeAt(state.position + 1); - while (++index < node.children.length) { - const child = node.children[index]; + if (!is_WS_OR_EOL(following)) { + break; + } - if (!generated(child)) { - const marker = /** @type {Marker} */ ( - value - .slice( - pointStart(child).offset, - pointStart(child.children[0]).offset - ) - .replace(/\s|\d/g, '') - .replace(/\[[x ]?]\s*$/i, '') - ); + detected = true; + state.position++; - if (option === 'consistent') { - option = marker; - } else if (marker !== option) { - file.message('Marker style should be `' + option + '`', child); - } - } + 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; + } } -); -var remarkLintOrderedListMarkerStyle$1 = remarkLintOrderedListMarkerStyle; + if (detected) { + state.tag = _tag; + state.anchor = _anchor; + state.kind = 'sequence'; + state.result = _result; + return true; + } + return false; +} -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module hard-break-spaces - * @fileoverview - * Warn when too many spaces are used to create a hard break. - * - * @example - * {"name": "ok.md"} - * - * Lorem ipsum·· - * dolor sit amet - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * Lorem ipsum··· - * dolor sit amet. - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 1:12-2:1: Use two spaces for hard line breaks - */ +function readBlockMapping(state, nodeIndent, flowIndent) { + var following, + allowCompact, + _line, + _keyLine, + _keyLineStart, + _keyPos, + _tag = state.tag, + _anchor = state.anchor, + _result = {}, + overridableKeys = Object.create(null), + keyTag = null, + keyNode = null, + valueNode = null, + atExplicitKey = false, + detected = false, + ch; -const remarkLintHardBreakSpaces = lintRule( - { - origin: 'remark-lint:hard-break-spaces', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-hard-break-spaces#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - const value = String(file); + // there is a leading tab before this token, so it can't be a block sequence/mapping; + // it can still be flow sequence/mapping or a scalar + if (state.firstTabInLine !== -1) return false; - visit$1(tree, 'break', (node) => { - if (!generated(node)) { - const slice = value - .slice(pointStart(node).offset, pointEnd(node).offset) - .split('\n', 1)[0] - .replace(/\r$/, ''); + if (state.anchor !== null) { + state.anchorMap[state.anchor] = _result; + } - if (slice.length > 2) { - file.message('Use two spaces for hard line breaks', node); + ch = state.input.charCodeAt(state.position); + + while (ch !== 0) { + if (!atExplicitKey && state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, 'tab characters must not be used in indentation'); + } + + following = state.input.charCodeAt(state.position + 1); + _line = state.line; // Save the current line. + + // + // 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, _keyLine, _keyLineStart, _keyPos); + 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'); } - }); - } -); -var remarkLintHardBreakSpaces$1 = remarkLintHardBreakSpaces; + state.position += 1; + ch = following; -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module no-duplicate-definitions - * @fileoverview - * Warn when duplicate definitions are found. - * - * @example - * {"name": "ok.md"} - * - * [foo]: bar - * [baz]: qux - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * [foo]: bar - * [foo]: qux - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 2:1-2:11: Do not use definitions with the same identifier (1:1) - */ + // + // Implicit notation case. Flow-style node as the key first, then ":", and the value. + // + } else { + _keyLine = state.line; + _keyLineStart = state.lineStart; + _keyPos = state.position; -const remarkLintNoDuplicateDefinitions = lintRule( - { - origin: 'remark-lint:no-duplicate-definitions', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-duplicate-definitions#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - /** @type {Record} */ - const map = Object.create(null); + if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) { + // Neither implicit nor explicit notation. + // Reading is done. Go to the epilogue. + break; + } - visit$1(tree, (node) => { - if ( - (node.type === 'definition' || node.type === 'footnoteDefinition') && - !generated(node) - ) { - const identifier = node.identifier; - const duplicate = map[identifier]; + if (state.line === _line) { + ch = state.input.charCodeAt(state.position); - if (duplicate) { - file.message( - 'Do not use definitions with the same identifier (' + - duplicate + - ')', - node - ); + while (is_WHITE_SPACE(ch)) { + ch = state.input.charCodeAt(++state.position); } - map[identifier] = stringifyPosition$1(pointStart(node)); - } - }); - } -); + if (ch === 0x3A/* : */) { + ch = state.input.charCodeAt(++state.position); -var remarkLintNoDuplicateDefinitions$1 = remarkLintNoDuplicateDefinitions; + if (!is_WS_OR_EOL(ch)) { + throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping'); + } -/** - * @typedef {import('mdast').Heading} Heading - * @typedef {'atx'|'atx-closed'|'setext'} Style - */ + if (atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos); + keyTag = keyNode = valueNode = null; + } -/** - * @param {Heading} node - * @param {Style} [relative] - * @returns {Style|null} - */ -function headingStyle(node, relative) { - var last = node.children[node.children.length - 1]; - var depth = node.depth; - var pos = node && node.position && node.position.end; - var final = last && last.position && last.position.end; + detected = true; + atExplicitKey = false; + allowCompact = false; + keyTag = state.tag; + keyNode = state.result; - if (!pos) { - return null - } + } else if (detected) { + throwError(state, 'can not read an implicit mapping pair; a colon is missed'); - // This can only occur for `'atx'` and `'atx-closed'` headings. - // This might incorrectly match `'atx'` headings with lots of trailing white - // space as an `'atx-closed'` heading. - if (!last) { - if (pos.column - 1 <= depth * 2) { - return consolidate(depth, relative) + } 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`. + } } - return 'atx-closed' - } + // + // Common reading code for both explicit and implicit notations. + // + if (state.line === _line || state.lineIndent > nodeIndent) { + if (atExplicitKey) { + _keyLine = state.line; + _keyLineStart = state.lineStart; + _keyPos = state.position; + } - if (final.line + 1 === pos.line) { - return 'setext' - } + if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) { + if (atExplicitKey) { + keyNode = state.result; + } else { + valueNode = state.result; + } + } - if (final.column + depth < pos.column) { - return 'atx-closed' - } + if (!atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos); + keyTag = keyNode = valueNode = null; + } - return consolidate(depth, relative) -} + skipSeparationSpace(state, true, -1); + ch = state.input.charCodeAt(state.position); + } -/** - * Get the probable style of an atx-heading, depending on preferred style. - * - * @param {number} depth - * @param {Style} relative - * @returns {Style|null} - */ -function consolidate(depth, relative) { - return depth < 3 - ? 'atx' - : relative === 'atx' || relative === 'setext' - ? relative - : null -} + if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) { + throwError(state, 'bad indentation of a mapping entry'); + } else if (state.lineIndent < nodeIndent) { + break; + } + } -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module no-heading-content-indent - * @fileoverview - * Warn when content of headings is indented. - * - * ## Fix - * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) - * removes all unneeded padding around content in headings. - * - * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) - * on how to automatically fix warnings for this rule. - * - * @example - * {"name": "ok.md"} - * - * #·Foo - * - * ## Bar·## - * - * ##·Baz - * - * Setext headings are not affected. - * - * Baz - * === - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * #··Foo - * - * ## Bar··## - * - * ##··Baz - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 1:4: Remove 1 space before this heading’s content - * 3:7: Remove 1 space after this heading’s content - * 5:7: Remove 1 space before this heading’s content - * - * @example - * {"name": "empty-heading.md"} - * - * #·· - */ + // + // Epilogue. + // -const remarkLintNoHeadingContentIndent = lintRule( - { - origin: 'remark-lint:no-heading-content-indent', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-heading-content-indent#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - visit$1(tree, 'heading', (node) => { - if (generated(node)) { - return - } + // Special case: last mapping's node contains only the key in explicit notation. + if (atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos); + } - const type = headingStyle(node, 'atx'); + // Expose the resulting mapping. + if (detected) { + state.tag = _tag; + state.anchor = _anchor; + state.kind = 'mapping'; + state.result = _result; + } - if (type === 'atx' || type === 'atx-closed') { - const head = pointStart(node.children[0]).column; + return detected; +} - // Ignore empty headings. - if (!head) { - return - } +function readTagProperty(state) { + var _position, + isVerbatim = false, + isNamed = false, + tagHandle, + tagName, + ch; - const diff = head - pointStart(node).column - 1 - node.depth; + ch = state.input.charCodeAt(state.position); - if (diff) { - file.message( - 'Remove ' + - Math.abs(diff) + - ' ' + - plural('space', Math.abs(diff)) + - ' before this heading’s content', - pointStart(node.children[0]) - ); - } - } + if (ch !== 0x21/* ! */) return false; - // Closed ATX headings always must have a space between their content and - // the final hashes, thus, there is no `add x spaces`. - if (type === 'atx-closed') { - const final = pointEnd(node.children[node.children.length - 1]); - const diff = pointEnd(node).column - final.column - 1 - node.depth; + if (state.tag !== null) { + throwError(state, 'duplication of a tag property'); + } - if (diff) { - file.message( - 'Remove ' + - diff + - ' ' + - plural('space', diff) + - ' after this heading’s content', - final - ); - } - } - }); + 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 = '!'; } -); -var remarkLintNoHeadingContentIndent$1 = remarkLintNoHeadingContentIndent; + _position = state.position; -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module no-inline-padding - * @fileoverview - * Warn when phrasing content is padded with spaces between their markers and - * content. - * - * Warns for emphasis, strong, delete, image, and link. - * - * @example - * {"name": "ok.md"} - * - * Alpha [bravo](http://echo.fox/trot) - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * Alpha [ bravo ](http://echo.fox/trot) - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 1:7-1:38: Don’t pad `link` with inner spaces - */ + if (isVerbatim) { + do { ch = state.input.charCodeAt(++state.position); } + while (ch !== 0 && ch !== 0x3E/* > */); -const remarkLintNoInlinePadding = lintRule( - { - origin: 'remark-lint:no-inline-padding', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-inline-padding#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - // Note: `emphasis`, `strong`, `delete` (GFM) can’t have padding anymore - // since CM. - visit$1(tree, (node) => { - if ( - (node.type === 'link' || node.type === 'linkReference') && - !generated(node) - ) { - const value = toString(node); + 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 (value.charAt(0) === ' ' || value.charAt(value.length - 1) === ' ') { - file.message('Don’t pad `' + node.type + '` with inner spaces', node); + 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'); } } - }); - } -); -var remarkLintNoInlinePadding$1 = remarkLintNoInlinePadding; + ch = state.input.charCodeAt(++state.position); + } -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module no-shortcut-reference-image - * @fileoverview - * Warn when shortcut reference images are used. - * - * Shortcut references render as images when a definition is found, and as - * plain text without definition. - * Sometimes, you don’t intend to create an image from the reference, but this - * rule still warns anyway. - * In that case, you can escape the reference like so: `!\[foo]`. - * - * @example - * {"name": "ok.md"} - * - * ![foo][] - * - * [foo]: http://foo.bar/baz.png - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * ![foo] - * - * [foo]: http://foo.bar/baz.png - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 1:1-1:7: Use the trailing [] on reference images - */ + tagName = state.input.slice(_position, state.position); -const remarkLintNoShortcutReferenceImage = lintRule( - { - origin: 'remark-lint:no-shortcut-reference-image', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-shortcut-reference-image#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - visit$1(tree, 'imageReference', (node) => { - if (!generated(node) && node.referenceType === 'shortcut') { - file.message('Use the trailing [] on reference images', node); - } - }); + if (PATTERN_FLOW_INDICATORS.test(tagName)) { + throwError(state, 'tag suffix cannot contain flow indicator characters'); + } } -); -var remarkLintNoShortcutReferenceImage$1 = remarkLintNoShortcutReferenceImage; + if (tagName && !PATTERN_TAG_URI.test(tagName)) { + throwError(state, 'tag name cannot contain such characters: ' + tagName); + } -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module no-shortcut-reference-link - * @fileoverview - * Warn when shortcut reference links are used. - * - * Shortcut references render as links when a definition is found, and as - * plain text without definition. - * Sometimes, you don’t intend to create a link from the reference, but this - * rule still warns anyway. - * In that case, you can escape the reference like so: `\[foo]`. - * - * @example - * {"name": "ok.md"} - * - * [foo][] - * - * [foo]: http://foo.bar/baz - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * [foo] - * - * [foo]: http://foo.bar/baz - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 1:1-1:6: Use the trailing `[]` on reference links - */ + try { + tagName = decodeURIComponent(tagName); + } catch (err) { + throwError(state, 'tag name is malformed: ' + tagName); + } -const remarkLintNoShortcutReferenceLink = lintRule( - { - origin: 'remark-lint:no-shortcut-reference-link', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-shortcut-reference-link#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - visit$1(tree, 'linkReference', (node) => { - if (!generated(node) && node.referenceType === 'shortcut') { - file.message('Use the trailing `[]` on reference links', node); - } - }); + if (isVerbatim) { + state.tag = tagName; + + } else if (_hasOwnProperty$1.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 + '"'); } -); -var remarkLintNoShortcutReferenceLink$1 = remarkLintNoShortcutReferenceLink; + return true; +} -/** - * @author Titus Wormer - * @copyright 2016 Titus Wormer - * @license MIT - * @module no-undefined-references - * @fileoverview - * Warn when references to undefined definitions are found. - * - * Options: `Object`, optional. - * - * The object can have an `allow` field, set to an array of strings that may - * appear between `[` and `]`, but that should not be treated as link - * identifiers. - * - * @example - * {"name": "ok.md"} - * - * [foo][] - * - * Just a [ bracket. - * - * Typically, you’d want to use escapes (with a backslash: \\) to escape what - * could turn into a \[reference otherwise]. - * - * Just two braces can’t link: []. - * - * [foo]: https://example.com - * - * @example - * {"name": "ok-allow.md", "setting": {"allow": ["...", "…"]}} - * - * > Eliding a portion of a quoted passage […] is acceptable. - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * [bar] - * - * [baz][] - * - * [text][qux] - * - * Spread [over - * lines][] - * - * > in [a - * > block quote][] - * - * [asd][a - * - * Can include [*emphasis*]. - * - * Multiple pairs: [a][b][c]. - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 1:1-1:6: Found reference to undefined definition - * 3:1-3:8: Found reference to undefined definition - * 5:1-5:12: Found reference to undefined definition - * 7:8-8:9: Found reference to undefined definition - * 10:6-11:17: Found reference to undefined definition - * 13:1-13:6: Found reference to undefined definition - * 15:13-15:25: Found reference to undefined definition - * 17:17-17:23: Found reference to undefined definition - * 17:23-17:26: Found reference to undefined definition - */ +function readAnchorProperty(state) { + var _position, + ch; -const remarkLintNoUndefinedReferences = lintRule( - { - origin: 'remark-lint:no-undefined-references', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-undefined-references#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file, option = {}) => { - const contents = String(file); - const loc = location(file); - const lineEnding = /(\r?\n|\r)[\t ]*(>[\t ]*)*/g; - const allow = new Set( - (option.allow || []).map((d) => normalizeIdentifier(d)) - ); - /** @type {Record} */ - const map = Object.create(null); + ch = state.input.charCodeAt(state.position); - visit$1(tree, (node) => { - if ( - (node.type === 'definition' || node.type === 'footnoteDefinition') && - !generated(node) - ) { - map[normalizeIdentifier(node.identifier)] = true; - } - }); + if (ch !== 0x26/* & */) return false; - visit$1(tree, (node) => { - // CM specifiers that references only form when defined. - // Still, they could be added by plugins, so let’s keep it. - /* c8 ignore next 10 */ - if ( - (node.type === 'imageReference' || - node.type === 'linkReference' || - node.type === 'footnoteReference') && - !generated(node) && - !(normalizeIdentifier(node.identifier) in map) && - !allow.has(normalizeIdentifier(node.identifier)) - ) { - file.message('Found reference to undefined definition', node); - } + if (state.anchor !== null) { + throwError(state, 'duplication of an anchor property'); + } - if (node.type === 'paragraph' || node.type === 'heading') { - findInPhrasing(node); - } - }); + ch = state.input.charCodeAt(++state.position); + _position = state.position; - /** - * @param {Heading|Paragraph} node - */ - function findInPhrasing(node) { - /** @type {Range[]} */ - let ranges = []; + while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) { + ch = state.input.charCodeAt(++state.position); + } - visit$1(node, (child) => { - // Ignore the node itself. - if (child === node) return + if (state.position === _position) { + throwError(state, 'name of an anchor node must contain at least one character'); + } - // Can’t have links in links, so reset ranges. - if (child.type === 'link' || child.type === 'linkReference') { - ranges = []; - return SKIP$1 - } + state.anchor = state.input.slice(_position, state.position); + return true; +} - // Enter non-text. - if (child.type !== 'text') return +function readAlias(state) { + var _position, alias, + ch; - const start = pointStart(child).offset; - const end = pointEnd(child).offset; + ch = state.input.charCodeAt(state.position); - // Bail if there’s no positional info. - if (typeof start !== 'number' || typeof end !== 'number') { - return EXIT$1 - } + if (ch !== 0x2A/* * */) return false; - const source = contents.slice(start, end); - /** @type {Array.<[number, string]>} */ - const lines = [[start, '']]; - let last = 0; + ch = state.input.charCodeAt(++state.position); + _position = state.position; - lineEnding.lastIndex = 0; - let match = lineEnding.exec(source); + while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) { + ch = state.input.charCodeAt(++state.position); + } - while (match) { - const index = match.index; - lines[lines.length - 1][1] = source.slice(last, index); - last = index + match[0].length; - lines.push([start + last, '']); - match = lineEnding.exec(source); - } + if (state.position === _position) { + throwError(state, 'name of an alias node must contain at least one character'); + } - lines[lines.length - 1][1] = source.slice(last); - let lineIndex = -1; + alias = state.input.slice(_position, state.position); - while (++lineIndex < lines.length) { - const line = lines[lineIndex][1]; - let index = 0; + if (!_hasOwnProperty$1.call(state.anchorMap, alias)) { + throwError(state, 'unidentified alias "' + alias + '"'); + } - while (index < line.length) { - const code = line.charCodeAt(index); + state.result = state.anchorMap[alias]; + skipSeparationSpace(state, true, -1); + return true; +} - // Skip past escaped brackets. - if (code === 92) { - const next = line.charCodeAt(index + 1); - index++; +function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) { + var allowBlockStyles, + allowBlockScalars, + allowBlockCollections, + indentStatus = 1, // 1: this>parent, 0: this=parent, -1: this parentIndent) { + indentStatus = 1; + } else if (state.lineIndent === parentIndent) { + indentStatus = 0; + } else if (state.lineIndent < parentIndent) { + indentStatus = -1; + } + } + } - // Shortcut or typical end of a reference. - const range = ranges.pop(); + if (indentStatus === 1) { + while (readTagProperty(state) || readAnchorProperty(state)) { + if (skipSeparationSpace(state, true, -1)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; - // Range should always exist. - // eslint-disable-next-line max-depth - if (range) { - range.push(lines[lineIndex][0] + index); - handleRange(range); - } - } - } - // Anything else. - else { - index++; - } - } + if (state.lineIndent > parentIndent) { + indentStatus = 1; + } else if (state.lineIndent === parentIndent) { + indentStatus = 0; + } else if (state.lineIndent < parentIndent) { + indentStatus = -1; } - }); + } else { + allowBlockCollections = false; + } + } + } - let index = -1; + if (allowBlockCollections) { + allowBlockCollections = atNewLine || allowCompact; + } - while (++index < ranges.length) { - handleRange(ranges[index]); - } + if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) { + if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) { + flowIndent = parentIndent; + } else { + flowIndent = parentIndent + 1; + } - return SKIP$1 + blockIndent = state.position - state.lineStart; - /** - * @param {Range} range - */ - function handleRange(range) { - if (range.length === 1) return - if (range.length === 3) range.length = 2; + 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; - // No need to warn for just `[]`. - if (range.length === 2 && range[0] + 2 === range[1]) return + } else if (readAlias(state)) { + hasContent = true; - const offset = range.length === 4 && range[2] + 2 !== range[3] ? 2 : 0; - const id = contents - .slice(range[0 + offset] + 1, range[1 + offset] - 1) - .replace(lineEnding, ' '); - const pos = { - start: loc.toPoint(range[0]), - end: loc.toPoint(range[range.length - 1]) - }; + if (state.tag !== null || state.anchor !== null) { + throwError(state, 'alias node should not have any properties'); + } - if ( - !generated({position: pos}) && - !(normalizeIdentifier(id) in map) && - !allow.has(normalizeIdentifier(id)) - ) { - file.message('Found reference to undefined definition', pos); + } 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); } } -); - -var remarkLintNoUndefinedReferences$1 = remarkLintNoUndefinedReferences; -/** - * @author Titus Wormer - * @copyright 2016 Titus Wormer - * @license MIT - * @module no-unused-definitions - * @fileoverview - * Warn when unused definitions are found. - * - * @example - * {"name": "ok.md"} - * - * [foo][] - * - * [foo]: https://example.com - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * [bar]: https://example.com - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 1:1-1:27: Found unused definition - */ + if (state.tag === null) { + if (state.anchor !== null) { + state.anchorMap[state.anchor] = state.result; + } -const own$1 = {}.hasOwnProperty; + } else 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 + '"'); + } -const remarkLintNoUnusedDefinitions = lintRule( - { - origin: 'remark-lint:no-unused-definitions', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-unused-definitions#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - /** @type {Record} */ - const map = Object.create(null); + for (typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) { + type = state.implicitTypes[typeIndex]; - visit$1(tree, (node) => { - if ( - (node.type === 'definition' || node.type === 'footnoteDefinition') && - !generated(node) - ) { - map[node.identifier.toUpperCase()] = {node, used: false}; + 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; } - }); - - visit$1(tree, (node) => { - if ( - node.type === 'imageReference' || - node.type === 'linkReference' || - node.type === 'footnoteReference' - ) { - const info = map[node.identifier.toUpperCase()]; + } + } else if (state.tag !== '!') { + if (_hasOwnProperty$1.call(state.typeMap[state.kind || 'fallback'], state.tag)) { + type = state.typeMap[state.kind || 'fallback'][state.tag]; + } else { + // looking for multi type + type = null; + typeList = state.typeMap.multi[state.kind || 'fallback']; - if (!generated(node) && info) { - info.used = true; + for (typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) { + if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) { + type = typeList[typeIndex]; + break; } } - }); + } - /** @type {string} */ - let identifier; + if (!type) { + throwError(state, 'unknown tag !<' + state.tag + '>'); + } - for (identifier in map) { - if (own$1.call(map, identifier)) { - const entry = map[identifier]; + 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 (!entry.used) { - file.message('Found unused definition', entry.node); - } + if (!type.resolve(state.result, state.tag)) { // `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, state.tag); + if (state.anchor !== null) { + state.anchorMap[state.anchor] = state.result; } } } -); -var remarkLintNoUnusedDefinitions$1 = remarkLintNoUnusedDefinitions; + if (state.listener !== null) { + state.listener('close', state); + } + return state.tag !== null || state.anchor !== null || hasContent; +} -/** - * @fileoverview - * remark preset to configure `remark-lint` with settings that prevent - * mistakes or stuff that fails across vendors. - */ +function readDocument(state) { + var documentStart = state.position, + _position, + directiveName, + directiveArgs, + hasDirectives = false, + ch; -/** @type {Preset} */ -const remarkPresetLintRecommended = { - plugins: [ - remarkLint, - // Unix compatibility. - remarkLintFinalNewline$1, - // Rendering across vendors differs greatly if using other styles. - remarkLintListItemBulletIndent$1, - [remarkLintListItemIndent$1, 'tab-size'], - // Differs or unsupported across vendors. - remarkLintNoAutoLinkWithoutProtocol$1, - remarkLintNoBlockquoteWithoutMarker$1, - remarkLintNoLiteralUrls$1, - [remarkLintOrderedListMarkerStyle$1, '.'], - // Mistakes. - remarkLintHardBreakSpaces$1, - remarkLintNoDuplicateDefinitions$1, - remarkLintNoHeadingContentIndent$1, - remarkLintNoInlinePadding$1, - remarkLintNoShortcutReferenceImage$1, - remarkLintNoShortcutReferenceLink$1, - remarkLintNoUndefinedReferences$1, - remarkLintNoUnusedDefinitions$1 - ] -}; + state.version = null; + state.checkLineBreaks = state.legacy; + state.tagMap = Object.create(null); + state.anchorMap = Object.create(null); -var remarkPresetLintRecommended$1 = remarkPresetLintRecommended; + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + skipSeparationSpace(state, true, -1); -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module blockquote-indentation - * @fileoverview - * Warn when block quotes are indented too much or too little. - * - * Options: `number` or `'consistent'`, default: `'consistent'`. - * - * `'consistent'` detects the first used indentation and will warn when - * other block quotes use a different indentation. - * - * @example - * {"name": "ok.md", "setting": 4} - * - * > Hello - * - * Paragraph. - * - * > World - * @example - * {"name": "ok.md", "setting": 2} - * - * > Hello - * - * Paragraph. - * - * > World - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * > Hello - * - * Paragraph. - * - * > World - * - * Paragraph. - * - * > World - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 5:5: Remove 1 space between block quote and content - * 9:3: Add 1 space between block quote and content - */ + ch = state.input.charCodeAt(state.position); -const remarkLintBlockquoteIndentation = lintRule( - { - origin: 'remark-lint:blockquote-indentation', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-blockquote-indentation#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file, option = 'consistent') => { - visit$1(tree, 'blockquote', (node) => { - if (generated(node) || node.children.length === 0) { - return - } + if (state.lineIndent > 0 || ch !== 0x25/* % */) { + break; + } - if (option === 'consistent') { - option = check(node); - } else { - const diff = option - check(node); + hasDirectives = true; + ch = state.input.charCodeAt(++state.position); + _position = state.position; - if (diff !== 0) { - const abs = Math.abs(diff); + while (ch !== 0 && !is_WS_OR_EOL(ch)) { + ch = state.input.charCodeAt(++state.position); + } - file.message( - (diff > 0 ? 'Add' : 'Remove') + - ' ' + - abs + - ' ' + - plural('space', abs) + - ' between block quote and content', - pointStart(node.children[0]) - ); - } + 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); } - }); - } -); -var remarkLintBlockquoteIndentation$1 = remarkLintBlockquoteIndentation; + if (ch === 0x23/* # */) { + do { ch = state.input.charCodeAt(++state.position); } + while (ch !== 0 && !is_EOL(ch)); + break; + } -/** - * @param {Blockquote} node - * @returns {number} - */ -function check(node) { - return pointStart(node.children[0]).column - pointStart(node).column -} + if (is_EOL(ch)) break; -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module checkbox-character-style - * @fileoverview - * Warn when list item checkboxes violate a given style. - * - * Options: `Object` or `'consistent'`, default: `'consistent'`. - * - * `'consistent'` detects the first used checked and unchecked checkbox - * styles and warns when subsequent checkboxes use different styles. - * - * Styles can also be passed in like so: - * - * ```js - * {checked: 'x', unchecked: ' '} - * ``` - * - * ## Fix - * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) - * formats checked checkboxes using `x` (lowercase X) and unchecked checkboxes - * as `·` (a single space). - * - * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) - * on how to automatically fix warnings for this rule. - * - * @example - * {"name": "ok.md", "setting": {"checked": "x"}, "gfm": true} - * - * - [x] List item - * - [x] List item - * - * @example - * {"name": "ok.md", "setting": {"checked": "X"}, "gfm": true} - * - * - [X] List item - * - [X] List item - * - * @example - * {"name": "ok.md", "setting": {"unchecked": " "}, "gfm": true} - * - * - [ ] List item - * - [ ] List item - * - [ ]·· - * - [ ] - * - * @example - * {"name": "ok.md", "setting": {"unchecked": "\t"}, "gfm": true} - * - * - [»] List item - * - [»] List item - * - * @example - * {"name": "not-ok.md", "label": "input", "gfm": true} - * - * - [x] List item - * - [X] List item - * - [ ] List item - * - [»] List item - * - * @example - * {"name": "not-ok.md", "label": "output", "gfm": true} - * - * 2:5: Checked checkboxes should use `x` as a marker - * 4:5: Unchecked checkboxes should use ` ` as a marker - * - * @example - * {"setting": {"unchecked": "💩"}, "name": "not-ok.md", "label": "output", "positionless": true, "gfm": true} - * - * 1:1: Incorrect unchecked checkbox marker `💩`: use either `'\t'`, or `' '` - * - * @example - * {"setting": {"checked": "💩"}, "name": "not-ok.md", "label": "output", "positionless": true, "gfm": true} - * - * 1:1: Incorrect checked checkbox marker `💩`: use either `'x'`, or `'X'` - */ + _position = state.position; -const remarkLintCheckboxCharacterStyle = lintRule( - { - origin: 'remark-lint:checkbox-character-style', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-checkbox-character-style#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file, option = 'consistent') => { - const value = String(file); - /** @type {'x'|'X'|'consistent'} */ - let checked = 'consistent'; - /** @type {' '|'\x09'|'consistent'} */ - let unchecked = 'consistent'; + while (ch !== 0 && !is_WS_OR_EOL(ch)) { + ch = state.input.charCodeAt(++state.position); + } - if (typeof option === 'object') { - checked = option.checked || 'consistent'; - unchecked = option.unchecked || 'consistent'; + directiveArgs.push(state.input.slice(_position, state.position)); } - if (unchecked !== 'consistent' && unchecked !== ' ' && unchecked !== '\t') { - file.fail( - 'Incorrect unchecked checkbox marker `' + - unchecked + - "`: use either `'\\t'`, or `' '`" - ); - } + if (ch !== 0) readLineBreak(state); - if (checked !== 'consistent' && checked !== 'x' && checked !== 'X') { - file.fail( - 'Incorrect checked checkbox marker `' + - checked + - "`: use either `'x'`, or `'X'`" - ); + if (_hasOwnProperty$1.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); - visit$1(tree, 'listItem', (node) => { - const head = node.children[0]; - const point = pointStart(head); + } else if (hasDirectives) { + throwError(state, 'directives end mark is expected'); + } - // Exit early for items without checkbox. - // A list item cannot be checked and empty, according to GFM. - if ( - typeof node.checked !== 'boolean' || - !head || - typeof point.offset !== 'number' - ) { - return - } + composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true); + skipSeparationSpace(state, true, -1); - // Move back to before `] `. - point.offset -= 2; - point.column -= 2; + 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'); + } - // Assume we start with a checkbox, because well, `checked` is set. - const match = /\[([\t Xx])]/.exec( - value.slice(point.offset - 2, point.offset + 1) - ); + state.documents.push(state.result); - // Failsafe to make sure we don‘t crash if there actually isn’t a checkbox. - /* c8 ignore next */ - if (!match) return + if (state.position === state.lineStart && testDocumentSeparator(state)) { - const style = node.checked ? checked : unchecked; + if (state.input.charCodeAt(state.position) === 0x2E/* . */) { + state.position += 3; + skipSeparationSpace(state, true, -1); + } + return; + } - if (style === 'consistent') { - if (node.checked) { - // @ts-expect-error: valid marker. - checked = match[1]; - } else { - // @ts-expect-error: valid marker. - unchecked = match[1]; - } - } else if (match[1] !== style) { - file.message( - (node.checked ? 'Checked' : 'Unchecked') + - ' checkboxes should use `' + - style + - '` as a marker', - point - ); - } - }); + if (state.position < (state.length - 1)) { + throwError(state, 'end of the stream or a document separator is expected'); + } else { + return; } -); +} -var remarkLintCheckboxCharacterStyle$1 = remarkLintCheckboxCharacterStyle; -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module checkbox-content-indent - * @fileoverview - * Warn when list item checkboxes are followed by too much whitespace. - * - * @example - * {"name": "ok.md", "gfm": true} - * - * - [ ] List item - * + [x] List Item - * * [X] List item - * - [ ] List item - * - * @example - * {"name": "not-ok.md", "label": "input", "gfm": true} - * - * - [ ] List item - * + [x] List item - * * [X] List item - * - [ ] List item - * - * @example - * {"name": "not-ok.md", "label": "output", "gfm": true} - * - * 2:7-2:8: Checkboxes should be followed by a single character - * 3:7-3:9: Checkboxes should be followed by a single character - * 4:7-4:10: Checkboxes should be followed by a single character - */ +function loadDocuments(input, options) { + input = String(input); + options = options || {}; -const remarkLintCheckboxContentIndent = lintRule( - { - origin: 'remark-lint:checkbox-content-indent', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-checkbox-content-indent#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - const value = String(file); - const loc = location(file); + if (input.length !== 0) { - visit$1(tree, 'listItem', (node) => { - const head = node.children[0]; - const point = pointStart(head); + // Add tailing `\n` if not exists + if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ && + input.charCodeAt(input.length - 1) !== 0x0D/* CR */) { + input += '\n'; + } - // Exit early for items without checkbox. - // A list item cannot be checked and empty, according to GFM. - if ( - typeof node.checked !== 'boolean' || - !head || - typeof point.offset !== 'number' - ) { - return - } + // Strip BOM + if (input.charCodeAt(0) === 0xFEFF) { + input = input.slice(1); + } + } - // Assume we start with a checkbox, because well, `checked` is set. - const match = /\[([\t xX])]/.exec( - value.slice(point.offset - 4, point.offset + 1) - ); + var state = new State$1(input, options); - // Failsafe to make sure we don‘t crash if there actually isn’t a checkbox. - /* c8 ignore next */ - if (!match) return + var nullpos = input.indexOf('\0'); - // Move past checkbox. - const initial = point.offset; - let final = initial; + if (nullpos !== -1) { + state.position = nullpos; + throwError(state, 'null byte is not allowed in input'); + } - while (/[\t ]/.test(value.charAt(final))) final++; + // Use 0 as string terminator. That significantly simplifies bounds check. + state.input += '\0'; - if (final - initial > 0) { - file.message('Checkboxes should be followed by a single character', { - start: loc.toPoint(initial), - end: loc.toPoint(final) - }); - } - }); + while (state.input.charCodeAt(state.position) === 0x20/* Space */) { + state.lineIndent += 1; + state.position += 1; } -); -var remarkLintCheckboxContentIndent$1 = remarkLintCheckboxContentIndent; + while (state.position < (state.length - 1)) { + readDocument(state); + } -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module code-block-style - * @fileoverview - * Warn when code blocks do not adhere to a given style. - * - * Options: `'consistent'`, `'fenced'`, or `'indented'`, default: `'consistent'`. - * - * `'consistent'` detects the first used code block style and warns when - * subsequent code blocks uses different styles. - * - * ## Fix - * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) - * formats code blocks using a fence if they have a language flag and - * indentation if not. - * Pass - * [`fences: true`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify#optionsfences) - * to always use fences for code blocks. - * - * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) - * on how to automatically fix warnings for this rule. - * - * @example - * {"setting": "indented", "name": "ok.md"} - * - * alpha() - * - * Paragraph. - * - * bravo() - * - * @example - * {"setting": "indented", "name": "not-ok.md", "label": "input"} - * - * ``` - * alpha() - * ``` - * - * Paragraph. - * - * ``` - * bravo() - * ``` - * - * @example - * {"setting": "indented", "name": "not-ok.md", "label": "output"} - * - * 1:1-3:4: Code blocks should be indented - * 7:1-9:4: Code blocks should be indented - * - * @example - * {"setting": "fenced", "name": "ok.md"} - * - * ``` - * alpha() - * ``` - * - * Paragraph. - * - * ``` - * bravo() - * ``` - * - * @example - * {"setting": "fenced", "name": "not-ok-fenced.md", "label": "input"} - * - * alpha() - * - * Paragraph. - * - * bravo() - * - * @example - * {"setting": "fenced", "name": "not-ok-fenced.md", "label": "output"} - * - * 1:1-1:12: Code blocks should be fenced - * 5:1-5:12: Code blocks should be fenced - * - * @example - * {"name": "not-ok-consistent.md", "label": "input"} - * - * alpha() - * - * Paragraph. - * - * ``` - * bravo() - * ``` - * - * @example - * {"name": "not-ok-consistent.md", "label": "output"} - * - * 5:1-7:4: Code blocks should be indented - * - * @example - * {"setting": "💩", "name": "not-ok-incorrect.md", "label": "output", "positionless": true} - * - * 1:1: Incorrect code block style `💩`: use either `'consistent'`, `'fenced'`, or `'indented'` - */ + return state.documents; +} -const remarkLintCodeBlockStyle = lintRule( - { - origin: 'remark-lint:code-block-style', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-code-block-style#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file, option = 'consistent') => { - const value = String(file); - if ( - option !== 'consistent' && - option !== 'fenced' && - option !== 'indented' - ) { - file.fail( - 'Incorrect code block style `' + - option + - "`: use either `'consistent'`, `'fenced'`, or `'indented'`" - ); - } +function loadAll$1(input, iterator, options) { + if (iterator !== null && typeof iterator === 'object' && typeof options === 'undefined') { + options = iterator; + iterator = null; + } - visit$1(tree, 'code', (node) => { - if (generated(node)) { - return - } + var documents = loadDocuments(input, options); - const initial = pointStart(node).offset; - const final = pointEnd(node).offset; + if (typeof iterator !== 'function') { + return documents; + } - const current = - node.lang || /^\s*([~`])\1{2,}/.test(value.slice(initial, final)) - ? 'fenced' - : 'indented'; + for (var index = 0, length = documents.length; index < length; index += 1) { + iterator(documents[index]); + } +} - if (option === 'consistent') { - option = current; - } else if (option !== current) { - file.message('Code blocks should be ' + option, node); - } - }); + +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 exception('expected a single document in the stream, but found more'); +} -var remarkLintCodeBlockStyle$1 = remarkLintCodeBlockStyle; -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module definition-spacing - * @fileoverview - * Warn when consecutive whitespace is used in a definition. - * - * @example - * {"name": "ok.md"} - * - * [example domain]: http://example.com "Example Domain" - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * [example····domain]: http://example.com "Example Domain" - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 1:1-1:57: Do not use consecutive whitespace in definition labels - */ +var loadAll_1 = loadAll$1; +var load_1 = load$1; -const label = /^\s*\[((?:\\[\s\S]|[^[\]])+)]/; +var loader = { + loadAll: loadAll_1, + load: load_1 +}; -const remarkLintDefinitionSpacing = lintRule( - { - origin: 'remark-lint:definition-spacing', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-definition-spacing#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - const value = String(file); +/*eslint-disable no-use-before-define*/ - visit$1(tree, (node) => { - if (node.type === 'definition' || node.type === 'footnoteDefinition') { - const start = pointStart(node).offset; - const end = pointEnd(node).offset; - if (typeof start === 'number' && typeof end === 'number') { - const match = value.slice(start, end).match(label); - if (match && /[ \t\n]{2,}/.test(match[1])) { - file.message( - 'Do not use consecutive whitespace in definition labels', - node - ); - } - } - } - }); - } -); -var remarkLintDefinitionSpacing$1 = remarkLintDefinitionSpacing; -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module fenced-code-flag - * @fileoverview - * Check fenced code block flags. - * - * Options: `Array.` or `Object`, optional. - * - * Providing an array is as passing `{flags: Array}`. - * - * The object can have an array of `'flags'` which are allowed: other flags - * will not be allowed. - * An `allowEmpty` field (`boolean`, default: `false`) can be set to allow - * code blocks without language flags. - * - * @example - * {"name": "ok.md"} - * - * ```alpha - * bravo() - * ``` - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * ``` - * alpha() - * ``` - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 1:1-3:4: Missing code language flag - * - * @example - * {"name": "ok.md", "setting": {"allowEmpty": true}} - * - * ``` - * alpha() - * ``` - * - * @example - * {"name": "not-ok.md", "setting": {"allowEmpty": false}, "label": "input"} - * - * ``` - * alpha() - * ``` - * - * @example - * {"name": "not-ok.md", "setting": {"allowEmpty": false}, "label": "output"} - * - * 1:1-3:4: Missing code language flag - * - * @example - * {"name": "ok.md", "setting": ["alpha"]} - * - * ```alpha - * bravo() - * ``` - * - * @example - * {"name": "ok.md", "setting": {"flags":["alpha"]}} - * - * ```alpha - * bravo() - * ``` - * - * @example - * {"name": "not-ok.md", "setting": ["charlie"], "label": "input"} - * - * ```alpha - * bravo() - * ``` - * - * @example - * {"name": "not-ok.md", "setting": ["charlie"], "label": "output"} - * - * 1:1-3:4: Incorrect code language flag - */ +var _toString = Object.prototype.toString; +var _hasOwnProperty = Object.prototype.hasOwnProperty; + +var CHAR_BOM = 0xFEFF; +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'; -const fence = /^ {0,3}([~`])\1{2,}/; +var DEPRECATED_BOOLEANS_SYNTAX = [ + 'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON', + 'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF' +]; -const remarkLintFencedCodeFlag = lintRule( - { - origin: 'remark-lint:fenced-code-flag', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-fenced-code-flag#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file, option) => { - const value = String(file); - let allowEmpty = false; - /** @type {string[]} */ - let allowed = []; +var DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/; - if (typeof option === 'object') { - if (Array.isArray(option)) { - allowed = option; - } else { - allowEmpty = Boolean(option.allowEmpty); +function compileStyleMap(schema, map) { + var result, keys, index, length, tag, style, type; - if (option.flags) { - allowed = option.flags; - } - } + 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]; - visit$1(tree, 'code', (node) => { - if (!generated(node)) { - if (node.lang) { - if (allowed.length > 0 && !allowed.includes(node.lang)) { - file.message('Incorrect code language flag', node); - } - } else { - const slice = value.slice( - pointStart(node).offset, - pointEnd(node).offset - ); + if (type && _hasOwnProperty.call(type.styleAliases, style)) { + style = type.styleAliases[style]; + } - if (!allowEmpty && fence.test(slice)) { - file.message('Missing code language flag', node); - } - } - } - }); + result[tag] = style; } -); -var remarkLintFencedCodeFlag$1 = remarkLintFencedCodeFlag; + return result; +} -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module fenced-code-marker - * @fileoverview - * Warn for violating fenced code markers. - * - * Options: `` '`' ``, `'~'`, or `'consistent'`, default: `'consistent'`. - * - * `'consistent'` detects the first used fenced code marker style and warns - * when subsequent fenced code blocks use different styles. - * - * ## Fix - * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify) - * formats fences using ``'`'`` (grave accent) by default. - * Pass - * [`fence: '~'`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify#optionsfence) - * to use `~` (tilde) instead. - * - * See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown) - * on how to automatically fix warnings for this rule. - * - * @example - * {"name": "ok.md"} - * - * Indented code blocks are not affected by this rule: - * - * bravo() - * - * @example - * {"name": "ok.md", "setting": "`"} - * - * ```alpha - * bravo() - * ``` - * - * ``` - * charlie() - * ``` - * - * @example - * {"name": "ok.md", "setting": "~"} - * - * ~~~alpha - * bravo() - * ~~~ - * - * ~~~ - * charlie() - * ~~~ - * - * @example - * {"name": "not-ok-consistent-tick.md", "label": "input"} - * - * ```alpha - * bravo() - * ``` - * - * ~~~ - * charlie() - * ~~~ - * - * @example - * {"name": "not-ok-consistent-tick.md", "label": "output"} - * - * 5:1-7:4: Fenced code should use `` ` `` as a marker - * - * @example - * {"name": "not-ok-consistent-tilde.md", "label": "input"} - * - * ~~~alpha - * bravo() - * ~~~ - * - * ``` - * charlie() - * ``` - * - * @example - * {"name": "not-ok-consistent-tilde.md", "label": "output"} - * - * 5:1-7:4: Fenced code should use `~` as a marker - * - * @example - * {"name": "not-ok-incorrect.md", "setting": "💩", "label": "output", "positionless": true} - * - * 1:1: Incorrect fenced code marker `💩`: use either `'consistent'`, `` '`' ``, or `'~'` - */ +function encodeHex(character) { + var string, handle, length; -const remarkLintFencedCodeMarker = lintRule( - { - origin: 'remark-lint:fenced-code-marker', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-fenced-code-marker#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file, option = 'consistent') => { - const contents = String(file); + string = character.toString(16).toUpperCase(); - if (option !== 'consistent' && option !== '~' && option !== '`') { - file.fail( - 'Incorrect fenced code marker `' + - option + - "`: use either `'consistent'`, `` '`' ``, or `'~'`" - ); - } + 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 exception('code point within a string may not be greater than 0xFFFFFFFF'); + } - visit$1(tree, 'code', (node) => { - const start = pointStart(node).offset; + return '\\' + handle + common.repeat('0', length - string.length) + string; +} - if (typeof start === 'number') { - const marker = contents - .slice(start, start + 4) - .replace(/^\s+/, '') - .charAt(0); - // Ignore unfenced code blocks. - if (marker === '~' || marker === '`') { - if (option === 'consistent') { - option = marker; - } else if (marker !== option) { - file.message( - 'Fenced code should use `' + - (option === '~' ? option : '` ` `') + - '` as a marker', - node - ); - } - } - } - }); +var QUOTING_TYPE_SINGLE = 1, + QUOTING_TYPE_DOUBLE = 2; + +function State(options) { + this.schema = options['schema'] || _default; + 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.quotingType = options['quotingType'] === '"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE; + this.forceQuotes = options['forceQuotes'] || false; + this.replacer = typeof options['replacer'] === 'function' ? options['replacer'] : null; + + 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; } -); -var remarkLintFencedCodeMarker$1 = remarkLintFencedCodeMarker; + return result; +} -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module file-extension - * @fileoverview - * Warn when the file extension differ from the preferred extension. - * - * Does not warn when given documents have no file extensions (such as - * `AUTHORS` or `LICENSE`). - * - * Options: `string`, default: `'md'` — Expected file extension. - * - * @example - * {"name": "readme.md"} - * - * @example - * {"name": "readme"} - * - * @example - * {"name": "readme.mkd", "label": "output", "positionless": true} - * - * 1:1: Incorrect extension: use `md` - * - * @example - * {"name": "readme.mkd", "setting": "mkd"} - */ +function generateNextLine(state, level) { + return '\n' + common.repeat(' ', state.indent * level); +} -const remarkLintFileExtension = lintRule( - { - origin: 'remark-lint:file-extension', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-file-extension#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (_, file, option = 'md') => { - const ext = file.extname; +function testImplicitResolving(state, str) { + var index, length, type; - if (ext && ext.slice(1) !== option) { - file.message('Incorrect extension: use `' + option + '`'); + for (index = 0, length = state.implicitTypes.length; index < length; index += 1) { + type = state.implicitTypes[index]; + + if (type.resolve(str)) { + return true; } } -); -var remarkLintFileExtension$1 = remarkLintFileExtension; + return false; +} -/** - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @module final-definition - * @fileoverview - * Warn when definitions are placed somewhere other than at the end of - * the file. - * - * @example - * {"name": "ok.md"} - * - * Paragraph. - * - * [example]: http://example.com "Example Domain" - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * Paragraph. - * - * [example]: http://example.com "Example Domain" - * - * Another paragraph. - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 3:1-3:47: Move definitions to the end of the file (after the node at line `5`) - * - * @example - * {"name": "ok-comments.md"} - * - * Paragraph. - * - * [example-1]: http://example.com/one/ - * - * - * - * [example-2]: http://example.com/two/ - */ +// [33] s-white ::= s-space | s-tab +function isWhitespace(c) { + return c === CHAR_SPACE || c === CHAR_TAB; +} -const remarkLintFinalDefinition = lintRule( - { - origin: 'remark-lint:final-definition', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-definition#readme' - }, - /** @type {import('unified-lint-rule').Rule} */ - (tree, file) => { - let last = 0; +// 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 !== CHAR_BOM) + || (0x10000 <= c && c <= 0x10FFFF); +} - visit$1( - tree, - (node) => { - // Ignore generated and HTML comment nodes. - if ( - node.type === 'root' || - generated(node) || - (node.type === 'html' && /^\s*