@grimoire-rs/indexer 0.1.9 → 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.
Files changed (42) hide show
  1. package/README.md +38 -0
  2. package/dist/cli/init.js +1 -1
  3. package/dist/cli/init.js.map +1 -1
  4. package/dist/config.d.ts +21 -1
  5. package/dist/config.d.ts.map +1 -1
  6. package/dist/config.js +19 -2
  7. package/dist/config.js.map +1 -1
  8. package/dist/enrich/index.d.ts.map +1 -1
  9. package/dist/enrich/index.js +62 -0
  10. package/dist/enrich/index.js.map +1 -1
  11. package/dist/renderer/astro/components/BrandMark.d.ts +14 -0
  12. package/dist/renderer/astro/components/BrandMark.d.ts.map +1 -0
  13. package/dist/renderer/astro/components/BrandMark.js +16 -0
  14. package/dist/renderer/astro/components/BrandMark.js.map +1 -0
  15. package/dist/renderer/astro/components/BrandMark.tsx +19 -0
  16. package/dist/renderer/astro/components/Catalog.d.ts.map +1 -1
  17. package/dist/renderer/astro/components/Catalog.js +310 -18
  18. package/dist/renderer/astro/components/Catalog.js.map +1 -1
  19. package/dist/renderer/astro/components/Catalog.tsx +445 -63
  20. package/dist/renderer/astro/components/CommandField.astro +43 -0
  21. package/dist/renderer/astro/components/PickerMenu.astro +68 -0
  22. package/dist/renderer/astro/components/VersionMenu.astro +6 -2
  23. package/dist/renderer/astro/content.config.ts +23 -5
  24. package/dist/renderer/astro/layouts/Base.astro +790 -76
  25. package/dist/renderer/astro/lib/catalog.d.ts +10 -0
  26. package/dist/renderer/astro/lib/catalog.d.ts.map +1 -1
  27. package/dist/renderer/astro/lib/catalog.js +28 -0
  28. package/dist/renderer/astro/lib/catalog.js.map +1 -1
  29. package/dist/renderer/astro/lib/catalog.ts +27 -0
  30. package/dist/renderer/astro/lib/code.d.ts +22 -0
  31. package/dist/renderer/astro/lib/code.d.ts.map +1 -0
  32. package/dist/renderer/astro/lib/code.js +21 -0
  33. package/dist/renderer/astro/lib/code.js.map +1 -0
  34. package/dist/renderer/astro/lib/code.ts +21 -0
  35. package/dist/renderer/astro/pages/index.astro +137 -43
  36. package/dist/renderer/astro/pages/p/[...slug].astro +403 -55
  37. package/dist/renderer/index.d.ts +23 -0
  38. package/dist/renderer/index.d.ts.map +1 -1
  39. package/dist/renderer/index.js +117 -30
  40. package/dist/renderer/index.js.map +1 -1
  41. package/package.json +5 -1
  42. package/dist/renderer/astro/components/CopyButton.astro +0 -24
@@ -18,4 +18,14 @@ export declare function addRegistryUrl(extension: string | null, registry: {
18
18
  alias: string;
19
19
  index: string;
20
20
  } | null): string | null;
21
+ /**
22
+ * A bundle member's `id` resolved to the reference the index stores.
23
+ *
24
+ * grim writes members relative to the bundle itself — `../skills/grim-usage:0`
25
+ * — so a member published alongside its bundle stays correct wherever the
26
+ * whole namespace is mirrored. The catalog keys on absolute, untagged refs,
27
+ * which is what this returns; an id that is already absolute passes through
28
+ * with only its tag or digest removed.
29
+ */
30
+ export declare function resolveMemberRef(bundleRef: string, id: string): string;
21
31
  //# sourceMappingURL=catalog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../../src/renderer/astro/lib/catalog.ts"],"names":[],"mappings":"AAOA,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAKrD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAWpF;AAID,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAa5D;AAcD,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAS3C;AAED,+EAA+E;AAC/E,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE9E;AAUD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,QAAQ,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAChD,MAAM,GAAG,IAAI,CAYf"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../../src/renderer/astro/lib/catalog.ts"],"names":[],"mappings":"AAOA,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAKrD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAWpF;AAID,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAa5D;AAcD,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAS3C;AAED,+EAA+E;AAC/E,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE9E;AAUD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,QAAQ,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAChD,MAAM,GAAG,IAAI,CAYf;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAgBtE"}
