| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- //#region src/utils.ts
- const postfixRE = /[?#].*$/;
- function cleanUrl(url) {
- return url.replace(postfixRE, "");
- }
- function extractQueryWithoutFragment(url) {
- const questionMarkIndex = url.indexOf("?");
- if (questionMarkIndex === -1) return "";
- const fragmentIndex = url.indexOf("#", questionMarkIndex);
- if (fragmentIndex === -1) return url.substring(questionMarkIndex);
- else return url.substring(questionMarkIndex, fragmentIndex);
- }
- //#endregion
- //#region src/composable-filters.ts
- var And = class {
- kind;
- args;
- constructor(...args) {
- if (args.length === 0) throw new Error("`And` expects at least one operand");
- this.args = args;
- this.kind = "and";
- }
- };
- var Or = class {
- kind;
- args;
- constructor(...args) {
- if (args.length === 0) throw new Error("`Or` expects at least one operand");
- this.args = args;
- this.kind = "or";
- }
- };
- var Not = class {
- kind;
- expr;
- constructor(expr) {
- this.expr = expr;
- this.kind = "not";
- }
- };
- var Id = class {
- kind;
- pattern;
- params;
- constructor(pattern, params) {
- this.pattern = pattern;
- this.kind = "id";
- this.params = params ?? { cleanUrl: false };
- }
- };
- var ModuleType = class {
- kind;
- pattern;
- constructor(pattern) {
- this.pattern = pattern;
- this.kind = "moduleType";
- }
- };
- var Code = class {
- kind;
- pattern;
- constructor(expr) {
- this.pattern = expr;
- this.kind = "code";
- }
- };
- var Query = class {
- kind;
- key;
- pattern;
- constructor(key, pattern) {
- this.pattern = pattern;
- this.key = key;
- this.kind = "query";
- }
- };
- var Include = class {
- kind;
- expr;
- constructor(expr) {
- this.expr = expr;
- this.kind = "include";
- }
- };
- var Exclude = class {
- kind;
- expr;
- constructor(expr) {
- this.expr = expr;
- this.kind = "exclude";
- }
- };
- function and(...args) {
- return new And(...args);
- }
- function or(...args) {
- return new Or(...args);
- }
- function not(expr) {
- return new Not(expr);
- }
- function id(pattern, params) {
- return new Id(pattern, params);
- }
- function moduleType(pattern) {
- return new ModuleType(pattern);
- }
- function code(pattern) {
- return new Code(pattern);
- }
- function query(key, pattern) {
- return new Query(key, pattern);
- }
- function include(expr) {
- return new Include(expr);
- }
- function exclude(expr) {
- return new Exclude(expr);
- }
- /**
- * convert a queryObject to FilterExpression like
- * ```js
- * and(query(k1, v1), query(k2, v2))
- * ```
- * @param queryFilterObject The query filter object needs to be matched.
- * @returns a `And` FilterExpression
- */
- function queries(queryFilter) {
- let arr = Object.entries(queryFilter).map(([key, value]) => {
- return new Query(key, value);
- });
- return and(...arr);
- }
- function interpreter(exprs, code$1, id$1, moduleType$1) {
- let arr = [];
- if (Array.isArray(exprs)) arr = exprs;
- else arr = [exprs];
- return interpreterImpl(arr, code$1, id$1, moduleType$1);
- }
- function interpreterImpl(expr, code$1, id$1, moduleType$1, ctx = {}) {
- let hasInclude = false;
- for (const e of expr) switch (e.kind) {
- case "include": {
- hasInclude = true;
- if (exprInterpreter(e.expr, code$1, id$1, moduleType$1, ctx)) return true;
- break;
- }
- case "exclude": {
- if (exprInterpreter(e.expr, code$1, id$1, moduleType$1)) return false;
- break;
- }
- }
- return !hasInclude;
- }
- function exprInterpreter(expr, code$1, id$1, moduleType$1, ctx = {}) {
- switch (expr.kind) {
- case "and": return expr.args.every((e) => exprInterpreter(e, code$1, id$1, moduleType$1, ctx));
- case "or": return expr.args.some((e) => exprInterpreter(e, code$1, id$1, moduleType$1, ctx));
- case "not": return !exprInterpreter(expr.expr, code$1, id$1, moduleType$1, ctx);
- case "id": {
- if (id$1 === void 0) throw new Error("`id` is required for `id` expression");
- if (expr.params.cleanUrl) id$1 = cleanUrl(id$1);
- return typeof expr.pattern === "string" ? id$1 === expr.pattern : expr.pattern.test(id$1);
- }
- case "moduleType": {
- if (moduleType$1 === void 0) throw new Error("`moduleType` is required for `moduleType` expression");
- return moduleType$1 === expr.pattern;
- }
- case "code": {
- if (code$1 === void 0) throw new Error("`code` is required for `code` expression");
- return typeof expr.pattern === "string" ? code$1.includes(expr.pattern) : expr.pattern.test(code$1);
- }
- case "query": {
- if (id$1 === void 0) throw new Error("`id` is required for `Query` expression");
- if (!ctx.urlSearchParamsCache) {
- let queryString = extractQueryWithoutFragment(id$1);
- ctx.urlSearchParamsCache = new URLSearchParams(queryString);
- }
- let urlParams = ctx.urlSearchParamsCache;
- if (typeof expr.pattern === "boolean") if (expr.pattern) return urlParams.has(expr.key);
- else return !urlParams.has(expr.key);
- else if (typeof expr.pattern === "string") return urlParams.get(expr.key) === expr.pattern;
- else return expr.pattern.test(urlParams.get(expr.key) ?? "");
- }
- default: throw new Error(`Expression ${JSON.stringify(expr)} is not expected.`);
- }
- }
- //#endregion
- //#region src/simple-filters.ts
- /**
- * Constructs a RegExp that matches the exact string specified.
- *
- * This is useful for plugin hook filters.
- *
- * @param str the string to match.
- * @param flags flags for the RegExp.
- *
- * @example
- * ```ts
- * import { exactRegex } from '@rolldown/pluginutils';
- * const plugin = {
- * name: 'plugin',
- * resolveId: {
- * filter: { id: exactRegex('foo') },
- * handler(id) {} // will only be called for `foo`
- * }
- * }
- * ```
- */
- function exactRegex(str, flags) {
- return new RegExp(`^${escapeRegex(str)}$`, flags);
- }
- /**
- * Constructs a RegExp that matches a value that has the specified prefix.
- *
- * This is useful for plugin hook filters.
- *
- * @param str the string to match.
- * @param flags flags for the RegExp.
- *
- * @example
- * ```ts
- * import { prefixRegex } from '@rolldown/pluginutils';
- * const plugin = {
- * name: 'plugin',
- * resolveId: {
- * filter: { id: prefixRegex('foo') },
- * handler(id) {} // will only be called for IDs starting with `foo`
- * }
- * }
- * ```
- */
- function prefixRegex(str, flags) {
- return new RegExp(`^${escapeRegex(str)}`, flags);
- }
- const escapeRegexRE = /[-/\\^$*+?.()|[\]{}]/g;
- function escapeRegex(str) {
- return str.replace(escapeRegexRE, "\\$&");
- }
- function makeIdFiltersToMatchWithQuery(input) {
- if (!Array.isArray(input)) return makeIdFilterToMatchWithQuery(input);
- return input.map((i) => makeIdFilterToMatchWithQuery(i));
- }
- function makeIdFilterToMatchWithQuery(input) {
- if (typeof input === "string") return `${input}{?*,}`;
- return makeRegexIdFilterToMatchWithQuery(input);
- }
- function makeRegexIdFilterToMatchWithQuery(input) {
- return new RegExp(input.source.replace(/(?<!\\)\$/g, "(?:\\?.*)?$"), input.flags);
- }
- //#endregion
- export { and, code, exactRegex, exclude, exprInterpreter, id, include, interpreter, interpreterImpl, makeIdFiltersToMatchWithQuery, moduleType, not, or, prefixRegex, queries, query };
|