@grove-dev/core 0.10.0 → 0.12.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.
- package/dist/awesome-readme.d.ts +39 -0
- package/dist/awesome-readme.d.ts.map +1 -1
- package/dist/awesome-readme.js +51 -7
- package/dist/awesome-readme.js.map +1 -1
- package/dist/build-data.d.ts.map +1 -1
- package/dist/build-data.js +8 -0
- package/dist/build-data.js.map +1 -1
- package/dist/collection-entries.d.ts +81 -0
- package/dist/collection-entries.d.ts.map +1 -0
- package/dist/collection-entries.js +74 -0
- package/dist/collection-entries.js.map +1 -0
- package/dist/collections-io.d.ts +17 -1
- package/dist/collections-io.d.ts.map +1 -1
- package/dist/collections-io.js +39 -5
- package/dist/collections-io.js.map +1 -1
- package/dist/collections.d.ts +95 -40
- package/dist/collections.d.ts.map +1 -1
- package/dist/collections.js +106 -1
- package/dist/collections.js.map +1 -1
- package/dist/collector.d.ts +18 -0
- package/dist/collector.d.ts.map +1 -1
- package/dist/collector.js +42 -2
- package/dist/collector.js.map +1 -1
- package/dist/content-body.d.ts +20 -1
- package/dist/content-body.d.ts.map +1 -1
- package/dist/content-body.js +67 -1
- package/dist/content-body.js.map +1 -1
- package/dist/index.d.ts +13 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -6
- package/dist/index.js.map +1 -1
- package/dist/llms.d.ts.map +1 -1
- package/dist/llms.js +4 -11
- package/dist/llms.js.map +1 -1
- package/dist/page-document.d.ts +24 -0
- package/dist/page-document.d.ts.map +1 -1
- package/dist/page-document.js +22 -1
- package/dist/page-document.js.map +1 -1
- package/dist/prepare.d.ts.map +1 -1
- package/dist/prepare.js +18 -24
- package/dist/prepare.js.map +1 -1
- package/dist/related.js +14 -3
- package/dist/related.js.map +1 -1
- package/dist/routes.d.ts +9 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +15 -0
- package/dist/routes.js.map +1 -0
- package/dist/schema.d.ts +230 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +63 -0
- package/dist/schema.js.map +1 -1
- package/dist/sitemap.d.ts.map +1 -1
- package/dist/sitemap.js +2 -9
- package/dist/sitemap.js.map +1 -1
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +340 -1
- package/dist/validate.js.map +1 -1
- package/package.json +1 -1
package/dist/collections.d.ts
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* - a `query` that filters an entry stream (stacks, platforms, categories,
|
|
8
8
|
* licenses, kinds, excludeStatuses, free-text q)
|
|
9
9
|
* - a `ranking` that decides order (quality, active, recency, stars, curated)
|
|
10
|
-
* - optional `
|
|
10
|
+
* - optional hand-picked `entries` (with per-record notes and pinning)
|
|
11
|
+
* - optional `editorial` intro/selection notes, a Markdown `content`
|
|
12
|
+
* body and `faq`
|
|
11
13
|
* - `seo` policy (indexable flag, optional overrides)
|
|
12
14
|
*
|
|
13
15
|
* `CollectionEntry` is the lightweight record shape that flows through
|
|
@@ -17,45 +19,88 @@
|
|
|
17
19
|
* `filterEntries` and `rankEntries` are pure functions; they share no
|
|
18
20
|
* state and never mutate their input.
|
|
19
21
|
*/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
22
|
+
import { z } from 'zod';
|
|
23
|
+
declare const rankingPresetSchema: z.ZodEnum<{
|
|
24
|
+
active: "active";
|
|
25
|
+
curated: "curated";
|
|
26
|
+
stars: "stars";
|
|
27
|
+
quality: "quality";
|
|
28
|
+
recency: "recency";
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* The shape of one `data/collections/<slug>.yml` file. Named
|
|
32
|
+
* `collectionDefinitionSchema` because `collectionSchema` is already the
|
|
33
|
+
* JSON-LD builder in `page-document.ts`.
|
|
34
|
+
*
|
|
35
|
+
* Top-level keys are loose so a consumer can carry its own fields next
|
|
36
|
+
* to Grove's; the blocks Grove reads are strict enough that a typo in
|
|
37
|
+
* `ranking.preset` or a string `minStars` fails `grove check` instead of
|
|
38
|
+
* silently producing an unfiltered, unranked page.
|
|
39
|
+
*/
|
|
40
|
+
export declare const collectionDefinitionSchema: z.ZodObject<{
|
|
41
|
+
slug: z.ZodString;
|
|
42
|
+
kind: z.ZodDefault<z.ZodEnum<{
|
|
43
|
+
curated: "curated";
|
|
44
|
+
generated: "generated";
|
|
45
|
+
}>>;
|
|
46
|
+
title: z.ZodString;
|
|
47
|
+
description: z.ZodString;
|
|
48
|
+
subject: z.ZodOptional<z.ZodString>;
|
|
49
|
+
content: z.ZodOptional<z.ZodString>;
|
|
50
|
+
query: z.ZodPrefault<z.ZodObject<{
|
|
51
|
+
stacks: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
52
|
+
platforms: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
53
|
+
categories: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
54
|
+
licenses: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
55
|
+
kinds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
56
|
+
excludeStatuses: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
57
|
+
minStars: z.ZodOptional<z.ZodNumber>;
|
|
58
|
+
minForks: z.ZodOptional<z.ZodNumber>;
|
|
59
|
+
q: z.ZodOptional<z.ZodString>;
|
|
60
|
+
relatedTo: z.ZodOptional<z.ZodObject<{
|
|
61
|
+
type: z.ZodOptional<z.ZodString>;
|
|
62
|
+
subjects: z.ZodArray<z.ZodString>;
|
|
63
|
+
}, z.core.$strip>>;
|
|
64
|
+
}, z.core.$strip>>;
|
|
65
|
+
entries: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
66
|
+
slug: z.ZodString;
|
|
67
|
+
note: z.ZodOptional<z.ZodString>;
|
|
68
|
+
pinned: z.ZodOptional<z.ZodBoolean>;
|
|
69
|
+
}, z.core.$strip>>>;
|
|
70
|
+
ranking: z.ZodPrefault<z.ZodObject<{
|
|
71
|
+
preset: z.ZodEnum<{
|
|
72
|
+
active: "active";
|
|
73
|
+
curated: "curated";
|
|
74
|
+
stars: "stars";
|
|
75
|
+
quality: "quality";
|
|
76
|
+
recency: "recency";
|
|
77
|
+
}>;
|
|
78
|
+
signals: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
79
|
+
}, z.core.$strip>>;
|
|
80
|
+
editorial: z.ZodOptional<z.ZodObject<{
|
|
81
|
+
introduction: z.ZodOptional<z.ZodString>;
|
|
82
|
+
selectionNote: z.ZodOptional<z.ZodString>;
|
|
83
|
+
lastReviewedAt: z.ZodOptional<z.ZodString>;
|
|
84
|
+
}, z.core.$strip>>;
|
|
85
|
+
faq: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
86
|
+
q: z.ZodString;
|
|
87
|
+
a: z.ZodString;
|
|
88
|
+
}, z.core.$strip>>>;
|
|
89
|
+
seo: z.ZodPrefault<z.ZodObject<{
|
|
90
|
+
index: z.ZodDefault<z.ZodBoolean>;
|
|
91
|
+
title: z.ZodOptional<z.ZodString>;
|
|
92
|
+
description: z.ZodOptional<z.ZodString>;
|
|
93
|
+
}, z.core.$strip>>;
|
|
94
|
+
}, z.core.$loose>;
|
|
95
|
+
export type Collection = z.infer<typeof collectionDefinitionSchema>;
|
|
96
|
+
export type CollectionKind = Collection['kind'];
|
|
97
|
+
export type RankingPreset = z.infer<typeof rankingPresetSchema>;
|
|
98
|
+
export type CollectionQuery = Collection['query'];
|
|
99
|
+
export type CollectionRanking = Collection['ranking'];
|
|
100
|
+
export type CollectionEditorial = NonNullable<Collection['editorial']>;
|
|
101
|
+
export type CollectionSeo = Collection['seo'];
|
|
102
|
+
export type CollectionPick = NonNullable<Collection['entries']>[number];
|
|
103
|
+
export type CollectionFaqItem = NonNullable<Collection['faq']>[number];
|
|
59
104
|
export interface CollectionEntry {
|
|
60
105
|
slug: string;
|
|
61
106
|
title: string;
|
|
@@ -82,7 +127,17 @@ export interface CollectionEntry {
|
|
|
82
127
|
curationScore?: number;
|
|
83
128
|
activityScore?: number;
|
|
84
129
|
categories?: string[];
|
|
130
|
+
/** Relation targets from the record, matched by `query.relatedTo`. */
|
|
131
|
+
relations?: Array<{
|
|
132
|
+
type: string;
|
|
133
|
+
to: string;
|
|
134
|
+
}>;
|
|
135
|
+
/** The curator's note for this record in the collection being run. */
|
|
136
|
+
note?: string;
|
|
137
|
+
/** True when the collection pins this record above the ranking. */
|
|
138
|
+
pinned?: boolean;
|
|
85
139
|
}
|
|
86
140
|
export declare function filterEntries(entries: CollectionEntry[], query: CollectionQuery): CollectionEntry[];
|
|
87
141
|
export declare function rankEntries(entries: CollectionEntry[], ranking: CollectionRanking): CollectionEntry[];
|
|
142
|
+
export {};
|
|
88
143
|
//# sourceMappingURL=collections.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../src/collections.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../src/collections.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,mBAAmB;;;;;;EAA+D,CAAC;AA2BzF;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8DrC,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AACpE,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;AAChD,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;AAClD,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;AACtD,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;AACvE,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;AAC9C,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACxE,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ;gEAC4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;+DAC2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;yDAEqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,sEAAsE;IACtE,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,eAAe,EAAE,EAC1B,KAAK,EAAE,eAAe,GACrB,eAAe,EAAE,CAiDnB;AAED,wBAAgB,WAAW,CACzB,OAAO,EAAE,eAAe,EAAE,EAC1B,OAAO,EAAE,iBAAiB,GACzB,eAAe,EAAE,CAcnB"}
|
package/dist/collections.js
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* - a `query` that filters an entry stream (stacks, platforms, categories,
|
|
8
8
|
* licenses, kinds, excludeStatuses, free-text q)
|
|
9
9
|
* - a `ranking` that decides order (quality, active, recency, stars, curated)
|
|
10
|
-
* - optional `
|
|
10
|
+
* - optional hand-picked `entries` (with per-record notes and pinning)
|
|
11
|
+
* - optional `editorial` intro/selection notes, a Markdown `content`
|
|
12
|
+
* body and `faq`
|
|
11
13
|
* - `seo` policy (indexable flag, optional overrides)
|
|
12
14
|
*
|
|
13
15
|
* `CollectionEntry` is the lightweight record shape that flows through
|
|
@@ -17,6 +19,103 @@
|
|
|
17
19
|
* `filterEntries` and `rankEntries` are pure functions; they share no
|
|
18
20
|
* state and never mutate their input.
|
|
19
21
|
*/
|
|
22
|
+
import { z } from 'zod';
|
|
23
|
+
const rankingPresetSchema = z.enum(['quality', 'active', 'curated', 'recency', 'stars']);
|
|
24
|
+
const collectionQuerySchema = z.object({
|
|
25
|
+
stacks: z.array(z.string()).optional(),
|
|
26
|
+
platforms: z.array(z.string()).optional(),
|
|
27
|
+
categories: z.array(z.string()).optional(),
|
|
28
|
+
licenses: z.array(z.string()).optional(),
|
|
29
|
+
kinds: z.array(z.string()).optional(),
|
|
30
|
+
excludeStatuses: z.array(z.string()).optional(),
|
|
31
|
+
/** Minimum GitHub star count. Entries below this are excluded. */
|
|
32
|
+
minStars: z.number().nonnegative().optional(),
|
|
33
|
+
/** Minimum GitHub fork count. Entries below this are excluded. */
|
|
34
|
+
minForks: z.number().nonnegative().optional(),
|
|
35
|
+
q: z.string().optional(),
|
|
36
|
+
/**
|
|
37
|
+
* Records related to any of these subjects (ids from
|
|
38
|
+
* `data/taxonomy/subjects.yml`). `type` narrows to one relation type;
|
|
39
|
+
* omitted, any relation to the subject matches.
|
|
40
|
+
*/
|
|
41
|
+
relatedTo: z
|
|
42
|
+
.object({
|
|
43
|
+
type: z.string().optional(),
|
|
44
|
+
subjects: z.array(z.string().min(1)).min(1),
|
|
45
|
+
})
|
|
46
|
+
.optional(),
|
|
47
|
+
});
|
|
48
|
+
/**
|
|
49
|
+
* The shape of one `data/collections/<slug>.yml` file. Named
|
|
50
|
+
* `collectionDefinitionSchema` because `collectionSchema` is already the
|
|
51
|
+
* JSON-LD builder in `page-document.ts`.
|
|
52
|
+
*
|
|
53
|
+
* Top-level keys are loose so a consumer can carry its own fields next
|
|
54
|
+
* to Grove's; the blocks Grove reads are strict enough that a typo in
|
|
55
|
+
* `ranking.preset` or a string `minStars` fails `grove check` instead of
|
|
56
|
+
* silently producing an unfiltered, unranked page.
|
|
57
|
+
*/
|
|
58
|
+
export const collectionDefinitionSchema = z.looseObject({
|
|
59
|
+
slug: z
|
|
60
|
+
.string()
|
|
61
|
+
.min(1)
|
|
62
|
+
.regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, 'slug must be lowercase kebab-case'),
|
|
63
|
+
kind: z.enum(['curated', 'generated']).default('curated'),
|
|
64
|
+
title: z.string().min(1),
|
|
65
|
+
description: z.string().min(1),
|
|
66
|
+
/**
|
|
67
|
+
* The subject this collection is the hub for — "alternatives to X" is
|
|
68
|
+
* a collection with `subject: x`. One hub per subject; records related
|
|
69
|
+
* to the subject link to it. Membership still comes from `entries` and
|
|
70
|
+
* `query` (usually `query.relatedTo`), so the hub cannot drift from
|
|
71
|
+
* the relations on the records.
|
|
72
|
+
*/
|
|
73
|
+
subject: z.string().min(1).optional(),
|
|
74
|
+
/**
|
|
75
|
+
* Path to the collection's long-form Markdown body, relative to the
|
|
76
|
+
* project root (convention: `./content/collections/<slug>.md`).
|
|
77
|
+
*/
|
|
78
|
+
content: z.string().min(1).optional(),
|
|
79
|
+
query: collectionQuerySchema.prefault({}),
|
|
80
|
+
/**
|
|
81
|
+
* Hand-picked records. A pick is in the collection whatever the
|
|
82
|
+
* `query` says; `note` is the curator's verdict for that record on
|
|
83
|
+
* this page and replaces the record's own description in the list;
|
|
84
|
+
* `pinned` keeps a pick at the top, in file order, above the ranking.
|
|
85
|
+
*
|
|
86
|
+
* Optional rather than defaulted so an existing `Collection` literal
|
|
87
|
+
* keeps type-checking.
|
|
88
|
+
*/
|
|
89
|
+
entries: z
|
|
90
|
+
.array(z.object({
|
|
91
|
+
slug: z.string().min(1),
|
|
92
|
+
note: z.string().min(1).optional(),
|
|
93
|
+
pinned: z.boolean().optional(),
|
|
94
|
+
}))
|
|
95
|
+
.optional(),
|
|
96
|
+
ranking: z
|
|
97
|
+
.object({
|
|
98
|
+
preset: rankingPresetSchema,
|
|
99
|
+
signals: z.array(z.string()).optional(),
|
|
100
|
+
})
|
|
101
|
+
.prefault({ preset: 'curated' }),
|
|
102
|
+
editorial: z
|
|
103
|
+
.object({
|
|
104
|
+
introduction: z.string().optional(),
|
|
105
|
+
selectionNote: z.string().optional(),
|
|
106
|
+
lastReviewedAt: z.string().optional(),
|
|
107
|
+
})
|
|
108
|
+
.optional(),
|
|
109
|
+
/** Questions answered on the page; also emitted as `FAQPage` JSON-LD. */
|
|
110
|
+
faq: z.array(z.object({ q: z.string().min(1), a: z.string().min(1) })).optional(),
|
|
111
|
+
seo: z
|
|
112
|
+
.object({
|
|
113
|
+
index: z.boolean().default(true),
|
|
114
|
+
title: z.string().optional(),
|
|
115
|
+
description: z.string().optional(),
|
|
116
|
+
})
|
|
117
|
+
.prefault({}),
|
|
118
|
+
});
|
|
20
119
|
export function filterEntries(entries, query) {
|
|
21
120
|
return entries.filter((entry) => {
|
|
22
121
|
if (query.stacks?.length && !query.stacks.includes(entry.stack ?? '')) {
|
|
@@ -58,6 +157,12 @@ export function filterEntries(entries, query) {
|
|
|
58
157
|
if (query.minForks != null && (entry.forks ?? 0) < query.minForks) {
|
|
59
158
|
return false;
|
|
60
159
|
}
|
|
160
|
+
if (query.relatedTo) {
|
|
161
|
+
const { type, subjects } = query.relatedTo;
|
|
162
|
+
const related = (entry.relations ?? []).some((relation) => subjects.includes(relation.to) && (!type || relation.type === type));
|
|
163
|
+
if (!related)
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
61
166
|
if (query.q) {
|
|
62
167
|
const hay = `${entry.title} ${entry.description}`.toLowerCase();
|
|
63
168
|
if (!hay.includes(query.q.toLowerCase()))
|
package/dist/collections.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collections.js","sourceRoot":"","sources":["../src/collections.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"collections.js","sourceRoot":"","sources":["../src/collections.ts"],"names":[],"mappings":"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"}
|
package/dist/collector.d.ts
CHANGED
|
@@ -6,5 +6,23 @@ export interface CollectionResult {
|
|
|
6
6
|
isEmpty: boolean;
|
|
7
7
|
isStale: boolean;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Resolve a collection against the entry stream.
|
|
11
|
+
*
|
|
12
|
+
* Membership is the union of the hand-picked `entries` and the `query`
|
|
13
|
+
* matches. An empty query matches every record, so it only takes part
|
|
14
|
+
* when it actually states a criterion — or when there are no picks at
|
|
15
|
+
* all, which keeps a query-less collection meaning "everything", as it
|
|
16
|
+
* always has.
|
|
17
|
+
*
|
|
18
|
+
* A pick is the curator's call: it skips the query, `excludeStatuses`
|
|
19
|
+
* included. It cannot resurrect a hidden or removed record, because
|
|
20
|
+
* those never reach the entry stream. A pick whose slug is not in the
|
|
21
|
+
* stream is skipped here; `grove check` reports it.
|
|
22
|
+
*
|
|
23
|
+
* Order: pinned picks first, in file order; everything else ranked by
|
|
24
|
+
* `ranking`. Under the `curated` preset "ranked" means picks in file
|
|
25
|
+
* order, then query matches in stream order.
|
|
26
|
+
*/
|
|
9
27
|
export declare function runCollection(collection: Collection, entries: CollectionEntry[]): CollectionResult;
|
|
10
28
|
//# sourceMappingURL=collector.d.ts.map
|
package/dist/collector.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAmB,MAAM,kBAAkB,CAAC;AAGrF,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAQD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,eAAe,EAAE,GACzB,gBAAgB,CAgClB"}
|
package/dist/collector.js
CHANGED
|
@@ -1,7 +1,47 @@
|
|
|
1
1
|
import { filterEntries, rankEntries } from './collections.js';
|
|
2
|
+
function hasCriteria(query) {
|
|
3
|
+
return Object.values(query).some((value) => Array.isArray(value) ? value.length > 0 : value !== undefined && value !== '');
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Resolve a collection against the entry stream.
|
|
7
|
+
*
|
|
8
|
+
* Membership is the union of the hand-picked `entries` and the `query`
|
|
9
|
+
* matches. An empty query matches every record, so it only takes part
|
|
10
|
+
* when it actually states a criterion — or when there are no picks at
|
|
11
|
+
* all, which keeps a query-less collection meaning "everything", as it
|
|
12
|
+
* always has.
|
|
13
|
+
*
|
|
14
|
+
* A pick is the curator's call: it skips the query, `excludeStatuses`
|
|
15
|
+
* included. It cannot resurrect a hidden or removed record, because
|
|
16
|
+
* those never reach the entry stream. A pick whose slug is not in the
|
|
17
|
+
* stream is skipped here; `grove check` reports it.
|
|
18
|
+
*
|
|
19
|
+
* Order: pinned picks first, in file order; everything else ranked by
|
|
20
|
+
* `ranking`. Under the `curated` preset "ranked" means picks in file
|
|
21
|
+
* order, then query matches in stream order.
|
|
22
|
+
*/
|
|
2
23
|
export function runCollection(collection, entries) {
|
|
3
|
-
const
|
|
4
|
-
const
|
|
24
|
+
const picks = collection.entries ?? [];
|
|
25
|
+
const bySlug = new Map(entries.map((entry) => [entry.slug, entry]));
|
|
26
|
+
const picked = [];
|
|
27
|
+
const seen = new Set();
|
|
28
|
+
for (const pick of picks) {
|
|
29
|
+
const entry = bySlug.get(pick.slug);
|
|
30
|
+
if (!entry || seen.has(pick.slug))
|
|
31
|
+
continue;
|
|
32
|
+
seen.add(pick.slug);
|
|
33
|
+
picked.push({
|
|
34
|
+
...entry,
|
|
35
|
+
...(pick.note ? { note: pick.note } : {}),
|
|
36
|
+
...(pick.pinned ? { pinned: true } : {}),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const matched = picks.length === 0 || hasCriteria(collection.query)
|
|
40
|
+
? filterEntries(entries, collection.query).filter((entry) => !seen.has(entry.slug))
|
|
41
|
+
: [];
|
|
42
|
+
const pinned = picked.filter((entry) => entry.pinned);
|
|
43
|
+
const rest = rankEntries([...picked.filter((entry) => !entry.pinned), ...matched], collection.ranking);
|
|
44
|
+
const ranked = [...pinned, ...rest];
|
|
5
45
|
const isEmpty = ranked.length === 0;
|
|
6
46
|
const isStale = !isEmpty && ranked.every((e) => e.status === 'archived');
|
|
7
47
|
return { collection, entries: ranked, totalCount: ranked.length, isEmpty, isStale };
|
package/dist/collector.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector.js","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAU9D,MAAM,UAAU,aAAa,CAC3B,UAAsB,EACtB,OAA0B;IAE1B,MAAM,
|
|
1
|
+
{"version":3,"file":"collector.js","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAU9D,SAAS,WAAW,CAAC,KAAsB;IACzC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CACzC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,CAC9E,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,aAAa,CAC3B,UAAsB,EACtB,OAA0B;IAE1B,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAU,CAAC,CAAC,CAAC;IAE7E,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QAC5C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM,CAAC,IAAI,CAAC;YACV,GAAG,KAAK;YACR,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GACX,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC;QACjD,CAAC,CAAC,aAAa,CAAC,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACnF,CAAC,CAAC,EAAE,CAAC;IAET,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,WAAW,CACtB,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,EACxD,UAAU,CAAC,OAAO,CACnB,CAAC;IACF,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IAEpC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;IACzE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AACtF,CAAC"}
|
package/dist/content-body.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Content body helpers — pure, dependency-free logic for reading and
|
|
3
3
|
* shaping the Markdown sidecar that sits next to each record.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* Six concerns live here, all framework-agnostic so any renderer
|
|
6
6
|
* (Astro today, future options) can compose them:
|
|
7
7
|
*
|
|
8
8
|
* 1. `resolveContentPath(contentPath, candidates?)`
|
|
@@ -33,6 +33,11 @@
|
|
|
33
33
|
* "X min read" pill on a detail page. Returns zeros (not throws)
|
|
34
34
|
* for empty input.
|
|
35
35
|
*
|
|
36
|
+
* 6. `stripLeadingH1(body)` / `shiftHeadings(body, by)` — keep a
|
|
37
|
+
* body's headings subordinate to the page or document that embeds
|
|
38
|
+
* it: one `<h1>` on a detail page, no `#` outranking the record's
|
|
39
|
+
* `###` in llms-full.txt.
|
|
40
|
+
*
|
|
36
41
|
* Why a separate module instead of tacking these onto `markdown.ts`?
|
|
37
42
|
* That file is the **awesome-list importer** (parses READMEs into
|
|
38
43
|
* Grove records). Conflating record-side rendering helpers with
|
|
@@ -57,6 +62,20 @@ export declare function resolveContentPath(contentPath: string, candidates?: str
|
|
|
57
62
|
* closing fence.
|
|
58
63
|
*/
|
|
59
64
|
export declare function stripFrontmatter(text: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* Drop a body's opening `# Title` line. A record detail page already
|
|
67
|
+
* renders the record name as its `<h1>`, so a sidecar that opens with
|
|
68
|
+
* its own title would put a second `<h1>` on the page. Only the first
|
|
69
|
+
* non-blank line is considered, and only an ATX heading of depth 1 —
|
|
70
|
+
* a `#` further down the body is the author's to keep.
|
|
71
|
+
*/
|
|
72
|
+
export declare function stripLeadingH1(body: string): string;
|
|
73
|
+
/**
|
|
74
|
+
* Push every ATX heading `by` levels deeper (capped at `######`) so a
|
|
75
|
+
* body can be embedded under an existing heading without its own
|
|
76
|
+
* headings outranking the section that contains it.
|
|
77
|
+
*/
|
|
78
|
+
export declare function shiftHeadings(body: string, by: number): string;
|
|
60
79
|
export interface ReadContentFileResult {
|
|
61
80
|
/** Markdown body with frontmatter stripped. */
|
|
62
81
|
body: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-body.d.ts","sourceRoot":"","sources":["../src/content-body.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"content-body.d.ts","sourceRoot":"","sources":["../src/content-body.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AA8BH;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAM5F;AAID;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrD;AAgCD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAO9D;AAID,MAAM,WAAW,qBAAqB;IACpC,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM,EAAE,GACpB,qBAAqB,GAAG,IAAI,CAoB9B;AAID;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQhD;AAID,MAAM,WAAW,QAAQ;IACvB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,EAAE,EAAE,MAAM,CAAC;IACX,yCAAyC;IACzC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CAC9B;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,QAAQ,EAAE,CAiCpF;AAID,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,cAAc,CAOhG"}
|
package/dist/content-body.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Content body helpers — pure, dependency-free logic for reading and
|
|
3
3
|
* shaping the Markdown sidecar that sits next to each record.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* Six concerns live here, all framework-agnostic so any renderer
|
|
6
6
|
* (Astro today, future options) can compose them:
|
|
7
7
|
*
|
|
8
8
|
* 1. `resolveContentPath(contentPath, candidates?)`
|
|
@@ -33,6 +33,11 @@
|
|
|
33
33
|
* "X min read" pill on a detail page. Returns zeros (not throws)
|
|
34
34
|
* for empty input.
|
|
35
35
|
*
|
|
36
|
+
* 6. `stripLeadingH1(body)` / `shiftHeadings(body, by)` — keep a
|
|
37
|
+
* body's headings subordinate to the page or document that embeds
|
|
38
|
+
* it: one `<h1>` on a detail page, no `#` outranking the record's
|
|
39
|
+
* `###` in llms-full.txt.
|
|
40
|
+
*
|
|
36
41
|
* Why a separate module instead of tacking these onto `markdown.ts`?
|
|
37
42
|
* That file is the **awesome-list importer** (parses READMEs into
|
|
38
43
|
* Grove records). Conflating record-side rendering helpers with
|
|
@@ -98,6 +103,67 @@ export function stripFrontmatter(text) {
|
|
|
98
103
|
return text;
|
|
99
104
|
return lines.slice(close + 2).join('\n');
|
|
100
105
|
}
|
|
106
|
+
// ── Heading normalisation ────────────────────────────────────────────
|
|
107
|
+
/**
|
|
108
|
+
* Walk a Markdown body line by line, calling `onLine` for every line
|
|
109
|
+
* outside a fenced code block. Shared by the heading helpers so a
|
|
110
|
+
* `# comment` inside a ``` fence is never mistaken for a heading —
|
|
111
|
+
* the same rule `extractToc` applies.
|
|
112
|
+
*/
|
|
113
|
+
function mapOutsideFences(body, onLine) {
|
|
114
|
+
let inFence = false;
|
|
115
|
+
let fenceMarker = '';
|
|
116
|
+
return body
|
|
117
|
+
.split(/\r?\n/)
|
|
118
|
+
.map((line) => {
|
|
119
|
+
const fence = line.match(/^\s*(```+|~~~+)/);
|
|
120
|
+
if (fence?.[1]) {
|
|
121
|
+
const marker = fence[1][0] === '`' ? '```' : '~~~';
|
|
122
|
+
if (!inFence) {
|
|
123
|
+
inFence = true;
|
|
124
|
+
fenceMarker = marker;
|
|
125
|
+
}
|
|
126
|
+
else if (marker === fenceMarker) {
|
|
127
|
+
inFence = false;
|
|
128
|
+
}
|
|
129
|
+
return line;
|
|
130
|
+
}
|
|
131
|
+
return inFence ? line : onLine(line);
|
|
132
|
+
})
|
|
133
|
+
.join('\n');
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Drop a body's opening `# Title` line. A record detail page already
|
|
137
|
+
* renders the record name as its `<h1>`, so a sidecar that opens with
|
|
138
|
+
* its own title would put a second `<h1>` on the page. Only the first
|
|
139
|
+
* non-blank line is considered, and only an ATX heading of depth 1 —
|
|
140
|
+
* a `#` further down the body is the author's to keep.
|
|
141
|
+
*/
|
|
142
|
+
export function stripLeadingH1(body) {
|
|
143
|
+
const lines = body.split(/\r?\n/);
|
|
144
|
+
const first = lines.findIndex((l) => l.trim() !== '');
|
|
145
|
+
if (first < 0 || !/^#\s+\S/.test(lines[first] ?? ''))
|
|
146
|
+
return body;
|
|
147
|
+
const rest = lines.slice(first + 1);
|
|
148
|
+
while (rest.length && rest[0]?.trim() === '')
|
|
149
|
+
rest.shift();
|
|
150
|
+
return rest.join('\n');
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Push every ATX heading `by` levels deeper (capped at `######`) so a
|
|
154
|
+
* body can be embedded under an existing heading without its own
|
|
155
|
+
* headings outranking the section that contains it.
|
|
156
|
+
*/
|
|
157
|
+
export function shiftHeadings(body, by) {
|
|
158
|
+
if (by <= 0)
|
|
159
|
+
return body;
|
|
160
|
+
return mapOutsideFences(body, (line) => {
|
|
161
|
+
const m = line.match(/^(#{1,6})(\s+.*)$/);
|
|
162
|
+
if (!m?.[1])
|
|
163
|
+
return line;
|
|
164
|
+
return `${'#'.repeat(Math.min(6, m[1].length + by))}${m[2] ?? ''}`;
|
|
165
|
+
});
|
|
166
|
+
}
|
|
101
167
|
/**
|
|
102
168
|
* Read a record's content file from disk and split it into
|
|
103
169
|
* frontmatter + body. Returns null when the file can't be located.
|
package/dist/content-body.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-body.js","sourceRoot":"","sources":["../src/content-body.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"content-body.js","sourceRoot":"","sources":["../src/content-body.ts"],"names":[],"mappings":"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"}
|