@@ -92,4 +92,32 @@ export function addRegistryUrl(extension, registry) {
92
92
  const query = new URLSearchParams({ index: url.href, alias: registry.alias });
93
93
  return `vscode://${extension}/add-registry?${query.toString()}`;
94
94
  }
95
+ /**
96
+ * A bundle member's `id` resolved to the reference the index stores.
97
+ *
98
+ * grim writes members relative to the bundle itself — `../skills/grim-usage:0`
99
+ * — so a member published alongside its bundle stays correct wherever the
100
+ * whole namespace is mirrored. The catalog keys on absolute, untagged refs,
101
+ * which is what this returns; an id that is already absolute passes through
102
+ * with only its tag or digest removed.
103
+ */
104
+ export function resolveMemberRef(bundleRef, id) {
105
+ const pinned = id.split("@")[0] ?? id;
106
+ // A tag is a colon *after* the last slash — `localhost:5000/x` is a host,
107
+ // not a tag.
108
+ const slash = pinned.lastIndexOf("/");
109
+ const colon = pinned.lastIndexOf(":");
110
+ const ref = colon > slash ? pinned.slice(0, colon) : pinned;
111
+ if (!ref.startsWith("."))
112
+ return ref;
113
+ // Relative: resolve against the directory the bundle itself lives in.
114
+ const segments = bundleRef.split("/").slice(0, -1);
115
+ for (const segment of ref.split("/")) {
116
+ if (segment === "..")
117
+ segments.pop();
118
+ else if (segment !== "." && segment !== "")
119
+ segments.push(segment);
120
+ }
121
+ return segments.join("/");
122
+ }
95
123
  //# sourceMappingURL=catalog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../../../src/renderer/astro/lib/catalog.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../../../src/renderer/astro/lib/catalog.ts"],"names":[],"mappings":"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"}
@@ -102,3 +102,30 @@ export function addRegistryUrl(
102
102
  const query = new URLSearchParams({ index: url.href, alias: registry.alias });
103
103
  return `vscode://${extension}/add-registry?${query.toString()}`;
104
104
  }
