@grimoire-rs/indexer 0.4.3 → 0.5.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 (61) hide show
  1. package/CHANGELOG.md +190 -0
  2. package/NOTICE +30 -0
  3. package/README.md +76 -331
  4. package/dist/cli/init.d.ts.map +1 -1
  5. package/dist/cli/init.js +35 -4
  6. package/dist/cli/init.js.map +1 -1
  7. package/dist/config.d.ts +107 -7
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/config.js +181 -36
  10. package/dist/config.js.map +1 -1
  11. package/dist/renderer/astro/components/CardLogo.d.ts +5 -0
  12. package/dist/renderer/astro/components/CardLogo.js +58 -0
  13. package/dist/renderer/astro/components/CardLogo.tsx +96 -0
  14. package/dist/renderer/astro/components/Catalog.d.ts +14 -1
  15. package/dist/renderer/astro/components/Catalog.js +467 -108
  16. package/dist/renderer/astro/components/Catalog.tsx +756 -349
  17. package/dist/renderer/astro/components/CommandBar.astro +66 -0
  18. package/dist/renderer/astro/components/CopyButton.d.ts +7 -0
  19. package/dist/renderer/astro/components/CopyButton.js +28 -0
  20. package/dist/renderer/astro/components/CopyButton.tsx +56 -0
  21. package/dist/renderer/astro/components/KindMark.d.ts +69 -0
  22. package/dist/renderer/astro/components/KindMark.js +66 -0
  23. package/dist/renderer/astro/components/KindMark.tsx +141 -0
  24. package/dist/renderer/astro/components/PackageCard.d.ts +18 -0
  25. package/dist/renderer/astro/components/PackageCard.js +50 -0
  26. package/dist/renderer/astro/components/PackageCard.tsx +273 -0
  27. package/dist/renderer/astro/components/PackageRow.d.ts +10 -0
  28. package/dist/renderer/astro/components/PackageRow.js +32 -0
  29. package/dist/renderer/astro/components/PackageRow.tsx +126 -0
  30. package/dist/renderer/astro/components/PickerMenu.astro +5 -14
  31. package/dist/renderer/astro/components/SiteFooter.astro +64 -0
  32. package/dist/renderer/astro/components/SiteHeader.astro +74 -0
  33. package/dist/renderer/astro/components/VersionMenu.astro +2 -2
  34. package/dist/renderer/astro/layouts/Base.astro +860 -206
  35. package/dist/renderer/astro/lib/base.d.ts +25 -0
  36. package/dist/renderer/astro/lib/base.js +23 -0
  37. package/dist/renderer/astro/lib/base.ts +27 -0
  38. package/dist/renderer/astro/lib/catalog.d.ts +24 -0
  39. package/dist/renderer/astro/lib/catalog.js +36 -0
  40. package/dist/renderer/astro/lib/catalog.ts +37 -0
  41. package/dist/renderer/astro/lib/commands.d.ts +58 -0
  42. package/dist/renderer/astro/lib/commands.js +86 -0
  43. package/dist/renderer/astro/lib/commands.ts +117 -0
  44. package/dist/renderer/astro/lib/keywordRail.d.ts +44 -0
  45. package/dist/renderer/astro/lib/keywordRail.js +99 -0
  46. package/dist/renderer/astro/lib/keywordRail.ts +110 -0
  47. package/dist/renderer/astro/pages/index.astro +40 -87
  48. package/dist/renderer/astro/pages/p/[...slug].astro +340 -195
  49. package/dist/renderer/astro/styles/tokens.css +40 -5
  50. package/dist/renderer/index.d.ts +58 -0
  51. package/dist/renderer/index.d.ts.map +1 -1
  52. package/dist/renderer/index.js +547 -5
  53. package/dist/renderer/index.js.map +1 -1
  54. package/dist/renderer/types.d.ts +9 -0
  55. package/dist/renderer/types.d.ts.map +1 -1
  56. package/package.json +9 -4
  57. package/templates/README.md +6 -0
  58. package/templates/ci/github-ratings.yml +5 -0
  59. package/templates/gitignore +4 -1
  60. package/templates/theme/README.md +38 -0
  61. package/templates/tsconfig.json +47 -0
