@dogsbay/format-astro 0.2.0-beta.11 → 0.2.0-beta.111

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 (50) hide show
  1. package/dist/base-path.d.ts +93 -7
  2. package/dist/base-path.d.ts.map +1 -1
  3. package/dist/base-path.js +122 -8
  4. package/dist/base-path.js.map +1 -1
  5. package/dist/blog.d.ts +134 -0
  6. package/dist/blog.d.ts.map +1 -0
  7. package/dist/blog.js +319 -0
  8. package/dist/blog.js.map +1 -0
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/cli.js +1 -0
  11. package/dist/cli.js.map +1 -1
  12. package/dist/diff-decoration.d.ts +79 -0
  13. package/dist/diff-decoration.d.ts.map +1 -0
  14. package/dist/diff-decoration.js +541 -0
  15. package/dist/diff-decoration.js.map +1 -0
  16. package/dist/granularity.d.ts +83 -0
  17. package/dist/granularity.d.ts.map +1 -0
  18. package/dist/granularity.js +247 -0
  19. package/dist/granularity.js.map +1 -0
  20. package/dist/index.d.ts +22 -4
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +26 -3
  23. package/dist/index.js.map +1 -1
  24. package/dist/lead.d.ts +19 -0
  25. package/dist/lead.d.ts.map +1 -1
  26. package/dist/lead.js +101 -6
  27. package/dist/lead.js.map +1 -1
  28. package/dist/llms-txt.d.ts +48 -2
  29. package/dist/llms-txt.d.ts.map +1 -1
  30. package/dist/llms-txt.js +131 -14
  31. package/dist/llms-txt.js.map +1 -1
  32. package/dist/plugins.js +1 -1
  33. package/dist/plugins.js.map +1 -1
  34. package/dist/project.d.ts +311 -13
  35. package/dist/project.d.ts.map +1 -1
  36. package/dist/project.js +2261 -211
  37. package/dist/project.js.map +1 -1
  38. package/dist/serialize.d.ts +23 -0
  39. package/dist/serialize.d.ts.map +1 -1
  40. package/dist/serialize.js +359 -138
  41. package/dist/serialize.js.map +1 -1
  42. package/dist/sitemap.d.ts +81 -0
  43. package/dist/sitemap.d.ts.map +1 -0
  44. package/dist/sitemap.js +200 -0
  45. package/dist/sitemap.js.map +1 -0
  46. package/dist/taxonomy.d.ts +48 -1
  47. package/dist/taxonomy.d.ts.map +1 -1
  48. package/dist/taxonomy.js +61 -23
  49. package/dist/taxonomy.js.map +1 -1
  50. package/package.json +8 -7
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Reserved route segment for the book rollup. NOT `_`-prefixed: Astro treats
3
+ * `src/pages/` files/dirs starting with `_` as private (non-routable), so a
4
+ * `_book.astro` would 404. `~book` is collision-proof instead — `slugify`
5
+ * strips `~`, so no content slug can ever produce this segment (no slugifier
6
+ * reservation needed).
7
+ */
8
+ export const BOOK_SEGMENT = "~book";
9
+ /**
10
+ * Rough estimate of a TreeNode[]'s textual content size in bytes — the sum of
11
+ * its prose text, pre-rendered html, and string prop values (code, etc.). Used
12
+ * as the granularity size cap's input: it tracks source size closely enough to
13
+ * catch the 10 MB+ rollups (rest_api, installing) that blow up build + DOM,
14
+ * without a full serialize. See docs-dev/granularity-book-perf.md.
15
+ */
16
+ export function estimateTreeBytes(tree) {
17
+ let bytes = 0;
18
+ const walk = (nodes) => {
19
+ for (const node of nodes) {
20
+ const n = node;
21
+ if (typeof n.html === "string")
22
+ bytes += n.html.length;
23
+ if (n.props) {
24
+ for (const v of Object.values(n.props))
25
+ if (typeof v === "string")
26
+ bytes += v.length;
27
+ }
28
+ if (Array.isArray(n.inline)) {
29
+ for (const i of n.inline) {
30
+ if (typeof i.text === "string")
31
+ bytes += i.text.length;
32
+ else if (typeof i.value === "string")
33
+ bytes += i.value.length;
34
+ }
35
+ }
36
+ if (n.children?.length)
37
+ walk(n.children);
38
+ }
39
+ };
40
+ walk(tree);
41
+ return bytes;
42
+ }
43
+ /**
44
+ * Assemble one book page from a nav subtree + the topic pages it references.
45
+ * Returns null when the subtree references no actual pages.
46
+ */
47
+ export function assembleBook(nav, pages, opts = {}) {
48
+ const hrefPrefix = opts.hrefPrefix ?? "";
49
+ const bookSegment = opts.bookSegment ?? BOOK_SEGMENT;
50
+ const bySlug = new Map(pages.map((p) => [p.slug, p]));
51
+ const topicAnchors = new Map();
52
+ const memberSlugs = [];
53
+ const seenAnchor = new Map();
54
+ const uniqueAnchor = (base) => {
55
+ const b = base || "section";
56
+ const n = seenAnchor.get(b) ?? 0;
57
+ seenAnchor.set(b, n + 1);
58
+ return n === 0 ? b : `${b}-${n}`;
59
+ };
60
+ const ordered = [];
61
+ const assign = (items, depth) => {
62
+ for (const item of items) {
63
+ const level = Math.min(depth + 2, 6);
64
+ const slug = slugFromHref(item.href, hrefPrefix);
65
+ const anchor = uniqueAnchor(slugify(slug ? lastSegment(slug) : item.label));
66
+ ordered.push({ label: item.label, level, slug, anchor });
67
+ if (slug && bySlug.has(slug)) {
68
+ topicAnchors.set(slug, anchor);
69
+ memberSlugs.push(slug);
70
+ }
71
+ if (item.children?.length)
72
+ assign(item.children, depth + 1);
73
+ }
74
+ };
75
+ assign(nav, 0);
76
+ if (memberSlugs.length === 0)
77
+ return null;
78
+ // Pass 2 — assemble: a heading per node, then the topic body (cloned, headings
79
+ // shifted to nest, and intra-book xrefs rewritten to in-page anchors).
80
+ const tree = [];
81
+ for (const { label, level, slug, anchor } of ordered) {
82
+ tree.push(bookHeading(level, label, anchor));
83
+ const page = slug ? bySlug.get(slug) : undefined;
84
+ if (page) {
85
+ // "Open as page ↗" — the way back from the book to the focused topic.
86
+ // Pushed OUTSIDE the body so rewriteIntraBookLinks (which runs on the
87
+ // clone only) doesn't collapse it to an in-page anchor.
88
+ tree.push(openAsPageNode(slug, hrefPrefix));
89
+ // Clone so we never mutate the topic page that is also emitted standalone.
90
+ const body = structuredClone(page.tree);
91
+ shiftHeadings(body, level - 1);
92
+ rewriteIntraBookLinks(body, topicAnchors, hrefPrefix);
93
+ tree.push(...body);
94
+ }
95
+ }
96
+ const title = opts.title ?? nav[0]?.label ?? "Book";
97
+ const base = bookSlugFrom(memberSlugs, slugify(title));
98
+ const slug = `${base}/${bookSegment}`;
99
+ const page = {
100
+ slug,
101
+ title,
102
+ tree,
103
+ headings: extractBookHeadings(tree),
104
+ // Quarantine marker — the emitters keep the book out of search / sitemap /
105
+ // llms and tag it noindex. Kept in frontmatter so it round-trips + is visible.
106
+ frontmatter: { noindex: true, granularity: "book" },
107
+ };
108
+ return { page, topicAnchors };
109
+ }
110
+ // ── pure helpers (ported from format-fluidtopics-rest/single-page.ts) ──────
111
+ /** The "Open as page ↗" affordance — a link from a book section back to its topic page. */
112
+ export function openAsPageNode(slug, hrefPrefix) {
113
+ const route = hrefPrefix ? `${hrefPrefix}/${slug}` : `/${slug}`;
114
+ return {
115
+ type: "paragraph",
116
+ props: { class: "dsb-open-as-page" },
117
+ children: [{ type: "prose", inline: [{ type: "link", href: route, children: [{ type: "text", text: "Open as page ↗" }] }] }],
118
+ };
119
+ }
120
+ /** A heading node for a nav entry's title, carrying the explicit anchor id. */
121
+ export function bookHeading(level, title, anchor) {
122
+ return {
123
+ type: "heading",
124
+ props: { level, slug: anchor, text: title },
125
+ children: [{ type: "prose", inline: [{ type: "text", text: title }] }],
126
+ };
127
+ }
128
+ /** Shift every heading in a (topic body) tree down by `offset` ranks (max H6). */
129
+ export function shiftHeadings(tree, offset) {
130
+ if (offset <= 0)
131
+ return;
132
+ for (const n of tree) {
133
+ if (n.type === "heading") {
134
+ const lvl = n.props?.level ?? 1;
135
+ if (!n.props)
136
+ n.props = {};
137
+ n.props.level = Math.min(lvl + offset, 6);
138
+ }
139
+ if (n.children)
140
+ shiftHeadings(n.children, offset);
141
+ }
142
+ }
143
+ /**
144
+ * Rewrite **intra-book** xrefs to in-page anchors so the reader stays in the
145
+ * book. A link is rewritten iff its target slug is in *this* book's
146
+ * `topicAnchors` (the "is it in this book?" test). Cross-book links (target not
147
+ * in the book) and external links are left untouched — they keep pointing at the
148
+ * canonical topic page, which is correct. Mutates `tree` (already a clone).
149
+ */
150
+ export function rewriteIntraBookLinks(tree, topicAnchors, hrefPrefix) {
151
+ const rewriteInline = (nodes) => {
152
+ for (const n of nodes) {
153
+ if (n.type === "link" && typeof n.href === "string") {
154
+ const slug = slugFromHref(n.href, hrefPrefix);
155
+ const anchor = slug ? topicAnchors.get(slug) : undefined;
156
+ if (anchor)
157
+ n.href = `#${anchor}`;
158
+ }
159
+ if (Array.isArray(n.children))
160
+ rewriteInline(n.children);
161
+ }
162
+ };
163
+ const walk = (ns) => {
164
+ for (const n of ns) {
165
+ if (n.inline)
166
+ rewriteInline(n.inline);
167
+ if (n.children)
168
+ walk(n.children);
169
+ }
170
+ };
171
+ walk(tree);
172
+ }
173
+ /**
174
+ * Longest common path prefix (slash-segment-wise) of the member slugs — the
175
+ * book's base route (e.g. the FT book base `…/16.0`). Falls back to `fallback`.
176
+ */
177
+ export function bookSlugFrom(slugs, fallback) {
178
+ const parts = slugs.filter(Boolean).map((s) => s.split("/"));
179
+ if (!parts.length)
180
+ return fallback;
181
+ const first = parts[0];
182
+ let i = 0;
183
+ for (; i < first.length; i++) {
184
+ const seg = first[i];
185
+ if (!parts.every((p) => p[i] === seg))
186
+ break;
187
+ }
188
+ return first.slice(0, i).join("/") || fallback;
189
+ }
190
+ /** Strip the route prefix + leading slash + anchor/query from a nav href → slug. */
191
+ export function slugFromHref(href, hrefPrefix) {
192
+ if (!href)
193
+ return "";
194
+ let s = href.split("#")[0].split("?")[0].trim();
195
+ if (hrefPrefix && s.startsWith(hrefPrefix))
196
+ s = s.slice(hrefPrefix.length);
197
+ return s.replace(/^\/+/, "").replace(/\/+$/, "");
198
+ }
199
+ function lastSegment(slug) {
200
+ return slug.split("/").pop() ?? slug;
201
+ }
202
+ /** Collect Heading[] from an assembled tree (nodes already carry props.slug/level/text). */
203
+ function extractBookHeadings(tree) {
204
+ const out = [];
205
+ const walk = (ns) => {
206
+ for (const n of ns) {
207
+ if (n.type === "heading") {
208
+ out.push({
209
+ depth: n.props?.level ?? 1,
210
+ slug: n.props?.slug ?? "",
211
+ text: n.props?.text ?? inlineText(n),
212
+ });
213
+ }
214
+ if (n.children)
215
+ walk(n.children);
216
+ }
217
+ };
218
+ walk(tree);
219
+ return out;
220
+ }
221
+ function inlineText(node) {
222
+ const parts = [];
223
+ const fromInline = (ns = []) => {
224
+ for (const n of ns) {
225
+ if (typeof n.text === "string")
226
+ parts.push(n.text);
227
+ else if (Array.isArray(n.children))
228
+ fromInline(n.children);
229
+ }
230
+ };
231
+ if (node.inline)
232
+ fromInline(node.inline);
233
+ if (node.children)
234
+ for (const c of node.children)
235
+ parts.push(inlineText(c));
236
+ return parts.join("").trim();
237
+ }
238
+ export function slugify(text) {
239
+ return (text
240
+ .toLowerCase()
241
+ .replace(/[^\w\s-]/g, "")
242
+ .replace(/\s+/g, "-")
243
+ .replace(/-+/g, "-")
244
+ .replace(/^-+|-+$/g, "")
245
+ .trim() || "section");
246
+ }
247
+ //# sourceMappingURL=granularity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"granularity.js","sourceRoot":"","sources":["../src/granularity.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,14 +1,32 @@
1
1
  export { treeToAstro, escapeExpr, escapeAttr, escapeTemplate } from "./serialize.js";
