@astryxdesign/cli 0.7.2 → 0.7.3-canary.06872b4
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/README.md +99 -66
- package/api/build/_adapter.d.mts +58 -0
- package/api/build/_adapter.mjs +115 -3
- package/api/build/blocks/blocks.d.mts +42 -0
- package/api/build/blocks/blocks.mjs +169 -0
- package/api/build/blocks/blocks.test.mjs +108 -0
- package/api/build/blocks/blocks.weights.json +1 -0
- package/api/build/build.mjs +25 -6
- package/api/build/kit/answer.d.mts +14 -0
- package/api/build/kit/answer.mjs +85 -0
- package/api/build/kit/answer.test.mjs +38 -0
- package/api/build/kit/kind.d.mts +25 -0
- package/api/build/kit/kind.mjs +170 -0
- package/api/build/kit/kit.d.mts +2 -4
- package/api/build/kit/kit.mjs +8 -398
- package/api/build/kit/rank.d.mts +3 -32
- package/api/build/kit/rank.mjs +25 -342
- package/api/build/kit/rank.test.mjs +2 -1
- package/api/build/kit/signals.d.mts +60 -0
- package/api/build/kit/signals.mjs +284 -0
- package/api/build/kit/start.d.mts +32 -0
- package/api/build/kit/start.mjs +163 -0
- package/api/build/kit/words.d.mts +72 -0
- package/api/build/kit/words.mjs +202 -0
- package/api/build/tree.d.mts +20 -0
- package/api/build/tree.mjs +52 -0
- package/api/build/tree.test.mjs +177 -0
- package/api/build/tree.weights.json +1 -0
- package/api/component/component.mjs +16 -2
- package/api/component/component.test.mjs +15 -0
- package/api/discover/_adapter.mjs +36 -9
- package/api/discover/_adapter.test.mjs +42 -0
- package/api/docs/_adapter.mjs +17 -5
- package/api/docs/docs.test.mjs +7 -1
- package/api/doctor/doctor.mjs +86 -12
- package/api/doctor/doctor.test.mjs +28 -3
- package/api/init/init.doc.mjs +20 -6
- package/api/init/init.test.mjs +18 -2
- package/api/init/init.type.d.mts +3 -3
- package/api/init/init.type.mjs +3 -3
- package/api/init/remove/remove.mjs +17 -4
- package/api/init/remove/remove.test.mjs +114 -2
- package/api/init/run/run.mjs +69 -6
- package/api/integration/authoring-checks.mjs +83 -9
- package/api/integration/pack-check.mjs +123 -4
- package/api/integration/pack-check.test.mjs +87 -0
- package/api/integration/validate-integration-case-disk.test.mjs +111 -0
- package/api/integration/validate-integration-gaps.test.mjs +1964 -0
- package/api/integration/validate-integration.d.mts +11 -2
- package/api/integration/validate-integration.mjs +226 -32
- package/api/integration/validate-integration.type.d.mts +58 -1
- package/api/integration/validate-integration.type.mjs +45 -2
- package/api/integration/validateIntegration.doc.mjs +1 -1
- package/api/search/ORDERING.md +28 -0
- package/api/search/_adapter.d.mts +66 -2
- package/api/search/_adapter.mjs +118 -10
- package/api/search/_candidate-score.d.mts +40 -0
- package/api/search/_candidate-score.mjs +238 -0
- package/api/search/_cards.json +6098 -0
- package/api/search/_compound.d.mts +50 -0
- package/api/search/_compound.mjs +170 -0
- package/api/search/_doc-searcher.d.mts +4 -0
- package/api/search/_doc-searcher.mjs +23 -0
- package/api/search/_doc-searcher.test.mjs +36 -0
- package/api/search/_doc-searcher.weights.json +1 -0
- package/api/search/_doc-text.d.mts +30 -0
- package/api/search/_doc-text.mjs +87 -0
- package/api/search/_entries.d.mts +52 -0
- package/api/search/_entries.mjs +158 -0
- package/api/search/_features.d.mts +35 -0
- package/api/search/_features.mjs +155 -0
- package/api/search/_gather-components.d.mts +26 -0
- package/api/search/_gather-components.mjs +284 -0
- package/api/search/_gather-docs.d.mts +20 -0
- package/api/search/_gather-docs.mjs +254 -0
- package/api/search/_gather-hooks.d.mts +12 -0
- package/api/search/_gather-hooks.mjs +52 -0
- package/api/search/_gather-templates.d.mts +25 -0
- package/api/search/_gather-templates.mjs +107 -0
- package/api/search/_lexical.d.mts +135 -0
- package/api/search/_lexical.mjs +351 -0
- package/api/search/_main-searcher.d.mts +19 -0
- package/api/search/_main-searcher.mjs +115 -0
- package/api/search/_main-searcher.test.mjs +106 -0
- package/api/search/_main-searcher.weights.json +1 -0
- package/api/search/_module-doc.d.mts +32 -0
- package/api/search/_module-doc.mjs +78 -0
- package/api/search/_order.d.mts +32 -0
- package/api/search/_order.mjs +162 -0
- package/api/search/_order.test.mjs +72 -0
- package/api/search/_priority.d.mts +50 -0
- package/api/search/_priority.mjs +139 -0
- package/api/search/_query-words.d.mts +25 -0
- package/api/search/_query-words.mjs +92 -0
- package/api/search/_query.d.mts +65 -0
- package/api/search/_query.mjs +176 -0
- package/api/search/_result.d.mts +97 -0
- package/api/search/_result.mjs +150 -0
- package/api/search/_score.d.mts +60 -0
- package/api/search/_score.mjs +283 -0
- package/api/search/_synonyms.d.mts +21 -0
- package/api/search/_synonyms.mjs +67 -0
- package/api/search/_template-searcher.d.mts +4 -0
- package/api/search/_template-searcher.mjs +23 -0
- package/api/search/_template-searcher.test.mjs +40 -0
- package/api/search/_template-searcher.weights.json +1 -0
- package/api/search/_titles.d.mts +33 -0
- package/api/search/_titles.mjs +65 -0
- package/api/search/_words.d.mts +64 -0
- package/api/search/_words.mjs +157 -0
- package/api/search/search.d.mts +22 -305
- package/api/search/search.doc.mjs +7 -5
- package/api/search/search.mjs +53 -2483
- package/api/search/search.type.d.mts +6 -1
- package/api/search/search.type.mjs +6 -1
- package/api/search/tree.d.mts +15 -0
- package/api/search/tree.mjs +40 -0
- package/api/search/tree.test.mjs +66 -0
- package/api/search/tree.weights.json +1 -0
- package/api/theme/build/build.packed-old-core.test.mjs +1 -0
- package/api/upgrade/_adapter.d.mts +57 -9
- package/api/upgrade/_adapter.mjs +198 -28
- package/api/upgrade/registry/registry.d.mts +10 -4
- package/api/upgrade/registry/registry.mjs +33 -16
- package/api/upgrade/registry/registry.test.mjs +85 -0
- package/api/upgrade/run/run.d.mts +4 -2
- package/api/upgrade/run/run.mjs +13 -2
- package/api/upgrade/run/run.test.mjs +417 -3
- package/api/upgrade/upgrade.doc.mjs +10 -5
- package/api/upgrade/upgrade.mjs +13 -2
- package/api/upgrade/upgrade.test.mjs +194 -0
- package/api/upgrade/upgrade.type.d.mts +5 -3
- package/api/upgrade/upgrade.type.mjs +8 -6
- package/assets/codemods/transforms/v0.7.0/__tests__/validate-data-token-ownership.test.mjs +11 -0
- package/assets/codemods/transforms/v0.7.0/validate-data-token-ownership.mjs +3 -3
- package/assets/docs/is-my-code-good.doc.mjs +287 -0
- package/assets/docs/tree/api.doc.mjs +6 -0
- package/assets/docs/tree/host-entry.doc.mjs +128 -0
- package/assets/docs/tree/template-grading-rubric.doc.mjs +16 -37
- package/assets/docs/tree/tokens-data.doc.mjs +2 -2
- package/assets/docs/working-with-ai.doc.mjs +6 -2
- package/assets/templates/themes/butter/butterTheme.ts +4 -2
- package/assets/templates/themes/stone/stoneTheme.ts +4 -2
- package/assets/templates/themes/y2k/y2kTheme.ts +4 -2
- package/authoring/debug/parse.d.mts +1 -1
- package/clients/cli/bin/astryx.mjs +7 -78
- package/clients/cli/commands/doctor.mjs +30 -0
- package/clients/cli/commands/doctor.test.mjs +65 -0
- package/clients/cli/commands/init.behavior.test.mjs +230 -1
- package/clients/cli/commands/init.doc.mjs +28 -9
- package/clients/cli/commands/init.flag-help.test.mjs +1 -0
- package/clients/cli/commands/init.mjs +2 -2
- package/clients/cli/commands/outside-project.test.mjs +2 -1
- package/clients/cli/commands/setup-nudge.test.mjs +61 -0
- package/clients/cli/commands/upgrade.doc.mjs +4 -2
- package/clients/cli/commands/upgrade.mjs +9 -2
- package/clients/cli/commands/upgrade.subfolder-path.test.mjs +97 -0
- package/clients/cli/index.mjs +19 -1
- package/clients/cli/run.mjs +108 -0
- package/foundation/agent-docs/agent-doc-state.d.mts +20 -7
- package/foundation/agent-docs/agent-doc-state.mjs +35 -8
- package/foundation/agent-docs/agent-docs.d.mts +100 -12
- package/foundation/agent-docs/agent-docs.mjs +1010 -99
- package/foundation/agent-docs/agent-docs.path-safety.test.mjs +1239 -17
- package/foundation/agent-docs/agent-docs.test.mjs +678 -35
- package/foundation/config/project.mjs +20 -22
- package/foundation/config/project.test.mjs +56 -0
- package/foundation/discovery/component-discovery.d.mts +37 -0
- package/foundation/discovery/component-discovery.mjs +80 -5
- package/foundation/discovery/component-loader.d.mts +1 -1
- package/foundation/discovery/docs-discovery.mjs +14 -1
- package/foundation/discovery/module-exports.d.mts +41 -0
- package/foundation/discovery/module-exports.mjs +253 -0
- package/foundation/discovery/template-adapter.mjs +18 -1
- package/foundation/discovery/template-needs.mjs +1 -44
- package/foundation/discovery/theme-discovery.mjs +147 -3
- package/foundation/doc-compiler/doc-loads.test.mjs +8 -0
- package/foundation/doc-compiler/read.mjs +59 -1
- package/foundation/doc-compiler/read.test.mjs +11 -2
- package/foundation/fs/paths.d.mts +70 -8
- package/foundation/fs/paths.mjs +556 -38
- package/foundation/fs/paths.test.mjs +430 -54
- package/foundation/integrations/autolink.d.mts +2 -1
- package/foundation/integrations/autolink.mjs +4 -13
- package/foundation/integrations/computer-integrations.d.mts +6 -3
- package/foundation/integrations/computer-integrations.mjs +38 -9
- package/foundation/integrations/contribution-inventory.d.mts +15 -20
- package/foundation/integrations/contribution-inventory.mjs +41 -5
- package/foundation/integrations/integrations.d.mts +27 -1
- package/foundation/integrations/integrations.mjs +61 -2
- package/foundation/integrations/validate-contributions.d.mts +115 -0
- package/foundation/integrations/validate-contributions.mjs +1168 -13
- package/foundation/release/handoff.d.mts +23 -4
- package/foundation/release/handoff.mjs +175 -8
- package/foundation/release/run-context.mjs +14 -0
- package/foundation/response/response-types.doc.mjs +1 -1
- package/foundation/route/route.d.mts +285 -0
- package/foundation/route/route.mjs +324 -0
- package/foundation/route/route.test.mjs +153 -0
- package/foundation/runtime/hosted-runtime.test.mjs +403 -0
- package/foundation/runtime/locked-versions.d.mts +32 -0
- package/foundation/runtime/locked-versions.mjs +65 -0
- package/foundation/runtime/package-root.d.mts +91 -0
- package/foundation/runtime/package-root.mjs +174 -0
- package/foundation/runtime/package-set.d.mts +62 -0
- package/foundation/runtime/package-set.mjs +130 -0
- package/foundation/runtime/package-set.test.mjs +432 -0
- package/host/door-conformance.test.mjs +274 -0
- package/host/index.d.ts +116 -0
- package/host/index.mjs +295 -0
- package/host/index.test.mjs +302 -0
- package/package.json +14 -9
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Word matching for search: stems and word forms, word starts,
|
|
5
|
+
* identifier spelling, joined names, and typo tolerance.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Light stemmer: strips common English suffixes so "charts"/"charting" and
|
|
10
|
+
* "chart" share a root. Deliberately crude (no Porter) — good enough to bridge
|
|
11
|
+
* plural/gerund gaps without a dependency.
|
|
12
|
+
* @param {string} w
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
export function stem(w) {
|
|
16
|
+
let s = w;
|
|
17
|
+
for (const suf of ['ing', 'ed', 'ies', 'es', 's']) {
|
|
18
|
+
if (s.length > suf.length + 2 && s.endsWith(suf)) {
|
|
19
|
+
s = suf === 'ies' ? s.slice(0, -3) + 'y' : s.slice(0, -suf.length);
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return s;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The forms of a word that count as the same word: itself, its stem, and its
|
|
28
|
+
* singular when it ends in a plural suffix — so "tables" is "table",
|
|
29
|
+
* "statuses" is "status", and "filtering" is "filter".
|
|
30
|
+
* @param {string} w - Lowercase word.
|
|
31
|
+
* @returns {Set<string>}
|
|
32
|
+
*/
|
|
33
|
+
export function wordForms(w) {
|
|
34
|
+
const forms = new Set([w, stem(w)]);
|
|
35
|
+
if (w.length > 3 && w.endsWith('s')) forms.add(w.slice(0, -1));
|
|
36
|
+
if (w.length > 4 && w.endsWith('es')) forms.add(w.slice(0, -2));
|
|
37
|
+
if (w.length > 4 && w.endsWith('ies')) forms.add(w.slice(0, -3) + 'y');
|
|
38
|
+
// A gerund keeps its verb: "spacing" lost a final e ("space"), and
|
|
39
|
+
// "dragging" doubled a consonant ("drag"). A past participle does not: it
|
|
40
|
+
// usually describes a state ("archived notes"), not the action a catalog
|
|
41
|
+
// word names.
|
|
42
|
+
if (w.length >= 6 && w.endsWith('ing')) {
|
|
43
|
+
const base = w.slice(0, -3);
|
|
44
|
+
forms.add(base);
|
|
45
|
+
forms.add(`${base}e`);
|
|
46
|
+
if (/([b-df-hj-np-tv-z])\1$/.test(base)) forms.add(base.slice(0, -1));
|
|
47
|
+
}
|
|
48
|
+
return forms;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The singulars a lowercase word may have when it ends in a plural suffix:
|
|
53
|
+
* "tokens" is "token", "boxes" is "box", "entries" is "entry".
|
|
54
|
+
* @param {string} w
|
|
55
|
+
* @returns {string[]}
|
|
56
|
+
*/
|
|
57
|
+
function singulars(w) {
|
|
58
|
+
/** @type {string[]} */
|
|
59
|
+
const out = [];
|
|
60
|
+
if (w.length > 3 && w.endsWith('s')) out.push(w.slice(0, -1));
|
|
61
|
+
if (w.length > 4 && w.endsWith('es')) out.push(w.slice(0, -2));
|
|
62
|
+
if (w.length > 4 && w.endsWith('ies')) out.push(w.slice(0, -3) + 'y');
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Whether two lowercase words are the same word, up to plural and stem form.
|
|
68
|
+
* @param {string} a
|
|
69
|
+
* @param {string} b
|
|
70
|
+
* @returns {boolean}
|
|
71
|
+
*/
|
|
72
|
+
export function sameWord(a, b) {
|
|
73
|
+
if (a === b) return true;
|
|
74
|
+
const forms = wordForms(a);
|
|
75
|
+
for (const f of wordForms(b)) if (forms.has(f)) return true;
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The lowercase words of a name or keyword: split at non-alphanumerics and at
|
|
81
|
+
* camelCase boundaries, so "TextInput" is ["text", "input"] and
|
|
82
|
+
* "Dashboard - Analytics" is ["dashboard", "analytics"].
|
|
83
|
+
* @param {string} text
|
|
84
|
+
* @returns {string[]}
|
|
85
|
+
*/
|
|
86
|
+
export function wordsOf(text) {
|
|
87
|
+
return String(text)
|
|
88
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
89
|
+
.replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')
|
|
90
|
+
.toLowerCase()
|
|
91
|
+
.split(/[^a-z0-9]+/)
|
|
92
|
+
.filter(Boolean);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Whether a term is found inside a name or keyword: it is one of its words, or
|
|
97
|
+
* the start of one (a truncation), and covers at least half of the whole
|
|
98
|
+
* string. Four letters minimum, so a short term never matches by accident.
|
|
99
|
+
* @param {string} term - Lowercase term.
|
|
100
|
+
* @param {string} text - The name or keyword as authored.
|
|
101
|
+
* @returns {boolean}
|
|
102
|
+
*/
|
|
103
|
+
export function startsAWordOf(term, text) {
|
|
104
|
+
if (term.length < 4) return false;
|
|
105
|
+
if (term.length / String(text).length < 0.5) return false;
|
|
106
|
+
// The term or its singular may start the word: "tokens" starts
|
|
107
|
+
// "tokenizer" through "token". A singular needs five letters, so "stats"
|
|
108
|
+
// does not start "status".
|
|
109
|
+
const starts = [term, ...singulars(term).filter(f => f.length >= 5)];
|
|
110
|
+
return wordsOf(text).some(
|
|
111
|
+
w => starts.some(f => w.startsWith(f)) || sameWord(term, w),
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* A query with its camelCase and PascalCase identifiers spelled as words, so
|
|
117
|
+
* `SidebarToggle` reads "sidebar toggle" and `useTablePaginationState` "use
|
|
118
|
+
* table pagination state". Plain words, and identifiers joined with `_` or `-`, are
|
|
119
|
+
* unchanged: a joined token that matches nothing stays unmatched.
|
|
120
|
+
* @param {string} query - The query as typed, before lowercasing.
|
|
121
|
+
* @returns {string} Lowercased.
|
|
122
|
+
*/
|
|
123
|
+
export function spellIdentifiers(query) {
|
|
124
|
+
return String(query)
|
|
125
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
126
|
+
.replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')
|
|
127
|
+
.toLowerCase();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* A name or keyword with its separators removed, lowercased: `Side Nav`,
|
|
132
|
+
* `side-nav`, and `SideNav` all join to `sidenav`.
|
|
133
|
+
* @param {string} text
|
|
134
|
+
* @returns {string}
|
|
135
|
+
*/
|
|
136
|
+
export function joined(text) {
|
|
137
|
+
return String(text)
|
|
138
|
+
.toLowerCase()
|
|
139
|
+
.replace(/[^a-z0-9]+/g, '');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* The fewest letters both words need before an edit distance counts as a
|
|
144
|
+
* typo, by distance. Below them, one edit usually makes a different word.
|
|
145
|
+
*/
|
|
146
|
+
const TYPO_MIN_LENGTH = {1: 5, 2: 8, 3: 11};
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @param {string} a
|
|
150
|
+
* @param {string} b
|
|
151
|
+
* @param {number} dist
|
|
152
|
+
*/
|
|
153
|
+
export const isTypo = (a, b, dist) =>
|
|
154
|
+
dist > 0 &&
|
|
155
|
+
dist <= 3 &&
|
|
156
|
+
Math.min(a.length, b.length) >=
|
|
157
|
+
TYPO_MIN_LENGTH[/** @type {1 | 2 | 3} */ (dist)];
|
package/api/search/search.d.mts
CHANGED
|
@@ -1,219 +1,6 @@
|
|
|
1
1
|
// @generated by scripts/sync-api-types.mjs from the JSDoc in api/**/*.mjs.
|
|
2
2
|
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* Light stemmer: strips common English suffixes so "charts"/"charting" and
|
|
6
|
-
* "chart" share a root. Deliberately crude (no Porter) — good enough to bridge
|
|
7
|
-
* plural/gerund gaps without a dependency.
|
|
8
|
-
* @param {string} w
|
|
9
|
-
* @returns {string}
|
|
10
|
-
*/
|
|
11
|
-
export function stem(w: string): string;
|
|
12
|
-
/**
|
|
13
|
-
* Whether two lowercase words are the same word, up to plural and stem form.
|
|
14
|
-
* @param {string} a
|
|
15
|
-
* @param {string} b
|
|
16
|
-
* @returns {boolean}
|
|
17
|
-
*/
|
|
18
|
-
export function sameWord(a: string, b: string): boolean;
|
|
19
|
-
/**
|
|
20
|
-
* A query with its camelCase and PascalCase identifiers spelled as words, so
|
|
21
|
-
* `SidebarToggle` reads "sidebar toggle" and `useTablePaginationState` "use
|
|
22
|
-
* table pagination state". Plain words, and identifiers joined with `_` or `-`, are
|
|
23
|
-
* unchanged: a joined token that matches nothing stays unmatched.
|
|
24
|
-
* @param {string} query - The query as typed, before lowercasing.
|
|
25
|
-
* @returns {string} Lowercased.
|
|
26
|
-
*/
|
|
27
|
-
export function spellIdentifiers(query: string): string;
|
|
28
|
-
/**
|
|
29
|
-
* The strongest hit a run of two or more adjacent query words has when it is
|
|
30
|
-
* read as one joined word, and the query words it covers. Readers type a
|
|
31
|
-
* compound name as separate words (`table header cell` is TableHeaderCell,
|
|
32
|
-
* `number field` the keyword `numberfield`), and no single word of the run
|
|
33
|
-
* matches on its own.
|
|
34
|
-
*
|
|
35
|
-
* - 100: the run joins to a component, hook, or template name, or its plural
|
|
36
|
-
* (`table header cells` is TableHeaderCell), or a hook name without its
|
|
37
|
-
* `use` prefix (`table sticky columns` is useTableStickyColumns).
|
|
38
|
-
* - 90: the run joins to a one-word keyword (`number field` is
|
|
39
|
-
* `numberfield`).
|
|
40
|
-
* - 95: the run joins to most of a name, cut short (`dropdown menu radio` is
|
|
41
|
-
* DropdownMenuRadioItem); 92: it is a name's leading words, covering at least half
|
|
42
|
-
* of it (`top nav mega` is TopNavMegaMenu); 70: it is two or more adjacent
|
|
43
|
-
* words of a name that cover at least half of it (`header cell` in
|
|
44
|
-
* TableHeaderCell), the same coverage a word prefix needs. These three
|
|
45
|
-
* are for components and hooks only.
|
|
46
|
-
*
|
|
47
|
-
* A doc's name is a route or key, so docs are left out.
|
|
48
|
-
* @param {string[]} words - The query's words, stopwords included.
|
|
49
|
-
* @param {Candidate} candidate
|
|
50
|
-
* @returns {{score: number, reason: string, covered: Set<string>, alias?: 'partial' | 'keyword', aliasWords?: number} | null}
|
|
51
|
-
* `covered` holds the run's words and every stretch of them joined. `alias`
|
|
52
|
-
* marks a hit on part of a name or on a keyword, not on the whole name.
|
|
53
|
-
*/
|
|
54
|
-
export function compoundHit(words: string[], candidate: Candidate): {
|
|
55
|
-
score: number;
|
|
56
|
-
reason: string;
|
|
57
|
-
covered: Set<string>;
|
|
58
|
-
alias?: "partial" | "keyword";
|
|
59
|
-
aliasWords?: number;
|
|
60
|
-
} | null;
|
|
61
|
-
/**
|
|
62
|
-
* Split a query into meaningful content tokens (lowercased, stopwords + very
|
|
63
|
-
* short words removed). Empty for single-word queries (callers fall back to
|
|
64
|
-
* whole-phrase scoring).
|
|
65
|
-
* @param {string} term - Already-lowercased query.
|
|
66
|
-
* @returns {string[]}
|
|
67
|
-
*/
|
|
68
|
-
export function tokenizeQuery(term: string): string[];
|
|
69
|
-
/**
|
|
70
|
-
* A match's domain priority: 0 (none), 1, or 2 (a doc the whole query names).
|
|
71
|
-
* A component, hook, template, or theme with priority ranks ahead of any doc
|
|
72
|
-
* without it, whatever the two scores are. Docs among themselves rank by
|
|
73
|
-
* priority, then score; everything else ranks among itself by score.
|
|
74
|
-
*
|
|
75
|
-
* A component, hook, template, or theme has priority (1) when one of the
|
|
76
|
-
* query's words, or the whole query, hits its name or an authored keyword at
|
|
77
|
-
* {@link STRONG_TOKEN_SCORE} or above, or when it matches every word.
|
|
78
|
-
*
|
|
79
|
-
* A doc has priority when the reader asked for that doc:
|
|
80
|
-
* - 2: the whole query is the topic's name, its last route segment, or its
|
|
81
|
-
* own title, as words and whatever the plural (`font setup` is
|
|
82
|
-
* typography/font-setup, `side panel` is "Side panels");
|
|
83
|
-
* - 1: a word of the query is the topic's name (`illustration` in a longer
|
|
84
|
-
* question is the illustrations guide);
|
|
85
|
-
* - 1: a query of two or more words is one of the topic's own declared
|
|
86
|
-
* keywords, whatever the plural (`code review` on a guide that declares it);
|
|
87
|
-
* - 1: the query holds one of the doc's titles whole (`resizable side panels`
|
|
88
|
-
* names "Side panels"; `light dark mode button` names "Light/Dark Mode");
|
|
89
|
-
* - 1: the doc matches every word of the query and one of them is a word of
|
|
90
|
-
* its title (`switch to a dark theme` and "Use a theme").
|
|
91
|
-
* A section answers to its topic's name.
|
|
92
|
-
*
|
|
93
|
-
* A doc that matched only by a heading holding the query, by one word, or by
|
|
94
|
-
* words spread through its text has no priority. Docs are split into many
|
|
95
|
-
* small topics, each with its own headings, so a common phrase such as
|
|
96
|
-
* `font size` hits a heading exactly (170) while the component the reader is
|
|
97
|
-
* after matches one word by keyword (`Text`, 98). Ranked on text alone, every
|
|
98
|
-
* split adds another doc above the component. Broad reference pages match every word of many queries
|
|
99
|
-
* in their text the same way. The score stays the text-match strength the
|
|
100
|
-
* result reports, so callers that gate on it (`build`) see the same numbers.
|
|
101
|
-
*
|
|
102
|
-
* @param {string} term - Lowercased search term.
|
|
103
|
-
* @param {string[]} tokens - Content tokens from tokenizeQuery(term).
|
|
104
|
-
* @param {Candidate} candidate
|
|
105
|
-
* @param {{score: number, matched: number, total: number}} hit - The
|
|
106
|
-
* candidate's scoreQuery result.
|
|
107
|
-
* @returns {0 | 1 | 2}
|
|
108
|
-
*/
|
|
109
|
-
export function domainPriority(term: string, tokens: string[], candidate: Candidate, hit: {
|
|
110
|
-
score: number;
|
|
111
|
-
matched: number;
|
|
112
|
-
total: number;
|
|
113
|
-
}, queryWords?: string[]): 0 | 1 | 2;
|
|
114
|
-
/**
|
|
115
|
-
* The first title or heading that holds every word of the query, in order and
|
|
116
|
-
* side by side, or null.
|
|
117
|
-
* @param {string} term - Lowercased full query.
|
|
118
|
-
* @param {string[] | undefined} titles
|
|
119
|
-
* @returns {string | null}
|
|
120
|
-
*/
|
|
121
|
-
export function headingWithPhrase(term: string, titles: string[] | undefined): string | null;
|
|
122
|
-
/**
|
|
123
|
-
* The first title or heading of two words or more that the query holds whole,
|
|
124
|
-
* in order and side by side, or null. A question such as "how do I add dark
|
|
125
|
-
* mode" names the "Dark mode" section outright, around words no title has.
|
|
126
|
-
* @param {string} term - Lowercased full query.
|
|
127
|
-
* @param {string[] | undefined} titles
|
|
128
|
-
* @returns {string | null}
|
|
129
|
-
*/
|
|
130
|
-
export function titleInQuery(term: string, titles: string[] | undefined): string | null;
|
|
131
|
-
/**
|
|
132
|
-
* @param {string} term - Lowercased full query.
|
|
133
|
-
* @param {string[]} tokens - Content tokens from tokenizeQuery(term).
|
|
134
|
-
* @param {Candidate} candidate
|
|
135
|
-
* @param {string[]} [words] - The query's words for compound names (see
|
|
136
|
-
* compoundHit); empty when the query names an entry outright.
|
|
137
|
-
* @param {{plain?: boolean}} [opts] - `plain`: score without matches on part
|
|
138
|
-
* of a name or a joined keyword.
|
|
139
|
-
* @returns {{score: number, reason: string, matched: number, total: number, alias?: 'partial' | 'keyword', aliasWords?: number} | null}
|
|
140
|
-
* `matched`/`total` are the query concepts this candidate answered, out of
|
|
141
|
-
* the concepts the query had. Callers that must distinguish "matched one word
|
|
142
|
-
* of three" from "matched all three" — `build`, which gates its pages group
|
|
143
|
-
* on coverage — cannot recover that from the score, because a single strong
|
|
144
|
-
* hit and a broad weak one land on the same number.
|
|
145
|
-
*/
|
|
146
|
-
export function scoreQuery(term: string, tokens: string[], candidate: Candidate, words?: string[], { plain }?: {
|
|
147
|
-
plain?: boolean;
|
|
148
|
-
}): {
|
|
149
|
-
score: number;
|
|
150
|
-
reason: string;
|
|
151
|
-
matched: number;
|
|
152
|
-
total: number;
|
|
153
|
-
alias?: "partial" | "keyword";
|
|
154
|
-
aliasWords?: number;
|
|
155
|
-
} | null;
|
|
156
|
-
/**
|
|
157
|
-
* Score a single candidate against the search term across name, keywords,
|
|
158
|
-
* and prose signals. Returns the best (highest) score plus a human reason,
|
|
159
|
-
* or null if nothing matched above the floor.
|
|
160
|
-
*
|
|
161
|
-
* @param {string} term - Lowercased search term.
|
|
162
|
-
* @param {object} candidate
|
|
163
|
-
* @param {string} candidate.name - Primary identifier (component/hook name, topic, template name).
|
|
164
|
-
* @param {string[]} [candidate.aliases] - Other names, scored like the name (a theme's display name).
|
|
165
|
-
* @param {string} [candidate.domain] - A component, hook, or template name
|
|
166
|
-
* also matches typed as words: `command palette` is CommandPalette.
|
|
167
|
-
* @param {string[]} [candidate.keywords] - Authored intent (componentsUsed, category words).
|
|
168
|
-
* @param {string[]} [candidate.weakKeywords] - Derived signal (components a page renders).
|
|
169
|
-
* @param {string} [candidate.description]
|
|
170
|
-
* @param {string[]} [candidate.prose] - Extra free-text blobs (doc section text, best practices).
|
|
171
|
-
* @param {string[]} [candidate.guidance] - Usage guidance (features, best practices) — scored a tier below description.
|
|
172
|
-
* @param {{fuzzy?: boolean, joins?: boolean}} [opts] - `fuzzy`: allow edit-distance (typo) matches. Default true; multi-word queries pass false. `joins`: read a spaced query joined into a name or keyword (default true); off when the query names an entry outright.
|
|
173
|
-
* @returns {{score: number, reason: string, alias?: 'partial' | 'keyword'} | null}
|
|
174
|
-
* `alias` marks a hit that read the query's words joined.
|
|
175
|
-
*/
|
|
176
|
-
export function scoreCandidate(term: string, { name, aliases, domain, keywords, weakKeywords, description, prose, guidance, }: {
|
|
177
|
-
name: string;
|
|
178
|
-
aliases?: string[] | undefined;
|
|
179
|
-
domain?: string | undefined;
|
|
180
|
-
keywords?: string[] | undefined;
|
|
181
|
-
weakKeywords?: string[] | undefined;
|
|
182
|
-
description?: string | undefined;
|
|
183
|
-
prose?: string[] | undefined;
|
|
184
|
-
guidance?: string[] | undefined;
|
|
185
|
-
}, { fuzzy, joins }?: {
|
|
186
|
-
fuzzy?: boolean;
|
|
187
|
-
joins?: boolean;
|
|
188
|
-
}): {
|
|
189
|
-
score: number;
|
|
190
|
-
reason: string;
|
|
191
|
-
alias?: "partial" | "keyword";
|
|
192
|
-
} | null;
|
|
193
|
-
/**
|
|
194
|
-
* The components (name and keywords) a search response was scored against, or
|
|
195
|
-
* null when that search was narrowed away from components.
|
|
196
|
-
* @param {object} response
|
|
197
|
-
* @returns {{name: string, keywords: string[]}[] | null}
|
|
198
|
-
*/
|
|
199
|
-
export function searchedComponents(response: object): {
|
|
200
|
-
name: string;
|
|
201
|
-
keywords: string[];
|
|
202
|
-
}[] | null;
|
|
203
|
-
/**
|
|
204
|
-
* Every component the project can use, Core's and its integrations', with the
|
|
205
|
-
* keywords its own doc declares: the discovery and doc reads search's own
|
|
206
|
-
* candidates use, without the import paths and prose a result carries. `build`
|
|
207
|
-
* reads it to tell a part of a page from a page when its search was narrowed
|
|
208
|
-
* away from components.
|
|
209
|
-
* @param {string} coreDir
|
|
210
|
-
* @param {string} cwd
|
|
211
|
-
* @returns {Promise<{name: string, keywords: string[]}[]>}
|
|
212
|
-
*/
|
|
213
|
-
export function componentKeywords(coreDir: string, cwd: string): Promise<{
|
|
214
|
-
name: string;
|
|
215
|
-
keywords: string[];
|
|
216
|
-
}[]>;
|
|
217
4
|
/**
|
|
218
5
|
* Unified ranked search across components, hooks, docs, templates, and themes.
|
|
219
6
|
*
|
|
@@ -226,99 +13,29 @@ export function componentKeywords(coreDir: string, cwd: string): Promise<{
|
|
|
226
13
|
*/
|
|
227
14
|
export function search(query: string, options?: {
|
|
228
15
|
cwd?: string | undefined;
|
|
229
|
-
type?: "component" | "hook" | "
|
|
16
|
+
type?: "component" | "hook" | "theme" | "doc" | "template" | undefined;
|
|
230
17
|
limit?: number | undefined;
|
|
231
18
|
}): Promise<import("./search.type.mjs").SearchResponse>;
|
|
232
|
-
export namespace SYNONYMS {
|
|
233
|
-
let dashboard: string[];
|
|
234
|
-
let login: string[];
|
|
235
|
-
let signup: string[];
|
|
236
|
-
let payment: string[];
|
|
237
|
-
let pricing: string[];
|
|
238
|
-
let chat: string[];
|
|
239
|
-
let settings: string[];
|
|
240
|
-
let calendar: string[];
|
|
241
|
-
let table: string[];
|
|
242
|
-
let gallery: string[];
|
|
243
|
-
let hero: string[];
|
|
244
|
-
let form: string[];
|
|
245
|
-
let profile: string[];
|
|
246
|
-
let documentation: string[];
|
|
247
|
-
let navigation: string[];
|
|
248
|
-
}
|
|
249
|
-
/** Valid domain filters for `--type`. */
|
|
250
|
-
export const SEARCH_DOMAINS: string[];
|
|
251
19
|
/**
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
* A search candidate gathered from one content domain. Extra underscore-
|
|
259
|
-
* prefixed fields carry domain-specific payload used only by {@link toResult}.
|
|
20
|
+
* The lexical ranker alone: keyword and fuzzy scoring of every candidate.
|
|
21
|
+
* `build` ranks from it.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} query
|
|
24
|
+
* @param {{cwd?: string, type?: 'component'|'hook'|'doc'|'template'|'theme', limit?: number}} [options]
|
|
25
|
+
* @returns {Promise<import('./search.type.mjs').SearchResponse>}
|
|
260
26
|
*/
|
|
261
|
-
export
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
weakKeywords?: string[] | undefined;
|
|
277
|
-
description?: string | undefined;
|
|
278
|
-
prose?: string[] | undefined;
|
|
279
|
-
guidance?: string[] | undefined;
|
|
280
|
-
/**
|
|
281
|
-
* - A doc's title and the headings inside it:
|
|
282
|
-
* the lines a reader scans to pick it. The whole query standing in one of
|
|
283
|
-
* them, or one of them standing whole in the query, is a top-tier match.
|
|
284
|
-
*/
|
|
285
|
-
titles?: string[] | undefined;
|
|
286
|
-
_import?: string | undefined;
|
|
287
|
-
_title?: string | undefined;
|
|
288
|
-
/**
|
|
289
|
-
* - A doc result's topic or docs-tree route.
|
|
290
|
-
*/
|
|
291
|
-
_topic?: string | undefined;
|
|
292
|
-
/**
|
|
293
|
-
* - A doc result's section key, when it is one section.
|
|
294
|
-
*/
|
|
295
|
-
_section?: string | undefined;
|
|
296
|
-
/**
|
|
297
|
-
* - The command that reads exactly this doc part.
|
|
298
|
-
*/
|
|
299
|
-
_command?: string | undefined;
|
|
300
|
-
/**
|
|
301
|
-
* - The command that opens the level above a doc
|
|
302
|
-
* part: its topic's section list, or the docs-tree namespace it sits in.
|
|
303
|
-
*/
|
|
304
|
-
_parent?: string | undefined;
|
|
305
|
-
/**
|
|
306
|
-
* - The npm package that owns the candidate:
|
|
307
|
-
* Core's package for its components, hooks, and templates, the integration's
|
|
308
|
-
* for what it contributed, and for a doc part the package that wrote it.
|
|
309
|
-
*/
|
|
310
|
-
_package?: string | undefined;
|
|
311
|
-
_displayName?: string | undefined;
|
|
312
|
-
_kind?: "page" | "block" | undefined;
|
|
313
|
-
_resultName?: string | undefined;
|
|
314
|
-
_commandName?: string | undefined;
|
|
315
|
-
/**
|
|
316
|
-
* - How an integration component holds its
|
|
317
|
-
* name, for the owner rule.
|
|
318
|
-
*/
|
|
319
|
-
_hold?: "file" | "doc" | undefined;
|
|
320
|
-
/**
|
|
321
|
-
* - An integration component's doc.
|
|
322
|
-
*/
|
|
323
|
-
_docPath?: string | undefined;
|
|
324
|
-
};
|
|
27
|
+
export function searchCore(query: string, options?: {
|
|
28
|
+
cwd?: string;
|
|
29
|
+
type?: "component" | "hook" | "doc" | "template" | "theme";
|
|
30
|
+
limit?: number;
|
|
31
|
+
}): Promise<import("./search.type.mjs").SearchResponse>;
|
|
32
|
+
export { scoreCandidate } from "./_candidate-score.mjs";
|
|
33
|
+
export { scoreQuery } from "./_score.mjs";
|
|
34
|
+
export { domainPriority } from "./_priority.mjs";
|
|
35
|
+
export { compoundHit } from "./_compound.mjs";
|
|
36
|
+
export { SYNONYMS } from "./_synonyms.mjs";
|
|
37
|
+
export { searchedComponents } from "./_result.mjs";
|
|
38
|
+
export { componentKeywords } from "./_adapter.mjs";
|
|
39
|
+
export { SEARCH_DOMAINS, STOPWORDS, tokenizeQuery } from "./_query.mjs";
|
|
40
|
+
export { headingWithPhrase, titleInQuery } from "./_titles.mjs";
|
|
41
|
+
export { sameWord, spellIdentifiers, stem } from "./_words.mjs";
|
|
@@ -17,11 +17,13 @@ export const doc = {
|
|
|
17
17
|
'Unified ranked search across components, hooks, docs, templates, and themes.',
|
|
18
18
|
description:
|
|
19
19
|
'The single "I\'m looking for X" entry point across every content domain. ' +
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
20
|
+
'Matching and scores are keyword + fuzzy (not embeddings). Between score bands ' +
|
|
21
|
+
'results keep the lexical order, whose domain priority can put a weaker ' +
|
|
22
|
+
'component, hook, template, or theme above a stronger doc, and a query that is an entry\'s exact name answers ' +
|
|
23
|
+
'with that entry first. Inside a band, fixed weights order the matches, so a ' +
|
|
24
|
+
'description match can lead a keyword match in the same band (55–99 holds both). ' +
|
|
25
|
+
'A component\'s usage guidance (its best practices) is indexed one tier below ' +
|
|
26
|
+
'its description, so the words a reader types still find it.' +
|
|
25
27
|
" In global mode: with `cwd` outside a project, items from integrations installed next to this CLI package globally are searched too, and theme results name no step that adds a theme to an app; inside a project, only the project's own integrations count. See {@link namespace:global} and {@link generic:computer-integrations}.",
|
|
26
28
|
importPath: '@astryxdesign/cli/api',
|
|
27
29
|
signature:
|