@squinch/core 0.1.1 → 0.2.0
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/api.d.ts +11 -0
- package/dist/api.js +44 -8
- package/package.json +6 -6
package/dist/api.d.ts
CHANGED
|
@@ -36,6 +36,17 @@ export declare function iconsUsedBy(files: ProjectFile[] | string): {
|
|
|
36
36
|
* them and a result of only `azure/key-vaults` reads as proof that
|
|
37
37
|
* `azure/key-vault` doesn't exist) can look them up via `packInfo`. */
|
|
38
38
|
export declare function searchIcons(query: string, pack?: string): string[];
|
|
39
|
+
/** The same search, saying how it matched. `relaxed: true` means no icon
|
|
40
|
+
* matched every word, so the hits are the closest partial matches instead —
|
|
41
|
+
* callers that print for an agent loop label them (`no exact match —
|
|
42
|
+
* closest:`), because near-misses answer the question and an empty list
|
|
43
|
+
* forces a second pass with different words. Measured before ranking
|
|
44
|
+
* existed: `rag` returned eighteen sto*rag*e rows with `sys/rag` dead last,
|
|
45
|
+
* and "message queue" / "object storage" returned nothing at all. */
|
|
46
|
+
export declare function searchIconsDetailed(query: string, pack?: string): {
|
|
47
|
+
hits: string[];
|
|
48
|
+
relaxed: boolean;
|
|
49
|
+
};
|
|
39
50
|
export type { ProjectFile };
|
|
40
51
|
export type * from "./model/types.js";
|
|
41
52
|
export { HUES } from "./model/types.js";
|
package/dist/api.js
CHANGED
|
@@ -69,6 +69,16 @@ export function iconsUsedBy(files) {
|
|
|
69
69
|
* them and a result of only `azure/key-vaults` reads as proof that
|
|
70
70
|
* `azure/key-vault` doesn't exist) can look them up via `packInfo`. */
|
|
71
71
|
export function searchIcons(query, pack) {
|
|
72
|
+
return searchIconsDetailed(query, pack).hits;
|
|
73
|
+
}
|
|
74
|
+
/** The same search, saying how it matched. `relaxed: true` means no icon
|
|
75
|
+
* matched every word, so the hits are the closest partial matches instead —
|
|
76
|
+
* callers that print for an agent loop label them (`no exact match —
|
|
77
|
+
* closest:`), because near-misses answer the question and an empty list
|
|
78
|
+
* forces a second pass with different words. Measured before ranking
|
|
79
|
+
* existed: `rag` returned eighteen sto*rag*e rows with `sys/rag` dead last,
|
|
80
|
+
* and "message queue" / "object storage" returned nothing at all. */
|
|
81
|
+
export function searchIconsDetailed(query, pack) {
|
|
72
82
|
// Vendors are inconsistent about number — Azure has "Container Registries"
|
|
73
83
|
// and "Data Factories" where everyone searches "container registry" and
|
|
74
84
|
// "data factory" — so both sides are singularized before comparing.
|
|
@@ -97,20 +107,46 @@ export function searchIcons(query, pack) {
|
|
|
97
107
|
}
|
|
98
108
|
}
|
|
99
109
|
const words = rawWords.map(stem);
|
|
100
|
-
const
|
|
110
|
+
const joined = words.join(" ");
|
|
111
|
+
const scored = [];
|
|
101
112
|
for (const name of allPackNames()) {
|
|
102
113
|
if (packFilter && name !== packFilter)
|
|
103
114
|
continue;
|
|
104
|
-
const aliases = packInfo(name)?.aliases ?? {};
|
|
105
115
|
const haystack = (id) => norm(`${id} ${iconTitle(name, id) ?? ""}`);
|
|
106
|
-
const
|
|
107
|
-
for (const id of
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
116
|
+
const matchedIds = new Set(iconIds(name).filter((id) => words.some((w) => haystack(id).includes(w)) || !words.length));
|
|
117
|
+
for (const id of matchedIds) {
|
|
118
|
+
const hay = haystack(id);
|
|
119
|
+
const hayWords = new Set(hay.split(" "));
|
|
120
|
+
scored.push({
|
|
121
|
+
hit: `${name}/${id}`,
|
|
122
|
+
exact: joined && norm(id) === joined ? 1 : 0,
|
|
123
|
+
whole: words.length && words.every((w) => hayWords.has(w)) ? 1 : 0,
|
|
124
|
+
matched: words.filter((w) => hay.includes(w)).length,
|
|
125
|
+
});
|
|
111
126
|
}
|
|
112
127
|
}
|
|
113
|
-
|
|
128
|
+
// One row per icon: an alias row is dropped only when its canonical is in
|
|
129
|
+
// the SAME result list. Checking the broader matched set instead deduped
|
|
130
|
+
// `sys/vector-search` (a full match) against a canonical that had only
|
|
131
|
+
// matched one word and was not being returned at all.
|
|
132
|
+
const dedupe = (list) => {
|
|
133
|
+
const present = new Set(list.map((s) => s.hit));
|
|
134
|
+
return list.filter((s) => {
|
|
135
|
+
const name = s.hit.slice(0, s.hit.indexOf("/"));
|
|
136
|
+
const id = s.hit.slice(s.hit.indexOf("/") + 1);
|
|
137
|
+
const canonical = (packInfo(name)?.aliases ?? {})[id];
|
|
138
|
+
return !(canonical && present.has(`${name}/${canonical}`)); // canonical covers it
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
const rank = (list) => dedupe(list)
|
|
142
|
+
.sort((a, b) => b.exact - a.exact || b.whole - a.whole || b.matched - a.matched || (a.hit < b.hit ? -1 : 1))
|
|
143
|
+
.map((s) => s.hit);
|
|
144
|
+
const full = scored.filter((s) => s.matched === words.length);
|
|
145
|
+
if (full.length || !words.length)
|
|
146
|
+
return { hits: rank(full), relaxed: false };
|
|
147
|
+
// Nothing matched every word: fall back to partial matches, best first.
|
|
148
|
+
// Capped — the point is a next move, not a directory listing.
|
|
149
|
+
return { hits: rank(scored).slice(0, 12), relaxed: true };
|
|
114
150
|
}
|
|
115
151
|
// the one colour vocabulary, for editors that complete it and tests that sweep it
|
|
116
152
|
export { HUES } from "./model/types.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@squinch/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "The Squinch engine: parse, model, layout and deterministic SVG rendering for architecture diagrams as code.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"architecture",
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"@lezer/lr": "^1.4.10",
|
|
34
34
|
"elkjs": "^0.12.0",
|
|
35
35
|
"fast-xml-parser": "^5.10.1",
|
|
36
|
-
"@squinch/pack-aws": "0.
|
|
37
|
-
"@squinch/pack-
|
|
38
|
-
"@squinch/pack-
|
|
39
|
-
"@squinch/pack-
|
|
40
|
-
"@squinch/pack-
|
|
36
|
+
"@squinch/pack-aws": "0.2.0",
|
|
37
|
+
"@squinch/pack-azure": "0.2.0",
|
|
38
|
+
"@squinch/pack-k8s": "0.2.0",
|
|
39
|
+
"@squinch/pack-logos": "0.2.0",
|
|
40
|
+
"@squinch/pack-sys": "0.2.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@fontsource/ibm-plex-mono": "^5.3.0",
|