2
- export { detectLeadingNodes } from "./lead.js";
2
+ export { detectLeadingNodes, deriveDescription } from "./lead.js";
3
3
  export type { LeadingNodeInfo } from "./lead.js";
4
4
  export type { AstroGenResult, AstroGenOptions, AstroRenderMode } from "./serialize.js";
5
- export { DEFAULT_BASE_PATH, normalizeBasePath, basePathSegments, joinBaseUrl, buildCurrentPath, } from "./base-path.js";
5
+ export { DEFAULT_BASE_PATH, normalizeBasePath, basePathSegments, joinBaseUrl, buildCurrentPath, parseSiteUrl, combinePrefix, resolvePrefixes, } from "./base-path.js";
6
6
  export { buildLlmsTxt, buildSectionLlmsTxt, buildLlmsFullTxt, extractFirstParagraph, } from "./llms-txt.js";
7
7
  export type { BuildLlmsTxtOptions, BuildLlmsFullTxtOptions, } from "./llms-txt.js";
8
- export { exportAstroProject, emitSiteScaffold, emitSiteConfig, emitAstroPages, emitConfigDerivedFiles, emitAgentReadinessFiles, emitSwitcherMap, emitMissingTranslationStubs, } from "./project.js";
9
- export type { AstroProjectOptions, SwitcherMap } from "./project.js";
8
+ export { buildSitemap, buildSitemapIndex } from "./sitemap.js";
9
+ export { buildBlogData, blogAdjacency, emitBlogFiles, indexPageCount, readingMinutes, countWords, BLOG_DEFAULTS, } from "./blog.js";
10
+ export type { BlogEmitConfig, BlogData, BlogPostRef, BlogAdjacency, } from "./blog.js";
11
+ export type { BuildSitemapOptions } from "./sitemap.js";
12
+ export { exportAstroProject, emitSiteScaffold, emitSiteConfig, emitAstroPages, emitConfigDerivedFiles, emitAgentReadinessFiles, emitSwitcherMap, emitMissingTranslationStubs, emitPassthroughAstroPages, emitDeployArtifacts, workersSubpathOutDir, makeSlugExcluder, } from "./project.js";
13
+ export type { AstroProjectOptions, SwitcherMap, PassthroughCopy, } from "./project.js";
10
14
  export { emitPluginRuntime } from "./plugins.js";