105
+
106
+ /**
107
+ * A bundle member's `id` resolved to the reference the index stores.
108
+ *
109
+ * grim writes members relative to the bundle itself — `../skills/grim-usage:0`
110
+ * — so a member published alongside its bundle stays correct wherever the
111
+ * whole namespace is mirrored. The catalog keys on absolute, untagged refs,
112
+ * which is what this returns; an id that is already absolute passes through
113
+ * with only its tag or digest removed.
114
+ */
115
+ export function resolveMemberRef(bundleRef: string, id: string): string {
116
+ const pinned = id.split("@")[0] ?? id;
117
+ // A tag is a colon *after* the last slash — `localhost:5000/x` is a host,
118
+ // not a tag.
119
+ const slash = pinned.lastIndexOf("/");
120
+ const colon = pinned.lastIndexOf(":");
121
+ const ref = colon > slash ? pinned.slice(0, colon) : pinned;
122
+ if (!ref.startsWith(".")) return ref;
123
+
124
+ // Relative: resolve against the directory the bundle itself lives in.
125
+ const segments = bundleRef.split("/").slice(0, -1);
126
+ for (const segment of ref.split("/")) {
127
+ if (segment === "..") segments.pop();
128
+ else if (segment !== "." && segment !== "") segments.push(segment);
129
+ }
130
+ return segments.join("/");
131
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Light and dark code themes.
3
+ *
4
+ * Shiki is what Astro already ships — the same highlighter VS Code renders
5
+ * with — so nothing here adds a library; this only stops the two consumers
6
+ * drifting onto different themes. The markdown pipeline reads it through
7
+ * `astro.config`'s `shikiConfig`, and the `<Code>` component on the package
8
+ * page takes it as a prop.
9
+ *
10
+ * A *pair*, not one theme: with a single theme a block stays dark on a light
11
+ * page. Given two, Shiki writes the light colour as an inline style and the
12
+ * dark one as a `--shiki-dark` custom property on the same token, and
13
+ * `Base.astro` swaps between them with the rest of the palette.
14
+ *
15
+ * GitHub's pair, deliberately boring: Shiki's best-tested themes, and neutral
16
+ * enough to sit on this page without fighting the accent.
17
+ */
18
+ export declare const SHIKI_THEMES: {
19
+ readonly light: "github-light";
20
+ readonly dark: "github-dark";
21
+ };
22
+ //# sourceMappingURL=code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../../../../src/renderer/astro/lib/code.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,YAAY;;;CAA0D,CAAC"}
@@ -0,0 +1,21 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2026 The Grimoire Authors
3
+ /**
4
+ * Light and dark code themes.
5
+ *
6
+ * Shiki is what Astro already ships — the same highlighter VS Code renders
7
+ * with — so nothing here adds a library; this only stops the two consumers
8
+ * drifting onto different themes. The markdown pipeline reads it through
9
+ * `astro.config`'s `shikiConfig`, and the `<Code>` component on the package
10
+ * page takes it as a prop.
11
+ *
12
+ * A *pair*, not one theme: with a single theme a block stays dark on a light
13
+ * page. Given two, Shiki writes the light colour as an inline style and the
14
+ * dark one as a `--shiki-dark` custom property on the same token, and
15
+ * `Base.astro` swaps between them with the rest of the palette.
16
+ *
17
+ * GitHub's pair, deliberately boring: Shiki's best-tested themes, and neutral
18
+ * enough to sit on this page without fighting the accent.
19
+ */
20
+ export const SHIKI_THEMES = { light: "github-light", dark: "github-dark" };
21
+ //# sourceMappingURL=code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code.js","sourceRoot":"","sources":["../../../../src/renderer/astro/lib/code.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,sCAAsC;AAEtC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAW,CAAC"}
@@ -0,0 +1,21 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2026 The Grimoire Authors
3
+
4
+ /**
5
+ * Light and dark code themes.
6
+ *
7
+ * Shiki is what Astro already ships — the same highlighter VS Code renders
8
+ * with — so nothing here adds a library; this only stops the two consumers
9
+ * drifting onto different themes. The markdown pipeline reads it through
10
+ * `astro.config`'s `shikiConfig`, and the `<Code>` component on the package
11
+ * page takes it as a prop.
12
+ *
13
+ * A *pair*, not one theme: with a single theme a block stays dark on a light
14
+ * page. Given two, Shiki writes the light colour as an inline style and the
15
+ * dark one as a `--shiki-dark` custom property on the same token, and
16
+ * `Base.astro` swaps between them with the rest of the palette.
17
+ *
18
+ * GitHub's pair, deliberately boring: Shiki's best-tested themes, and neutral
19
+ * enough to sit on this page without fighting the accent.
20
+ */
21
+ export const SHIKI_THEMES = { light: "github-light", dark: "github-dark" } as const;
@@ -1,9 +1,19 @@
1
1
  ---
2
2
  import Base from "../layouts/Base.astro";
3
3
  import Catalog from "../components/Catalog.tsx";
4
- import CopyButton from "../components/CopyButton.astro";
4
+ import CommandField from "../components/CommandField.astro";
5
+ import PickerMenu from "../components/PickerMenu.astro";
6
+ import { BrandMark } from "../components/BrandMark.tsx";
7
+ import { FolderRoot, Globe } from "lucide-preact";
5
8
  import { addRegistryUrl } from "../lib/catalog";
6
9
  import { data } from "../lib/data";
10
+ import {
11
+ mdiApple,
12
+ mdiConsole,
13
+ mdiMicrosoftVisualStudioCode,
14
+ mdiMicrosoftWindows,
15
+ mdiPenguin,
16
+ } from "@mdi/js";
7
17
 
8
18
  const { config, packages } = data;
9
19
 
@@ -12,24 +22,54 @@ const { config, packages } = data;
12
22
  // confirmation. Null whenever the link would not work — see `addRegistryUrl`.
13
23
  const addRegistry = addRegistryUrl(config.vscodeExtension, config.registry);
14
24
 
15
- // The "add this index" ergonomic (`helm repo add`): the command a visitor
16
- // needs to point their own grim at *this* index, plus the equivalent
17
- // hand-edit. Absent `registry` config means the index has no public URL to
18
- // hand out, so the block is omitted rather than guessed.
19
- const registryRows = config.registry
25
+ // The extension's own marketplace page the one thing on this page that
26
+ // helps a visitor who does not have it installed yet.
27
+ const marketplace = config.vscodeExtension
28
+ ? `https://marketplace.visualstudio.com/items?itemName=${config.vscodeExtension}`
29
+ : null;
30
+
31
+ // The "add this index" ergonomic (`helm repo add`): the one command a
32
+ // visitor needs to point their own grim at *this* index. Absent `registry`
33
+ // config means the index has no public URL to hand out, so the block is
34
+ // omitted rather than guessed.
35
+ const addCommand = config.registry
36
+ ? `grim config registry add ${config.registry.alias} --index ${config.registry.index}`
37
+ : null;
38
+
39
+ // One installer row usually covers several platforms ("Linux / macOS"), and
40
+ // the toggle reads better as the platforms themselves than as the config's
41
+ // row labels — so a row expands into one button per platform it names, all
42
+ // pointing at the same command. A row naming none (a custom label) keeps a
43
+ // single generic button, so an unrecognized platform is never dropped.
44
+ //
45
+ // `mdiPenguin`, not `mdiLinux`: Tux's own silhouette is a solid mass that
46
+ // reads as an indistinct blob at 16px, where the plainer penguin keeps its
47
+ // outline. Still a brand mark from the same set, so it sits beside Apple
48
+ // and Windows without a weight change.
49
+ const PLATFORMS = [
50
+ { match: /linux/i, name: "Linux", path: mdiPenguin },
51
+ { match: /mac|darwin|osx|apple/i, name: "macOS", path: mdiApple },
52
+ { match: /win/i, name: "Windows", path: mdiMicrosoftWindows },
53
+ ];
54
+ const installChoices = config.install.flatMap((row) => {
55
+ const hits = PLATFORMS.filter((p) => p.match.test(row.os));
56
+ return hits.length > 0
57
+ ? hits.map((p) => ({ name: p.name, path: p.path, command: row.command }))
58
+ : [{ name: row.os, path: mdiConsole, command: row.command }];
59
+ });
60
+
61
+ // Registry scope, the same two-way choice the package cards offer and drawn
62
+ // with the same two Lucide glyphs. Global leads: someone arriving from an
63
+ // index website wants this index available everywhere, not wired into
64
+ // whichever directory happens to be open — and it is also the scope that
65
+ // works with no project at all.
66
+ // `--global` leads rather than trails: it is a top-level flag, and appended
67
+ // after a long `--index <url>` it fell off the end of the line, so switching
68
+ // scope looked like it changed nothing at all.
69
+ const scopeChoices = addCommand
20
70
  ? [
21
- {
22
- os: "add index",
23
- command: `grim config registry add ${config.registry.alias} --index ${config.registry.index}`,
24
- block: false,
25
- label: "Copy the registry add command",
26
- },
27
- {
28
- os: "grimoire.toml",
29
- command: `[[registries]]\nalias = "${config.registry.alias}"\nindex = "${config.registry.index}"`,
30
- block: true,
31
- label: "Copy the registries TOML entry",
32
- },
71
+ { name: "Global", command: `grim --global ${addCommand.slice("grim ".length)}`, Icon: Globe },
72
+ { name: "Project", command: addCommand, Icon: FolderRoot },
33
73
  ]
34
74
  : [];
35
75
  ---
@@ -43,41 +83,95 @@ const registryRows = config.registry
43
83
  config.installDocsUrl && (
44
84
  <Fragment>
45
85
  {" "}
46
- Copy an <code>add</code> command below — or{" "}
47
- <a href={config.installDocsUrl}>install grim</a> first.
86
+ <a href={config.installDocsUrl}>Install grim</a>, add this index,
87
+ then <code>grim add</code> anything below.
48
88
  </Fragment>
49
89
  )
50
90
  }
