shelving 1.245.0 → 1.246.1
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/extract/PackageExtractor.d.ts +1 -0
- package/extract/PackageExtractor.js +12 -6
- package/package.json +1 -1
- package/util/tree.d.ts +3 -2
- package/util/tree.js +7 -3
|
@@ -32,6 +32,7 @@ export interface PackageExtractorOptions {
|
|
|
32
32
|
* - Static export keys (e.g. `"./api"`, `"./firestore/client"`) become one module each.
|
|
33
33
|
* - Wildcard export keys (e.g. `"./util/*"`) expand against the source tree — one module per matching child file or subdirectory.
|
|
34
34
|
* - Each export's *target* extension (e.g. the `.js` in `"./util/*.js"`) is mapped to source extensions via `extensions`, so built `.js` paths resolve to their `.ts` sources.
|
|
35
|
+
* - Each module's `title` is prefixed with the package `name` (e.g. `ui` → `shelving/ui`) so listings read as package subpaths.
|
|
35
36
|
* - The `"."` root export is skipped — its content is the root tree element itself.
|
|
36
37
|
* - Throws if a static export key has no matching source element in the tree.
|
|
37
38
|
*
|
|
@@ -16,6 +16,7 @@ const DEFAULT_EXTENSIONS = {
|
|
|
16
16
|
* - Static export keys (e.g. `"./api"`, `"./firestore/client"`) become one module each.
|
|
17
17
|
* - Wildcard export keys (e.g. `"./util/*"`) expand against the source tree — one module per matching child file or subdirectory.
|
|
18
18
|
* - Each export's *target* extension (e.g. the `.js` in `"./util/*.js"`) is mapped to source extensions via `extensions`, so built `.js` paths resolve to their `.ts` sources.
|
|
19
|
+
* - Each module's `title` is prefixed with the package `name` (e.g. `ui` → `shelving/ui`) so listings read as package subpaths.
|
|
19
20
|
* - The `"."` root export is skipped — its content is the root tree element itself.
|
|
20
21
|
* - Throws if a static export key has no matching source element in the tree.
|
|
21
22
|
*
|
|
@@ -56,7 +57,9 @@ export class PackageExtractor extends Extractor {
|
|
|
56
57
|
async extract(packageJson) {
|
|
57
58
|
const pkgPath = requirePath(packageJson, this._base, this.extract);
|
|
58
59
|
const pkg = (await Bun.file(pkgPath).json());
|
|
59
|
-
const
|
|
60
|
+
const tree = this._tree;
|
|
61
|
+
// Read the package name alongside its exports — the name prefixes each module title (e.g. `ui` → `shelving/ui`).
|
|
62
|
+
const { name, exports = {} } = pkg;
|
|
60
63
|
const modules = [];
|
|
61
64
|
for (const [key, value] of Object.entries(exports)) {
|
|
62
65
|
if (key === ".")
|
|
@@ -76,18 +79,21 @@ export class PackageExtractor extends Extractor {
|
|
|
76
79
|
modules.push(this._module.extract({ name: subpath, source }));
|
|
77
80
|
}
|
|
78
81
|
}
|
|
79
|
-
|
|
82
|
+
// Prefix the package name onto each module's title so listings read `shelving/ui` rather than a bare `ui`, making modules glanceable as package subpaths.
|
|
83
|
+
const children = name
|
|
84
|
+
? modules.map(module => ({ ...module, props: { ...module.props, title: `${name}/${module.props.title ?? module.props.name}` } }))
|
|
85
|
+
: modules;
|
|
80
86
|
// Canonical URL `path`s aren't stamped here — they're derived from tree structure when the tree is flattened (`flattenTree()`) in the UI layer.
|
|
81
87
|
return {
|
|
82
88
|
type: "tree-element",
|
|
83
|
-
key:
|
|
89
|
+
key: name ?? tree.key,
|
|
84
90
|
props: {
|
|
85
91
|
source: tree.props.source,
|
|
86
|
-
name:
|
|
87
|
-
title:
|
|
92
|
+
name: name ?? tree.props.name,
|
|
93
|
+
title: name ?? tree.props.title,
|
|
88
94
|
description: pkg.description ?? tree.props.description,
|
|
89
95
|
content: tree.props.content,
|
|
90
|
-
children
|
|
96
|
+
children,
|
|
91
97
|
},
|
|
92
98
|
};
|
|
93
99
|
}
|
package/package.json
CHANGED
package/util/tree.d.ts
CHANGED
|
@@ -185,8 +185,9 @@ export interface SearchTreeOptions {
|
|
|
185
185
|
* Search the descendants of a tree element and return the best-ranked matches.
|
|
186
186
|
*
|
|
187
187
|
* - Walks every descendant of `scope` (depth-first; `scope` itself is not a candidate), optionally narrowed by `options.filter`.
|
|
188
|
-
* - Tokenises `query` with `getWords()` so quoted phrases match literally: `searchTree(root, '"hello world" foo')`
|
|
189
|
-
* -
|
|
188
|
+
* - Tokenises `query` with `getWords()` so quoted phrases match literally: `searchTree(root, '"hello world" foo')` matches the phrase `hello world` *and* the word `foo`.
|
|
189
|
+
* - Requires *every* token to match (AND, not OR): a candidate is only returned when each token matches at least one of its props. So `date util` returns only elements matching both `date` and `util`, not either alone.
|
|
190
|
+
* - Ranks each candidate (case-insensitive) per token, summing each token's best tier: `name` exact > `name` starts-with > `name` includes > `title` includes > `description` includes > `content` includes. A `name` match always outranks a content-only match.
|
|
190
191
|
* - An empty `query` returns the (filtered) candidates in tree order — useful for a filter-only or "show everything" listing.
|
|
191
192
|
*
|
|
192
193
|
* @param scope The element whose descendants are searched.
|
package/util/tree.js
CHANGED
|
@@ -47,8 +47,9 @@ function _flatKey(element) {
|
|
|
47
47
|
* Search the descendants of a tree element and return the best-ranked matches.
|
|
48
48
|
*
|
|
49
49
|
* - Walks every descendant of `scope` (depth-first; `scope` itself is not a candidate), optionally narrowed by `options.filter`.
|
|
50
|
-
* - Tokenises `query` with `getWords()` so quoted phrases match literally: `searchTree(root, '"hello world" foo')`
|
|
51
|
-
* -
|
|
50
|
+
* - Tokenises `query` with `getWords()` so quoted phrases match literally: `searchTree(root, '"hello world" foo')` matches the phrase `hello world` *and* the word `foo`.
|
|
51
|
+
* - Requires *every* token to match (AND, not OR): a candidate is only returned when each token matches at least one of its props. So `date util` returns only elements matching both `date` and `util`, not either alone.
|
|
52
|
+
* - Ranks each candidate (case-insensitive) per token, summing each token's best tier: `name` exact > `name` starts-with > `name` includes > `title` includes > `description` includes > `content` includes. A `name` match always outranks a content-only match.
|
|
52
53
|
* - An empty `query` returns the (filtered) candidates in tree order — useful for a filter-only or "show everything" listing.
|
|
53
54
|
*
|
|
54
55
|
* @param scope The element whose descendants are searched.
|
|
@@ -91,7 +92,7 @@ const _SCORE_NAME_INCLUDES = 100;
|
|
|
91
92
|
const _SCORE_TITLE = 10;
|
|
92
93
|
const _SCORE_DESCRIPTION = 4;
|
|
93
94
|
const _SCORE_CONTENT = 1;
|
|
94
|
-
/** Score one element's props against the (already lower-cased) query tokens —
|
|
95
|
+
/** Score one element's props against the (already lower-cased) query tokens — every token must match (AND), each contributing its best-matching tier, summed. */
|
|
95
96
|
function _scoreElement(props, tokens) {
|
|
96
97
|
const name = props.name.toLowerCase();
|
|
97
98
|
const title = props.title?.toLowerCase() ?? "";
|
|
@@ -99,6 +100,7 @@ function _scoreElement(props, tokens) {
|
|
|
99
100
|
const content = props.content?.toLowerCase() ?? "";
|
|
100
101
|
let score = 0;
|
|
101
102
|
for (const token of tokens) {
|
|
103
|
+
// Every token must match somewhere — a single token that matches nothing drops the candidate entirely (AND, not OR).
|
|
102
104
|
if (name === token)
|
|
103
105
|
score += _SCORE_NAME_EXACT;
|
|
104
106
|
else if (name.startsWith(token))
|
|
@@ -111,6 +113,8 @@ function _scoreElement(props, tokens) {
|
|
|
111
113
|
score += _SCORE_DESCRIPTION;
|
|
112
114
|
else if (content.includes(token))
|
|
113
115
|
score += _SCORE_CONTENT;
|
|
116
|
+
else
|
|
117
|
+
return 0;
|
|
114
118
|
}
|
|
115
119
|
return score;
|
|
116
120
|
}
|