11
15
  export type { EmitPluginRuntimeOptions, PluginClientModulesGroup, PluginStylesGroup, PluginClientConfig, } from "./plugins.js";
12
16
  export { buildTaxonomyData, emitTaxonomyForName, emitTaxonomyRoutes, getPageTerms, } from "./taxonomy.js";
13
17
  export type { TaxonomyEmitConfig, TaxonomyTerm, TaxonomyPageRef, TaxonomyData, } from "./taxonomy.js";
18
+ export { DIFF_CSS, decorateDiff, diffMarksOf, hasDiffMarks, injectAttrs, inlineSegmentsToHtml, } from "./diff-decoration.js";
19
+ export type { DiffMarks } from "./diff-decoration.js";
20
+ /**
21
+ * Granularity book view — assemble a nav subtree into one page.
22
+ *
23
+ * Exported because it is the PLATFORM generalization of the same algorithm
24
+ * `format-fluidtopics-rest/src/single-page.ts` implements against khub TOCs:
25
+ * without an export, no other package could reach it, which is a large part of
26
+ * why the fold described in that module never happened.
27
+ *
28
+ * See plans/granularity-views.md and docs/single-page-view.md.
29
+ */
30
+ export { BOOK_SEGMENT, assembleBook, bookHeading, bookSlugFrom, estimateTreeBytes, openAsPageNode, rewriteIntraBookLinks, shiftHeadings, slugFromHref, } from "./granularity.js";
31
+ export type { AssembleBookOptions, BookView } from "./granularity.js";
14
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKvF,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,eAAe,CAAC;AAavB,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EACV,wBAAwB,EACxB,wBAAwB,EACxB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAKtB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,YAAY,GACb,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMrF,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKvF,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAK/D,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,UAAU,EACV,aAAa,GACd,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,cAAc,EACd,QAAQ,EACR,WAAW,EACX,aAAa,GACd,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAaxD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,2BAA2B,EAC3B,yBAAyB,EACzB,mBAAmB,EAKnB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,mBAAmB,EACnB,WAAW,EACX,eAAe,GAChB,MAAM,cAAc,CAAC;AAKtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EACV,wBAAwB,EACxB,wBAAwB,EACxB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAKtB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,WAAW,EACX,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;;;;;;;;GASG;AACH,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,YAAY,GACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -4,13 +4,19 @@ export { treeToAstro, escapeExpr, escapeAttr, escapeTemplate } from "./serialize
4
4
  // has a leading H1 / paragraph so format-astro can decide whether
