@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.
Files changed (58) hide show
  1. package/dist/awesome-readme.d.ts +39 -0
  2. package/dist/awesome-readme.d.ts.map +1 -1
  3. package/dist/awesome-readme.js +51 -7
  4. package/dist/awesome-readme.js.map +1 -1
  5. package/dist/build-data.d.ts.map +1 -1
  6. package/dist/build-data.js +8 -0
  7. package/dist/build-data.js.map +1 -1
  8. package/dist/collection-entries.d.ts +81 -0
  9. package/dist/collection-entries.d.ts.map +1 -0
  10. package/dist/collection-entries.js +74 -0
  11. package/dist/collection-entries.js.map +1 -0
  12. package/dist/collections-io.d.ts +17 -1
  13. package/dist/collections-io.d.ts.map +1 -1
  14. package/dist/collections-io.js +39 -5
  15. package/dist/collections-io.js.map +1 -1
  16. package/dist/collections.d.ts +95 -40
  17. package/dist/collections.d.ts.map +1 -1
  18. package/dist/collections.js +106 -1
  19. package/dist/collections.js.map +1 -1
  20. package/dist/collector.d.ts +18 -0
  21. package/dist/collector.d.ts.map +1 -1
  22. package/dist/collector.js +42 -2
  23. package/dist/collector.js.map +1 -1
  24. package/dist/content-body.d.ts +20 -1
  25. package/dist/content-body.d.ts.map +1 -1
  26. package/dist/content-body.js +67 -1
  27. package/dist/content-body.js.map +1 -1
  28. package/dist/index.d.ts +13 -10
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +9 -6
  31. package/dist/index.js.map +1 -1
  32. package/dist/llms.d.ts.map +1 -1
  33. package/dist/llms.js +4 -11
  34. package/dist/llms.js.map +1 -1
  35. package/dist/page-document.d.ts +24 -0
  36. package/dist/page-document.d.ts.map +1 -1
  37. package/dist/page-document.js +22 -1
  38. package/dist/page-document.js.map +1 -1
  39. package/dist/prepare.d.ts.map +1 -1
  40. package/dist/prepare.js +18 -24
  41. package/dist/prepare.js.map +1 -1
  42. package/dist/related.js +14 -3
  43. package/dist/related.js.map +1 -1
  44. package/dist/routes.d.ts +9 -0
  45. package/dist/routes.d.ts.map +1 -0
  46. package/dist/routes.js +15 -0
  47. package/dist/routes.js.map +1 -0
  48. package/dist/schema.d.ts +230 -0
  49. package/dist/schema.d.ts.map +1 -1
  50. package/dist/schema.js +63 -0
  51. package/dist/schema.js.map +1 -1
  52. package/dist/sitemap.d.ts.map +1 -1
  53. package/dist/sitemap.js +2 -9
  54. package/dist/sitemap.js.map +1 -1
  55. package/dist/validate.d.ts.map +1 -1
  56. package/dist/validate.js +340 -1
  57. package/dist/validate.js.map +1 -1
  58. package/package.json +1 -1
@@ -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 `editorial` intro/selection notes and review metadata
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
- export type CollectionKind = 'curated' | 'generated';
21
- export type RankingPreset = 'quality' | 'active' | 'curated' | 'recency' | 'stars';
22
- export interface CollectionQuery {
23
- stacks?: string[];
24
- platforms?: string[];
25
- categories?: string[];
26
- licenses?: string[];
27
- kinds?: string[];
28
- excludeStatuses?: string[];
29
- /** Minimum GitHub star count. Entries below this are excluded. */
30
- minStars?: number;
31
- /** Minimum GitHub fork count. Entries below this are excluded. */
32
- minForks?: number;
33
- q?: string;
34
- }
35
- export interface CollectionRanking {
36
- preset: RankingPreset;
37
- signals?: string[];
38
- }
39
- export interface CollectionEditorial {
40
- introduction?: string;
41
- selectionNote?: string;
42
- lastReviewedAt?: string;
43
- }
44
- export interface CollectionSeo {
45
- index: boolean;
46
- title?: string;
47
- description?: string;
48
- }
49
- export interface Collection {
50
- slug: string;
51
- kind: CollectionKind;
52
- title: string;
53
- description: string;
54
- query: CollectionQuery;
55
- ranking: CollectionRanking;
56
- editorial?: CollectionEditorial;
57
- seo: CollectionSeo;
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;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,WAAW,CAAC;AAErD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnF,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,GAAG,EAAE,aAAa,CAAC;CACpB;AAED,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;CACvB;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,eAAe,EAAE,EAC1B,KAAK,EAAE,eAAe,GACrB,eAAe,EAAE,CA0CnB;AAED,wBAAgB,WAAW,CACzB,OAAO,EAAE,eAAe,EAAE,EAC1B,OAAO,EAAE,iBAAiB,GACzB,eAAe,EAAE,CAcnB"}
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"}
@@ -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 `editorial` intro/selection notes and review metadata
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()))
@@ -1 +1 @@
1
- {"version":3,"file":"collections.js","sourceRoot":"","sources":["../src/collections.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"collections.js","sourceRoot":"","sources":["../src/collections.ts"],"names":[],"mappings":"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"}
@@ -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
@@ -1 +1 @@
1
- {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGpE,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;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,eAAe,EAAE,GACzB,gBAAgB,CAMlB"}
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 filtered = filterEntries(entries, collection.query);
4
- const ranked = rankEntries(filtered, collection.ranking);
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 };
@@ -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,QAAQ,GAAG,aAAa,CAAC,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IACzD,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"}
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"}
@@ -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
- * Five concerns live here, all framework-agnostic so any renderer
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;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;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"}
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"}
@@ -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
- * Five concerns live here, all framework-agnostic so any renderer
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.
@@ -1 +1 @@
1
- {"version":3,"file":"content-body.js","sourceRoot":"","sources":["../src/content-body.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"content-body.js","sourceRoot":"","sources":["../src/content-body.ts"],"names":[],"mappings":"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"}