@grimoire-rs/indexer 0.5.1 → 0.5.3
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/CHANGELOG.md +127 -1
- package/dist/renderer/astro/components/CardLogo.d.ts +2 -2
- package/dist/renderer/astro/components/CardLogo.tsx +2 -2
- package/dist/renderer/astro/components/Catalog.d.ts +12 -4
- package/dist/renderer/astro/components/Catalog.js +356 -88
- package/dist/renderer/astro/components/Catalog.tsx +442 -108
- package/dist/renderer/astro/components/PackageCard.d.ts +2 -2
- package/dist/renderer/astro/components/PackageCard.js +1 -1
- package/dist/renderer/astro/components/PackageCard.tsx +11 -3
- package/dist/renderer/astro/components/PackageRow.d.ts +2 -2
- package/dist/renderer/astro/components/PackageRow.tsx +2 -2
- package/dist/renderer/astro/layouts/Base.astro +145 -51
- package/dist/renderer/astro/lib/catalog.d.ts +31 -1
- package/dist/renderer/astro/lib/catalog.js +32 -0
- package/dist/renderer/astro/lib/catalog.ts +73 -1
- package/dist/renderer/astro/lib/search.d.ts +17 -0
- package/dist/renderer/astro/lib/search.js +138 -0
- package/dist/renderer/astro/lib/search.ts +157 -0
- package/dist/renderer/astro/pages/index.astro +45 -2
- package/dist/renderer/astro/styles/tokens.css +6 -1
- package/dist/renderer/index.d.ts.map +1 -1
- package/dist/renderer/index.js +52 -0
- package/dist/renderer/index.js.map +1 -1
- package/package.json +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -21,6 +21,130 @@ props `{ pkg }` → `{ pkg, compact }`.
|
|
|
21
21
|
|
|
22
22
|
## [Unreleased]
|
|
23
23
|
|
|
24
|
+
## [0.5.3] - 2026-09-01
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- **Search is fuzzy, and reaches every field an index publishes.** It was a
|
|
29
|
+
case-insensitive substring test over the seven fields the island is handed, so
|
|
30
|
+
a typo matched nothing and a package could not be found by its licence,
|
|
31
|
+
vendor, repository, authors or documentation. A query now splits on spaces
|
|
32
|
+
into terms that are AND-combined and order-independent, and each may land on a
|
|
33
|
+
different key — `astro grimoire` finds a package whose keywords carry one word
|
|
34
|
+
and whose vendor carries the other. The full record set comes from
|
|
35
|
+
`/all.json`, already published and already a frozen public URL, so it costs
|
|
36
|
+
the island no payload: it and the matcher load on the first keystroke and not
|
|
37
|
+
before, as an 8.5 KB gzipped chunk nothing preloads. Until they land, and if
|
|
38
|
+
the fetch fails, the substring pass stands — the field is never dead.
|
|
39
|
+
- **`relevance`, a sort mode**, and the reason the fuzzy pass is worth having:
|
|
40
|
+
it orders by match score. It is offered, stored and server-rendered like every
|
|
41
|
+
other mode, and with no query to rank it answers alphabetically — the order
|
|
42
|
+
the catalog opens on anyway — so a reader can leave it set and have every
|
|
43
|
+
later search come back ranked.
|
|
44
|
+
- **A clear button in the search field.** Chromium and Safari draw one of their
|
|
45
|
+
own, in the UA's styling, in the same corner the `/` hint occupies, and it
|
|
46
|
+
cannot be restyled beyond hiding. So it is hidden and the control is rendered:
|
|
47
|
+
the hint's exact box, carrying an X instead of the key. The two never coexist,
|
|
48
|
+
and clicking it returns focus to the field.
|
|
49
|
+
- **`sitemap.xml`, and a `robots.txt` naming it.** Written by `buildSite` from
|
|
50
|
+
the package list it already holds: every package page stated once, with no
|
|
51
|
+
crawler obliged to render an island or scroll it. This site emitted neither
|
|
52
|
+
before, so the landing page was the only path to a detail page — and the
|
|
53
|
+
windowed catalog below would have made that path a thin one.
|
|
54
|
+
- **A `<noscript>` catalog on the landing page**, listing every package. Without
|
|
55
|
+
JavaScript the island never hydrates, so the reader would otherwise get one
|
|
56
|
+
slice of cards under a toolbar that does nothing.
|
|
57
|
+
|
|
58
|
+
### Changed
|
|
59
|
+
|
|
60
|
+
- **The catalog builds a viewport of the index, not all of it.** At 500
|
|
61
|
+
packages it took 1.9s to appear for a reader whose stored view is the list and
|
|
62
|
+
1.5s to switch views; both are now under 50ms, and the landing page goes from
|
|
63
|
+
3.42MB to 795KB. The island builds one viewport's worth and *grows* the slice
|
|
64
|
+
as a sentinel below the list comes into view — a growing slice rather than
|
|
65
|
+
true virtualization, so an item that has been built stays built and find-in-page
|
|
66
|
+
keeps working over everything reached. The keyword rail's two geometry-reading
|
|
67
|
+
layout effects are gated on a signature of the visible chips rather than
|
|
68
|
+
running on every commit, and the filter, sort and rail chain is memoized.
|
|
69
|
+
- **The island is shipped only the fields a card renders**, through a new
|
|
70
|
+
`CardPackage` type and `cardPackage()` projection exported from
|
|
71
|
+
`lib/catalog.ts`. Astro serializes island props into an attribute on
|
|
72
|
+
`<astro-island>`, so every field handed to `<Catalog>` was paid for twice on
|
|
73
|
+
the landing page: at 250 packages the attribute was 323,044 bytes, 17.5% of
|
|
74
|
+
the page, most of it fields no card or row reads. It is 201,554 now (-37.6%).
|
|
75
|
+
Three Unstable-tier components take the narrower type — `PackageCard`,
|
|
76
|
+
`PackageRow` and `CardLogo`, props `{ pkg: CatalogPackage }` →
|
|
77
|
+
`{ pkg: CardPackage }`. An override reading `license`, `authors`, `vendor`,
|
|
78
|
+
`documentation`, `compatibility`, `revision`, `support`, `repository`,
|
|
79
|
+
`title`, `owner`, `schema`, `tags` or an unknown enrichment key off `pkg` now
|
|
80
|
+
fails to compile rather than rendering `undefined` in the browser; the detail
|
|
81
|
+
pages are untouched, and read the full record as before.
|
|
82
|
+
- **The list view's columns are sized for the description.** The two marks are
|
|
83
|
+
`min-content` rather than `auto` and the name is `fit-content(14rem)` rather
|
|
84
|
+
than `minmax(8rem, 14rem)` — that 8rem floor made a list of short names pay a
|
|
85
|
+
fixed 8rem, so the description started after a column of empty space. The
|
|
86
|
+
row's gutter drops a step with them.
|
|
87
|
+
|
|
88
|
+
### Fixed
|
|
89
|
+
|
|
90
|
+
- **The list view's rows lost their subgrid columns.** `content-visibility:
|
|
91
|
+
auto`, added as a paint bound, applies size containment — and a size-contained
|
|
92
|
+
element cannot be a subgrid, so `grid-template-columns: subgrid` degraded to
|
|
93
|
+
`none` in silence and every row computed its own equal-sixths grid. Every cell
|
|
94
|
+
lined up perfectly and the alignment was fake. The bound comes off; what it
|
|
95
|
+
was aimed at is held by `loading="lazy"` on the logo and by the window above.
|
|
96
|
+
- **The agent badge cleared WCAG AA.** `--grim-color-kind-agent` was `#b0641a`,
|
|
97
|
+
4.484:1 against the white card and so under AA's 4.5 for the 11.5px badge it
|
|
98
|
+
tints; it is `#a05c17` now, 5.20:1. Its four siblings were audited at the same
|
|
99
|
+
time and clear it unaided, so they are unchanged, and so is the dark palette.
|
|
100
|
+
- **A stored `table` view no longer flips after the first paint.** The pre-paint
|
|
101
|
+
gate listed the sort, dir and deprecated preferences only, so a reader whose
|
|
102
|
+
stored view is the list got the server's cards painted first and the island's
|
|
103
|
+
table a moment later. `?kw=` had the same gap on the other half of the
|
|
104
|
+
condition — the parameter a keyword chip on a package page links to was never
|
|
105
|
+
checked. Both lists are pinned by a test now.
|
|
106
|
+
- **The sort control's focus ring stays off a mouse click.** Chromium matches
|
|
107
|
+
`:focus-visible` on a `<select>` after a plain click, so the accent ring lit on
|
|
108
|
+
click and stayed lit beside the thin neutral chips until the reader clicked
|
|
109
|
+
elsewhere. No selector distinguishes focus that arrived from a pointer, so the
|
|
110
|
+
element marks itself on `pointerdown` and a keypress or a blur clears it. The
|
|
111
|
+
keyboard path keeps both the ring and its focus.
|
|
112
|
+
|
|
113
|
+
## [0.5.2] - 2026-08-31
|
|
114
|
+
|
|
115
|
+
### Fixed
|
|
116
|
+
|
|
117
|
+
- **The sort control drew two borders when clicked.** Hover tints a control's
|
|
118
|
+
border to the accent and focus drew a 2px accent outline standing 1px clear
|
|
119
|
+
of it, so anyone who reached the control with a mouse had both at once — one
|
|
120
|
+
state reading as two lines with a gap between them. The ring merges onto the
|
|
121
|
+
border now, the way the card's focus state already did, and the offset comes
|
|
122
|
+
off every bordered control in the toolbar together rather than off the one
|
|
123
|
+
that showed it: the search field, the keyword overflow menu's search, both
|
|
124
|
+
sort halves and both view picks. Keyword chips gain the same ring, having
|
|
125
|
+
taken the browser's default until now.
|
|
126
|
+
- **A long address no longer wraps the card's head onto a second line.** A
|
|
127
|
+
namespace breaks at its own slashes and dots, so a wide one took two rows and
|
|
128
|
+
left the card taller than its neighbours with the tail of the address against
|
|
129
|
+
the padding edge. It stays on one line and the overflow is trimmed from the
|
|
130
|
+
*front* — the registry host is on every address in an index and the
|
|
131
|
+
repository at the tail is what tells two apart — with the whole of it in the
|
|
132
|
+
element's `title`.
|
|
133
|
+
- **Keyword chips could stutter, or stop part-way through the rail's slide.**
|
|
134
|
+
The rail's FLIP pass inverted each chip with an inline `transition: none` and
|
|
135
|
+
a `translate`, then dropped both on the next animation frame; any commit
|
|
136
|
+
landing inside that window left the chip carrying the offset with its
|
|
137
|
+
transition disabled, and nothing else took those off. It also measured seats
|
|
138
|
+
with `getBoundingClientRect`, which reports where a chip is *drawn*, so a
|
|
139
|
+
chip caught mid-slide recorded its animated box and the next inversion
|
|
140
|
+
compounded the error instead of correcting it. Neither window was rare: the
|
|
141
|
+
rail's own fit measurement re-commits whenever a rescore changes how many
|
|
142
|
+
chips fit. Seats now come from `offsetLeft`/`offsetTop`, which ignore
|
|
143
|
+
transforms and scroll, and the slide is a Web Animation — it starts without a
|
|
144
|
+
frame, writes nothing to `style`, and clears itself when it finishes or is
|
|
145
|
+
cancelled. `prefers-reduced-motion` is honoured by the effect rather than by
|
|
146
|
+
the stylesheet, and `--grim-duration-slow` is still its length.
|
|
147
|
+
|
|
24
148
|
## [0.5.1] - 2026-08-31
|
|
25
149
|
|
|
26
150
|
### Added
|
|
@@ -265,6 +389,8 @@ props `{ pkg }` → `{ pkg, compact }`.
|
|
|
265
389
|
boot can leave a `.index-*` holding Vite's `deps_temp_<hash>`, which the
|
|
266
390
|
dependency optimizer recreates after the removal has already returned.
|
|
267
391
|
|
|
268
|
-
[Unreleased]: https://github.com/grimoire-rs/indexer/compare/v0.5.
|
|
392
|
+
[Unreleased]: https://github.com/grimoire-rs/indexer/compare/v0.5.3...HEAD
|
|
393
|
+
[0.5.3]: https://github.com/grimoire-rs/indexer/compare/v0.5.2...v0.5.3
|
|
394
|
+
[0.5.2]: https://github.com/grimoire-rs/indexer/compare/v0.5.1...v0.5.2
|
|
269
395
|
[0.5.1]: https://github.com/grimoire-rs/indexer/compare/v0.5.0...v0.5.1
|
|
270
396
|
[0.5.0]: https://github.com/grimoire-rs/indexer/compare/v0.4.4...v0.5.0
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CardPackage } from "../lib/catalog.js";
|
|
2
2
|
export declare function CardLogo({ pkg }: {
|
|
3
|
-
pkg:
|
|
3
|
+
pkg: CardPackage;
|
|
4
4
|
}): import("preact").JSX.Element;
|
|
5
5
|
//# sourceMappingURL=CardLogo.d.ts.map
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { useEffect, useRef, useState } from "preact/hooks";
|
|
8
8
|
import { Image, ImageOff } from "lucide-preact";
|
|
9
9
|
import { withBase } from "../lib/base.js";
|
|
10
|
-
import type {
|
|
10
|
+
import type { CardPackage } from "../lib/catalog.js";
|
|
11
11
|
|
|
12
12
|
export /**
|
|
13
13
|
* The card's 28px logo slot, in its three states.
|
|
@@ -24,7 +24,7 @@ export /**
|
|
|
24
24
|
* so it opts into the global handler in `Base.astro` instead — keep the two
|
|
25
25
|
* placeholders looking alike.
|
|
26
26
|
*/
|
|
27
|
-
function CardLogo({ pkg }: { pkg:
|
|
27
|
+
function CardLogo({ pkg }: { pkg: CardPackage }) {
|
|
28
28
|
const [state, setState] = useState<"loading" | "ready" | "broken">("loading");
|
|
29
29
|
const imgRef = useRef<HTMLImageElement>(null);
|
|
30
30
|
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
|
|
1
|
+
import { type CardPackage } from "../lib/catalog.js";
|
|
2
|
+
/**
|
|
3
|
+
* `relevance` orders by how well each package answered the query on screen,
|
|
4
|
+
* where the other three order by something every package carries. It is
|
|
5
|
+
* offered and stored like any of them even so: with no query it has nothing
|
|
6
|
+
* to rank, and `CHAINS.relevance` answers that with alphabetical — the order
|
|
7
|
+
* the catalog opens on anyway — so a reader can leave the catalog set to it
|
|
8
|
+
* and have every later search come back ranked without touching the control.
|
|
9
|
+
*/
|
|
10
|
+
export type Sort = "name" | "updated" | "rating" | "relevance";
|
|
3
11
|
export type Dir = "asc" | "desc";
|
|
4
12
|
/** Roomy cards, or the same packages as a scannable list. */
|
|
5
13
|
export type View = "cards" | "table";
|
|
@@ -13,9 +21,9 @@ export type View = "cards" | "table";
|
|
|
13
21
|
* order actually is rather than which way a flag is set.
|
|
14
22
|
*/
|
|
15
23
|
export declare const NATURAL: Record<Sort, Dir>;
|
|
16
|
-
export declare function compare(a:
|
|
24
|
+
export declare function compare(a: CardPackage, b: CardPackage, sort: Sort, dir?: Dir): number;
|
|
17
25
|
export default function Catalog({ packages, vscodeExtension, }: {
|
|
18
|
-
packages:
|
|
26
|
+
packages: CardPackage[];
|
|
19
27
|
vscodeExtension: string | null;
|
|
20
28
|
}): import("preact").JSX.Element;
|
|
21
29
|
//# sourceMappingURL=Catalog.d.ts.map
|