5
5
  // to inject frontmatter title + description at the top of <main>.
6
6
  // See plans/auto-lede.md.
7
- export { detectLeadingNodes } from "./lead.js";
7
+ export { detectLeadingNodes, deriveDescription } from "./lead.js";
8
8
  // Base-path helpers — single source of truth for the `basePath` URL
9
9
  // prefix shared across project / nav / llms-txt / taxonomy emitters.
10
10
  // See plans/configurable-base-path.md.
11
- export { DEFAULT_BASE_PATH, normalizeBasePath, basePathSegments, joinBaseUrl, buildCurrentPath, } from "./base-path.js";
11
+ export { DEFAULT_BASE_PATH, normalizeBasePath, basePathSegments, joinBaseUrl, buildCurrentPath, parseSiteUrl, combinePrefix, resolvePrefixes, } from "./base-path.js";
12
12
  // llms.txt + llms-full.txt builders (LLM discovery files)
13
13
  export { buildLlmsTxt, buildSectionLlmsTxt, buildLlmsFullTxt, extractFirstParagraph, } from "./llms-txt.js";
14
+ // Sitemap builders (per-mount, sitemaps.org 0.9)
15
+ export { buildSitemap, buildSitemapIndex } from "./sitemap.js";
16
+ // Blog emission — reverse-chron index + post adjacency. The sibling of
17
+ // taxonomy.ts: same data-file + generated-route + writer-override shape,
18
+ // sorted by date instead of grouped by term. See plans/blog-capability.md.
19
+ export { buildBlogData, blogAdjacency, emitBlogFiles, indexPageCount, readingMinutes, countWords, BLOG_DEFAULTS, } from "./blog.js";
14
20
  // Project export — orchestrator + per-tier emitters
