@vltpkg/query 0.0.0-12 → 0.0.0-13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/attribute.d.ts.map +1 -1
- package/dist/esm/attribute.js +4 -11
- package/dist/esm/attribute.js.map +1 -1
- package/dist/esm/id.d.ts.map +1 -1
- package/dist/esm/id.js +2 -0
- package/dist/esm/id.js.map +1 -1
- package/dist/esm/index.d.ts +59 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +201 -8
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/pseudo/outdated.d.ts.map +1 -1
- package/dist/esm/pseudo/outdated.js +3 -3
- package/dist/esm/pseudo/outdated.js.map +1 -1
- package/dist/esm/pseudo/published.d.ts.map +1 -1
- package/dist/esm/pseudo/published.js +1 -2
- package/dist/esm/pseudo/published.js.map +1 -1
- package/dist/esm/pseudo/root.d.ts +8 -0
- package/dist/esm/pseudo/root.d.ts.map +1 -0
- package/dist/esm/pseudo/root.js +22 -0
- package/dist/esm/pseudo/root.js.map +1 -0
- package/dist/esm/pseudo/semver.d.ts.map +1 -1
- package/dist/esm/pseudo/semver.js +2 -1
- package/dist/esm/pseudo/semver.js.map +1 -1
- package/dist/esm/pseudo/type.d.ts +8 -0
- package/dist/esm/pseudo/type.d.ts.map +1 -0
- package/dist/esm/pseudo/type.js +22 -0
- package/dist/esm/pseudo/type.js.map +1 -0
- package/dist/esm/pseudo/workspace.d.ts.map +1 -1
- package/dist/esm/pseudo/workspace.js +5 -2
- package/dist/esm/pseudo/workspace.js.map +1 -1
- package/dist/esm/pseudo.d.ts.map +1 -1
- package/dist/esm/pseudo.js +21 -38
- package/dist/esm/pseudo.js.map +1 -1
- package/dist/esm/types.d.ts +10 -0
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/types.js +13 -0
- package/dist/esm/types.js.map +1 -1
- package/package.json +8 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attribute.d.ts","sourceRoot":"","sources":["../../src/attribute.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAG7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"attribute.d.ts","sourceRoot":"","sources":["../../src/attribute.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAG7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAG7C,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAA;AAOpE;;;GAGG;AACH,eAAO,MAAM,yBAAyB,SAC9B,QAAQ,cACF,MAAM,EAAE,aACT,MAAM,KAChB,MAAM,EAAE,GAAG,SA+Db,CAAA;AAID,eAAO,MAAM,gBAAgB,UACpB,WAAW,cACN,YAAY,GAAG,SAAS,SAC7B,MAAM,gBACC,MAAM,eACP,OAAO,qBACF,MAAM,EAAE,KACzB,WAsCF,CAAA;AAcD,eAAO,MAAM,qBAAqB,2BAEjC,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,UACb,WAAW,KACjB,OAAO,CAAC,WAAW,CA6BrB,CAAA"}
|
package/dist/esm/attribute.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { error } from '@vltpkg/error-cause';
|
|
2
2
|
import { asAttributeNode } from "./types.js";
|
|
3
|
+
import { removeDanglingEdges } from "./pseudo/helpers.js";
|
|
3
4
|
// JSONField has a mapped type constituent that would coerce to [object Object]
|
|
4
5
|
// when stringified, which is what we want in this case.
|
|
5
6
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
@@ -93,17 +94,7 @@ export const filterAttributes = (state, comparator, value, propertyName, insensi
|
|
|
93
94
|
deleteNode(node);
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
|
-
|
|
97
|
-
// edge.name is a special case in order
|
|
98
|
-
// to be able to match missing nodes by name
|
|
99
|
-
if (propertyName === 'name' && check(edge.name)) {
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
// remove any remaining dangling edge
|
|
103
|
-
if (!edge.to) {
|
|
104
|
-
state.partial.edges.delete(edge);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
97
|
+
removeDanglingEdges(state);
|
|
107
98
|
return state;
|
|
108
99
|
};
|
|
109
100
|
// ref: https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors
|
|
@@ -135,6 +126,8 @@ export const attribute = async (state) => {
|
|
|
135
126
|
const value = curr.value || '';
|
|
136
127
|
const propertyName = curr.attribute;
|
|
137
128
|
const insensitive = !!curr.insensitive;
|
|
129
|
+
// Increment the commonCounter for specificity
|
|
130
|
+
state.specificity.commonCounter += 1;
|
|
138
131
|
return filterAttributes(state, operatorFn, value, propertyName, insensitive);
|
|
139
132
|
};
|
|
140
133
|
//# sourceMappingURL=attribute.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attribute.js","sourceRoot":"","sources":["../../src/attribute.ts"],"names":[],"mappings":"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","sourcesContent":["import { error } from '@vltpkg/error-cause'\nimport type { NodeLike } from '@vltpkg/graph'\nimport type { JSONField, Manifest } from '@vltpkg/types'\nimport { asAttributeNode } from './types.ts'\nimport type { ParserState } from './types.ts'\n\nexport type ComparatorFn = (attr: string, value?: string) => boolean\n\n// JSONField has a mapped type constituent that would coerce to [object Object]\n// when stringified, which is what we want in this case.\n// eslint-disable-next-line @typescript-eslint/no-base-to-string\nconst jsonFieldToString = (v: JSONField) => String(v)\n\n/**\n * Retrieve the {@link Manifest} values found at the given `properties`\n * location for a given {@link Node}.\n */\nexport const getManifestPropertyValues = (\n node: NodeLike,\n properties: string[],\n attribute: string,\n): string[] | undefined => {\n if (!node.manifest) return\n\n const traverse = new Set<JSONField>([node.manifest as JSONField])\n const props = new Set<JSONField>()\n for (const key of properties) {\n for (const prop of traverse) {\n /* c8 ignore start - should be impossible */\n if (!prop) {\n throw error('failed to find nested property in :attr', {\n found: properties,\n })\n }\n /* c8 ignore stop */\n\n // expand the result list to include nested array values\n if (Array.isArray(prop)) {\n for (const p of prop) {\n traverse.add(p)\n }\n continue\n }\n\n // guard for inspecting keys of objects next\n if (\n typeof prop === 'string' ||\n typeof prop === 'number' ||\n typeof prop === 'boolean'\n ) {\n continue\n }\n\n // assign next value when found\n if (key in prop) {\n const nextValue = prop[key]\n if (nextValue) {\n if (key === attribute) {\n props.add(nextValue)\n } else {\n traverse.delete(prop)\n traverse.add(nextValue)\n }\n }\n }\n }\n }\n // if no value was found after trying a given key\n // then there's nothing to be collected\n if (!props.size) return\n\n // expand the result to include array values\n const collect = new Set<string>()\n for (const prop of props) {\n if (Array.isArray(prop)) {\n for (const p of prop) {\n collect.add(p ? jsonFieldToString(p) : '')\n }\n } else {\n collect.add(jsonFieldToString(prop))\n }\n }\n\n return [...collect]\n}\n\n// decorator style of function that will filter `ParserState` results\n// based on a provided `comparator` function\nexport const filterAttributes = (\n state: ParserState,\n comparator: ComparatorFn | undefined,\n value: string,\n propertyName: string,\n insensitive: boolean,\n prefixProperties: string[] = [],\n): ParserState => {\n const check = (attr: JSONField) =>\n comparator?.(\n insensitive ?\n jsonFieldToString(attr).toLowerCase()\n : jsonFieldToString(attr),\n insensitive ? value.toLowerCase() : value,\n )\n const deleteNode = (node: NodeLike) => {\n for (const edge of node.edgesIn) {\n state.partial.edges.delete(edge)\n }\n state.partial.nodes.delete(node)\n }\n\n for (const node of state.partial.nodes) {\n const prefixes =\n prefixProperties.length ? prefixProperties : [propertyName]\n const attrs = getManifestPropertyValues(\n node,\n prefixes,\n propertyName,\n )\n\n // if no attribute value was found, that means the attribute won't match\n if (!attrs?.length) {\n deleteNode(node)\n continue\n }\n\n // if the node attribute value won't match, then remove the node\n if (comparator && !attrs.some(check)) {\n deleteNode(node)\n }\n }\n\n for (const edge of state.partial.edges) {\n // edge.name is a special case in order\n // to be able to match missing nodes by name\n if (propertyName === 'name' && check(edge.name)) {\n continue\n }\n // remove any remaining dangling edge\n if (!edge.to) {\n state.partial.edges.delete(edge)\n }\n }\n return state\n}\n\n// ref: https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors\nconst attributeSelectors: Record<string, ComparatorFn> = {\n '=': (attr: string, value = '') => attr === value,\n '^=': (attr: string, value = '') => attr.startsWith(value),\n '$=': (attr: string, value = '') => attr.endsWith(value),\n '~=': (attr: string, value = '') =>\n new Set<string>(attr.match(/\\w+/g)).has(value),\n '*=': (attr: string, value = '') => attr.includes(value),\n '|=': (attr: string, value = '') =>\n attr === value || attr.startsWith(`${value}-`),\n undefined: (attr: string) => !!attr,\n}\nexport const attributeSelectorsMap = new Map<string, ComparatorFn>(\n Object.entries(attributeSelectors),\n)\n\n/**\n * Parse attributes selectors, e.g: `[name]`, `[name=value]`, etc\n */\nexport const attribute = async (\n state: ParserState,\n): Promise<ParserState> => {\n await state.cancellable()\n\n const curr = asAttributeNode(state.current)\n const operatorFn = attributeSelectorsMap.get(String(curr.operator))\n if (!operatorFn) {\n if (state.loose) {\n return state\n }\n\n throw error(`Unsupported attribute operator: ${curr.operator}`, {\n found: state.current,\n })\n }\n\n const value = curr.value || ''\n const propertyName = curr.attribute\n const insensitive = !!curr.insensitive\n return filterAttributes(\n state,\n operatorFn,\n value,\n propertyName,\n insensitive,\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"attribute.js","sourceRoot":"","sources":["../../src/attribute.ts"],"names":[],"mappings":"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","sourcesContent":["import { error } from '@vltpkg/error-cause'\nimport type { NodeLike } from '@vltpkg/graph'\nimport type { JSONField, Manifest } from '@vltpkg/types'\nimport { asAttributeNode } from './types.ts'\nimport type { ParserState } from './types.ts'\nimport { removeDanglingEdges } from './pseudo/helpers.ts'\n\nexport type ComparatorFn = (attr: string, value?: string) => boolean\n\n// JSONField has a mapped type constituent that would coerce to [object Object]\n// when stringified, which is what we want in this case.\n// eslint-disable-next-line @typescript-eslint/no-base-to-string\nconst jsonFieldToString = (v: JSONField) => String(v)\n\n/**\n * Retrieve the {@link Manifest} values found at the given `properties`\n * location for a given {@link Node}.\n */\nexport const getManifestPropertyValues = (\n node: NodeLike,\n properties: string[],\n attribute: string,\n): string[] | undefined => {\n if (!node.manifest) return\n\n const traverse = new Set<JSONField>([node.manifest as JSONField])\n const props = new Set<JSONField>()\n for (const key of properties) {\n for (const prop of traverse) {\n /* c8 ignore start - should be impossible */\n if (!prop) {\n throw error('failed to find nested property in :attr', {\n found: properties,\n })\n }\n /* c8 ignore stop */\n\n // expand the result list to include nested array values\n if (Array.isArray(prop)) {\n for (const p of prop) {\n traverse.add(p)\n }\n continue\n }\n\n // guard for inspecting keys of objects next\n if (\n typeof prop === 'string' ||\n typeof prop === 'number' ||\n typeof prop === 'boolean'\n ) {\n continue\n }\n\n // assign next value when found\n if (key in prop) {\n const nextValue = prop[key]\n if (nextValue) {\n if (key === attribute) {\n props.add(nextValue)\n } else {\n traverse.delete(prop)\n traverse.add(nextValue)\n }\n }\n }\n }\n }\n // if no value was found after trying a given key\n // then there's nothing to be collected\n if (!props.size) return\n\n // expand the result to include array values\n const collect = new Set<string>()\n for (const prop of props) {\n if (Array.isArray(prop)) {\n for (const p of prop) {\n collect.add(p ? jsonFieldToString(p) : '')\n }\n } else {\n collect.add(jsonFieldToString(prop))\n }\n }\n\n return [...collect]\n}\n\n// decorator style of function that will filter `ParserState` results\n// based on a provided `comparator` function\nexport const filterAttributes = (\n state: ParserState,\n comparator: ComparatorFn | undefined,\n value: string,\n propertyName: string,\n insensitive: boolean,\n prefixProperties: string[] = [],\n): ParserState => {\n const check = (attr: JSONField) =>\n comparator?.(\n insensitive ?\n jsonFieldToString(attr).toLowerCase()\n : jsonFieldToString(attr),\n insensitive ? value.toLowerCase() : value,\n )\n const deleteNode = (node: NodeLike) => {\n for (const edge of node.edgesIn) {\n state.partial.edges.delete(edge)\n }\n state.partial.nodes.delete(node)\n }\n\n for (const node of state.partial.nodes) {\n const prefixes =\n prefixProperties.length ? prefixProperties : [propertyName]\n const attrs = getManifestPropertyValues(\n node,\n prefixes,\n propertyName,\n )\n\n // if no attribute value was found, that means the attribute won't match\n if (!attrs?.length) {\n deleteNode(node)\n continue\n }\n\n // if the node attribute value won't match, then remove the node\n if (comparator && !attrs.some(check)) {\n deleteNode(node)\n }\n }\n\n removeDanglingEdges(state)\n return state\n}\n\n// ref: https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors\nconst attributeSelectors: Record<string, ComparatorFn> = {\n '=': (attr: string, value = '') => attr === value,\n '^=': (attr: string, value = '') => attr.startsWith(value),\n '$=': (attr: string, value = '') => attr.endsWith(value),\n '~=': (attr: string, value = '') =>\n new Set<string>(attr.match(/\\w+/g)).has(value),\n '*=': (attr: string, value = '') => attr.includes(value),\n '|=': (attr: string, value = '') =>\n attr === value || attr.startsWith(`${value}-`),\n undefined: (attr: string) => !!attr,\n}\nexport const attributeSelectorsMap = new Map<string, ComparatorFn>(\n Object.entries(attributeSelectors),\n)\n\n/**\n * Parse attributes selectors, e.g: `[name]`, `[name=value]`, etc\n */\nexport const attribute = async (\n state: ParserState,\n): Promise<ParserState> => {\n await state.cancellable()\n\n const curr = asAttributeNode(state.current)\n const operatorFn = attributeSelectorsMap.get(String(curr.operator))\n if (!operatorFn) {\n if (state.loose) {\n return state\n }\n\n throw error(`Unsupported attribute operator: ${curr.operator}`, {\n found: state.current,\n })\n }\n\n const value = curr.value || ''\n const propertyName = curr.attribute\n const insensitive = !!curr.insensitive\n\n // Increment the commonCounter for specificity\n state.specificity.commonCounter += 1\n\n return filterAttributes(\n state,\n operatorFn,\n value,\n propertyName,\n insensitive,\n )\n}\n"]}
|
package/dist/esm/id.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../src/id.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C;;GAEG;AACH,eAAO,MAAM,EAAE,UACN,WAAW,KACjB,OAAO,CAAC,WAAW,
|
|
1
|
+
{"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../src/id.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C;;GAEG;AACH,eAAO,MAAM,EAAE,UACN,WAAW,KACjB,OAAO,CAAC,WAAW,CAoCrB,CAAA"}
|
package/dist/esm/id.js
CHANGED
package/dist/esm/id.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id.js","sourceRoot":"","sources":["../../src/id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAG7C;;GAEG;AACH,MAAM,CAAC,MAAM,EAAE,GAAG,KAAK,EACrB,KAAkB,EACI,EAAE;IACxB,MAAM,EAAE,KAAK,EAAE,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAEjD,8CAA8C;IAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,KAAK,CAAC,yBAAyB,CAAC,CAAA;IACxC,CAAC;IACD,oBAAoB;IAEpB,wCAAwC;IACxC,yCAAyC;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACxB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YAChC,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;gBACZ,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YACrC,CAAC;QACH,CAAC;IACH,CAAC;IAED,uDAAuD;IACvD,yDAAyD;IACzD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvC,IACE,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC;YACvB,IAAI,CAAC,IAAI,KAAK,KAAK;YACnB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAC7B,CAAC;YACD,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAClC,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA","sourcesContent":["import { error } from '@vltpkg/error-cause'\nimport { asIdentifierNode } from './types.ts'\nimport type { ParserState } from './types.ts'\n\n/**\n * Parse ids, e.g: `#foo`\n */\nexport const id = async (\n state: ParserState,\n): Promise<ParserState> => {\n const { value } = asIdentifierNode(state.current)\n\n /* c8 ignore start - should not be possible */\n if (!value) {\n throw error('Missing identifier name')\n }\n /* c8 ignore stop */\n\n // Filter out any edges and their linked\n // nodes if they don't match the id value\n for (const edge of state.partial.edges) {\n if (edge.name !== value) {\n state.partial.edges.delete(edge)\n if (edge.to) {\n state.partial.nodes.delete(edge.to)\n }\n }\n }\n\n // Filter out importer nodes, this extra step is needed\n // to filter out nodes that have no edges linking to them\n for (const node of state.partial.nodes) {\n if (\n node.edgesIn.size === 0 &&\n node.name !== value &&\n state.partial.nodes.has(node)\n ) {\n state.partial.nodes.delete(node)\n }\n }\n\n return state\n}\n"]}
|
|
1
|
+
{"version":3,"file":"id.js","sourceRoot":"","sources":["../../src/id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAG7C;;GAEG;AACH,MAAM,CAAC,MAAM,EAAE,GAAG,KAAK,EACrB,KAAkB,EACI,EAAE;IACxB,MAAM,EAAE,KAAK,EAAE,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAEjD,8CAA8C;IAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,KAAK,CAAC,yBAAyB,CAAC,CAAA;IACxC,CAAC;IACD,oBAAoB;IAEpB,wCAAwC;IACxC,yCAAyC;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACxB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YAChC,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;gBACZ,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YACrC,CAAC;QACH,CAAC;IACH,CAAC;IAED,uDAAuD;IACvD,yDAAyD;IACzD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvC,IACE,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC;YACvB,IAAI,CAAC,IAAI,KAAK,KAAK;YACnB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAC7B,CAAC;YACD,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAClC,CAAC;IACH,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,WAAW,CAAC,SAAS,IAAI,CAAC,CAAA;IAEhC,OAAO,KAAK,CAAA;AACd,CAAC,CAAA","sourcesContent":["import { error } from '@vltpkg/error-cause'\nimport { asIdentifierNode } from './types.ts'\nimport type { ParserState } from './types.ts'\n\n/**\n * Parse ids, e.g: `#foo`\n */\nexport const id = async (\n state: ParserState,\n): Promise<ParserState> => {\n const { value } = asIdentifierNode(state.current)\n\n /* c8 ignore start - should not be possible */\n if (!value) {\n throw error('Missing identifier name')\n }\n /* c8 ignore stop */\n\n // Filter out any edges and their linked\n // nodes if they don't match the id value\n for (const edge of state.partial.edges) {\n if (edge.name !== value) {\n state.partial.edges.delete(edge)\n if (edge.to) {\n state.partial.nodes.delete(edge.to)\n }\n }\n }\n\n // Filter out importer nodes, this extra step is needed\n // to filter out nodes that have no edges linking to them\n for (const node of state.partial.nodes) {\n if (\n node.edgesIn.size === 0 &&\n node.name !== value &&\n state.partial.nodes.has(node)\n ) {\n state.partial.nodes.delete(node)\n }\n }\n\n // Increment the idCounter for specificity\n state.specificity.idCounter += 1\n\n return state\n}\n"]}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -15,6 +15,53 @@ export type QueryOptions = {
|
|
|
15
15
|
specOptions: SpecOptions;
|
|
16
16
|
securityArchive: SecurityArchiveLike | undefined;
|
|
17
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* A valid item of a given breadcrumb.
|
|
20
|
+
*/
|
|
21
|
+
export type InteractiveBreadcrumbItem = {
|
|
22
|
+
value: string;
|
|
23
|
+
type: string;
|
|
24
|
+
prev: InteractiveBreadcrumbItem | undefined;
|
|
25
|
+
next: InteractiveBreadcrumbItem | undefined;
|
|
26
|
+
importer: boolean;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* The InteractiveBreadcrumb class is used to represent a valid breadcrumb.
|
|
30
|
+
*
|
|
31
|
+
* "Breadcrumb" is a term used to describe the subset of the query language
|
|
32
|
+
* that uses only root/workspace selectors, id selectors & combinators.
|
|
33
|
+
*
|
|
34
|
+
* It implements an iterable, doubly-linked list of items that can be used
|
|
35
|
+
* to navigate through the breadcrumb.
|
|
36
|
+
*
|
|
37
|
+
* It also validates that each element of the provided query string is
|
|
38
|
+
* valid according to the previous definition of a "breadcrumb".
|
|
39
|
+
*/
|
|
40
|
+
export declare class InteractiveBreadcrumb implements Iterable<InteractiveBreadcrumbItem> {
|
|
41
|
+
#private;
|
|
42
|
+
comment: string | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Initializes the interactive breadcrumb with a query string.
|
|
45
|
+
*/
|
|
46
|
+
constructor(query: string);
|
|
47
|
+
/**
|
|
48
|
+
* The current breadcrumb item.
|
|
49
|
+
*/
|
|
50
|
+
get current(): InteractiveBreadcrumbItem;
|
|
51
|
+
/**
|
|
52
|
+
* The next breadcrumb item.
|
|
53
|
+
*/
|
|
54
|
+
next(): InteractiveBreadcrumbItem | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* The previous breadcrumb item.
|
|
57
|
+
*/
|
|
58
|
+
prev(): InteractiveBreadcrumbItem | undefined;
|
|
59
|
+
[Symbol.iterator](): ArrayIterator<InteractiveBreadcrumbItem>;
|
|
60
|
+
/**
|
|
61
|
+
* Empties the current breadcrumb list.
|
|
62
|
+
*/
|
|
63
|
+
clear(): void;
|
|
64
|
+
}
|
|
18
65
|
/**
|
|
19
66
|
* The Query class is used to search the graph for nodes and edges
|
|
20
67
|
* using the Dependency Selector Syntax (DSS).
|
|
@@ -27,6 +74,13 @@ export declare class Query {
|
|
|
27
74
|
* skip hydrating the security archive if it's not needed.
|
|
28
75
|
*/
|
|
29
76
|
static hasSecuritySelectors(query: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Sorts an array of QueryResponse objects by specificity. Objects with
|
|
79
|
+
* higher idCounter values come first, if idCounter values are equal,
|
|
80
|
+
* then objects with higher commonCounter values come first. Otherwise,
|
|
81
|
+
* the original order is preserved.
|
|
82
|
+
*/
|
|
83
|
+
static specificitySort(responses: QueryResponse[]): QueryResponse[];
|
|
30
84
|
constructor({ graph, retries, specOptions, securityArchive, }: QueryOptions);
|
|
31
85
|
/**
|
|
32
86
|
* Search the graph for nodes and edges that match the given query.
|
|
@@ -36,5 +90,10 @@ export declare class Query {
|
|
|
36
90
|
* Parses a query string in order to retrieve an array of tokens.
|
|
37
91
|
*/
|
|
38
92
|
static getQueryTokens(query: string): ParsedSelectorToken[];
|
|
93
|
+
/**
|
|
94
|
+
* Returns an {@link InteractiveBreadcrumb} list of items
|
|
95
|
+
* for a given query string.
|
|
96
|
+
*/
|
|
97
|
+
static getBreadcrumbItems(query: string): InteractiveBreadcrumb;
|
|
39
98
|
}
|
|
40
99
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAY,SAAS,EAAY,MAAM,eAAe,CAAA;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAY,SAAS,EAAY,MAAM,eAAe,CAAA;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAgBnE,OAAO,KAAK,EAEV,mBAAmB,EAEnB,WAAW,EAEX,aAAa,EAGd,MAAM,YAAY,CAAA;AAEnB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAE3C,cAAc,YAAY,CAAA;AAE1B,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,WAAW,CAAA;IACnB,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAA;CACnB,CAAA;AA+CD,eAAO,MAAM,IAAI,UACR,WAAW,KACjB,OAAO,CAAC,WAAW,CAsDrB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,SAAS,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,WAAW,CAAA;IACxB,eAAe,EAAE,mBAAmB,GAAG,SAAS,CAAA;CACjD,CAAA;AAiDD;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,yBAAyB,GAAG,SAAS,CAAA;IAC3C,IAAI,EAAE,yBAAyB,GAAG,SAAS,CAAA;IAC3C,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,qBACX,YAAW,QAAQ,CAAC,yBAAyB,CAAC;;IAI9C,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAE3B;;OAEG;gBACS,KAAK,EAAE,MAAM;IA0GzB;;OAEG;IACH,IAAI,OAAO,IAAI,yBAAyB,CAEvC;IAED;;OAEG;IACH,IAAI,IAAI,yBAAyB,GAAG,SAAS;IAQ7C;;OAEG;IACH,IAAI,IAAI,yBAAyB,GAAG,SAAS;IAQ7C,CAAC,MAAM,CAAC,QAAQ,CAAC;IAIjB;;OAEG;IACH,KAAK;CAON;AAED;;;GAGG;AACH,qBAAa,KAAK;;IAOhB;;;;OAIG;IACH,MAAM,CAAC,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IASnD;;;;;OAKG;IACH,MAAM,CAAC,eAAe,CACpB,SAAS,EAAE,aAAa,EAAE,GACzB,aAAa,EAAE;gBAqBN,EACV,KAAK,EACL,OAAO,EACP,WAAW,EACX,eAAe,GAChB,EAAE,YAAY;IAuLf;;OAEG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,EACE,MAAM,EACN,QAA0C,GAC3C,EAAE,aAAa,GACf,OAAO,CAAC,aAAa,CAAC;IAmEzB;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,EAAE;IAoE3D;;;OAGG;IACH,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,qBAAqB;CAGhE"}
|
package/dist/esm/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { attribute } from "./attribute.js";
|
|
|
4
4
|
import { combinator } from "./combinator.js";
|
|
5
5
|
import { id } from "./id.js";
|
|
6
6
|
import { pseudo } from "./pseudo.js";
|
|
7
|
-
import { isPostcssNodeWithChildren, asPostcssNodeWithChildren, isSelectorNode, isPseudoNode, isIdentifierNode, isAttributeNode, } from "./types.js";
|
|
7
|
+
import { isPostcssNodeWithChildren, asPostcssNodeWithChildren, isSelectorNode, isPseudoNode, isIdentifierNode, isAttributeNode, isCombinatorNode, isCommentNode, } from "./types.js";
|
|
8
8
|
import { joinDepIDTuple } from '@vltpkg/dep-id/browser';
|
|
9
9
|
export * from "./types.js";
|
|
10
10
|
const noopFn = async (state) => state;
|
|
@@ -16,7 +16,17 @@ const selectors = {
|
|
|
16
16
|
},
|
|
17
17
|
/* c8 ignore end */
|
|
18
18
|
combinator,
|
|
19
|
-
comment:
|
|
19
|
+
comment: async (state) => {
|
|
20
|
+
if (state.current.value && !state.comment) {
|
|
21
|
+
const commentValue = state.current.value;
|
|
22
|
+
const cleanComment = commentValue
|
|
23
|
+
.replace(/^\/\*/, '')
|
|
24
|
+
.replace(/\*\/$/, '')
|
|
25
|
+
.trim();
|
|
26
|
+
state.comment = cleanComment;
|
|
27
|
+
}
|
|
28
|
+
return state;
|
|
29
|
+
},
|
|
20
30
|
id,
|
|
21
31
|
nesting: noopFn,
|
|
22
32
|
pseudo,
|
|
@@ -125,6 +135,155 @@ const setMethodToJSON = (node) => {
|
|
|
125
135
|
insights,
|
|
126
136
|
});
|
|
127
137
|
};
|
|
138
|
+
/**
|
|
139
|
+
* The InteractiveBreadcrumb class is used to represent a valid breadcrumb.
|
|
140
|
+
*
|
|
141
|
+
* "Breadcrumb" is a term used to describe the subset of the query language
|
|
142
|
+
* that uses only root/workspace selectors, id selectors & combinators.
|
|
143
|
+
*
|
|
144
|
+
* It implements an iterable, doubly-linked list of items that can be used
|
|
145
|
+
* to navigate through the breadcrumb.
|
|
146
|
+
*
|
|
147
|
+
* It also validates that each element of the provided query string is
|
|
148
|
+
* valid according to the previous definition of a "breadcrumb".
|
|
149
|
+
*/
|
|
150
|
+
export class InteractiveBreadcrumb {
|
|
151
|
+
#current;
|
|
152
|
+
#items;
|
|
153
|
+
comment;
|
|
154
|
+
/**
|
|
155
|
+
* Initializes the interactive breadcrumb with a query string.
|
|
156
|
+
*/
|
|
157
|
+
constructor(query) {
|
|
158
|
+
this.#items = [];
|
|
159
|
+
const ast = parse(query);
|
|
160
|
+
// Keep track of the previous AST node for consolidation
|
|
161
|
+
let prevNode;
|
|
162
|
+
// iterates only at the first level of the AST since
|
|
163
|
+
// any nested nodes are invalid syntax
|
|
164
|
+
for (const item of ast.first.nodes) {
|
|
165
|
+
const isWorkspaceOrProject = isPseudoNode(item) &&
|
|
166
|
+
(item.value === ':workspace' || item.value === ':project');
|
|
167
|
+
const allowedPseudoNodes = isPseudoNode(item) &&
|
|
168
|
+
(item.value === ':root' ||
|
|
169
|
+
item.value === ':workspace' ||
|
|
170
|
+
item.value === ':project');
|
|
171
|
+
const allowedTypes = isIdentifierNode(item) ||
|
|
172
|
+
allowedPseudoNodes ||
|
|
173
|
+
(isCombinatorNode(item) && item.value === '>') ||
|
|
174
|
+
isCommentNode(item);
|
|
175
|
+
// Check if this is a nested selector that's not an allowed pseudo
|
|
176
|
+
const isNestedSelector = isPostcssNodeWithChildren(item) &&
|
|
177
|
+
!(allowedPseudoNodes && item.nodes.length === 0);
|
|
178
|
+
// validation, only the root/workspace selectors, id selectors
|
|
179
|
+
// and combinators are valid ast node items
|
|
180
|
+
if (isNestedSelector || !allowedTypes) {
|
|
181
|
+
throw error('Invalid query', { found: item });
|
|
182
|
+
}
|
|
183
|
+
// combinators and comments are skipped
|
|
184
|
+
if (isCombinatorNode(item)) {
|
|
185
|
+
prevNode = undefined;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
else if (isCommentNode(item)) {
|
|
189
|
+
const cleanComment = item.value
|
|
190
|
+
.replace(/^\/\*/, '')
|
|
191
|
+
.replace(/\*\/$/, '')
|
|
192
|
+
.trim();
|
|
193
|
+
this.comment = cleanComment;
|
|
194
|
+
prevNode = undefined;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
// check if we need to consolidate with previous item
|
|
198
|
+
const isPrevWorkspaceOrProject = prevNode &&
|
|
199
|
+
isPseudoNode(prevNode) &&
|
|
200
|
+
(prevNode.value === ':workspace' ||
|
|
201
|
+
prevNode.value === ':project');
|
|
202
|
+
const isPrevId = prevNode && isIdentifierNode(prevNode);
|
|
203
|
+
const isCurrentId = isIdentifierNode(item);
|
|
204
|
+
const lastItem = this.#items.length > 0 ?
|
|
205
|
+
this.#items[this.#items.length - 1]
|
|
206
|
+
: null;
|
|
207
|
+
// current node is ID, previous was workspace/project
|
|
208
|
+
if (isCurrentId && isPrevWorkspaceOrProject && lastItem) {
|
|
209
|
+
// Modify the last item to include the ID
|
|
210
|
+
lastItem.value = `${lastItem.value}#${item.value}`;
|
|
211
|
+
prevNode = undefined;
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
// current node is workspace/project, previous was ID
|
|
215
|
+
if (isWorkspaceOrProject && isPrevId && lastItem) {
|
|
216
|
+
// Modify the last item to include the pseudo
|
|
217
|
+
lastItem.value = `${lastItem.value}${item.value}`;
|
|
218
|
+
lastItem.importer = true;
|
|
219
|
+
prevNode = undefined;
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
// Default case: create a new item normally
|
|
223
|
+
const prev = this.#items[this.#items.length - 1];
|
|
224
|
+
const newItem = {
|
|
225
|
+
value: item.value,
|
|
226
|
+
type: item.type,
|
|
227
|
+
prev,
|
|
228
|
+
next: undefined,
|
|
229
|
+
importer: allowedPseudoNodes,
|
|
230
|
+
};
|
|
231
|
+
if (prev) {
|
|
232
|
+
prev.next = newItem;
|
|
233
|
+
}
|
|
234
|
+
this.#items.push(newItem);
|
|
235
|
+
prevNode = item;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
// the parsed query should have at least one item
|
|
239
|
+
// that is then going to be set as the current item
|
|
240
|
+
if (!this.#items[0]) {
|
|
241
|
+
throw error('Failed to parse query', {
|
|
242
|
+
found: query,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
this.#current = this.#items[0];
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* The current breadcrumb item.
|
|
249
|
+
*/
|
|
250
|
+
get current() {
|
|
251
|
+
return this.#current;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* The next breadcrumb item.
|
|
255
|
+
*/
|
|
256
|
+
next() {
|
|
257
|
+
if (!this.#current.next) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
this.#current = this.#current.next;
|
|
261
|
+
return this.#current;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* The previous breadcrumb item.
|
|
265
|
+
*/
|
|
266
|
+
prev() {
|
|
267
|
+
if (!this.#current.prev) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
this.#current = this.#current.prev;
|
|
271
|
+
return this.#current;
|
|
272
|
+
}
|
|
273
|
+
[Symbol.iterator]() {
|
|
274
|
+
return this.#items.values();
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Empties the current breadcrumb list.
|
|
278
|
+
*/
|
|
279
|
+
clear() {
|
|
280
|
+
for (const item of this.#items) {
|
|
281
|
+
item.prev = undefined;
|
|
282
|
+
item.next = undefined;
|
|
283
|
+
}
|
|
284
|
+
this.#items.length = 0;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
128
287
|
/**
|
|
129
288
|
* The Query class is used to search the graph for nodes and edges
|
|
130
289
|
* using the Dependency Selector Syntax (DSS).
|
|
@@ -148,6 +307,26 @@ export class Query {
|
|
|
148
307
|
}
|
|
149
308
|
return false;
|
|
150
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* Sorts an array of QueryResponse objects by specificity. Objects with
|
|
312
|
+
* higher idCounter values come first, if idCounter values are equal,
|
|
313
|
+
* then objects with higher commonCounter values come first. Otherwise,
|
|
314
|
+
* the original order is preserved.
|
|
315
|
+
*/
|
|
316
|
+
static specificitySort(responses) {
|
|
317
|
+
return [...responses].sort((a, b) => {
|
|
318
|
+
// First compare by idCounter (higher comes first)
|
|
319
|
+
if (a.specificity.idCounter !== b.specificity.idCounter) {
|
|
320
|
+
return b.specificity.idCounter - a.specificity.idCounter;
|
|
321
|
+
}
|
|
322
|
+
// If idCounter values are equal, compare by commonCounter
|
|
323
|
+
if (a.specificity.commonCounter !== b.specificity.commonCounter) {
|
|
324
|
+
return (b.specificity.commonCounter - a.specificity.commonCounter);
|
|
325
|
+
}
|
|
326
|
+
// If both counters are equal, preserve original order
|
|
327
|
+
return 0;
|
|
328
|
+
});
|
|
329
|
+
}
|
|
151
330
|
constructor({ graph, retries, specOptions, securityArchive, }) {
|
|
152
331
|
this.#cache = new Map();
|
|
153
332
|
this.#graph = graph;
|
|
@@ -178,10 +357,8 @@ export class Query {
|
|
|
178
357
|
abandoned: securityArchiveEntry.alerts.some(i => i.type === 'missingAuthor'),
|
|
179
358
|
confused: securityArchiveEntry.alerts.some(i => i.type === 'manifestConfusion'),
|
|
180
359
|
cve: securityArchiveEntry.alerts
|
|
181
|
-
.
|
|
182
|
-
|
|
183
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain
|
|
184
|
-
.map(i => i.props?.cveId),
|
|
360
|
+
.map(i => i.props?.cveId)
|
|
361
|
+
.filter(i => i !== undefined),
|
|
185
362
|
cwe: Array.from(new Set(securityArchiveEntry.alerts
|
|
186
363
|
.filter(i => i.props?.cveId)
|
|
187
364
|
.flatMap(i => i.props?.cwes?.map(j => j.id)))),
|
|
@@ -243,7 +420,12 @@ export class Query {
|
|
|
243
420
|
*/
|
|
244
421
|
async search(query, { signal, scopeIDs = [joinDepIDTuple(['file', '.'])], }) {
|
|
245
422
|
if (!query)
|
|
246
|
-
return {
|
|
423
|
+
return {
|
|
424
|
+
edges: [],
|
|
425
|
+
nodes: [],
|
|
426
|
+
comment: '',
|
|
427
|
+
specificity: { idCounter: 0, commonCounter: 0 },
|
|
428
|
+
};
|
|
247
429
|
const cachedResult = this.#cache.get(query);
|
|
248
430
|
if (cachedResult) {
|
|
249
431
|
return cachedResult;
|
|
@@ -260,7 +442,7 @@ export class Query {
|
|
|
260
442
|
const loose = asPostcssNodeWithChildren(current).nodes.length > 1;
|
|
261
443
|
// builds initial state and walks over it,
|
|
262
444
|
// retrieving the collected result
|
|
263
|
-
const { collect } = await walk({
|
|
445
|
+
const { collect, comment, specificity } = await walk({
|
|
264
446
|
cancellable: async () => {
|
|
265
447
|
await new Promise(resolve => {
|
|
266
448
|
setTimeout(resolve, 0);
|
|
@@ -276,6 +458,7 @@ export class Query {
|
|
|
276
458
|
nodes: new Set(),
|
|
277
459
|
edges: new Set(),
|
|
278
460
|
},
|
|
461
|
+
comment: '',
|
|
279
462
|
loose,
|
|
280
463
|
partial: { nodes, edges },
|
|
281
464
|
retries: this.#retries,
|
|
@@ -284,10 +467,13 @@ export class Query {
|
|
|
284
467
|
specOptions: this.#specOptions,
|
|
285
468
|
scopeIDs,
|
|
286
469
|
walk,
|
|
470
|
+
specificity: { idCounter: 0, commonCounter: 0 },
|
|
287
471
|
});
|
|
288
472
|
const res = {
|
|
289
473
|
edges: this.#getQueryResponseEdges(collect.edges),
|
|
290
474
|
nodes: this.#getQueryResponseNodes(collect.nodes),
|
|
475
|
+
comment,
|
|
476
|
+
specificity,
|
|
291
477
|
};
|
|
292
478
|
this.#cache.set(query, res);
|
|
293
479
|
return res;
|
|
@@ -353,5 +539,12 @@ export class Query {
|
|
|
353
539
|
processNode(ast(query));
|
|
354
540
|
return tokens;
|
|
355
541
|
}
|
|
542
|
+
/**
|
|
543
|
+
* Returns an {@link InteractiveBreadcrumb} list of items
|
|
544
|
+
* for a given query string.
|
|
545
|
+
*/
|
|
546
|
+
static getBreadcrumbItems(query) {
|
|
547
|
+
return new InteractiveBreadcrumb(query);
|
|
548
|
+
}
|
|
356
549
|
}
|
|
357
550
|
//# sourceMappingURL=index.js.map
|