@dogsbay/types 0.1.2

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.
@@ -0,0 +1,350 @@
1
+ import type { TreeNode } from "./tree.js";
2
+ import type { PageMeta } from "./meta.js";
3
+ /**
4
+ * A page for format conversion: slug → tree.
5
+ *
6
+ * This is the universal contract between importers and exporters.
7
+ * Importers produce ExportPage[], exporters consume them.
8
+ */
9
+ export interface Heading {
10
+ depth: number;
11
+ slug: string;
12
+ text: string;
13
+ /** Symbol kind for API reference TOC entries (class, meth, attr, func, module) */
14
+ kind?: string;
15
+ }
16
+ export interface ExportPage {
17
+ /** File path relative to docs root, e.g. "getting-started" or "guides/install" */
18
+ slug: string;
19
+ /** Page title */
20
+ title: string;
21
+ /** Page content as TreeNode[] */
22
+ tree: TreeNode[];
23
+ /** Headings extracted during parsing (for TOC generation) */
24
+ headings: Heading[];
25
+ /** Target URL for redirect/navigation pages (no body content, just a link) */
26
+ redirect?: string;
27
+ /**
28
+ * Raw frontmatter data from the source page. Includes all YAML fields that
29
+ * were present in the original source (title, description, tags, custom
30
+ * fields like pcx_content_type, sidebar.*, etc.).
31
+ *
32
+ * Importers populate this with all frontmatter values; exporters can use
33
+ * specific keys or emit the whole object as frontmatter on output.
34
+ * Specific fields (title, redirect) are also lifted to named ExportPage
35
+ * fields for convenient access.
36
+ */
37
+ frontmatter?: Record<string, unknown>;
38
+ /**
39
+ * Parsed, validated, normalized metadata. Populated by importers
40
+ * via `parseMeta(frontmatter, options)`. Drives taxonomy emission,
41
+ * status badges, search facets, and Diátaxis-aware layouts.
42
+ *
43
+ * `frontmatter` stays opaque (preserves unknown keys for round-
44
+ * trip); `meta` is the typed slice the renderer consumes.
45
+ */
46
+ meta?: PageMeta;
47
+ /**
48
+ * Axis metadata for multi-source aggregation. Populated by the
49
+ * loader when ≥1 axis is active so downstream emitters (the
50
+ * version switcher data file, the per-page frontmatter that
51
+ * lets a page identify itself in the switcher) can reconstruct
52
+ * cross-axis equivalents.
53
+ *
54
+ * Undefined when no axis is active (single-source / single-
55
+ * version / single-namespace site). When set, `originalSlug`
56
+ * is always present (the slug as the importer produced it,
57
+ * before any axis prefixing); `namespace` / `version` /
58
+ * `locale` are present only when their axis is active.
59
+ *
60
+ * See plans/multi-source-content.md.
61
+ */
62
+ multiSource?: MultiSourceMeta;
63
+ }
64
+ /**
65
+ * Per-page axis metadata. Set by the loader's aggregator when
66
+ * multi-source axes are active; consumed by emitters that need
67
+ * to reconstruct cross-version / cross-locale / cross-namespace
68
+ * equivalents (switcherMap.json, hreflang tags, etc.).
69
+ */
70
+ export interface MultiSourceMeta {
71
+ /** Namespace key (when namespace axis active). */
72
+ namespace?: string;
73
+ /** Version id (when version axis active). */
74
+ version?: string;
75
+ /** Locale code (when locale axis active; reserved for PR 5). */
76
+ locale?: string;
77
+ /**
78
+ * Slug as the importer produced it, BEFORE the loader applied
79
+ * any axis prefix. Lets emitters compute the logical key
80
+ * (`<namespace>/<originalSlug>`) that identifies "this same
81
+ * page across versions / locales".
82
+ */
83
+ originalSlug: string;
84
+ }
85
+ /**
86
+ * Navigation item for sidebar/TOC structures.
87
+ *
88
+ * Universal across formats — importers extract nav from source config
89
+ * (mkdocs.yml, sidebars.js, folder structure), exporters write it to
90
+ * the target format's nav mechanism.
91
+ */
92
+ export interface NavItem {
93
+ label: string;
94
+ href?: string;
95
+ children?: NavItem[];
96
+ }
97
+ /**
98
+ * Standard interface for format plugins.
99
+ *
100
+ * Each format package (e.g. @dogsbay/format-mkdocs) exports a plugin
101
+ * conforming to this interface. The CLI discovers and composes them.
102
+ */
103
+ export interface FormatPlugin {
104
+ /** Format identifier, e.g. "mkdocs", "obsidian", "astro" */
105
+ name: string;
106
+ /** Whether this format supports importing (source → tree) */
107
+ canImport: boolean;
108
+ /** Whether this format supports exporting (tree → target) */
109
+ canExport: boolean;
110
+ /** Auto-detect whether a path is this format */
111
+ detectSource: (path: string) => boolean;
112
+ /** Format-specific CLI options for import */
113
+ importOptions?: FormatOption[];
114
+ /** Format-specific CLI options for export */
115
+ exportOptions?: FormatOption[];
116
+ /** Import: read source format, produce pages + nav */
117
+ import?(source: string, opts: Record<string, unknown>): Promise<{
118
+ pages: ExportPage[];
119
+ nav: NavItem[];
120
+ }>;
121
+ /** Export: write pages + nav to target format */
122
+ export?(pages: ExportPage[], nav: NavItem[], output: string, opts: Record<string, unknown>): Promise<void>;
123
+ }
124
+ export interface FormatOption {
125
+ flags: string;
126
+ description: string;
127
+ default?: string;
128
+ }
129
+ /**
130
+ * Plausible analytics configuration.
131
+ *
132
+ * When present in `SiteConfig`, the docs layout emits a `<script>` tag
133
+ * loading Plausible's tracker. Cookie-less by default, no consent banner
134
+ * needed for EU.
135
+ */
136
+ export interface PlausibleConfig {
137
+ /**
138
+ * Tracking domain — the value used as `data-domain` on the script tag.
139
+ * Typically matches the site's hostname, e.g. "docs.example.com".
140
+ */
141
+ domain: string;
142
+ /**
143
+ * Optional override for the Plausible script URL. Use this when
144
+ * self-hosting Plausible or proxying through your own subdomain.
145
+ * Default: "https://plausible.io/js/script.js".
146
+ */
147
+ scriptUrl?: string;
148
+ }
149
+ /**
150
+ * Runtime site configuration consumed by docs-layout and other runtime
151
+ * components. Written to `src/data/site.json` by `exportAstroProject`.
152
+ *
153
+ * Every field is optional except `siteName`, which has a sensible
154
+ * default ("Documentation") emitted by the project generator. Fields
155
+ * left undefined are omitted from the emitted JSON to keep output clean.
156
+ */
157
+ export interface SiteConfig {
158
+ /** Site name shown in header, page title suffixes, copyright notices. */
159
+ siteName: string;
160
+ /**
161
+ * Canonical site URL. Required for `<link rel="canonical">`,
162
+ * sitemap.xml entries, and absolute OG meta tags. Without it, those
163
+ * features degrade to relative URLs.
164
+ */
165
+ siteUrl?: string;
166
+ /**
167
+ * Site-wide description used as the default `<meta name="description">`
168
+ * and fallback `og:description` when a page doesn't supply one.
169
+ */
170
+ description?: string;
171
+ /**
172
+ * Default OG image URL — used as `og:image` and `twitter:image`
173
+ * fallback when a page doesn't set `ogImage` in its frontmatter.
174
+ * Should be ~1200x630 PNG/JPG.
175
+ */
176
+ ogImage?: string;
177
+ /**
178
+ * Twitter / X handle including the leading "@". Emits as
179
+ * `<meta name="twitter:site">`.
180
+ */
181
+ twitterHandle?: string;
182
+ /**
183
+ * Theme color hint for browsers / iOS Safari status bar. Hex string
184
+ * e.g. "#0a0a0a".
185
+ */
186
+ themeColor?: string;
187
+ /**
188
+ * Source repo URL (for edit-on-GitHub links and similar). Combined
189
+ * with `editUri` to produce per-page edit URLs.
190
+ */
191
+ repoUrl?: string;
192
+ /**
193
+ * Path prefix appended to `repoUrl` for edit URLs, e.g.
194
+ * "blob/main/docs/". Resulting per-page link is
195
+ * `{repoUrl}/{editUri}/{slug}.md`.
196
+ */
197
+ editUri?: string;
198
+ /** Footer copyright text. */
199
+ copyright?: string;
200
+ /**
201
+ * Brand keywords for the site, used by the
202
+ * `seo/h1-brand-keyword` audit rule to verify that landing
203
+ * pages (home + `meta.type: landing` pages) include at least
204
+ * one of these strings in their H1 heading.
205
+ *
206
+ * Match is case-insensitive substring; ordering doesn't
207
+ * matter. Most sites set 1-3 entries (full name, short name,
208
+ * tagline). Sites that omit this config get no
209
+ * brand-keyword findings.
210
+ */
211
+ brandKeywords?: string[];
212
+ /**
213
+ * Plausible analytics configuration. When set, docs-layout emits the
214
+ * tracker script. When undefined, no analytics script is injected.
215
+ */
216
+ plausible?: PlausibleConfig;
217
+ /**
218
+ * Display config for hierarchical tag chips, sourced from
219
+ * `taxonomies.tags.prefixes` in `dogsbay.config.yml`. Keyed by
220
+ * the top-level prefix (`concept`, `difficulty`, etc.) — each
221
+ * entry supplies an optional human label and one of the closed
222
+ * palette colors. Consumed by `<TagList>` to render two-part
223
+ * chips with prefix-keyed colors. See plans/tag-display-config.md.
224
+ */
225
+ tagPrefixes?: Record<string, TagPrefixDisplay>;
226
+ /**
227
+ * Per-tag leaf-label overrides (slug → display string). URLs and
228
+ * taxonomy term-page paths still use the slug; only chip text
229
+ * changes. Sourced from `taxonomies.tags.labels`.
230
+ */
231
+ tagLabels?: Record<string, string>;
232
+ /**
233
+ * Map of taxonomy name → index path, sourced from declared
234
+ * `taxonomies` entries in `dogsbay.config.yml`. Lets renderer
235
+ * components (`TypeBadge`, `StatusBadge`, etc.) discover whether
236
+ * a built-in field has a browse destination AND what its path is.
237
+ *
238
+ * Example: `{ tags: "/tags", type: "/types", status: "/by-status" }`.
239
+ * A field absent from this map has no destination — the badge
240
+ * renders as a plain span; a field present in the map renders as
241
+ * a link to `<indexPath>/<value>/`.
242
+ *
243
+ * See plans/tag-display-config.md.
244
+ */
245
+ taxonomyIndexPaths?: Record<string, string>;
246
+ /**
247
+ * Per-taxonomy display config (prefixes + labels), keyed by
248
+ * taxonomy name. Powers the search-facet UI (`<SearchFacets>`)
249
+ * — facet checkboxes show "Concept: Accessibility" instead of
250
+ * `concept/a11y`, "How-to" instead of `how-to`, etc., reusing
251
+ * the same prefix/label mapping that drives `<TagList>` and
252
+ * the taxonomy term pages.
253
+ *
254
+ * `tagPrefixes` / `tagLabels` mirror `taxonomyDisplay.tags`
255
+ * for back-compat with the chip-rendering path. `<TagList>`
256
+ * still consumes those.
257
+ *
258
+ * See plans/search-facets.md.
259
+ */
260
+ taxonomyDisplay?: Record<string, TaxonomyDisplay>;
261
+ /**
262
+ * Per-page LLM action UI configuration ("Copy as markdown",
263
+ * "Open in Claude/ChatGPT/…"). When omitted, the action cluster
264
+ * is not rendered. See plans/llm-page-actions.md.
265
+ *
266
+ * The agent-readiness data layer (.md endpoints, llms.txt,
267
+ * Accept negotiation) is independent of this config — it always
268
+ * ships as long as `mdMirror` / `llmsTxt` are enabled in
269
+ * AstroProjectOptions. This config only controls the
270
+ * human-facing UI cluster.
271
+ */
272
+ llmActions?: LlmActionsConfig;
273
+ }
274
+ /**
275
+ * Closed list of LLM provider deep-link targets. Each one is a
276
+ * web app accepting `?q=` query strings to seed a new chat with
277
+ * the provided prompt text. Order in this union determines render
278
+ * order when no explicit list is configured.
279
+ */
280
+ export type LlmProviderName = "claude" | "chatgpt" | "perplexity" | "gemini";
281
+ /**
282
+ * Where the per-page LLM action cluster appears.
283
+ * - `header` — top-right of the page header (sticky, always visible)
284
+ * - `inline` — directly below the breadcrumb, above the H1
285
+ * - `both` — both placements; useful for sites that want the
286
+ * cluster visible during long scrolls AND in line
287
+ * with the content for first-glance discovery
288
+ */
289
+ export type LlmActionsPlacement = "header" | "inline" | "both";
290
+ /**
291
+ * Per-page LLM action UI configuration.
292
+ *
293
+ * Default behavior when this object is enabled but partial:
294
+ * - `providers` → all four providers, in this order:
295
+ * claude, chatgpt, perplexity, gemini.
296
+ * - `placement` → "header"
297
+ * - `copyButton` → true
298
+ * - `promptTemplate` → "Read this docs page: {url}"
299
+ * - `footerLink` → true (footer link to /llms.txt)
300
+ *
301
+ * Per-page opt-out is via frontmatter `llmActions: false` — see
302
+ * format-astro/src/project.ts.
303
+ */
304
+ export interface LlmActionsConfig {
305
+ /**
306
+ * Master toggle. When `false`, no PageActions UI is rendered
307
+ * regardless of other fields. Default `true` when the parent
308
+ * `llmActions` object is present.
309
+ */
310
+ enabled?: boolean;
311
+ /** Provider list, in render order. */
312
+ providers?: LlmProviderName[];
313
+ /** Where to render the action cluster. */
314
+ placement?: LlmActionsPlacement;
315
+ /** Show the standalone "Copy markdown" button next to the dropdown. */
316
+ copyButton?: boolean;
317
+ /**
318
+ * Prompt template for "Open in {provider}" deep links. The
319
+ * placeholder `{url}` is replaced by the absolute `.md` URL of
320
+ * the current page; the result is URL-encoded into `?q=`.
321
+ */
322
+ promptTemplate?: string;
323
+ /** Add a footer link to `/llms.txt`. */
324
+ footerLink?: boolean;
325
+ }
326
+ /** Per-taxonomy display config — display labels for chip / facet UI. */
327
+ export interface TaxonomyDisplay {
328
+ /** Per-prefix display config keyed by top-level segment. */
329
+ prefixes?: Record<string, TagPrefixDisplay>;
330
+ /** Per-slug label overrides; key = full slug, value = display string. */
331
+ labels?: Record<string, string>;
332
+ }
333
+ /**
334
+ * Display config for one taxonomy prefix. Color is one of the
335
+ * fixed palette names emitted into the runtime by `<TagList>`.
336
+ * Both fields are optional: with only `label`, the chip renders
337
+ * two-part text in the default palette slot; with only `color`,
338
+ * the slug stays as the chip label.
339
+ */
340
+ export interface TagPrefixDisplay {
341
+ label?: string;
342
+ color?: TagPaletteName;
343
+ }
344
+ /**
345
+ * Closed palette of color names for tag chip backgrounds. Mirrored
346
+ * from `@dogsbay/cli`'s `PaletteName` so runtime consumers can
347
+ * type-narrow without importing CLI internals.
348
+ */
349
+ export type TagPaletteName = "blue" | "amber" | "emerald" | "violet" | "rose" | "slate";
350
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;;;;;;;;;;;;;OAcG;IACH,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,SAAS,EAAE,OAAO,CAAC;IACnB,6DAA6D;IAC7D,SAAS,EAAE,OAAO,CAAC;IACnB,gDAAgD;IAChD,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,6CAA6C;IAC7C,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,6CAA6C;IAC7C,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,sDAAsD;IACtD,MAAM,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,GAAG,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC,CAAC;IACzG,iDAAiD;IACjD,MAAM,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5G;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;OAGG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC/C;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC;;;;;;;;;;;;OAYG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAClD;;;;;;;;;;OAUG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAED;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;AAE7E;;;;;;;GAOG;AACH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE/D;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sCAAsC;IACtC,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC;IAC9B,0CAA0C;IAC1C,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,uEAAuE;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC5C,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,OAAO,GACP,SAAS,GACT,QAAQ,GACR,MAAM,GACN,OAAO,CAAC"}
package/dist/format.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ export type { TreeNode, InlineNode, InlineText, InlineLink, InlineImage, InlineCode, InlineFootnoteRef, InlineKbd, InlineIcon, InlineMath, InlineHtml, InlineBreak } from "./tree.js";
2
+ export { treeToJson, chunkByHeadings, extractText } from "./json.js";
3
+ export type { RagChunk } from "./json.js";
4
+ export type { ExportPage, Heading, NavItem, FormatPlugin, FormatOption, SiteConfig, PlausibleConfig, TagPrefixDisplay, TagPaletteName, TaxonomyDisplay, LlmActionsConfig, LlmActionsPlacement, LlmProviderName } from "./format.js";
5
+ export type { PageMeta, PageStatus, ParseMetaOptions } from "./meta.js";
6
+ export { parseMeta } from "./meta.js";
7
+ export type { DogsbayPlugin, DogsbayPluginContext, DogsbayPluginFactory, PluginVisibleConfig, PluginLogger, PluginRule, PluginIssue, PluginConfigEntry, EmitFilesHelpers, AstroIntegrationRef, } from "./plugin.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACtL,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACrE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACpO,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { treeToJson, chunkByHeadings, extractText } from "./json.js";
2
+ export { parseMeta } from "./meta.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAIrE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
package/dist/json.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import type { TreeNode } from "./tree.js";
2
+ /**
3
+ * A chunk of content suitable for RAG retrieval.
4
+ * Each chunk corresponds to a heading section in the document.
5
+ */
6
+ export interface RagChunk {
7
+ heading: string | null;
8
+ headingLevel: number;
9
+ path: string[];
10
+ content: string;
11
+ metadata: Record<string, unknown>;
12
+ }
13
+ /**
14
+ * Convert a TreeNode[] to structured JSON for LLM consumption.
15
+ */
16
+ export declare function treeToJson(nodes: TreeNode[]): unknown;
17
+ /**
18
+ * Split a TreeNode[] into chunks at heading boundaries.
19
+ * Each chunk contains the text content under a heading section.
20
+ */
21
+ export declare function chunkByHeadings(nodes: TreeNode[], maxLevel?: number): RagChunk[];
22
+ /**
23
+ * Extract plain text from a TreeNode, stripping any markup.
24
+ */
25
+ export declare function extractText(node: TreeNode): string;
26
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAErD;AAkBD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,QAAQ,EAAE,EACjB,QAAQ,GAAE,MAAU,GACnB,QAAQ,EAAE,CAoDZ;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAiBlD"}
package/dist/json.js ADDED
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Convert a TreeNode[] to structured JSON for LLM consumption.
3
+ */
4
+ export function treeToJson(nodes) {
5
+ return nodes.map(nodeToJson);
6
+ }
7
+ function nodeToJson(node) {
8
+ const result = { type: node.type };
9
+ if (node.props && Object.keys(node.props).length > 0) {
10
+ result.props = node.props;
11
+ }
12
+ if (node.html) {
13
+ result.text = node.html;
14
+ }
15
+ if (node.children && node.children.length > 0) {
16
+ result.children = node.children.map(nodeToJson);
17
+ }
18
+ return result;
19
+ }
20
+ /**
21
+ * Split a TreeNode[] into chunks at heading boundaries.
22
+ * Each chunk contains the text content under a heading section.
23
+ */
24
+ export function chunkByHeadings(nodes, maxLevel = 3) {
25
+ const chunks = [];
26
+ const headingStack = [];
27
+ let currentContent = [];
28
+ let currentHeading = null;
29
+ let currentLevel = 0;
30
+ function flush() {
31
+ const content = currentContent.join("\n").trim();
32
+ if (content || currentHeading) {
33
+ chunks.push({
34
+ heading: currentHeading,
35
+ headingLevel: currentLevel,
36
+ path: headingStack.map((h) => h.title),
37
+ content,
38
+ metadata: {},
39
+ });
40
+ }
41
+ currentContent = [];
42
+ }
43
+ function walkNodes(nodes) {
44
+ for (const node of nodes) {
45
+ if (node.type === "heading") {
46
+ const level = node.props?.level ?? 1;
47
+ if (level <= maxLevel) {
48
+ flush();
49
+ while (headingStack.length > 0 &&
50
+ headingStack[headingStack.length - 1].level >= level) {
51
+ headingStack.pop();
52
+ }
53
+ const title = extractText(node);
54
+ headingStack.push({ title, level });
55
+ currentHeading = title;
56
+ currentLevel = level;
57
+ continue;
58
+ }
59
+ }
60
+ currentContent.push(extractText(node));
61
+ }
62
+ }
63
+ walkNodes(nodes);
64
+ flush();
65
+ return chunks;
66
+ }
67
+ /**
68
+ * Extract plain text from a TreeNode, stripping any markup.
69
+ */
70
+ export function extractText(node) {
71
+ const parts = [];
72
+ if (node.html) {
73
+ parts.push(stripHtml(node.html));
74
+ }
75
+ if (node.type === "code" && node.props?.code) {
76
+ parts.push(String(node.props.code).trim());
77
+ }
78
+ if (node.children) {
79
+ for (const child of node.children) {
80
+ parts.push(extractText(child));
81
+ }
82
+ }
83
+ return parts.filter(Boolean).join(" ").trim();
84
+ }
85
+ function stripHtml(html) {
86
+ return html.replace(/<[^>]+>/g, "").trim();
87
+ }
88
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"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"}
package/dist/meta.d.ts ADDED
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Typed page metadata — the parsed, validated, normalized slice of
3
+ * frontmatter the renderer cares about.
4
+ *
5
+ * Importers populate `ExportPage.meta` by calling `parseMeta` on the
6
+ * source frontmatter. Free-form / format-specific keys stay in
7
+ * `ExportPage.frontmatter` (opaque, preserved for round-trip).
8
+ *
9
+ * See plans/metadata-and-taxonomies.md for the design rationale.
10
+ */
11
+ /** Lifecycle states. Closed enum — fixed set with defined render semantics. */
12
+ export type PageStatus = "draft" | "preview" | "stable" | "deprecated";
13
+ export interface PageMeta {
14
+ /**
15
+ * Flat or slash-nested string tags. `tags: ["api/rest"]` means the
16
+ * page lives under `/tags/api/` AND `/tags/api/rest/` at emit
17
+ * time. Slash is the only nesting separator.
18
+ */
19
+ tags?: string[];
20
+ /**
21
+ * Broader grouping. Auto-derived from path when frontmatter
22
+ * doesn't supply a valid value (`content/guides/auth.md` →
23
+ * `["guides"]`). Override with `category: foo` or
24
+ * `category: [foo, bar]`.
25
+ *
26
+ * No first-class "belongs nowhere" sentinel in v1: `category: []`
27
+ * falls through to slug-derived default. See
28
+ * plans/metadata-and-taxonomies.md.
29
+ */
30
+ category?: string[];
31
+ /**
32
+ * Page type. Open string. Diátaxis values (`tutorial`, `how-to`,
33
+ * `reference`, `explanation`) are conventional; users can add
34
+ * `api-endpoint`, `release-notes`, etc.
35
+ */
36
+ type?: string;
37
+ /** Lifecycle. Drafts excluded from prod builds; deprecated gets a banner. */
38
+ status?: PageStatus;
39
+ /** Audience facets — `["developer"]`, `["admin", "end-user"]`, etc. */
40
+ audience?: string[];
41
+ /** ISO date strings. Consumers parse to Date when needed. */
42
+ updated?: string;
43
+ created?: string;
44
+ /** Sort hint for navigation/list pages. Lower weight first. */
45
+ weight?: number;
46
+ /**
47
+ * Free-form properties beyond well-known fields. Queryable from
48
+ * templates; doesn't get auto-generated index pages. Validate via
49
+ * `propSchema` in `dogsbay.config.yml`.
50
+ */
51
+ props?: Record<string, unknown>;
52
+ /**
53
+ * Custom taxonomies declared in config. Key is the taxonomy name
54
+ * (e.g. `audience`, `product`); value is the term list. Term
55
+ * strings may be slash-nested when the taxonomy is hierarchical.
56
+ */
57
+ taxonomies?: Record<string, string[]>;
58
+ }
59
+ /**
60
+ * Options for `parseMeta`. The slug enables path-based `category`
61
+ * auto-derivation; the `taxonomyNames` set tells the parser which
62
+ * frontmatter keys to lift into `meta.taxonomies`.
63
+ */
64
+ export interface ParseMetaOptions {
65
+ /**
66
+ * Slug of the page being parsed (e.g. `"guides/auth"`). Used to
67
+ * auto-derive `category` when frontmatter doesn't set it. Pass
68
+ * `undefined` to skip path-based derivation.
69
+ */
70
+ slug?: string;
71
+ /**
72
+ * Names of user-declared taxonomies (from `dogsbay.config.yml`'s
73
+ * `taxonomies:` block). Frontmatter values for these keys are
74
+ * lifted into `meta.taxonomies[name]`. Without this, the parser
75
+ * doesn't know which extra keys to treat as taxonomies vs
76
+ * arbitrary frontmatter.
77
+ */
78
+ taxonomyNames?: readonly string[];
79
+ }
80
+ /**
81
+ * Parse and normalize frontmatter into `PageMeta`. Pure function;
82
+ * no I/O. Unknown frontmatter keys are not lifted — they stay in
83
+ * the caller's opaque frontmatter copy.
84
+ *
85
+ * Behavior:
86
+ * - `tags`, `audience` accept string[] or single string (coerced).
87
+ * - `category` accepts string[] or single string. When absent and
88
+ * `slug` is provided, auto-derives from path segments (excluding
89
+ * the leaf filename).
90
+ * - `type` accepts any string.
91
+ * - `status` accepts only the four enum values; others are dropped.
92
+ * - `weight` accepts numbers; non-numeric is dropped.
93
+ * - `updated` / `created` are stored as ISO strings; Date objects
94
+ * are converted via `.toISOString()`.
95
+ * - `props` accepts an object; non-objects dropped.
96
+ * - Keys named in `options.taxonomyNames` are lifted into
97
+ * `meta.taxonomies` as string arrays.
98
+ */
99
+ export declare function parseMeta(frontmatter: Record<string, unknown> | undefined, options?: ParseMetaOptions): PageMeta;
100
+ //# sourceMappingURL=meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../src/meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,+EAA+E;AAC/E,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEvE,MAAM,WAAW,QAAQ;IACvB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,6EAA6E;IAC7E,MAAM,CAAC,EAAE,UAAU,CAAC;IAEpB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEhC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACvC;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAUD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CACvB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAChD,OAAO,GAAE,gBAAqB,GAC7B,QAAQ,CAwCV"}
package/dist/meta.js ADDED
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Typed page metadata — the parsed, validated, normalized slice of
3
+ * frontmatter the renderer cares about.
4
+ *
5
+ * Importers populate `ExportPage.meta` by calling `parseMeta` on the
6
+ * source frontmatter. Free-form / format-specific keys stay in
7
+ * `ExportPage.frontmatter` (opaque, preserved for round-trip).
8
+ *
9
+ * See plans/metadata-and-taxonomies.md for the design rationale.
10
+ */
11
+ /** Closed enum for status validation. */
12
+ const STATUS_VALUES = [
13
+ "draft",
14
+ "preview",
15
+ "stable",
16
+ "deprecated",
17
+ ];
18
+ /**
19
+ * Parse and normalize frontmatter into `PageMeta`. Pure function;
20
+ * no I/O. Unknown frontmatter keys are not lifted — they stay in
21
+ * the caller's opaque frontmatter copy.
22
+ *
23
+ * Behavior:
24
+ * - `tags`, `audience` accept string[] or single string (coerced).
25
+ * - `category` accepts string[] or single string. When absent and
26
+ * `slug` is provided, auto-derives from path segments (excluding
27
+ * the leaf filename).
28
+ * - `type` accepts any string.
29
+ * - `status` accepts only the four enum values; others are dropped.
30
+ * - `weight` accepts numbers; non-numeric is dropped.
31
+ * - `updated` / `created` are stored as ISO strings; Date objects
32
+ * are converted via `.toISOString()`.
33
+ * - `props` accepts an object; non-objects dropped.
34
+ * - Keys named in `options.taxonomyNames` are lifted into
35
+ * `meta.taxonomies` as string arrays.
36
+ */
37
+ export function parseMeta(frontmatter, options = {}) {
38
+ const fm = frontmatter ?? {};
39
+ const meta = {};
40
+ const tags = coerceStringArray(fm.tags);
41
+ if (tags)
42
+ meta.tags = tags;
43
+ const category = coerceStringArray(fm.category) ?? deriveCategoryFromSlug(options.slug);
44
+ if (category)
45
+ meta.category = category;
46
+ if (typeof fm.type === "string" && fm.type.length > 0) {
47
+ meta.type = fm.type;
48
+ }
49
+ if (typeof fm.status === "string" && STATUS_VALUES.includes(fm.status)) {
50
+ meta.status = fm.status;
51
+ }
52
+ const audience = coerceStringArray(fm.audience);
53
+ if (audience)
54
+ meta.audience = audience;
55
+ const updated = coerceIsoDate(fm.updated);
56
+ if (updated)
57
+ meta.updated = updated;
58
+ const created = coerceIsoDate(fm.created);
59
+ if (created)
60
+ meta.created = created;
61
+ if (typeof fm.weight === "number" && Number.isFinite(fm.weight)) {
62
+ meta.weight = fm.weight;
63
+ }
64
+ if (isPlainObject(fm.props)) {
65
+ meta.props = { ...fm.props };
66
+ }
67
+ const taxonomies = collectTaxonomies(fm, options.taxonomyNames);
68
+ if (taxonomies)
69
+ meta.taxonomies = taxonomies;
70
+ return meta;
71
+ }
72
+ /**
73
+ * Auto-derive `category` from a slug. The leaf segment is treated
74
+ * as the page filename and dropped; remaining segments become the
75
+ * category path.
76
+ *
77
+ * - `"guides/auth"` → `["guides"]`
78
+ * - `"guides/oauth/setup"` → `["guides", "oauth"]`
79
+ * - `"intro"` → undefined (no parent path)
80
+ * - `""` / undefined → undefined
81
+ */
82
+ function deriveCategoryFromSlug(slug) {
83
+ if (!slug)
84
+ return undefined;
85
+ const parts = slug.split("/").filter((p) => p.length > 0);
86
+ if (parts.length < 2)
87
+ return undefined;
88
+ return parts.slice(0, -1);
89
+ }
90
+ function coerceStringArray(value) {
91
+ if (typeof value === "string") {
92
+ return value.length > 0 ? [value] : undefined;
93
+ }
94
+ if (Array.isArray(value)) {
95
+ const out = value.filter((v) => typeof v === "string" && v.length > 0);
96
+ return out.length > 0 ? out : undefined;
97
+ }
98
+ return undefined;
99
+ }
100
+ function coerceIsoDate(value) {
101
+ if (value instanceof Date && !Number.isNaN(value.getTime())) {
102
+ return value.toISOString();
103
+ }
104
+ if (typeof value === "string" && value.length > 0) {
105
+ const parsed = new Date(value);
106
+ return Number.isNaN(parsed.getTime()) ? undefined : parsed.toISOString();
107
+ }
108
+ return undefined;
109
+ }
110
+ function isPlainObject(value) {
111
+ return (typeof value === "object" &&
112
+ value !== null &&
113
+ !Array.isArray(value) &&
114
+ !(value instanceof Date));
115
+ }
116
+ function collectTaxonomies(fm, taxonomyNames) {
117
+ if (!taxonomyNames || taxonomyNames.length === 0)
118
+ return undefined;
119
+ const out = {};
120
+ for (const name of taxonomyNames) {
121
+ // Skip well-known names that have their own typed slot.
122
+ if (name === "tags" || name === "category" || name === "audience")
123
+ continue;
124
+ const value = coerceStringArray(fm[name]);
125
+ if (value)
126
+ out[name] = value;
127
+ }
128
+ return Object.keys(out).length > 0 ? out : undefined;
129
+ }
130
+ //# sourceMappingURL=meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.js","sourceRoot":"","sources":["../src/meta.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Plugin types — the surface third-party plugins target.
3
+ *
4
+ * Design and rationale: plans/plugin-api.md.
5
+ *
6
+ * The interface is deliberately framework-agnostic. Plugins do NOT
7
+ * see the inner workings of the Astro build; they receive parsed
8
+ * pages as TreeNode-bearing `ExportPage[]` and contribute generated
9
+ * outputs (transformed pages, audit rules, client modules, styles,
10
+ * astro integrations) through named hooks.
11
+ *
12
+ * The runtime side (loader, codegen) lives in `packages/cli`. This
13
+ * file owns only the shapes — keeping `@dogsbay/types` light.
14
+ */
15
+ import type { ExportPage, NavItem, SiteConfig } from "./format.js";
16
+ /**
17
+ * Logger handed to plugin hooks. Output is automatically prefixed
18
+ * with the plugin's id so users can attribute messages.
19
+ */
20
+ export interface PluginLogger {
21
+ info(msg: string): void;
22
+ warn(msg: string): void;
23
+ error(msg: string): void;
24
+ debug(msg: string): void;
25
+ }
26
+ /**
27
+ * Read-only context passed to every plugin hook.
28
+ *
29
+ * Plugins MUST NOT mutate `config` directly — return a new config
30
+ * from `extendConfig` to change resolved configuration. The other
31
+ * fields are stable across the build.
32
+ */
33
+ export interface DogsbayPluginContext {
34
+ /**
35
+ * Resolved site configuration — the same shape `dogsbay site
36
+ * build` works against, with defaults applied.
37
+ *
38
+ * Plugins receive this as a snapshot. To modify config, return
39
+ * a new value from `extendConfig`. Hooks fired AFTER
40
+ * `extendConfig` see the modified config.
41
+ */
42
+ readonly config: PluginVisibleConfig;
43
+ /** Absolute path of the directory containing `dogsbay.config.yml`. */
44
+ readonly siteRoot: string;
45
+ /**
46
+ * Absolute path of the generated Astro project. Usually
47
+ * `<siteRoot>/astro`; sometimes `<siteRoot>` when `output: "."`
48
+ * is configured.
49
+ */
50
+ readonly outputDir: string;
51
+ /** Logger prefixed with the plugin's id. */
52
+ readonly logger: PluginLogger;
53
+ /**
54
+ * Build command currently running. Lets plugins skip work that
55
+ * only matters in production builds, or run dev-only diagnostics.
56
+ */
57
+ readonly command: "build" | "dev" | "check";
58
+ }
59
+ /**
60
+ * Subset of the resolved config that plugins are allowed to read.
61
+ *
62
+ * The full `DogsbayConfig` lives in `@dogsbay/cli`; re-exposing it
63
+ * here would cause a circular dep. Plugins typically only need
64
+ * `site` (for name, basePath, etc.) plus the option pieces they
65
+ * declared themselves. Cast through `unknown` if you genuinely need
66
+ * deeper access — that's a deliberate friction point because the
67
+ * shape can change between minor versions.
68
+ */
69
+ export interface PluginVisibleConfig {
70
+ site: SiteConfig;
71
+ /** Free-form access for everything the typed surface omits. */
72
+ [key: string]: unknown;
73
+ }
74
+ /**
75
+ * Audit rule contract — re-stated here to avoid a circular dep
76
+ * between `@dogsbay/types` and `@dogsbay/cli` (where the canonical
77
+ * audit module lives). The shape MUST stay in sync with
78
+ * `packages/cli/src/audit/types.ts` — adapted via a runtime
79
+ * pass-through in the loader.
80
+ */
81
+ export interface PluginRule {
82
+ id: string;
83
+ category: string;
84
+ stage: "source" | "source-corpus" | "dist";
85
+ severity: "error" | "warning";
86
+ description: string;
87
+ /**
88
+ * The audit runner narrows this on the rule's declared `stage`.
89
+ * Plugins import the concrete context types from
90
+ * `@dogsbay/cli/audit` if they need typed access.
91
+ */
92
+ run(ctx: unknown): PluginIssue[];
93
+ }
94
+ export interface PluginIssue {
95
+ ruleId: string;
96
+ severity: "error" | "warning" | "info";
97
+ file: string;
98
+ line?: number;
99
+ message: string;
100
+ context?: string;
101
+ }
102
+ /**
103
+ * Helpers passed to `emitFiles` so plugins don't need to import
104
+ * `node:fs` directly. The runtime resolves all paths relative to
105
+ * `outputDir`.
106
+ */
107
+ export interface EmitFilesHelpers {
108
+ /** Write a UTF-8 / Uint8Array file to `<outputDir>/<relPath>`. */
109
+ writeFile(relPath: string, contents: string | Uint8Array): void;
110
+ /** Recursively copy `srcAbs` (absolute) to `<outputDir>/<destRel>`. */
111
+ copyDir(srcAbs: string, destRel: string): void;
112
+ }
113
+ /**
114
+ * The plugin shape. All fields except `name` are optional; plugins
115
+ * implement only the hooks they need.
116
+ *
117
+ * Lifecycle order during `dogsbay site build`:
118
+ *
119
+ * 1. `extendConfig` — modify resolved config
120
+ * 2. (content import runs)
121
+ * 3. `onContentImported` — mutate pages + nav
122
+ * 4. `transformNav` — sugar for nav-only patches
123
+ * 5. (format-astro emitters run)
124
+ * 6. `emitFiles` — write extra files
125
+ * 7. (client-module / config / style codegen runs)
126
+ * 8. `auditRules` — registered for `site check`
127
+ * 9. (astro.config.mjs codegen)
128
+ *
129
+ * `clientModules`, `styles`, `defineClientConfig`, `componentWrappers`,
130
+ * and `addAstroIntegrations` are queried before the corresponding
131
+ * codegen step; their return value is treated as data, not as a
132
+ * lifecycle hook with side-effect ordering.
133
+ */
134
+ export interface DogsbayPlugin {
135
+ /**
136
+ * npm package name (or local synthetic name). Used in diagnostics
137
+ * and as the default `id` if `id` isn't set.
138
+ */
139
+ name: string;
140
+ /**
141
+ * Plugin instance id. Defaults to `name`. Provide explicitly when
142
+ * the same plugin is loaded twice (e.g. one OpenAPI instance per
143
+ * schema). The loader auto-suffixes (`#1`, `#2`) duplicates if
144
+ * no explicit id is supplied — that's a fallback, not a
145
+ * recommendation.
146
+ */
147
+ id?: string;
148
+ /** Plugin ids that MUST run after this one. */
149
+ before?: string[];
150
+ /** Plugin ids that MUST run before this one. */
151
+ after?: string[];
152
+ extendConfig?(ctx: DogsbayPluginContext): PluginVisibleConfig | Promise<PluginVisibleConfig>;
153
+ onContentImported?(pages: ExportPage[], nav: NavItem[], ctx: DogsbayPluginContext): {
154
+ pages: ExportPage[];
155
+ nav: NavItem[];
156
+ } | Promise<{
157
+ pages: ExportPage[];
158
+ nav: NavItem[];
159
+ }>;
160
+ transformNav?(nav: NavItem[], ctx: DogsbayPluginContext): NavItem[] | Promise<NavItem[]> | undefined;
161
+ emitFiles?(ctx: DogsbayPluginContext & {
162
+ pages: ExportPage[];
163
+ nav: NavItem[];
164
+ } & EmitFilesHelpers): void | Promise<void>;
165
+ /**
166
+ * Absolute paths of `.js` / `.ts` modules to import in the docs
167
+ * layout. Each module is loaded for its side effects and SHOULD
168
+ * listen for `astro:page-load` to handle view transitions.
169
+ */
170
+ clientModules?(ctx: DogsbayPluginContext): string[];
171
+ /**
172
+ * Absolute paths of `.css` files to inject into the layout. Each
173
+ * file is copied into `<outputDir>/src/styles/plugins/` and
174
+ * imported from the global stylesheet.
175
+ */
176
+ styles?(ctx: DogsbayPluginContext): string[];
177
+ /**
178
+ * Build-time → client-time config bridge. The returned value is
179
+ * exposed at `virtual:dogsbay-plugin-config/<plugin-id>` so the
180
+ * client modules can `import config from ".../<plugin-id>"`.
181
+ *
182
+ * The value is JSON-serialized into a TypeScript file at codegen
183
+ * time, so it must be JSON-safe (no functions, classes, or
184
+ * circular refs). Strings, numbers, booleans, arrays, and plain
185
+ * objects are fine.
186
+ */
187
+ defineClientConfig?(ctx: DogsbayPluginContext): unknown;
188
+ /**
189
+ * Wrap a built-in slot. Unlike Starlight (single-string-replaces-
190
+ * everything), wrappers compose: each plugin's wrapper sees the
191
+ * previous wrapper's output via `<slot />`. Order matches plugin
192
+ * declaration order — earlier-declared wrappers are outermost,
193
+ * later-declared wrappers are innermost.
194
+ *
195
+ * Each plugin's wrapper component MUST render a `<slot />` —
196
+ * that's where the inner content lands. The runtime emits a
197
+ * `<Slot>Stack.astro` codegen file that imports each wrapper and
198
+ * recursively nests them; per-page emission uses the stack
199
+ * around the article body.
200
+ *
201
+ * Available slots in v1:
202
+ * - "MarkdownContent" — wraps the page article body
203
+ *
204
+ * Future slots (DocsHeader, Sidebar, TOC, Footer, Pagination)
205
+ * land as plugin demand surfaces.
206
+ *
207
+ * @returns map of slot name → absolute path to the wrapper
208
+ * `.astro` component shipped with the plugin
209
+ */
210
+ componentWrappers?(ctx: DogsbayPluginContext): Record<string, string>;
211
+ auditRules?(ctx: DogsbayPluginContext): PluginRule[];
212
+ /**
213
+ * Astro integrations to register on the generated project. Use
214
+ * for things no Dogsbay hook covers (sitemap, OG image generation,
215
+ * custom Vite plugins). The integrations are appended to the
216
+ * `integrations:` array in `astro.config.mjs` via codegen, so they
217
+ * must be importable from npm package paths — local-file
218
+ * integrations need the plugin to ship them as part of its package.
219
+ */
220
+ addAstroIntegrations?(ctx: DogsbayPluginContext): AstroIntegrationRef[];
221
+ }
222
+ /**
223
+ * Reference to an Astro integration as it should appear in the
224
+ * generated `astro.config.mjs`. Avoids a `@types/astro` dep here.
225
+ *
226
+ * Example:
227
+ * { import: "@astrojs/sitemap", options: { customPages: [] } }
228
+ * → import sitemap from "@astrojs/sitemap";
229
+ * // ...
230
+ * integrations: [..., sitemap({ customPages: [] })]
231
+ */
232
+ export interface AstroIntegrationRef {
233
+ /** Module specifier for the integration's default export. */
234
+ import: string;
235
+ /**
236
+ * Options to pass to the integration factory. Must be JSON-safe;
237
+ * the codegen serializes via `JSON.stringify`. For options that
238
+ * can't be JSON-serialized (functions, etc.), use a thin wrapper
239
+ * package and pass options through `extendConfig` instead.
240
+ */
241
+ options?: unknown;
242
+ /**
243
+ * Optional factory call name. Defaults to the integration's
244
+ * default export. Use when the package's default export is the
245
+ * integration object itself rather than a factory.
246
+ */
247
+ callable?: boolean;
248
+ }
249
+ /**
250
+ * Plugin factory — the default export plugin authors ship.
251
+ *
252
+ * The factory pattern (rather than a plain object) gives plugin
253
+ * authors a place to validate options and stash per-instance state
254
+ * before returning the hook bag.
255
+ */
256
+ export type DogsbayPluginFactory<O = unknown> = (options?: O) => DogsbayPlugin;
257
+ /**
258
+ * Plugin entry as it appears in `dogsbay.config.yml`. Either a bare
259
+ * package name (no options) or a `{ name, id?, options? }` object.
260
+ */
261
+ export type PluginConfigEntry = string | {
262
+ /** npm package name or local path. */
263
+ name: string;
264
+ /** Optional instance id; required when the same plugin appears more than once. */
265
+ id?: string;
266
+ /** Options forwarded to the plugin's factory. */
267
+ options?: unknown;
268
+ };
269
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
package/dist/plugin.js ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Plugin types — the surface third-party plugins target.
3
+ *
4
+ * Design and rationale: plans/plugin-api.md.
5
+ *
6
+ * The interface is deliberately framework-agnostic. Plugins do NOT
7
+ * see the inner workings of the Astro build; they receive parsed
8
+ * pages as TreeNode-bearing `ExportPage[]` and contribute generated
9
+ * outputs (transformed pages, audit rules, client modules, styles,
10
+ * astro integrations) through named hooks.
11
+ *
12
+ * The runtime side (loader, codegen) lives in `packages/cli`. This
13
+ * file owns only the shapes — keeping `@dogsbay/types` light.
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
package/dist/tree.d.ts ADDED
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Universal document tree node.
3
+ *
4
+ * All format loaders (MkDocs, AsciiDoc, DITA, Dogsbay MD) produce TreeNode[].
5
+ * All renderers (ContentRenderer.astro) and exporters consume TreeNode[].
6
+ *
7
+ * This is a semantic model — it captures what content means, not how it was
8
+ * originally written. Format-specific syntax details do not belong here.
9
+ */
10
+ export interface TreeNode {
11
+ /** Semantic node type: "callout", "tabs", "code", "heading", "paragraph", etc. */
12
+ type: string;
13
+ /** Semantic properties. Shape depends on type. */
14
+ props?: Record<string, unknown>;
15
+ /** Pre-rendered HTML content (for inline/prose nodes). */
16
+ html?: string;
17
+ /** Child nodes for container types. */
18
+ children?: TreeNode[];
19
+ /** Structured inline children (replaces html for portable rendering). */
20
+ inline?: InlineNode[];
21
+ /**
22
+ * Arbitrary metadata that travels with the node but does not affect
23
+ * rendering. Loaders can attach source-format hints, provenance info,
24
+ * or processing flags here. Renderers and exporters should ignore
25
+ * keys they do not recognise.
26
+ */
27
+ meta?: Record<string, unknown>;
28
+ }
29
+ /**
30
+ * Inline node — structured representation of inline/rich text content.
31
+ *
32
+ * Inspired by Notion's rich text model: formatting is flat annotations
33
+ * on spans, not nested elements. `{ bold: true, italic: true }` rather
34
+ * than `<strong><em>text</em></strong>`.
35
+ *
36
+ * Links use `children` because link text can contain formatted spans.
37
+ */
38
+ export type InlineNode = InlineText | InlineLink | InlineImage | InlineCode | InlineHighlight | InlineFootnoteRef | InlineKbd | InlineIcon | InlineMath | InlineHtml | InlineBreak;
39
+ /** Text span with flat formatting annotations. */
40
+ export interface InlineText {
41
+ type: "text";
42
+ text: string;
43
+ bold?: boolean;
44
+ italic?: boolean;
45
+ strikethrough?: boolean;
46
+ }
47
+ /** Link wrapping inline children (link text can contain formatting). */
48
+ export interface InlineLink {
49
+ type: "link";
50
+ href: string;
51
+ title?: string;
52
+ children: InlineNode[];
53
+ }
54
+ /** Image (block or inline depending on context). */
55
+ export interface InlineImage {
56
+ type: "image";
57
+ src: string;
58
+ alt?: string;
59
+ title?: string;
60
+ width?: number;
61
+ height?: number;
62
+ }
63
+ /** Inline code span. */
64
+ export interface InlineCode {
65
+ type: "code";
66
+ text: string;
67
+ }
68
+ /** Highlighted/marked text (==text== in Obsidian/pymdownx.mark). */
69
+ export interface InlineHighlight {
70
+ type: "highlight";
71
+ children: InlineNode[];
72
+ }
73
+ /** Footnote reference. */
74
+ export interface InlineFootnoteRef {
75
+ type: "footnote-ref";
76
+ label: string;
77
+ content?: string;
78
+ }
79
+ /** Keyboard shortcut keys. */
80
+ export interface InlineKbd {
81
+ type: "kbd";
82
+ keys: string[];
83
+ }
84
+ /** Inline math: $E=mc^2$ — rendered by app-level math component. */
85
+ export interface InlineMath {
86
+ type: "math";
87
+ latex: string;
88
+ }
89
+ /**
90
+ * Icon or emoji shortcode (e.g. :material-check:, :smile:).
91
+ * Resolved at render time by an IconRegistry.
92
+ */
93
+ export interface InlineIcon {
94
+ type: "icon";
95
+ /** Full shortcode name as written (e.g. "material-check", "smile") */
96
+ name: string;
97
+ /** Icon library: "material" | "fontawesome" | "octicons" | "simple" | "emoji" | "custom" */
98
+ library?: string;
99
+ /** Sub-variant (e.g. "brands", "solid", "regular" for FontAwesome) */
100
+ variant?: string;
101
+ /** Size hint from shortcode (e.g. "16", "24" for Octicons) */
102
+ size?: string;
103
+ /** Attributes from attr_list syntax { .class style="..." } */
104
+ attrs?: Record<string, string>;
105
+ }
106
+ /** Raw HTML escape hatch for unsupported inline types. */
107
+ export interface InlineHtml {
108
+ type: "html-inline";
109
+ html: string;
110
+ }
111
+ /** Line break. */
112
+ export interface InlineBreak {
113
+ type: "break";
114
+ }
115
+ //# sourceMappingURL=tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":"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"}
package/dist/tree.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.js","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@dogsbay/types",
3
+ "version": "0.1.2",
4
+ "description": "Universal document tree model for Dogsbay format loaders and renderers",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "test": "vitest run",
17
+ "test:watch": "vitest"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md"
22
+ ],
23
+ "keywords": [
24
+ "dogsbay",
25
+ "documentation",
26
+ "treenode",
27
+ "types"
28
+ ],
29
+ "devDependencies": {
30
+ "typescript": "^5.7.0",
31
+ "vitest": "^3.0.0"
32
+ },
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/dogsbay/dogsbay.git",
37
+ "directory": "packages/types"
38
+ },
39
+ "homepage": "https://github.com/dogsbay/dogsbay/tree/main/packages/types",
40
+ "bugs": {
41
+ "url": "https://github.com/dogsbay/dogsbay/issues"
42
+ }
43
+ }