15
21
  //
16
22
  // `exportAstroProject` is the high-level entry: generates a complete
@@ -22,7 +28,12 @@ export { buildLlmsTxt, buildSectionLlmsTxt, buildLlmsFullTxt, extractFirstParagr
22
28
  // alone; `dogsbay site build` calls `emitAstroPages` +
23
29
  // `emitConfigDerivedFiles` + `emitAgentReadinessFiles`. Pure
24
30
  // `dogsbay convert --to astro` (Step 7) calls only `emitAstroPages`.
25
- export { exportAstroProject, emitSiteScaffold, emitSiteConfig, emitAstroPages, emitConfigDerivedFiles, emitAgentReadinessFiles, emitSwitcherMap, emitMissingTranslationStubs, } from "./project.js";
31
+ export { exportAstroProject, emitSiteScaffold, emitSiteConfig, emitAstroPages, emitConfigDerivedFiles, emitAgentReadinessFiles, emitSwitcherMap, emitMissingTranslationStubs, emitPassthroughAstroPages, emitDeployArtifacts,
32
+ // Where a Workers subpath-mounted build actually lands. Consumers that
33
+ // read the BUILT site (e.g. `dogsbay site check --dist`) must resolve
34
+ // the same directory the emitter told Astro to write to, or they audit
35
+ // an empty dist/ root.
36
+ workersSubpathOutDir, makeSlugExcluder, } from "./project.js";
26
37
  // Plugin runtime codegen — emits the entry, virtual config modules,
27
38
  // stylesheets, and Vite alias file each plugin needs to participate
28
39
  // in the Astro / Vite build. See plans/plugin-api.md.
@@ -31,4 +42,16 @@ export { emitPluginRuntime } from "./plugins.js";
31
42
  // Per declared taxonomy in `dogsbay.config.yml`'s `taxonomies:` block,
32
43
  // emits a JSON data file + index/term .astro route files.
33
44
  export { buildTaxonomyData, emitTaxonomyForName, emitTaxonomyRoutes, getPageTerms, } from "./taxonomy.js";
45
+ export { DIFF_CSS, decorateDiff, diffMarksOf, hasDiffMarks, injectAttrs, inlineSegmentsToHtml, } from "./diff-decoration.js";
46
+ /**
47
+ * Granularity book view — assemble a nav subtree into one page.
48
+ *
49
+ * Exported because it is the PLATFORM generalization of the same algorithm
50
+ * `format-fluidtopics-rest/src/single-page.ts` implements against khub TOCs:
51
+ * without an export, no other package could reach it, which is a large part of
52
+ * why the fold described in that module never happened.
53
+ *
54
+ * See plans/granularity-views.md and docs/single-page-view.md.
55
+ */
56
+ export { BOOK_SEGMENT, assembleBook, bookHeading, bookSlugFrom, estimateTreeBytes, openAsPageNode, rewriteIntraBookLinks, shiftHeadings, slugFromHref, } from "./granularity.js";
34
57
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErF,gEAAgE;AAChE,kEAAkE;AAClE,kEAAkE;AAClE,0BAA0B;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAI/C,oEAAoE;AACpE,qEAAqE;AACrE,uCAAuC;AACvC,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,0DAA0D;AAC1D,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AAMvB,oDAAoD;AACpD,EAAE;AACF,qEAAqE;AACrE,kEAAkE;AAClE,mBAAmB;AACnB,EAAE;AACF,gEAAgE;AAChE,sEAAsE;AACtE,uDAAuD;AACvD,6DAA6D;AAC7D,qEAAqE;AACrE,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AAGtB,oEAAoE;AACpE,oEAAoE;AACpE,sDAAsD;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAQjD,kEAAkE;AAClE,uEAAuE;AACvE,0DAA0D;AAC1D,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,GACb,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErF,gEAAgE;AAChE,kEAAkE;AAClE,kEAAkE;AAClE,0BAA0B;AAC1B,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAIlE,oEAAoE;AACpE,qEAAqE;AACrE,uCAAuC;AACvC,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAExB,0DAA0D;AAC1D,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AAMvB,iDAAiD;AACjD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAE/D,uEAAuE;AACvE,yEAAyE;AACzE,2EAA2E;AAC3E,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,UAAU,EACV,aAAa,GACd,MAAM,WAAW,CAAC;AASnB,oDAAoD;AACpD,EAAE;AACF,qEAAqE;AACrE,kEAAkE;AAClE,mBAAmB;AACnB,EAAE;AACF,gEAAgE;AAChE,sEAAsE;AACtE,uDAAuD;AACvD,6DAA6D;AAC7D,qEAAqE;AACrE,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,2BAA2B,EAC3B,yBAAyB,EACzB,mBAAmB;AACnB,uEAAuE;AACvE,sEAAsE;AACtE,uEAAuE;AACvE,uBAAuB;AACvB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAOtB,oEAAoE;AACpE,oEAAoE;AACpE,sDAAsD;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAQjD,kEAAkE;AAClE,uEAAuE;AACvE,0DAA0D;AAC1D,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,GACb,MAAM,eAAe,CAAC;AAOvB,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,WAAW,EACX,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAG9B;;;;;;;;;GASG;AACH,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,YAAY,GACb,MAAM,kBAAkB,CAAC"}
package/dist/lead.d.ts CHANGED
@@ -36,4 +36,23 @@ export interface LeadingNodeInfo {
36
36
  * `false` for both flags when the tree is empty.
37
37
  */
38
38
  export declare function detectLeadingNodes(tree: TreeNode[] | undefined): LeadingNodeInfo;
39
+ /**
40
+ * Derive a `<meta name="description">` from a page body when the
41
+ * frontmatter doesn't supply one: the first prose paragraph,
42
+ * whitespace-collapsed and truncated at a word boundary.
43
+ *
44
+ * Deliberately Minja-unaware. This only runs at build time, on the
45
+ * preprocessed (resolved) tree — `{{ var }}` and `{% include %}` are
46
+ * already gone, so the first paragraph is real prose. (A still-undefined
47
+ * `{{ var }}` survives `preserve` mode, but that's a content bug equally
48
+ * visible in the body and already flagged by the `unresolved-directives`
49
+ * audit — not the description's job to scrub.) The `--no-preprocess` /
50
+ * `dogsbay convert` paths emit unresolved output by design, where a
51
+ * slightly-off description is the least of it.
52
+ *
53
+ * Scans past a leading H1 / heading / code to the first prose paragraph;
54
+ * returns `undefined` when the page has no prose. See
55
+ * plans/auto-meta-description.md.
56
+ */
57
+ export declare function deriveDescription(tree: TreeNode[] | undefined, maxLen?: number): string | undefined;
39
58
  //# sourceMappingURL=lead.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lead.d.ts","sourceRoot":"","sources":["../src/lead.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,KAAK,EAAE,OAAO,CAAC;IACf;;;;;;;;;OASG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,QAAQ,EAAE,GAAG,SAAS,GAC3B,eAAe,CAcjB"}
1
+ {"version":3,"file":"lead.d.ts","sourceRoot":"","sources":["../src/lead.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,KAAK,EAAE,OAAO,CAAC;IACf;;;;;;;;;OASG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,QAAQ,EAAE,GAAG,SAAS,GAC3B,eAAe,CAmCjB;AAmBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,QAAQ,EAAE,GAAG,SAAS,EAC5B,MAAM,SAAM,GACX,MAAM,GAAG,SAAS,CAYpB"}
package/dist/lead.js CHANGED
@@ -8,13 +8,37 @@ export function detectLeadingNodes(tree) {
8
8
  if (!tree || tree.length === 0) {
9
9
  return { hasH1: false, hasLede: false };
10
10
  }
11
- const first = tree[0];
12
- const firstIsH1 = isH1(first);
13
- if (firstIsH1) {
14
- const second = tree[1];
15
- return { hasH1: true, hasLede: isParagraph(second) };
11
+ // H1 detection looks past two things that are not content:
12
+ //
13
+ // - leading raw-HTML CHROME (banners, toolbars — the comparison view
14
+ // injects both). Only tree[0] was inspected before, so a page that
15
+ // opened with a banner "had no H1" and the layout added a second
16
+ // one (external review);
17
+ // - a transparent `group` wrapper, which by definition adds no
18
+ // semantics — it exists only to carry an attribute for a run of
19
+ // blocks (the comparison marks a whole added/removed page with one).
20
+ // A wrapper that hid the page's H1 would resurrect the same bug.
21
+ //
22
+ // LEDE detection deliberately still keys off tree[0]: a paragraph that
23
+ // merely follows an HTML block is not the page's lede, and treating it
24
+ // as one silently suppresses the frontmatter description on any
25
+ // imported page opening with a <figure>/hero block (code review,
26
+ // 2026-07-13). Only an H1 introduces a lede.
27
+ let list = tree;
28
+ for (;;) {
29
+ let i = 0;
30
+ while (i < list.length && list[i]?.type === "html")
31
+ i++;
32
+ const first = list[i];
33
+ if (first?.type === "group" && first.children?.length) {
34
+ list = first.children;
35
+ continue;
36
+ }
37
+ if (isH1(first)) {
38
+ return { hasH1: true, hasLede: isParagraph(list[i + 1]) };
39
+ }
40
+ return { hasH1: false, hasLede: isParagraph(tree[0]) };
16
41
  }
17
- return { hasH1: false, hasLede: isParagraph(first) };
18
42
  }
19
43
  function isH1(node) {
20
44
  if (!node || node.type !== "heading")
@@ -35,4 +59,75 @@ function isParagraph(node) {
35
59
  return false;
36
60
  return node.type === "paragraph";
37
61
  }
62
+ /**
63
+ * Derive a `<meta name="description">` from a page body when the
64
+ * frontmatter doesn't supply one: the first prose paragraph,
65
+ * whitespace-collapsed and truncated at a word boundary.
66
+ *
67
+ * Deliberately Minja-unaware. This only runs at build time, on the
68
+ * preprocessed (resolved) tree — `{{ var }}` and `{% include %}` are
69
+ * already gone, so the first paragraph is real prose. (A still-undefined
70
+ * `{{ var }}` survives `preserve` mode, but that's a content bug equally
71
+ * visible in the body and already flagged by the `unresolved-directives`
72
+ * audit — not the description's job to scrub.) The `--no-preprocess` /
73
+ * `dogsbay convert` paths emit unresolved output by design, where a
74
+ * slightly-off description is the least of it.
75
+ *
76
+ * Scans past a leading H1 / heading / code to the first prose paragraph;
77
+ * returns `undefined` when the page has no prose. See
78
+ * plans/auto-meta-description.md.
79
+ */
80
+ export function deriveDescription(tree, maxLen = 155) {
81
+ if (!tree || tree.length === 0)
82
+ return undefined;
83
+ // Skip a leading H1 (the page title) so the lede is the node after it.
84
+ let i = isH1(tree[0]) ? 1 : 0;
85
+ for (; i < tree.length; i++) {
86
+ const node = tree[i];
87
+ if (node.type !== "paragraph")
88
+ continue; // skip headings/code/etc.
89
+ const text = paragraphText(node).replace(/\s+/g, " ").trim();
90
+ if (!text)
91
+ continue;
92
+ return truncateAtWord(text, maxLen);
93
+ }
94
+ return undefined;
95
+ }
96
+ /**
97
+ * Flatten a paragraph node's text. Tolerant of the three shapes
98
+ * format-astro already handles: flat `node.inline`, wrapped
99
+ * `node.children[{ inline }]`, and pre-rendered `node.html`.
100
+ */
101
+ function paragraphText(node) {
102
+ const parts = [];
103
+ const visit = (n) => {
104
+ if (!n || typeof n !== "object")
105
+ return;
106
+ const o = n;
107
+ if (typeof o.text === "string")
108
+ parts.push(o.text);
109
+ if (typeof o.code === "string")
110
+ parts.push(o.code);
111
+ if (Array.isArray(o.inline))
112
+ o.inline.forEach(visit);
113
+ if (Array.isArray(o.children))
114
+ o.children.forEach(visit);
115
+ };
116
+ if (Array.isArray(node.inline))
117
+ node.inline.forEach(visit);
118
+ else if (Array.isArray(node.children))
119
+ node.children.forEach(visit);
120
+ else if (typeof node.html === "string") {
121
+ parts.push(node.html.replace(/<[^>]+>/g, ""));
122
+ }
123
+ return parts.join("");
124
+ }
125
+ function truncateAtWord(s, max) {
126
+ if (s.length <= max)
127
+ return s;
128
+ const cut = s.slice(0, max);
129
+ const lastSpace = cut.lastIndexOf(" ");
130
+ const base = lastSpace > max * 0.6 ? cut.slice(0, lastSpace) : cut;
131
+ return base.replace(/[\s.,;:!?-]+$/, "") + "…";
132
+ }
38
133
  //# sourceMappingURL=lead.js.map
package/dist/lead.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"lead.js","sourceRoot":"","sources":["../src/lead.ts"],"names":[],"mappings":"AAiCA;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAA4B;IAE5B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC1C,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IAE9B,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACvB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;IACvD,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;AACvD,CAAC;AAED,SAAS,IAAI,CAAC,IAA0B;IACtC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACnD,kEAAkE;IAClE,8DAA8D;IAC9D,sCAAsC;IACtC,MAAM,KAAK,GAAI,IAAsC,CAAC,KAAK,CAAC;IAC5D,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,KAAK,CAAC,CAAC;IAClD,MAAM,KAAK,GAAI,IAAI,CAAC,KAAwC,EAAE,KAAK,CAAC;IACpE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,KAAK,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,WAAW,CAAC,IAA0B;IAC7C,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,OAAO,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"lead.js","sourceRoot":"","sources":["../src/lead.ts"],"names":[],"mappings":"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"}
@@ -35,6 +35,49 @@ export interface BuildLlmsTxtOptions {
35
35
  * Default: "Documentation".
36
36
  */
37
37
  topLevelLabel?: string;
38
+ /**
39
+ * Label for pages that exist in `pages` but are not reachable via
40
+ * `nav`. They're appended under a final section so agents see the
41
+ * full content surface even when nav curates a subset for human
42
+ * sidebars. Default: "Other pages". Set to `false` to suppress
43
+ * orphan emission entirely (matches pre-decoupling behavior).
44
+ */
45
+ otherPagesLabel?: string | false;
46
+ /**
47
+ * Other sites on this host to link at the end of the index — the
48
+ * `llms.txt` half of `site.aggregates`.
49
+ *
50
+ * Emitted as links, NOT inlined. Inlining would give an agent
51
+ * everything in one fetch but go stale on the aggregated site's next
52
+ * build, and this file is generated by a DIFFERENT build that has no
53
+ * way to know that happened.
54
+ */
55
+ aggregates?: AggregateEntry[];
56
+ /** Heading for the aggregates section. Default "Other sites". */
57
+ aggregatesLabel?: string;
58
+ /**
59
+ * Free-form guidance placed directly under the site description:
60
+ * what this site is good for and when an agent should reach for it.
61
+ *
62
+ * The llms.txt spec gives you a title, a blockquote and a link
63
+ * index — all of which describe what EXISTS. None of them say when
64
+ * the site is the right answer, which is the question an agent is
65
+ * actually holding. An audit put it as "generic marketing copy does
66
+ * not read as guidance", and that is fair: this is worth writing
67
+ * only if it names concrete jobs.
68
+ *
69
+ * Emitted verbatim as markdown so an author can use a list, and
70
+ * omitted entirely when unset rather than filled with a default —
71
+ * an invented "when to use" is worse than none.
72
+ */
73
+ whenToUse?: string;
74
+ }
75
+ /** One entry in the aggregates section. See `site.aggregates`. */
76
+ export interface AggregateEntry {
77
+ name: string;
78
+ description?: string;
79
+ url?: string;
80
+ llmsTxt?: string;
38
81
  }
39
82
  export interface BuildLlmsFullTxtOptions extends BuildLlmsTxtOptions {
40
83
  /**
@@ -56,8 +99,11 @@ export interface BuildLlmsFullTxtOptions extends BuildLlmsTxtOptions {
56
99
  * Layout:
57
100
  * - One `## {label}` section per top-level nav group with children.
58
101
  * - Top-level leaf nav items collected into a single
59
- * `## {topLevelLabel}` block at the end.
60
- * - External hrefs and pages not in nav are skipped.
102
+ * `## {topLevelLabel}` block.
103
+ * - Pages reachable in `pages` but absent from `nav` appended under
104
+ * a final `## {otherPagesLabel}` section. Set `otherPagesLabel`
105
+ * to `false` to suppress (e.g. when nav is the publish list).
106
+ * - External hrefs are skipped.
61
107
  */
62
108
  export declare function buildLlmsTxt(siteConfig: Pick<SiteConfig, "siteName" | "description" | "siteUrl">, nav: NavItem[], pages: ExportPage[], options?: BuildLlmsTxtOptions): string;
63
109
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"llms-txt.d.ts","sourceRoot":"","sources":["../src/llms-txt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EACV,UAAU,EAEV,OAAO,EACP,UAAU,EACV,QAAQ,EACT,MAAM,gBAAgB,CAAC;AAUxB,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,uBAAwB,SAAQ,mBAAmB;IAClE;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;IACjC;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,MAAM,CAAC;CAC9C;AAID;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,GAAG,SAAS,CAAC,EACpE,GAAG,EAAE,OAAO,EAAE,EACd,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,GAAE,mBAAwB,GAChC,MAAM,CAoDR;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC,EACpD,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,GAAE,mBAAwB,GAChC,MAAM,CAqBR;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,GAAG,SAAS,CAAC,EACpE,GAAG,EAAE,OAAO,EAAE,EACd,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,GAAE,uBAA4B,GACpC,MAAM,CA8CR;AAsGD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,CAO9D"}
1
+ {"version":3,"file":"llms-txt.d.ts","sourceRoot":"","sources":["../src/llms-txt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EACV,UAAU,EAEV,OAAO,EACP,UAAU,EACV,QAAQ,EACT,MAAM,gBAAgB,CAAC;AAYxB,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACjC;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,kEAAkE;AAClE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,uBAAwB,SAAQ,mBAAmB;IAClE;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;IACjC;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,MAAM,CAAC;CAC9C;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,GAAG,SAAS,CAAC,EACpE,GAAG,EAAE,OAAO,EAAE,EACd,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,GAAE,mBAAwB,GAChC,MAAM,CAsGR;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC,EACpD,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,GAAE,mBAAwB,GAChC,MAAM,CAqBR;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,GAAG,SAAS,CAAC,EACpE,GAAG,EAAE,OAAO,EAAE,EACd,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,GAAE,uBAA4B,GACpC,MAAM,CA+DR;AA4KD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,CAO9D"}