@@ -0,0 +1,58 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // Copyright 2026 The Grimoire Authors
4
+ // The package logo slot, shared by the card and the table row — and split out
5
+ // of `Catalog.tsx` so that replacing either of those under `theme/components/`
6
+ // does not mean re-implementing the three states a logo has here.
7
+ import { useEffect, useRef, useState } from "preact/hooks";
8
+ import { Image, ImageOff } from "lucide-preact";
9
+ import { withBase } from "../lib/base.js";
10
+ export /**
11
+ * The card's 28px logo slot, in its three states.
12
+ *
13
+ * The third one is the reason this is a component rather than inline JSX: a
14
+ * package can declare a `logo` whose file is not actually served — the
15
+ * enrich step failed, the asset was pruned, the path is stale — and the
16
+ * browser's own broken-image glyph is both ugly and says nothing. So a
17
+ * declared-but-unreachable logo degrades to a marked placeholder, which is
18
+ * deliberately *not* the same as the initial-letter tile a package with no
19
+ * logo at all gets: one is a fault worth seeing, the other is normal.
20
+ *
21
+ * The static detail page needs the same treatment but cannot use `onError`,
22
+ * so it opts into the global handler in `Base.astro` instead — keep the two
23
+ * placeholders looking alike.
24
+ */ function CardLogo({ pkg }) {
25
+ const [state, setState] = useState("loading");
26
+ const imgRef = useRef(null);
27
+ // The image is server-rendered, so the browser begins fetching it while
28
+ // parsing the HTML — long before this island hydrates. Two consequences,
29
+ // and the slot markup below answers both: `onError` can fire before any
30
+ // listener exists (the placeholder used to appear only sometimes), and a
31
+ // failed image paints the browser's broken glyph on the way (the flash on
32
+ // reload). Starting the image hidden means nothing is ever shown until it
33
+ // is known to be good.
34
+ //
35
+ // `complete` says the browser finished, not how it went. `decode()` is
36
+ // what separates the two: it rejects for a failure and resolves for a good
37
+ // image — including an SVG with no intrinsic size, where the usual
38
+ // `naturalWidth === 0` test reports a false failure. Gating on `complete`
39
+ // means it never starts a fetch, so `loading="lazy"` still holds off
40
+ // -screen cards.
41
+ useEffect(() => {
42
+ setState("loading");
43
+ const img = imgRef.current;
44
+ if (!img?.complete)
45
+ return;
46
+ let live = true;
47
+ img.decode().then(() => live && setState("ready"), () => live && setState("broken"));
48
+ return () => {
49
+ live = false;
50
+ };
51
+ }, [pkg.logo]);
52
+ if (!pkg.logo) {
53
+ return (_jsx("span", { class: "card-logo card-logo-fallback", "aria-hidden": "true", style: {
54
+ background: `var(--grim-color-kind-${pkg.kind}, var(--grim-color-muted))`,
55
+ }, children: pkg.name[0]?.toUpperCase() }));
56
+ }
57
+ return (_jsxs("span", { class: "card-logo logo-slot", "data-state": state, role: state === "broken" ? "img" : undefined, "aria-label": state === "broken" ? "Logo image unavailable" : undefined, title: state === "broken" ? "Logo image unavailable" : undefined, children: [state === "broken" ? (_jsx(ImageOff, { class: "logo-mark", "aria-hidden": "true" })) : (_jsx(Image, { class: "logo-mark", "aria-hidden": "true" })), _jsx("img", { ref: imgRef, src: withBase(pkg.logo), alt: "", loading: "lazy", onLoad: () => setState("ready"), onError: () => setState("broken") })] }));
58
+ }
@@ -0,0 +1,96 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2026 The Grimoire Authors
3
+
4
+ // The package logo slot, shared by the card and the table row — and split out
5
+ // of `Catalog.tsx` so that replacing either of those under `theme/components/`
6
+ // does not mean re-implementing the three states a logo has here.
7
+ import { useEffect, useRef, useState } from "preact/hooks";
8
+ import { Image, ImageOff } from "lucide-preact";
9
+ import { withBase } from "../lib/base.js";
10
+ import type { CatalogPackage } from "../lib/catalog.js";
11
+
12
+ export /**
13
+ * The card's 28px logo slot, in its three states.
14
+ *
15
+ * The third one is the reason this is a component rather than inline JSX: a
16
+ * package can declare a `logo` whose file is not actually served — the
17
+ * enrich step failed, the asset was pruned, the path is stale — and the
18
+ * browser's own broken-image glyph is both ugly and says nothing. So a
19
+ * declared-but-unreachable logo degrades to a marked placeholder, which is
20
+ * deliberately *not* the same as the initial-letter tile a package with no
21
+ * logo at all gets: one is a fault worth seeing, the other is normal.
22
+ *
23
+ * The static detail page needs the same treatment but cannot use `onError`,
24
+ * so it opts into the global handler in `Base.astro` instead — keep the two
25
+ * placeholders looking alike.
26
+ */
27
+ function CardLogo({ pkg }: { pkg: CatalogPackage }) {
28
+ const [state, setState] = useState<"loading" | "ready" | "broken">("loading");
29
+ const imgRef = useRef<HTMLImageElement>(null);
30
+
31
+ // The image is server-rendered, so the browser begins fetching it while
32
+ // parsing the HTML — long before this island hydrates. Two consequences,
33
+ // and the slot markup below answers both: `onError` can fire before any
34
+ // listener exists (the placeholder used to appear only sometimes), and a
35
+ // failed image paints the browser's broken glyph on the way (the flash on
36
+ // reload). Starting the image hidden means nothing is ever shown until it
37
+ // is known to be good.
38
+ //
39
+ // `complete` says the browser finished, not how it went. `decode()` is
40
+ // what separates the two: it rejects for a failure and resolves for a good
41
+ // image — including an SVG with no intrinsic size, where the usual
42
+ // `naturalWidth === 0` test reports a false failure. Gating on `complete`
43
+ // means it never starts a fetch, so `loading="lazy"` still holds off
44
+ // -screen cards.
45
+ useEffect(() => {
46
+ setState("loading");
47
+ const img = imgRef.current;
48
+ if (!img?.complete) return;
49
+ let live = true;
50
+ img.decode().then(
51
+ () => live && setState("ready"),
52
+ () => live && setState("broken"),
53
+ );
54
+ return () => {
55
+ live = false;
56
+ };
57
+ }, [pkg.logo]);
58
+
59
+ if (!pkg.logo) {
60
+ return (
61
+ <span
62
+ class="card-logo card-logo-fallback"
63
+ aria-hidden="true"
64
+ style={{
65
+ background: `var(--grim-color-kind-${pkg.kind}, var(--grim-color-muted))`,
66
+ }}
67
+ >
68
+ {pkg.name[0]?.toUpperCase()}
69
+ </span>
70
+ );
71
+ }
72
+
73
+ return (
74
+ <span
75
+ class="card-logo logo-slot"
76
+ data-state={state}
77
+ role={state === "broken" ? "img" : undefined}
78
+ aria-label={state === "broken" ? "Logo image unavailable" : undefined}
79
+ title={state === "broken" ? "Logo image unavailable" : undefined}
80
+ >
81
+ {state === "broken" ? (
82
+ <ImageOff class="logo-mark" aria-hidden="true" />
83
+ ) : (
84
+ <Image class="logo-mark" aria-hidden="true" />
85
+ )}
86
+ <img
87
+ ref={imgRef}
88
+ src={withBase(pkg.logo)}
89
+ alt=""
90
+ loading="lazy"
91
+ onLoad={() => setState("ready")}
92
+ onError={() => setState("broken")}
93
+ />
94
+ </span>
95
+ );
96
+ }
@@ -1,6 +1,19 @@
1
1
  import { type CatalogPackage } from "../lib/catalog.js";
2
2
  export type Sort = "name" | "updated" | "rating";
3
- export declare function compare(a: CatalogPackage, b: CatalogPackage, sort: Sort): number;
3
+ export type Dir = "asc" | "desc";
4
+ /** Roomy cards, or the same packages as a scannable list. */
5
+ export type View = "cards" | "table";
6
+ /**
7
+ * The direction each field is *worth* reading first in — A→Z for a name,
8
+ * newest and best-liked first for the two ranked keys.
9
+ *
10
+ * Picking a field selects its natural direction; the toggle beside the
11
+ * combo box reverses that. So "descending" is not a global default a reader
12
+ * has to correct on every mode, and the arrow always describes what the
13
+ * order actually is rather than which way a flag is set.
14
+ */
15
+ export declare const NATURAL: Record<Sort, Dir>;
16
+ export declare function compare(a: CatalogPackage, b: CatalogPackage, sort: Sort, dir?: Dir): number;
4
17
  export default function Catalog({ packages, vscodeExtension, }: {
5
18
  packages: CatalogPackage[];
6
19
  vscodeExtension: string | null;