UNPKG

@limetech/lime-elements

Version:
1,880 lines (1,679 loc) 652 kB
import { g as getDefaultExportFromCjs } from './_commonjsHelpers-BFTU3MAI.js'; /** * Throw a given error. * * @param {Error|null|undefined} [error] * Maybe error. * @returns {asserts error is null|undefined} */ function bail(error) { if (error) { throw error } } var extend$1; var hasRequiredExtend; function requireExtend () { if (hasRequiredExtend) return extend$1; hasRequiredExtend = 1; 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]; }; 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; // 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; }; return extend$1; } var extendExports = requireExtend(); var extend = /*@__PURE__*/getDefaultExportFromCjs(extendExports); function isPlainObject(value) { if (typeof value !== 'object' || value === null) { return false; } const prototype = Object.getPrototypeOf(value); return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value); } /** * @typedef {(error?: Error|null|undefined, ...output: Array<any>) => void} Callback * @typedef {(...input: Array<any>) => any} Middleware * * @typedef {(...input: Array<any>) => void} Run * Call all middleware. * @typedef {(fn: Middleware) => Pipeline} Use * Add `fn` (middleware) to the list. * @typedef {{run: Run, use: Use}} Pipeline * Middleware. */ /** * Create new middleware. * * @returns {Pipeline} */ function trough() { /** @type {Array<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 {Array<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`. * @this {any} * @param {Array<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.apply(this, parameters); } catch (error) { const exception = /** @type {Error} */ (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); } } /** * @typedef {import('unist').Node} Node * @typedef {import('unist').Point} Point * @typedef {import('unist').Position} Position */ /** * @typedef NodeLike * @property {string} type * @property {PositionLike | null | undefined} [position] * * @typedef PointLike * @property {number | null | undefined} [line] * @property {number | null | undefined} [column] * @property {number | null | undefined} [offset] * * @typedef PositionLike * @property {PointLike | null | undefined} [start] * @property {PointLike | null | undefined} [end] */ /** * Serialize the positional info of a point, position (start and end points), * or node. * * @param {Node | NodeLike | Point | PointLike | Position | PositionLike | null | undefined} [value] * Node, position, or point. * @returns {string} * Pretty printed positional info of a node (`string`). * * In the format of a range `ls:cs-le:ce` (when given `node` or `position`) * or a point `l:c` (when given `point`), where `l` stands for line, `c` for * column, `s` for `start`, and `e` for end. * An empty string (`''`) is returned if the given value is neither `node`, * `position`, nor `point`. */ function stringifyPosition$1(value) { // Nothing. if (!value || typeof value !== 'object') { return '' } // Node. if ('position' in value || 'type' in value) { return position$3(value.position) } // Position. if ('start' in value || 'end' in value) { return position$3(value) } // Point. if ('line' in value || 'column' in value) { return point$3(value) } // ? return '' } /** * @param {Point | PointLike | null | undefined} point * @returns {string} */ function point$3(point) { return index$1(point && point.line) + ':' + index$1(point && point.column) } /** * @param {Position | PositionLike | null | undefined} pos * @returns {string} */ function position$3(pos) { return point$3(pos && pos.start) + '-' + point$3(pos && pos.end) } /** * @param {number | null | undefined} value * @returns {number} */ function index$1(value) { return value && typeof value === 'number' ? value : 1 } /** * @typedef {import('unist').Node} Node * @typedef {import('unist').Point} Point * @typedef {import('unist').Position} Position */ /** * Message. */ let VFileMessage$1 = class VFileMessage extends Error { /** * Create a message for `reason`. * * > 🪦 **Note**: also has obsolete signatures. * * @overload * @param {string} reason * @param {Options | null | undefined} [options] * @returns * * @overload * @param {string} reason * @param {Node | NodeLike | null | undefined} parent * @param {string | null | undefined} [origin] * @returns * * @overload * @param {string} reason * @param {Point | Position | null | undefined} place * @param {string | null | undefined} [origin] * @returns * * @overload * @param {string} reason * @param {string | null | undefined} [origin] * @returns * * @overload * @param {Error | VFileMessage} cause * @param {Node | NodeLike | null | undefined} parent * @param {string | null | undefined} [origin] * @returns * * @overload * @param {Error | VFileMessage} cause * @param {Point | Position | null | undefined} place * @param {string | null | undefined} [origin] * @returns * * @overload * @param {Error | VFileMessage} cause * @param {string | null | undefined} [origin] * @returns * * @param {Error | VFileMessage | string} causeOrReason * Reason for message, should use markdown. * @param {Node | NodeLike | Options | Point | Position | string | null | undefined} [optionsOrParentOrPlace] * Configuration (optional). * @param {string | null | undefined} [origin] * Place in code where the message originates (example: * `'my-package:my-rule'` or `'my-rule'`). * @returns * Instance of `VFileMessage`. */ // eslint-disable-next-line complexity constructor(causeOrReason, optionsOrParentOrPlace, origin) { super(); if (typeof optionsOrParentOrPlace === 'string') { origin = optionsOrParentOrPlace; optionsOrParentOrPlace = undefined; } /** @type {string} */ let reason = ''; /** @type {Options} */ let options = {}; let legacyCause = false; if (optionsOrParentOrPlace) { // Point. if ( 'line' in optionsOrParentOrPlace && 'column' in optionsOrParentOrPlace ) { options = {place: optionsOrParentOrPlace}; } // Position. else if ( 'start' in optionsOrParentOrPlace && 'end' in optionsOrParentOrPlace ) { options = {place: optionsOrParentOrPlace}; } // Node. else if ('type' in optionsOrParentOrPlace) { options = { ancestors: [optionsOrParentOrPlace], place: optionsOrParentOrPlace.position }; } // Options. else { options = {...optionsOrParentOrPlace}; } } if (typeof causeOrReason === 'string') { reason = causeOrReason; } // Error. else if (!options.cause && causeOrReason) { legacyCause = true; reason = causeOrReason.message; options.cause = causeOrReason; } if (!options.ruleId && !options.source && typeof origin === 'string') { const index = origin.indexOf(':'); if (index === -1) { options.ruleId = origin; } else { options.source = origin.slice(0, index); options.ruleId = origin.slice(index + 1); } } if (!options.place && options.ancestors && options.ancestors) { const parent = options.ancestors[options.ancestors.length - 1]; if (parent) { options.place = parent.position; } } const start = options.place && 'start' in options.place ? options.place.start : options.place; /* eslint-disable no-unused-expressions */ /** * Stack of ancestor nodes surrounding the message. * * @type {Array<Node> | undefined} */ this.ancestors = options.ancestors || undefined; /** * Original error cause of the message. * * @type {Error | undefined} */ this.cause = options.cause || undefined; /** * Starting column of message. * * @type {number | undefined} */ this.column = start ? start.column : undefined; /** * State of problem. * * * `true` — error, file not usable * * `false` — warning, change may be needed * * `undefined` — change likely not needed * * @type {boolean | null | undefined} */ this.fatal = undefined; // Field from `Error`. /** * Reason for message. * * @type {string} */ this.message = reason; /** * Starting line of error. * * @type {number | undefined} */ this.line = start ? start.line : undefined; // Field from `Error`. /** * Serialized positional info of message. * * On normal errors, this would be something like `ParseError`, buit in * `VFile` messages we use this space to show where an error happened. */ this.name = stringifyPosition$1(options.place) || '1:1'; /** * Place of message. * * @type {Point | Position | undefined} */ this.place = options.place || undefined; /** * Reason for message, should use markdown. * * @type {string} */ this.reason = this.message; /** * Category of message (example: `'my-rule'`). * * @type {string | undefined} */ this.ruleId = options.ruleId || undefined; /** * Namespace of message (example: `'my-package'`). * * @type {string | undefined} */ this.source = options.source || undefined; // Field from `Error`. /** * Stack of message. * * This is used by normal errors to show where something happened in * programming code, irrelevant for `VFile` messages, * * @type {string} */ this.stack = legacyCause && options.cause && typeof options.cause.stack === 'string' ? options.cause.stack : ''; /* eslint-enable no-unused-expressions */ } }; VFileMessage$1.prototype.file = ''; VFileMessage$1.prototype.name = ''; VFileMessage$1.prototype.reason = ''; VFileMessage$1.prototype.message = ''; VFileMessage$1.prototype.stack = ''; VFileMessage$1.prototype.column = undefined; VFileMessage$1.prototype.line = undefined; VFileMessage$1.prototype.ancestors = undefined; VFileMessage$1.prototype.cause = undefined; VFileMessage$1.prototype.fatal = undefined; VFileMessage$1.prototype.place = undefined; VFileMessage$1.prototype.ruleId = undefined; VFileMessage$1.prototype.source = undefined; // A derivative work based on: // <https://github.com/browserify/path-browserify>. // Which is licensed: // // MIT License // // Copyright (c) 2013 James Halliday // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of // the Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // A derivative work based on: // // Parts of that are extracted from Node’s internal `path` module: // <https://github.com/nodejs/node/blob/master/lib/path.js>. // Which is licensed: // // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. const path = {basename: basename$1, dirname: dirname$1, extname: extname$1, join: join$1, sep: '/'}; /* eslint-disable max-depth, complexity */ /** * Get the basename from a path. * * @param {string} path * File path. * @param {string | null | undefined} [ext] * Extension to strip. * @returns {string} * Stem or basename. */ function basename$1(path, ext) { if (ext !== undefined && typeof ext !== 'string') { throw new TypeError('"ext" argument must be a string') } assertPath$3(path); let start = 0; let end = -1; let index = path.length; /** @type {boolean | undefined} */ let seenNonSlash; if (ext === undefined || ext.length === 0 || ext.length > path.length) { while (index--) { if (path.codePointAt(index) === 47 /* `/` */) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now. if (seenNonSlash) { start = index + 1; break } } else if (end < 0) { // We saw the first non-path separator, mark this as the end of our // path component. seenNonSlash = true; end = index + 1; } } return end < 0 ? '' : path.slice(start, end) } if (ext === path) { return '' } let firstNonSlashEnd = -1; let extIndex = ext.length - 1; while (index--) { if (path.codePointAt(index) === 47 /* `/` */) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now. if (seenNonSlash) { start = index + 1; break } } else { if (firstNonSlashEnd < 0) { // We saw the first non-path separator, remember this index in case // we need it if the extension ends up not matching. seenNonSlash = true; firstNonSlashEnd = index + 1; } if (extIndex > -1) { // Try to match the explicit extension. if (path.codePointAt(index) === ext.codePointAt(extIndex--)) { if (extIndex < 0) { // We matched the extension, so mark this as the end of our path // component end = index; } } else { // Extension does not match, so our result is the entire path // component extIndex = -1; end = firstNonSlashEnd; } } } } if (start === end) { end = firstNonSlashEnd; } else if (end < 0) { end = path.length; } return path.slice(start, end) } /** * Get the dirname from a path. * * @param {string} path * File path. * @returns {string} * File path. */ function dirname$1(path) { assertPath$3(path); if (path.length === 0) { return '.' } let end = -1; let index = path.length; /** @type {boolean | undefined} */ let unmatchedSlash; // Prefix `--` is important to not run on `0`. while (--index) { if (path.codePointAt(index) === 47 /* `/` */) { if (unmatchedSlash) { end = index; break } } else if (!unmatchedSlash) { // We saw the first non-path separator unmatchedSlash = true; } } return end < 0 ? path.codePointAt(0) === 47 /* `/` */ ? '/' : '.' : end === 1 && path.codePointAt(0) === 47 /* `/` */ ? '//' : path.slice(0, end) } /** * Get an extname from a path. * * @param {string} path * File path. * @returns {string} * Extname. */ function extname$1(path) { assertPath$3(path); let index = path.length; let end = -1; let startPart = 0; let startDot = -1; // Track the state of characters (if any) we see before our first dot and // after any path separator we find. let preDotState = 0; /** @type {boolean | undefined} */ let unmatchedSlash; while (index--) { const code = path.codePointAt(index); if (code === 47 /* `/` */) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now. if (unmatchedSlash) { startPart = index + 1; break } continue } if (end < 0) { // We saw the first non-path separator, mark this as the end of our // extension. unmatchedSlash = true; end = index + 1; } if (code === 46 /* `.` */) { // If this is our first dot, mark it as the start of our extension. if (startDot < 0) { startDot = index; } else if (preDotState !== 1) { preDotState = 1; } } else if (startDot > -1) { // We saw a non-dot and non-path separator before our dot, so we should // have a good chance at having a non-empty extension. preDotState = -1; } } if ( startDot < 0 || end < 0 || // We saw a non-dot character immediately before the dot. preDotState === 0 || // The (right-most) trimmed path component is exactly `..`. (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) ) { return '' } return path.slice(startDot, end) } /** * Join segments from a path. * * @param {Array<string>} segments * Path segments. * @returns {string} * File path. */ function join$1(...segments) { let index = -1; /** @type {string | undefined} */ let joined; while (++index < segments.length) { assertPath$3(segments[index]); if (segments[index]) { joined = joined === undefined ? segments[index] : joined + '/' + segments[index]; } } return joined === undefined ? '.' : normalize$3(joined) } /** * Normalize a basic file path. * * @param {string} path * File path. * @returns {string} * File path. */ // Note: `normalize` is not exposed as `path.normalize`, so some code is // manually removed from it. function normalize$3(path) { assertPath$3(path); const absolute = path.codePointAt(0) === 47; /* `/` */ // Normalize the path according to POSIX rules. let value = normalizeString$1(path, !absolute); if (value.length === 0 && !absolute) { value = '.'; } if (value.length > 0 && path.codePointAt(path.length - 1) === 47 /* / */) { value += '/'; } return absolute ? '/' + value : value } /** * Resolve `.` and `..` elements in a path with directory names. * * @param {string} path * File path. * @param {boolean} allowAboveRoot * Whether `..` can move above root. * @returns {string} * File path. */ function normalizeString$1(path, allowAboveRoot) { let result = ''; let lastSegmentLength = 0; let lastSlash = -1; let dots = 0; let index = -1; /** @type {number | undefined} */ let code; /** @type {number} */ let lastSlashIndex; while (++index <= path.length) { if (index < path.length) { code = path.codePointAt(index); } else if (code === 47 /* `/` */) { break } else { code = 47; /* `/` */ } if (code === 47 /* `/` */) { if (lastSlash === index - 1 || dots === 1) ; else if (lastSlash !== index - 1 && dots === 2) { if ( result.length < 2 || lastSegmentLength !== 2 || result.codePointAt(result.length - 1) !== 46 /* `.` */ || result.codePointAt(result.length - 2) !== 46 /* `.` */ ) { if (result.length > 2) { lastSlashIndex = result.lastIndexOf('/'); if (lastSlashIndex !== result.length - 1) { if (lastSlashIndex < 0) { result = ''; lastSegmentLength = 0; } else { result = result.slice(0, lastSlashIndex); lastSegmentLength = result.length - 1 - result.lastIndexOf('/'); } lastSlash = index; dots = 0; continue } } else if (result.length > 0) { result = ''; lastSegmentLength = 0; lastSlash = index; dots = 0; continue } } if (allowAboveRoot) { result = result.length > 0 ? result + '/..' : '..'; lastSegmentLength = 2; } } else { if (result.length > 0) { result += '/' + path.slice(lastSlash + 1, index); } else { result = path.slice(lastSlash + 1, index); } lastSegmentLength = index - lastSlash - 1; } lastSlash = index; dots = 0; } else if (code === 46 /* `.` */ && dots > -1) { dots++; } else { dots = -1; } } return result } /** * Make sure `path` is a string. * * @param {string} path * File path. * @returns {asserts path is string} * Nothing. */ function assertPath$3(path) { if (typeof path !== 'string') { throw new TypeError( 'Path must be a string. Received ' + JSON.stringify(path) ) } } /* eslint-enable max-depth, complexity */ // Somewhat based on: // <https://github.com/defunctzombie/node-process/blob/master/browser.js>. // But I don’t think one tiny line of code can be copyrighted. 😅 const proc = {cwd: cwd$1}; function cwd$1() { return '/' } /** * Checks if a value has the shape of a WHATWG URL object. * * Using a symbol or instanceof would not be able to recognize URL objects * coming from other implementations (e.g. in Electron), so instead we are * checking some well known properties for a lack of a better test. * * We use `href` and `protocol` as they are the only properties that are * easy to retrieve and calculate due to the lazy nature of the getters. * * We check for auth attribute to distinguish legacy url instance with * WHATWG URL instance. * * @param {unknown} fileUrlOrPath * File path or URL. * @returns {fileUrlOrPath is URL} * Whether it’s a URL. */ // From: <https://github.com/nodejs/node/blob/6a3403c/lib/internal/url.js#L720> function isUrl$1(fileUrlOrPath) { return Boolean( fileUrlOrPath !== null && typeof fileUrlOrPath === 'object' && 'href' in fileUrlOrPath && fileUrlOrPath.href && 'protocol' in fileUrlOrPath && fileUrlOrPath.protocol && // @ts-expect-error: indexing is fine. fileUrlOrPath.auth === undefined ) } // See: <https://github.com/nodejs/node/blob/6a3403c/lib/internal/url.js> /** * @param {URL | string} path * File URL. * @returns {string} * File URL. */ function urlToPath$1(path) { if (typeof path === 'string') { path = new URL(path); } else if (!isUrl$1(path)) { /** @type {NodeJS.ErrnoException} */ const error = new TypeError( 'The "path" argument must be of type string or an instance of URL. Received `' + path + '`' ); error.code = 'ERR_INVALID_ARG_TYPE'; throw error } if (path.protocol !== 'file:') { /** @type {NodeJS.ErrnoException} */ const error = new TypeError('The URL must be of scheme file'); error.code = 'ERR_INVALID_URL_SCHEME'; throw error } return getPathFromURLPosix$1(path) } /** * Get a path from a POSIX URL. * * @param {URL} url * URL. * @returns {string} * File path. */ function getPathFromURLPosix$1(url) { if (url.hostname !== '') { /** @type {NodeJS.ErrnoException} */ const error = new TypeError( 'File URL host must be "localhost" or empty on darwin' ); error.code = 'ERR_INVALID_FILE_URL_HOST'; throw error } const pathname = url.pathname; let index = -1; while (++index < pathname.length) { if ( pathname.codePointAt(index) === 37 /* `%` */ && pathname.codePointAt(index + 1) === 50 /* `2` */ ) { const third = pathname.codePointAt(index + 2); if (third === 70 /* `F` */ || third === 102 /* `f` */) { /** @type {NodeJS.ErrnoException} */ const error = new TypeError( 'File URL path must not include encoded / characters' ); error.code = 'ERR_INVALID_FILE_URL_PATH'; throw error } } } return decodeURIComponent(pathname) } /** * @typedef {import('unist').Node} Node * @typedef {import('unist').Point} Point * @typedef {import('unist').Position} Position * @typedef {import('vfile-message').Options} MessageOptions * @typedef {import('../index.js').Data} Data * @typedef {import('../index.js').Value} Value */ /** * 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$1 = /** @type {const} */ ([ 'history', 'path', 'basename', 'stem', 'extname', 'dirname' ]); let VFile$1 = class VFile { /** * Create a new virtual file. * * `options` is treated as: * * * `string` or `Uint8Array` — `{value: options}` * * `URL` — `{path: options}` * * `VFile` — shallow copies its data over to the new file * * `object` — all fields are shallow copied over to the new file * * Path related fields are set in the following order (least specific to * most specific): `history`, `path`, `basename`, `stem`, `extname`, * `dirname`. * * You cannot set `dirname` or `extname` without setting either `history`, * `path`, `basename`, or `stem` too. * * @param {Compatible | null | undefined} [value] * File value. * @returns * New instance. */ constructor(value) { /** @type {Options | VFile} */ let options; if (!value) { options = {}; } else if (isUrl$1(value)) { options = {path: value}; } else if (typeof value === 'string' || isUint8Array$2(value)) { options = {value}; } else { options = value; } /* eslint-disable no-unused-expressions */ /** * Base of `path` (default: `process.cwd()` or `'/'` in browsers). * * @type {string} */ this.cwd = proc.cwd(); /** * Place to store custom info (default: `{}`). * * It’s OK to store custom data directly on the file but moving it to * `data` is recommended. * * @type {Data} */ this.data = {}; /** * List of file paths the file moved between. * * The first is the original path and the last is the current path. * * @type {Array<string>} */ this.history = []; /** * List of messages associated with the file. * * @type {Array<VFileMessage>} */ this.messages = []; /* eslint-enable no-unused-expressions */ // Set path related properties in the correct order. let index = -1; while (++index < order$1.length) { const prop = order$1[index]; // Note: we specifically use `in` instead of `hasOwnProperty` to accept // `vfile`s too. if ( prop in options && options[prop] !== undefined && options[prop] !== null ) { // @ts-expect-error: TS doesn’t understand basic reality. 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$1.includes(prop)) { // @ts-expect-error: fine to set other things. this[prop] = options[prop]; } } } /** * Get the basename (including extname) (example: `'index.min.js'`). * * @returns {string | undefined} * Basename. */ get basename() { return typeof this.path === 'string' ? path.basename(this.path) : undefined } /** * Set basename (including extname) (`'index.min.js'`). * * Cannot contain path separators (`'/'` on unix, macOS, and browsers, `'\'` * on windows). * Cannot be nullified (use `file.path = file.dirname` instead). * * @param {string} basename * Basename. * @returns {undefined} * Nothing. */ set basename(basename) { assertNonEmpty$1(basename, 'basename'); assertPart$1(basename, 'basename'); this.path = path.join(this.dirname || '', basename); } /** * Get the parent path (example: `'~'`). * * @returns {string | undefined} * Dirname. */ get dirname() { return typeof this.path === 'string' ? path.dirname(this.path) : undefined } /** * Set the parent path (example: `'~'`). * * Cannot be set if there’s no `path` yet. * * @param {string | undefined} dirname * Dirname. * @returns {undefined} * Nothing. */ set dirname(dirname) { assertPath$2(this.basename, 'dirname'); this.path = path.join(dirname || '', this.basename); } /** * Get the extname (including dot) (example: `'.js'`). * * @returns {string | undefined} * Extname. */ get extname() { return typeof this.path === 'string' ? path.extname(this.path) : undefined } /** * Set the extname (including dot) (example: `'.js'`). * * Cannot contain path separators (`'/'` on unix, macOS, and browsers, `'\'` * on windows). * Cannot be set if there’s no `path` yet. * * @param {string | undefined} extname * Extname. * @returns {undefined} * Nothing. */ set extname(extname) { assertPart$1(extname, 'extname'); assertPath$2(this.dirname, 'extname'); if (extname) { if (extname.codePointAt(0) !== 46 /* `.` */) { throw new Error('`extname` must start with `.`') } if (extname.includes('.', 1)) { throw new Error('`extname` cannot contain multiple dots') } } this.path = path.join(this.dirname, this.stem + (extname || '')); } /** * Get the full path (example: `'~/index.min.js'`). * * @returns {string} * Path. */ get path() { return this.history[this.history.length - 1] } /** * Set the full path (example: `'~/index.min.js'`). * * Cannot be nullified. * You can set a file URL (a `URL` object with a `file:` protocol) which will * be turned into a path with `url.fileURLToPath`. * * @param {URL | string} path * Path. * @returns {undefined} * Nothing. */ set path(path) { if (isUrl$1(path)) { path = urlToPath$1(path); } assertNonEmpty$1(path, 'path'); if (this.path !== path) { this.history.push(path); } } /** * Get the stem (basename w/o extname) (example: `'index.min'`). * * @returns {string | undefined} * Stem. */ get stem() { return typeof this.path === 'string' ? path.basename(this.path, this.extname) : undefined } /** * Set the stem (basename w/o extname) (example: `'index.min'`). * * Cannot contain path separators (`'/'` on unix, macOS, and browsers, `'\'` * on windows). * Cannot be nullified (use `file.path = file.dirname` instead). * * @param {string} stem * Stem. * @returns {undefined} * Nothing. */ set stem(stem) { assertNonEmpty$1(stem, 'stem'); assertPart$1(stem, 'stem'); this.path = path.join(this.dirname || '', stem + (this.extname || '')); } // Normal prototypal methods. /** * Create a fatal message for `reason` associated with the file. * * The `fatal` field of the message is set to `true` (error; file not usable) * and the `file` field is set to the current file path. * The message is added to the `messages` field on `file`. * * > 🪦 **Note**: also has obsolete signatures. * * @overload * @param {string} reason * @param {MessageOptions | null | undefined} [options] * @returns {never} * * @overload * @param {string} reason * @param {Node | NodeLike | null | undefined} parent * @param {string | null | undefined} [origin] * @returns {never} * * @overload * @param {string} reason * @param {Point | Position | null | undefined} place * @param {string | null | undefined} [origin] * @returns {never} * * @overload * @param {string} reason * @param {string | null | undefined} [origin] * @returns {never} * * @overload * @param {Error | VFileMessage} cause * @param {Node | NodeLike | null | undefined} parent * @param {string | null | undefined} [origin] * @returns {never} * * @overload * @param {Error | VFileMessage} cause * @param {Point | Position | null | undefined} place * @param {string | null | undefined} [origin] * @returns {never} * * @overload * @param {Error | VFileMessage} cause * @param {string | null | undefined} [origin] * @returns {never} * * @param {Error | VFileMessage | string} causeOrReason * Reason for message, should use markdown. * @param {Node | NodeLike | MessageOptions | Point | Position | string | null | undefined} [optionsOrParentOrPlace] * Configuration (optional). * @param {string | null | undefined} [origin] * Place in code where the message originates (example: * `'my-package:my-rule'` or `'my-rule'`). * @returns {never} * Never. * @throws {VFileMessage} * Message. */ fail(causeOrReason, optionsOrParentOrPlace, origin) { // @ts-expect-error: the overloads are fine. const message = this.message(causeOrReason, optionsOrParentOrPlace, origin); message.fatal = true; throw message } /** * Create an info message for `reason` associated with the file. * * The `fatal` field of the message is set to `undefined` (info; change * likely not needed) and the `file` field is set to the current file path. * The message is added to the `messages` field on `file`. * * > 🪦 **Note**: also has obsolete signatures. * * @overload * @param {string} reason * @param {MessageOptions | null | undefined} [options] * @returns {VFileMessage} * * @overload * @param {string} reason * @param {Node | NodeLike | null | undefined} parent * @param {string | null | undefined} [origin] * @returns {VFileMessage} * * @overload * @param {string} reason * @param {Point | Position | null | undefined} place * @param {string | null | undefined} [origin] * @returns {VFileMessage} * * @overload * @param {string} reason * @param {string | null | undefined} [origin] * @returns {VFileMessage} * * @overload * @param {Error | VFileMessage} cause * @param {Node | NodeLike | null | undefined} parent * @param {string | null | undefined} [origin] * @returns {VFileMessage} * * @overload * @param {Error | VFileMessage} cause * @param {Point | Position | null | undefined} place * @param {string | null | undefined} [origin] * @returns {VFileMessage} * * @overload * @param {Error | VFileMessage} cause * @param {string | null | undefined} [origin] * @returns {VFileMessage} * * @param {Error | VFileMessage | string} causeOrReason * Reason for message, should use markdown. * @param {Node | NodeLike | MessageOptions | Point | Position | string | null | undefined} [optionsOrParentOrPlace] * Configuration (optional). * @param {string | null | undefined} [origin] * Place in code where the message originates (example: * `'my-package:my-rule'` or `'my-rule'`). * @returns {VFileMessage} * Message. */ info(causeOrReason, optionsOrParentOrPlace, origin) { // @ts-expect-error: the overloads are fine. const message = this.message(causeOrReason, optionsOrParentOrPlace, origin); message.fatal = undefined; return message } /** * Create a message for `reason` associated with the file. * * The `fatal` field of the message is set to `false` (warning; change may be * needed) and the `file` field is set to the current file path. * The message is added to the `messages` field on `file`. * * > 🪦 **Note**: also has obsolete signatures. * * @overload * @param {string} reason * @param {MessageOptions | null | undefined} [options] * @returns {VFileMessage} * * @overload * @param {string} reason * @param {Node | NodeLike | null | undefined} parent * @param {string | null | undefined} [origin] * @returns {VFileMessage} * * @overload * @param {string} reason * @param {Point | Position | null | undefined} place * @param {string | null | undefined} [origin] * @returns {VFileMessage} * * @overload * @param {string} reason * @param {string | null | undefined} [origin] * @returns {VFileMessage} * * @overload * @param {Error | VFileMessage} cause * @param {Node | NodeLike | null | undefined} parent * @param {string | null | undefined} [origin] * @returns {VFileMessage} * * @overload * @param {Error | VFileMessage} cause * @param {Point | Position | null | undefined} place * @param {string | null | undefined} [origin] * @returns {VFileMessage} * * @overload * @param {Error | VFileMessage} cause * @param {string | null | undefined} [origin] * @returns {VFileMessage} * * @param {Error | VFileMessage | string} causeOrReason * Reason for message, should use markdown. * @param {Node | NodeLike | MessageOptions | Point | Position | string | null | undefined} [optionsOrParentOrPlace] * Configuration (optional). * @param {string | null | undefined} [origin] * Place in code where the message originates (example: * `'my-package:my-rule'` or `'my-rule'`). * @returns {VFileMessage} * Message. */ message(causeOrReason, optionsOrParentOrPlace, origin) { const message = new VFileMessage$1( // @ts-expect-error: the overloads are fine. causeOrReason, optionsOrParentOrPlace, origin ); if (this.path) { message.name = this.path + ':' + message.name; message.file = this.path; } message.fatal = false; this.messages.push(message); return message } /** * Serialize the file. * * > **Note**: which encodings are supported depends on the engine. * > For info on Node.js, see: * > <https://nodejs.org/api/util.html#whatwg-supported-encodings>. * * @param {string | null | undefined} [encoding='utf8'] * Character encoding to understand `value` as when it’s a `Uint8Array` * (default: `'utf-8'`). * @returns {string} * Serialized file. */ toString(encoding) { if (this.value === undefined) { return '' } if (typeof this.value === 'string') { return this.value } const decoder = new TextDecoder(encoding || undefined); return decoder.decode(this.value) } }; /** * Assert that `part` is not a path (as in, does not contain `path.sep`). * * @param {string | null | undefined} part * File path part. * @param {string} name * Part name. * @returns {undefined} * Nothing. */ function assertPart$1(part, name) { if (part && part.includes(path.sep)) { throw new Error( '`' + name + '` cannot be a path: did not expect `' + path.sep + '`' ) } } /** * Assert that `part` is not empty. * * @param {string | undefined} part * Thing. * @param {string} name * Part name. * @returns {asserts part is string} * Nothing. */ function assertNonEmpty$1(part, name) { if (!part) { throw new Error('`' + name + '` cannot be empty') } } /** * Assert `path` exists. * * @param {string | undefined} path * Path. * @param {string} name * Dependency name. * @returns {asserts path is string} * Nothing. */ function assertPath$2(path, name) { if (!path) { throw new Error('Setting `' + name + '` requires `path` to be set too') } } /** * Assert `value` is an `Uint8Array`. * * @param {unknown} value * thing. * @returns {value is Uint8Array} * Whether `value` is an `Uint8Array`. */ function isUint8Array$2(value) { return Boolean( value && typeof value === 'object' && 'byteLength' in value && 'byteOffset' in value ) } const CallableInstance = /** * @type {new <Parameters extends Array<unknown>, Result>(property: string | symbol) => (...parameters: Parameters) => Result} */ ( /** @type {unknown} */ ( /** * @this {Function} * @param {string | symbol} property * @returns {(...parameters: Array<unknown>) => unknown} */ function (property) { const self = this; const constr = self.constructor; const proto = /** @type {Record<string | symbol, Function>} */ ( // Prototypes do exist. // type-coverage:ignore-next-line constr.prototype ); const value = proto[property]; /** @type {(...parameters: Array<unknown>) => unknown} */ const apply = function () { return value.apply(apply, arguments) }; Object.setPrototypeOf(apply, proto); // Not needed for us in `unified`: we only call this on the `copy` // function, // and we don't need to add its fields (`length`, `name`) // over. // See also: GH-246. // const names = Object.getOwnPropertyNames(value) // // for (const p of names) { // const descriptor = Object.getOwnPropertyDescriptor(value, p) // if (descriptor) Object.defineProperty(apply, p, descriptor) // } return apply } ) ); /** * @typedef {import('trough').Pipeline} Pipeline * * @typedef {import('unist').Node} Node * * @typedef {import('vfile').Compatible} Compatible * @typedef {import('vfile').Value} Value * * @typedef {import('../index.js').CompileResultMap} CompileResultMap * @typedef {import('../index.js').Data} Data * @typedef {import('../index.js').Settings} Settings */ // To do: next major: drop `Compiler`, `Parser`: prefer lowercase. // To do: we could start yielding `never` in TS when a parser is missing and // `parse` is called. // Currently, we allow directly setting `processor.parser`, which is untyped. const own$8 = {}.hasOwnProperty; /** * @template {Node | undefined} [ParseTree=undefined] * Output of `parse` (optional). * @template {Node | undefined} [HeadTree=undefined] * Input for `run` (optional). * @template {Node | undefined} [TailTree=undefined] * Output for `run` (optional). * @template {Node | undefined} [CompileTree=undefined] * Input of `stringify` (optional). * @template {CompileResults | undefined} [CompileResult=undefined] * Output of `stringify` (optional). * @extends {CallableInstance<[], Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>>} */ class Processor extends CallableInstance { /** * Create a processor. */ constructor() { // If `Processor()` is called (w/o new), `copy` is called instead. super('copy'); /** * Compiler to use (deprecated). * * @deprecated * Use `compiler` instead. * @type {( * Compiler<