51
91
  </p>
92
+ {/* Beside the description, not under it: getting set up is a sidebar to
93
+ reading what this index is. Two labelled rows of one shape — the
94
+ command, then the ways to act on it, inside a single border. */}
52
95
  {
53
- (config.install.length > 0 || registryRows.length > 0) && (
54
- <div class="install">
55
- {config.install.map((row) => (
56
- <div class="install-row">
57
- <span class="os">{row.os}</span>
58
- <code>{row.command}</code>
59
- <CopyButton value={row.command} label={`Copy the ${row.os} install command`} />
60
- </div>
61
- ))}
62
- {registryRows.map((row) => (
63
- <div class="install-row">
64
- <span class="os">{row.os}</span>
65
- <code class:list={[{ block: row.block }]}>{row.command}</code>
66
- <CopyButton value={row.command} label={row.label} />
67
- </div>
68
- ))}
69
- {addRegistry && (
70
- <div class="install-row">
71
- <span class="os">VS Code</span>
72
- <a class="vscode-add" href={addRegistry}>
73
- Add this index to VS Code
74
- </a>
75
- </div>
96
+ (installChoices.length > 0 || addCommand || addRegistry) && (
97
+ <div class="hero-side">
98
+ {installChoices.length > 0 && (
99
+ <Fragment>
100
+ <span class="side-label">install grim</span>
101
+ <div class="cmd-bar" data-os-switch data-os-detect data-os-noun="install command">
102
+ {installChoices.length > 1 && (
103
+ <PickerMenu
104
+ choices={installChoices}
105
+ title="Platform"
106
+ label="Choose your platform"
107
+ />
108
+ )}
109
+ <CommandField
110
+ value={installChoices[0].command}
111
+ name={`${installChoices[0].name} install command`}
112
+ label="Copy the install command"
113
+ />
114
+ {marketplace && (
115
+ <a
116
+ class="seg brand-link"
117
+ href={marketplace}
118
+ target="_blank"
119
+ rel="noopener noreferrer"
120
+ title="Get the VS Code extension"
121
+ aria-label="Get the VS Code extension from the marketplace"
122
+ >
123
+ <BrandMark path={mdiMicrosoftVisualStudioCode} />
124
+ </a>
125
+ )}
126
+ </div>
127
+ </Fragment>
128
+ )}
129
+ {(addCommand || addRegistry) && (
130
+ <Fragment>
131
+ <span class="side-label">add registry</span>
132
+ <div class="cmd-bar" data-os-switch data-os-noun="registry add command">
133
+ {scopeChoices.length > 0 && (
134
+ <PickerMenu choices={scopeChoices} title="Scope" label="Choose the scope" />
135
+ )}
136
+ {scopeChoices.length > 0 && (
137
+ <CommandField
138
+ value={scopeChoices[0].command}
139
+ name={`${scopeChoices[0].name} registry add command`}
140
+ label="Copy the registry add command"
141
+ />
142
+ )}
143
+ {addRegistry && (
144
+ <a
145
+ class="seg brand-link"
146
+ href={addRegistry}
147
+ title="Add this index via VS Code"
148
+ aria-label="Add this index via VS Code"
149
+ >
150
+ <BrandMark path={mdiMicrosoftVisualStudioCode} />
151
+ </a>
152
+ )}
153
+ </div>
154
+ </Fragment>
76
155
  )}
77
156
  </div>
78
157
  )
79
158
  }
80
159
  </div>
81
160
 
161
+ {/* Right after the bar, on purpose: the layout's picker script sits at the
162
+ end of the document, past the whole catalog, and the browser can paint
163
+ before it runs — long enough to show a Linux command to someone on
164
+ Windows. Here it lands in the same parse as the hero. A platform the
165
+ bar does not offer leaves the configured first choice alone. */}
166
+ <script is:inline>
167
+ for (const bar of document.querySelectorAll("[data-os-detect]")) {
168
+ const host = window.__grimHostOs();
169
+ const match = [...bar.querySelectorAll("[data-os-pick]")].find(
170
+ (p) => p.dataset.osName === host,
171
+ );
172
+ if (match) window.__grimPick(bar, match);
173
+ }
174
+ </script>
175
+
82
176
  <Catalog client:load packages={packages} vscodeExtension={config.vscodeExtension} />
83
177
  </Base>