@grove-dev/astro 0.1.5 → 0.2.5
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/LICENSE +21 -0
- package/dist/index.d.ts +4 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -22
- package/dist/index.js.map +1 -1
- package/dist/layouts/index.d.ts +25 -0
- package/dist/layouts/index.d.ts.map +1 -0
- package/dist/layouts/index.js +25 -0
- package/dist/layouts/index.js.map +1 -0
- package/dist/lib/display.d.ts +33 -0
- package/dist/lib/display.d.ts.map +1 -0
- package/dist/lib/display.js +104 -0
- package/dist/lib/display.js.map +1 -0
- package/dist/lib/format.d.ts +30 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +73 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/index.d.ts +26 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +26 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/lenses.d.ts +96 -0
- package/dist/lib/lenses.d.ts.map +1 -0
- package/dist/lib/lenses.js +181 -0
- package/dist/lib/lenses.js.map +1 -0
- package/dist/lib/repo.d.ts +30 -0
- package/dist/lib/repo.d.ts.map +1 -0
- package/dist/lib/repo.js +44 -0
- package/dist/lib/repo.js.map +1 -0
- package/dist/lib/scores.d.ts +38 -0
- package/dist/lib/scores.d.ts.map +1 -0
- package/dist/lib/scores.js +83 -0
- package/dist/lib/scores.js.map +1 -0
- package/dist/lib/search.d.ts +199 -0
- package/dist/lib/search.d.ts.map +1 -0
- package/dist/lib/search.js +357 -0
- package/dist/lib/search.js.map +1 -0
- package/dist/lib/taxonomy-counts.d.ts +25 -0
- package/dist/lib/taxonomy-counts.d.ts.map +1 -0
- package/dist/lib/taxonomy-counts.js +41 -0
- package/dist/lib/taxonomy-counts.js.map +1 -0
- package/package.json +7 -7
- package/src/components/AppsIndexRow.astro +204 -0
- package/src/components/AppsPagination.astro +126 -0
- package/src/components/CategoryGrid.astro +86 -17
- package/src/components/ContributorsGrid.astro +149 -0
- package/src/components/DecisionRow.astro +89 -0
- package/src/components/ExploreByCategory.astro +67 -0
- package/src/components/ExploreByStack.astro +72 -0
- package/src/components/Hero.astro +246 -0
- package/src/components/Icon.astro +223 -0
- package/src/components/ItemCard.astro +306 -30
- package/src/components/MinimalAbout.astro +82 -0
- package/src/components/OriginalCollection.astro +116 -0
- package/src/components/RecordSection.astro +88 -0
- package/src/components/RefinePanel.astro +197 -0
- package/src/components/ScoreBars.astro +92 -22
- package/src/components/SmartLensTabs.astro +71 -0
- package/src/components/StackGrid.astro +132 -0
- package/src/components/WhyThisExists.astro +116 -0
- package/src/index.ts +61 -14
- package/src/layouts/BaseLayout.astro +227 -15
- package/src/layouts/Container.astro +57 -0
- package/src/layouts/Footer.astro +235 -0
- package/src/layouts/Header.astro +159 -0
- package/src/layouts/SectionHeader.astro +58 -0
- package/{templates/default/src/components/layout → src/layouts}/Seo.astro +62 -38
- package/src/layouts/ThemeToggle.astro +110 -0
- package/src/layouts/astro-shim.d.ts +29 -0
- package/src/layouts/index.ts +24 -0
- package/src/lib/display.ts +118 -0
- package/src/lib/format.ts +65 -0
- package/src/lib/index.ts +26 -0
- package/src/lib/lenses.ts +241 -0
- package/src/lib/repo.ts +44 -0
- package/src/lib/scores.ts +94 -0
- package/src/lib/search.ts +481 -0
- package/src/lib/taxonomy-counts.ts +60 -0
- package/src/styles.css +366 -638
- package/templates/default/astro.config.mjs +8 -6
- package/templates/default/content/pages/about.md +66 -0
- package/templates/default/content/pages/methodology.md +103 -0
- package/templates/default/data/generated/records.full.json +8 -0
- package/templates/default/data/generated/records.index.json +7 -0
- package/templates/default/data/generated/records.json +8 -0
- package/templates/default/data/generated/site-config.json +31 -0
- package/templates/default/data/records/.gitkeep +0 -0
- package/templates/default/grove.config.ts +36 -0
- package/templates/default/package.json +6 -5
- package/templates/default/public/llms-full.txt +14 -0
- package/templates/default/public/llms.txt +11 -0
- package/templates/default/src/components/layout/BaseLayout.astro +10 -57
- package/templates/default/src/components/layout/Footer.astro +16 -134
- package/templates/default/src/components/layout/Header.astro +25 -126
- package/templates/default/src/data/records.ts +193 -0
- package/templates/default/src/lib/markdown.ts +171 -0
- package/templates/default/src/pages/about.astro +95 -429
- package/templates/default/src/pages/index.astro +263 -61
- package/templates/default/src/pages/projects/[slug].astro +480 -0
- package/templates/default/src/pages/projects/index.astro +193 -0
- package/templates/default/src/pages/sitemap.xml.ts +73 -61
- package/templates/default/src/pages/submit.astro +122 -411
- package/templates/default/src/styles/global.css +42 -68
- package/src/components/ActiveFilterChips.astro +0 -20
- package/src/components/DirectoryFilters.astro +0 -100
- package/src/components/DirectoryHero.astro +0 -32
- package/src/components/HealthBadge.astro +0 -12
- package/src/components/LensTabs.astro +0 -26
- package/src/components/MethodologyPanel.astro +0 -20
- package/src/components/Pagination.astro +0 -24
- package/src/components/ProjectDetail.astro +0 -166
- package/src/components/SubmitDraft.astro +0 -137
- package/templates/default/src/components/AppCard.astro +0 -248
- package/templates/default/src/components/AppSection.astro +0 -58
- package/templates/default/src/components/AppsIndexRow.astro +0 -230
- package/templates/default/src/components/AppsPagination.astro +0 -147
- package/templates/default/src/components/CategoryGrid.astro +0 -80
- package/templates/default/src/components/ContributorsGrid.astro +0 -105
- package/templates/default/src/components/DecisionRow.astro +0 -219
- package/templates/default/src/components/ExploreByCategory.astro +0 -74
- package/templates/default/src/components/ExploreByStack.astro +0 -102
- package/templates/default/src/components/Hero.astro +0 -176
- package/templates/default/src/components/MinimalAbout.astro +0 -57
- package/templates/default/src/components/OriginalCollection.astro +0 -144
- package/templates/default/src/components/RefinePanel.astro +0 -272
- package/templates/default/src/components/ScoreBars.astro +0 -72
- package/templates/default/src/components/SmartLensTabs.astro +0 -65
- package/templates/default/src/components/StackGrid.astro +0 -95
- package/templates/default/src/components/WhyThisExists.astro +0 -81
- package/templates/default/src/components/icons/Icon.astro +0 -148
- package/templates/default/src/components/layout/SectionHeader.astro +0 -42
- package/templates/default/src/components/layout/ThemeToggle.astro +0 -97
- package/templates/default/src/data/apps.ts +0 -149
- package/templates/default/src/data/categories.ts +0 -27
- package/templates/default/src/data/config.ts +0 -28
- package/templates/default/src/data/contributors.ts +0 -96
- package/templates/default/src/data/stacks.ts +0 -47
- package/templates/default/src/data/stats.ts +0 -65
- package/templates/default/src/data/types.ts +0 -248
- package/templates/default/src/lib/apps-search.ts +0 -228
- package/templates/default/src/lib/format.ts +0 -36
- package/templates/default/src/lib/lenses.ts +0 -98
- package/templates/default/src/lib/repo.ts +0 -12
- package/templates/default/src/lib/scores.ts +0 -51
- package/templates/default/src/lib/taxonomy-counts.ts +0 -31
- package/templates/default/src/pages/apps/[slug].astro +0 -709
- package/templates/default/src/pages/apps/index.astro +0 -669
- package/templates/default/src/pages/contributors.astro +0 -142
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL-driven search/filter/sort state for the directory list page.
|
|
3
|
+
*
|
|
4
|
+
* Multi-value fields use repeated keys: `?stack=Flutter&stack=RN`.
|
|
5
|
+
* Single-value fields (q, sort, page, lens) are scalar. Empty
|
|
6
|
+
* / undefined fields mean "no filter on this dimension".
|
|
7
|
+
*
|
|
8
|
+
* The functions here are generic over a record-like shape that
|
|
9
|
+
* carries the index payload (see `toIndexRecord` in
|
|
10
|
+
* `@grove-dev/core`). The list page only needs `name`, `slug`,
|
|
11
|
+
* `description`, `category`, `tags`, `stack`, `stacks`, `platforms`,
|
|
12
|
+
* `repoUrl`, `logoUrl`, `health`, `curation`, and `github.{stars,
|
|
13
|
+
* pushedAt}` — all of which are present in the index projection.
|
|
14
|
+
*/
|
|
15
|
+
import { labelDisplay, statusDisplay } from "./display.js";
|
|
16
|
+
import { applyLens, lensFromSearchParams } from "./lenses.js";
|
|
17
|
+
/** Available sort orders, in UI order. */
|
|
18
|
+
export const SORT_OPTIONS = [
|
|
19
|
+
{ value: "recently-updated", label: "Recently updated" },
|
|
20
|
+
{ value: "most-starred", label: "Most starred" },
|
|
21
|
+
{ value: "recently-added", label: "Recently added" },
|
|
22
|
+
{ value: "best-overall", label: "Best overall" },
|
|
23
|
+
{ value: "alphabetical", label: "Alphabetical" },
|
|
24
|
+
];
|
|
25
|
+
const DEFAULT_SORT = "recently-updated";
|
|
26
|
+
const DEFAULT_PAGE = 1;
|
|
27
|
+
/**
|
|
28
|
+
* How many records per page. Constant for now; future versions may
|
|
29
|
+
* vary per blueprint.
|
|
30
|
+
*/
|
|
31
|
+
export const PAGE_SIZE = 24;
|
|
32
|
+
const KEYS = {
|
|
33
|
+
q: "q",
|
|
34
|
+
stacks: "stack",
|
|
35
|
+
platforms: "platform",
|
|
36
|
+
categories: "category",
|
|
37
|
+
labels: "label",
|
|
38
|
+
licenses: "license",
|
|
39
|
+
statuses: "status",
|
|
40
|
+
lens: "lens",
|
|
41
|
+
sort: "sort",
|
|
42
|
+
page: "page",
|
|
43
|
+
};
|
|
44
|
+
// ── Search param round-tripping ──────────────────────────────────
|
|
45
|
+
/**
|
|
46
|
+
* Read filters from a URLSearchParams (or anything URLSearchParams-
|
|
47
|
+
* shaped, e.g. the result of `new URL(req.url).searchParams`).
|
|
48
|
+
*/
|
|
49
|
+
export function filtersFromSearchParams(sp) {
|
|
50
|
+
const rawSort = sp.get(KEYS.sort);
|
|
51
|
+
// Backwards-compat: old "most-mature" sort now maps to "best-overall".
|
|
52
|
+
const normalizedSort = rawSort === "most-mature" ? "best-overall" : rawSort;
|
|
53
|
+
const sort = normalizedSort && SORT_OPTIONS.some((o) => o.value === normalizedSort)
|
|
54
|
+
? normalizedSort
|
|
55
|
+
: undefined;
|
|
56
|
+
const rawPage = Number(sp.get(KEYS.page));
|
|
57
|
+
const page = Number.isFinite(rawPage) && rawPage >= 1 ? Math.floor(rawPage) : undefined;
|
|
58
|
+
return {
|
|
59
|
+
q: sp.get(KEYS.q) ?? undefined,
|
|
60
|
+
stacks: sp.getAll(KEYS.stacks).filter(Boolean),
|
|
61
|
+
platforms: sp.getAll(KEYS.platforms).filter(Boolean),
|
|
62
|
+
categories: sp.getAll(KEYS.categories).filter(Boolean),
|
|
63
|
+
labels: sp.getAll(KEYS.labels).filter(Boolean),
|
|
64
|
+
licenses: sp.getAll(KEYS.licenses).filter(Boolean),
|
|
65
|
+
statuses: sp
|
|
66
|
+
.getAll(KEYS.statuses)
|
|
67
|
+
.flatMap((s) => s.split(","))
|
|
68
|
+
.filter(Boolean),
|
|
69
|
+
lens: lensFromSearchParams(sp) || undefined,
|
|
70
|
+
sort,
|
|
71
|
+
page,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Serialize a filters object back to URLSearchParams. Undefined /
|
|
76
|
+
* empty values are dropped. Defaults (sort, page 1) are also dropped
|
|
77
|
+
* to keep URLs short and canonical.
|
|
78
|
+
*/
|
|
79
|
+
export function searchParamsFromFilters(f) {
|
|
80
|
+
const sp = new URLSearchParams();
|
|
81
|
+
if (f.q)
|
|
82
|
+
sp.set(KEYS.q, f.q);
|
|
83
|
+
for (const v of f.stacks ?? [])
|
|
84
|
+
sp.append(KEYS.stacks, v);
|
|
85
|
+
for (const v of f.platforms ?? [])
|
|
86
|
+
sp.append(KEYS.platforms, v);
|
|
87
|
+
for (const v of f.categories ?? [])
|
|
88
|
+
sp.append(KEYS.categories, v);
|
|
89
|
+
for (const v of f.labels ?? [])
|
|
90
|
+
sp.append(KEYS.labels, v);
|
|
91
|
+
for (const v of f.licenses ?? [])
|
|
92
|
+
sp.append(KEYS.licenses, v);
|
|
93
|
+
if (f.statuses?.length)
|
|
94
|
+
sp.set(KEYS.statuses, f.statuses.join(","));
|
|
95
|
+
if (f.lens)
|
|
96
|
+
sp.set(KEYS.lens, f.lens);
|
|
97
|
+
if (f.sort && f.sort !== DEFAULT_SORT)
|
|
98
|
+
sp.set(KEYS.sort, f.sort);
|
|
99
|
+
if (f.page && f.page !== DEFAULT_PAGE)
|
|
100
|
+
sp.set(KEYS.page, String(f.page));
|
|
101
|
+
return sp;
|
|
102
|
+
}
|
|
103
|
+
// ── Filter application ───────────────────────────────────────────
|
|
104
|
+
/**
|
|
105
|
+
* True if any filter is active (i.e. the result list isn't "all
|
|
106
|
+
* records, default sort").
|
|
107
|
+
*/
|
|
108
|
+
export function hasAnyFilter(f) {
|
|
109
|
+
if (f.q && f.q.trim())
|
|
110
|
+
return true;
|
|
111
|
+
if (f.lens)
|
|
112
|
+
return true;
|
|
113
|
+
return Boolean((f.stacks?.length ?? 0) +
|
|
114
|
+
(f.platforms?.length ?? 0) +
|
|
115
|
+
(f.categories?.length ?? 0) +
|
|
116
|
+
(f.labels?.length ?? 0) +
|
|
117
|
+
(f.licenses?.length ?? 0) +
|
|
118
|
+
(f.statuses?.length ?? 0));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Return the subset of records that match all active filters (AND
|
|
122
|
+
* across dimensions, OR within a dimension).
|
|
123
|
+
*
|
|
124
|
+
* `q` is a case-insensitive substring search across name, owner,
|
|
125
|
+
* description, category, stack/stacks/platforms, tags, and license.
|
|
126
|
+
* Other dimensions are exact match.
|
|
127
|
+
*/
|
|
128
|
+
export function filterApps(records, f) {
|
|
129
|
+
const q = f.q?.trim().toLowerCase();
|
|
130
|
+
const stacks = f.stacks?.length ? new Set(f.stacks) : null;
|
|
131
|
+
const platforms = f.platforms?.length ? new Set(f.platforms) : null;
|
|
132
|
+
const categories = f.categories?.length ? new Set(f.categories) : null;
|
|
133
|
+
const labels = f.labels?.length ? new Set(f.labels) : null;
|
|
134
|
+
const licenses = f.licenses?.length ? new Set(f.licenses) : null;
|
|
135
|
+
const statuses = f.statuses?.length ? new Set(f.statuses) : null;
|
|
136
|
+
return records.filter((r) => {
|
|
137
|
+
if (q) {
|
|
138
|
+
const ownerMatch = /github\.com\/([^/]+)\//.exec(r.repoUrl ?? "")?.[1]?.toLowerCase() ??
|
|
139
|
+
"";
|
|
140
|
+
const haystack = [
|
|
141
|
+
r.name,
|
|
142
|
+
ownerMatch,
|
|
143
|
+
r.description ?? "",
|
|
144
|
+
r.category ?? "",
|
|
145
|
+
r.stack ?? "",
|
|
146
|
+
...(r.stacks ?? []),
|
|
147
|
+
...(r.platforms ?? []),
|
|
148
|
+
...(r.tags ?? []),
|
|
149
|
+
r.github?.license ?? "",
|
|
150
|
+
r.health?.status ? statusDisplay(r.health.status) : "",
|
|
151
|
+
]
|
|
152
|
+
.join(" ")
|
|
153
|
+
.toLowerCase();
|
|
154
|
+
if (!haystack.includes(q))
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
if (stacks) {
|
|
158
|
+
const allStacks = [r.stack, ...(r.stacks ?? [])].filter((s) => Boolean(s));
|
|
159
|
+
if (!allStacks.some((s) => stacks.has(s)))
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
if (platforms) {
|
|
163
|
+
if (!r.platforms?.some((p) => platforms.has(p)))
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
if (categories) {
|
|
167
|
+
if (!r.category || !categories.has(r.category))
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
if (labels) {
|
|
171
|
+
if (!r.curation?.labels?.some((l) => labels.has(l)))
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
if (licenses) {
|
|
175
|
+
const license = r.github?.license;
|
|
176
|
+
if (!license || !licenses.has(license))
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
if (statuses) {
|
|
180
|
+
const status = r.health?.status;
|
|
181
|
+
if (!status || !statuses.has(status))
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
return true;
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
// ── Lenses, sort, pagination ─────────────────────────────────────
|
|
188
|
+
/**
|
|
189
|
+
* Apply lens → filter → sort pipeline. Lens is applied first because
|
|
190
|
+
* it's a single-select "view" that may be broader or narrower than
|
|
191
|
+
* the regular filter dimensions.
|
|
192
|
+
*/
|
|
193
|
+
export function pipeline(records, filters) {
|
|
194
|
+
const afterLens = applyLens(records, filters.lens ?? "");
|
|
195
|
+
const afterFilter = filterApps(afterLens, filters);
|
|
196
|
+
return applySort(afterFilter, effectiveSort(filters));
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Sort records in-place-free: returns a new array. Stable for ties.
|
|
200
|
+
* Records missing the sort key (e.g. no stars) sink to the bottom
|
|
201
|
+
* rather than vanishing.
|
|
202
|
+
*/
|
|
203
|
+
export function applySort(records, sort) {
|
|
204
|
+
const arr = records.slice();
|
|
205
|
+
const ts = (s) => (s ? new Date(s).valueOf() : 0);
|
|
206
|
+
switch (sort) {
|
|
207
|
+
case "most-starred":
|
|
208
|
+
arr.sort((a, b) => (b.github?.stars ?? 0) - (a.github?.stars ?? 0));
|
|
209
|
+
break;
|
|
210
|
+
case "recently-updated":
|
|
211
|
+
arr.sort((a, b) => ts(b.github?.pushedAt) - ts(a.github?.pushedAt));
|
|
212
|
+
break;
|
|
213
|
+
case "recently-added":
|
|
214
|
+
// Index payload doesn't have a dedicated "addedAt" yet — fall
|
|
215
|
+
// back to `pushedAt` so the sort still works. Once we add an
|
|
216
|
+
// explicit addedAt field, swap the key here.
|
|
217
|
+
arr.sort((a, b) => ts(b.github?.pushedAt) - ts(a.github?.pushedAt));
|
|
218
|
+
break;
|
|
219
|
+
case "best-overall": {
|
|
220
|
+
// Composite: scores.overall → scores.maturity → scores.activity →
|
|
221
|
+
// active status → license present → stars. Avoids ranking by
|
|
222
|
+
// stars alone.
|
|
223
|
+
const score = (x, k) => (typeof x.scores?.[k] === "number" ? x.scores[k] : 0);
|
|
224
|
+
const active = (x) => (x.health?.status === "active" ? 1 : 0);
|
|
225
|
+
const licensed = (x) => (x.github?.license ? 1 : 0);
|
|
226
|
+
arr.sort((a, b) => {
|
|
227
|
+
const sOverall = score(b, "overall") - score(a, "overall");
|
|
228
|
+
if (sOverall !== 0)
|
|
229
|
+
return sOverall;
|
|
230
|
+
const sMaturity = score(b, "maturity") - score(a, "maturity");
|
|
231
|
+
if (sMaturity !== 0)
|
|
232
|
+
return sMaturity;
|
|
233
|
+
const sActivity = score(b, "activity") - score(a, "activity");
|
|
234
|
+
if (sActivity !== 0)
|
|
235
|
+
return sActivity;
|
|
236
|
+
const sActive = active(b) - active(a);
|
|
237
|
+
if (sActive !== 0)
|
|
238
|
+
return sActive;
|
|
239
|
+
const sLicensed = licensed(b) - licensed(a);
|
|
240
|
+
if (sLicensed !== 0)
|
|
241
|
+
return sLicensed;
|
|
242
|
+
return (b.github?.stars ?? 0) - (a.github?.stars ?? 0);
|
|
243
|
+
});
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
case "alphabetical":
|
|
247
|
+
arr.sort((a, b) => a.name.localeCompare(b.name));
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
return arr;
|
|
251
|
+
}
|
|
252
|
+
/** Slice an array for a given page (1-based). */
|
|
253
|
+
export function paginate(items, page, pageSize = PAGE_SIZE) {
|
|
254
|
+
const start = (page - 1) * pageSize;
|
|
255
|
+
return items.slice(start, start + pageSize);
|
|
256
|
+
}
|
|
257
|
+
/** Total number of pages given an item count. Always >= 1. */
|
|
258
|
+
export function totalPages(itemCount, pageSize = PAGE_SIZE) {
|
|
259
|
+
return Math.max(1, Math.ceil(itemCount / pageSize));
|
|
260
|
+
}
|
|
261
|
+
/** Resolve the effective sort from a filters object, applying default. */
|
|
262
|
+
export function effectiveSort(f) {
|
|
263
|
+
return f.sort ?? DEFAULT_SORT;
|
|
264
|
+
}
|
|
265
|
+
/** Resolve the effective page from a filters object, applying default. */
|
|
266
|
+
export function effectivePage(f) {
|
|
267
|
+
return f.page ?? DEFAULT_PAGE;
|
|
268
|
+
}
|
|
269
|
+
// ── Facets ───────────────────────────────────────────────────────
|
|
270
|
+
/**
|
|
271
|
+
* Return a flat list of active-filter chips for display + removal.
|
|
272
|
+
* Used by the "x" button on each chip in the UI.
|
|
273
|
+
*/
|
|
274
|
+
export function activeFilterChips(f) {
|
|
275
|
+
const out = [];
|
|
276
|
+
if (f.q && f.q.trim()) {
|
|
277
|
+
out.push({ key: "q", value: "", label: `“${f.q}”` });
|
|
278
|
+
}
|
|
279
|
+
for (const v of f.stacks ?? []) {
|
|
280
|
+
out.push({ key: "stacks", value: v, label: `Stack: ${v}` });
|
|
281
|
+
}
|
|
282
|
+
for (const v of f.platforms ?? []) {
|
|
283
|
+
out.push({ key: "platforms", value: v, label: `Platform: ${v}` });
|
|
284
|
+
}
|
|
285
|
+
for (const v of f.categories ?? []) {
|
|
286
|
+
out.push({ key: "categories", value: v, label: `Category: ${v}` });
|
|
287
|
+
}
|
|
288
|
+
for (const v of f.labels ?? []) {
|
|
289
|
+
out.push({ key: "labels", value: v, label: labelDisplay(v) ?? v });
|
|
290
|
+
}
|
|
291
|
+
for (const v of f.licenses ?? []) {
|
|
292
|
+
out.push({ key: "licenses", value: v, label: `License: ${v}` });
|
|
293
|
+
}
|
|
294
|
+
if (f.lens) {
|
|
295
|
+
// Inline map keeps this function dependency-free for unit tests
|
|
296
|
+
// (no need to import from `lenses.ts` to render a chip label).
|
|
297
|
+
const LENS_CHIP_LABELS = {
|
|
298
|
+
all: "All",
|
|
299
|
+
hot: "Trending",
|
|
300
|
+
new: "Recently added",
|
|
301
|
+
mature: "Established",
|
|
302
|
+
featured: "Featured",
|
|
303
|
+
"needs-review": "Needs review",
|
|
304
|
+
};
|
|
305
|
+
out.push({ key: "lens", value: f.lens, label: LENS_CHIP_LABELS[f.lens] ?? f.lens });
|
|
306
|
+
}
|
|
307
|
+
if (f.statuses && f.statuses.length) {
|
|
308
|
+
for (const v of f.statuses) {
|
|
309
|
+
out.push({ key: "statuses", value: v, label: statusDisplay(v) });
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return out;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Build the full list of facet values from the record array,
|
|
316
|
+
* preserving a sensible order (frequency desc, then alphabetical
|
|
317
|
+
* for ties).
|
|
318
|
+
*/
|
|
319
|
+
export function buildFacets(records) {
|
|
320
|
+
const counts = {
|
|
321
|
+
stack: new Map(),
|
|
322
|
+
platform: new Map(),
|
|
323
|
+
category: new Map(),
|
|
324
|
+
label: new Map(),
|
|
325
|
+
license: new Map(),
|
|
326
|
+
};
|
|
327
|
+
for (const r of records) {
|
|
328
|
+
const allStacks = new Set([r.stack, ...(r.stacks ?? [])].filter((s) => Boolean(s)));
|
|
329
|
+
for (const s of allStacks) {
|
|
330
|
+
counts.stack.set(s, (counts.stack.get(s) ?? 0) + 1);
|
|
331
|
+
}
|
|
332
|
+
for (const p of r.platforms ?? []) {
|
|
333
|
+
counts.platform.set(p, (counts.platform.get(p) ?? 0) + 1);
|
|
334
|
+
}
|
|
335
|
+
if (r.category) {
|
|
336
|
+
counts.category.set(r.category, (counts.category.get(r.category) ?? 0) + 1);
|
|
337
|
+
}
|
|
338
|
+
for (const l of r.curation?.labels ?? []) {
|
|
339
|
+
counts.label.set(l, (counts.label.get(l) ?? 0) + 1);
|
|
340
|
+
}
|
|
341
|
+
const license = r.github?.license;
|
|
342
|
+
if (license) {
|
|
343
|
+
counts.license.set(license, (counts.license.get(license) ?? 0) + 1);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
const sortByCountThenName = (m) => [...m.entries()]
|
|
347
|
+
.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
|
|
348
|
+
.map(([value, count]) => ({ value, count }));
|
|
349
|
+
return {
|
|
350
|
+
stacks: sortByCountThenName(counts.stack),
|
|
351
|
+
platforms: sortByCountThenName(counts.platform),
|
|
352
|
+
categories: sortByCountThenName(counts.category),
|
|
353
|
+
labels: sortByCountThenName(counts.label),
|
|
354
|
+
licenses: sortByCountThenName(counts.license),
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build-time helpers that compute taxonomy counts from an array of
|
|
3
|
+
* records. Generic over any object that carries the index-payload
|
|
4
|
+
* fields the UI cares about (`category`, `stack` / `stacks`,
|
|
5
|
+
* `curation.labels`). No filesystem / data import — consumers pass
|
|
6
|
+
* the records explicitly so this stays testable.
|
|
7
|
+
*
|
|
8
|
+
* All functions are synchronous and cheap — they're called from
|
|
9
|
+
* Astro page frontmatter at build time, never on the client.
|
|
10
|
+
*/
|
|
11
|
+
export interface Taxonomable {
|
|
12
|
+
category?: string;
|
|
13
|
+
stack?: string;
|
|
14
|
+
stacks?: string[];
|
|
15
|
+
curation?: {
|
|
16
|
+
labels?: string[];
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/** Number of records per category name. */
|
|
20
|
+
export declare function countByCategory<T extends Taxonomable>(records: T[]): Map<string, number>;
|
|
21
|
+
/** Number of records per primary stack (combines `stack` and `stacks`). */
|
|
22
|
+
export declare function countByStack<T extends Taxonomable>(records: T[]): Map<string, number>;
|
|
23
|
+
/** Number of records per curated label (curation.labels). */
|
|
24
|
+
export declare function countByLabel<T extends Taxonomable>(records: T[]): Map<string, number>;
|
|
25
|
+
//# sourceMappingURL=taxonomy-counts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taxonomy-counts.d.ts","sourceRoot":"","sources":["../../src/lib/taxonomy-counts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAClC;AAED,2CAA2C;AAC3C,wBAAgB,eAAe,CAAC,CAAC,SAAS,WAAW,EACnD,OAAO,EAAE,CAAC,EAAE,GACX,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAOrB;AAED,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,EAChD,OAAO,EAAE,CAAC,EAAE,GACX,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAarB;AAED,6DAA6D;AAC7D,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,EAChD,OAAO,EAAE,CAAC,EAAE,GACX,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAQrB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build-time helpers that compute taxonomy counts from an array of
|
|
3
|
+
* records. Generic over any object that carries the index-payload
|
|
4
|
+
* fields the UI cares about (`category`, `stack` / `stacks`,
|
|
5
|
+
* `curation.labels`). No filesystem / data import — consumers pass
|
|
6
|
+
* the records explicitly so this stays testable.
|
|
7
|
+
*
|
|
8
|
+
* All functions are synchronous and cheap — they're called from
|
|
9
|
+
* Astro page frontmatter at build time, never on the client.
|
|
10
|
+
*/
|
|
11
|
+
/** Number of records per category name. */
|
|
12
|
+
export function countByCategory(records) {
|
|
13
|
+
const m = new Map();
|
|
14
|
+
for (const r of records) {
|
|
15
|
+
const k = r.category || "Other";
|
|
16
|
+
m.set(k, (m.get(k) ?? 0) + 1);
|
|
17
|
+
}
|
|
18
|
+
return m;
|
|
19
|
+
}
|
|
20
|
+
/** Number of records per primary stack (combines `stack` and `stacks`). */
|
|
21
|
+
export function countByStack(records) {
|
|
22
|
+
const m = new Map();
|
|
23
|
+
for (const r of records) {
|
|
24
|
+
const keys = new Set([r.stack, ...(r.stacks ?? [])].filter((s) => Boolean(s)));
|
|
25
|
+
for (const k of keys) {
|
|
26
|
+
m.set(k, (m.get(k) ?? 0) + 1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return m;
|
|
30
|
+
}
|
|
31
|
+
/** Number of records per curated label (curation.labels). */
|
|
32
|
+
export function countByLabel(records) {
|
|
33
|
+
const m = new Map();
|
|
34
|
+
for (const r of records) {
|
|
35
|
+
for (const l of r.curation?.labels ?? []) {
|
|
36
|
+
m.set(l, (m.get(l) ?? 0) + 1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return m;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=taxonomy-counts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taxonomy-counts.js","sourceRoot":"","sources":["../../src/lib/taxonomy-counts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,2CAA2C;AAC3C,MAAM,UAAU,eAAe,CAC7B,OAAY;IAEZ,MAAM,CAAC,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC;QAChC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,YAAY,CAC1B,OAAY;IAEZ,MAAM,CAAC,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,IAAI,GAAG,CAClB,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CACnC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAC/B,CACF,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,YAAY,CAC1B,OAAY;IAEZ,MAAM,CAAC,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;YACzC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grove-dev/astro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Astro framework adapter for Grove. Components, layouts, design tokens, and a default template.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -37,15 +37,15 @@
|
|
|
37
37
|
"import": "./dist/index.js"
|
|
38
38
|
},
|
|
39
39
|
"./styles.css": "./src/styles.css",
|
|
40
|
+
"./components/*.astro": "./src/components/*.astro",
|
|
40
41
|
"./components/*": "./src/components/*.astro",
|
|
41
|
-
"./layouts
|
|
42
|
-
"./
|
|
43
|
-
"./templates/*": "./templates/*"
|
|
42
|
+
"./layouts/*.astro": "./src/layouts/*.astro",
|
|
43
|
+
"./layouts/*": "./src/layouts/*.astro"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"
|
|
47
|
-
"@grove-dev/
|
|
48
|
-
"
|
|
46
|
+
"astro": "^6.4.6",
|
|
47
|
+
"@grove-dev/core": "0.2.5",
|
|
48
|
+
"@grove-dev/ui": "0.2.5"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"astro": "^6.0.0"
|