nimbus-docs 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli/index.js +49 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/client.d.ts +12 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +38 -6
- package/dist/client.js.map +1 -1
- package/dist/content.d.ts +62 -6
- package/dist/content.d.ts.map +1 -1
- package/dist/content.js +11 -5
- package/dist/content.js.map +1 -1
- package/dist/{diagnostic-C6OaBe_o.d.ts → diagnostic-ewiZxpSO.d.ts} +4 -1
- package/dist/diagnostic-ewiZxpSO.d.ts.map +1 -0
- package/dist/index.d.ts +138 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1709 -174
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +164 -19
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +290 -50
- package/dist/react.js.map +1 -1
- package/dist/{rules-DnAP-j89.js → rules-DDDvKkyJ.js} +250 -2
- package/dist/rules-DDDvKkyJ.js.map +1 -0
- package/dist/schemas.d.ts +87 -4
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +32 -6
- package/dist/schemas.js.map +1 -1
- package/dist/strict-keys-fbKKxxKL.js +141 -0
- package/dist/strict-keys-fbKKxxKL.js.map +1 -0
- package/dist/types.d.ts +49 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -4
- package/CHANGELOG.md +0 -19
- package/dist/diagnostic-C6OaBe_o.d.ts.map +0 -1
- package/dist/rules-DnAP-j89.js.map +0 -1
- package/dist/strict-keys-BiXiT3pq.js +0 -35
- package/dist/strict-keys-BiXiT3pq.js.map +0 -1
package/dist/client.js
CHANGED
|
@@ -111,9 +111,10 @@ const FOCUSABLE = "a[href], button:not([disabled]), input:not([disabled]):not([t
|
|
|
111
111
|
* Used by: Tabs.astro, PackageManagers.astro
|
|
112
112
|
*/
|
|
113
113
|
function initTabs(config) {
|
|
114
|
-
const { container, tabSelector, panelSelector, indicator = null, rovingTabindex = true, sync, onActivate } = config;
|
|
115
|
-
const
|
|
116
|
-
const
|
|
114
|
+
const { container, tabSelector, panelSelector, boundarySelector, indicator = null, rovingTabindex = true, sync, onActivate } = config;
|
|
115
|
+
const owned = (el) => !boundarySelector || el.closest(boundarySelector) === container;
|
|
116
|
+
const tabs = Array.from(container.querySelectorAll(tabSelector)).filter(owned);
|
|
117
|
+
const panels = Array.from(container.querySelectorAll(panelSelector)).filter(owned);
|
|
117
118
|
const tablist = container.querySelector("[role=tablist]") ?? container;
|
|
118
119
|
let currentIndex = -1;
|
|
119
120
|
let isInitialActivation = true;
|
|
@@ -341,6 +342,32 @@ function codeCopy() {
|
|
|
341
342
|
//#endregion
|
|
342
343
|
//#region src/client/heading-anchors.ts
|
|
343
344
|
/** Add hoverable self-links to markdown headings with ids. */
|
|
345
|
+
let liveRegion = null;
|
|
346
|
+
/**
|
|
347
|
+
* Singleton polite live region for the "copied" announcement.
|
|
348
|
+
* Visually hidden via inline styles so the framework doesn't depend on
|
|
349
|
+
* a starter utility class.
|
|
350
|
+
*/
|
|
351
|
+
function announce(message) {
|
|
352
|
+
if (!liveRegion || !liveRegion.isConnected) {
|
|
353
|
+
liveRegion = document.createElement("div");
|
|
354
|
+
liveRegion.setAttribute("aria-live", "polite");
|
|
355
|
+
Object.assign(liveRegion.style, {
|
|
356
|
+
position: "absolute",
|
|
357
|
+
width: "1px",
|
|
358
|
+
height: "1px",
|
|
359
|
+
padding: "0",
|
|
360
|
+
margin: "-1px",
|
|
361
|
+
overflow: "hidden",
|
|
362
|
+
clipPath: "inset(50%)",
|
|
363
|
+
whiteSpace: "nowrap",
|
|
364
|
+
border: "0"
|
|
365
|
+
});
|
|
366
|
+
document.body.appendChild(liveRegion);
|
|
367
|
+
}
|
|
368
|
+
liveRegion.textContent = "";
|
|
369
|
+
liveRegion.textContent = message;
|
|
370
|
+
}
|
|
344
371
|
function applyHeadingAnchors() {
|
|
345
372
|
document.querySelectorAll(".docs-content :is(h2, h3, h4)[id]").forEach((heading) => {
|
|
346
373
|
if (heading.hasAttribute("data-heading-anchor-ready")) return;
|
|
@@ -348,15 +375,20 @@ function applyHeadingAnchors() {
|
|
|
348
375
|
const link = document.createElement("a");
|
|
349
376
|
link.href = `#${heading.id}`;
|
|
350
377
|
link.className = "heading-anchor";
|
|
351
|
-
link.setAttribute("aria-label", `
|
|
378
|
+
link.setAttribute("aria-label", `Copy link to ${heading.textContent?.trim() ?? "section"}`);
|
|
352
379
|
link.textContent = "#";
|
|
380
|
+
link.addEventListener("click", () => {
|
|
381
|
+
const url = new URL(link.getAttribute("href") ?? `#${heading.id}`, location.href).href;
|
|
382
|
+
navigator.clipboard?.writeText(url).then(() => announce("Link copied to clipboard"), () => {});
|
|
383
|
+
});
|
|
353
384
|
heading.appendChild(link);
|
|
354
385
|
});
|
|
355
386
|
}
|
|
356
387
|
/**
|
|
357
388
|
* Add hoverable `#` self-links to all `h2`–`h4` headings in `.docs-content`.
|
|
358
|
-
*
|
|
359
|
-
*
|
|
389
|
+
* Clicking one navigates (hash) *and* copies the absolute deep link, with an
|
|
390
|
+
* `aria-live` announcement for screen readers. Re-runs on `astro:page-load`
|
|
391
|
+
* for View Transitions. Call once (e.g. from BaseLayout).
|
|
360
392
|
*/
|
|
361
393
|
function headingAnchors() {
|
|
362
394
|
applyHeadingAnchors();
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":[],"sources":["../src/client/mount.ts","../src/client/ids.ts","../src/client/disclosure.ts","../src/client/dom.ts","../src/client/tabs-controller.ts","../src/client/scroll-lock.ts","../src/client/code-copy.ts","../src/client/heading-anchors.ts"],"sourcesContent":["/**\n * mount.ts — Discover, mount, and unmount component instances.\n *\n * The single entry point used by every `*.client.ts` to wire its component.\n * Handles three concerns:\n *\n * 1. Initial discovery — finds elements matching `selector` and calls `init`\n * on each, storing the returned teardown.\n * 2. View transitions — on `astro:before-swap`, runs every teardown so\n * document/window listeners come down before the DOM is replaced.\n * 3. Re-mount — on `astro:page-load`, re-runs discovery against the new DOM.\n *\n * The init function receives the root element and returns a `destroy()`\n * function. The root element is the keying mechanism — calling mount again\n * against an already-tracked element is a no-op.\n *\n * Usage:\n *\n * mount(\"[data-nb-collapsible]\", (root) => {\n * const disclosure = makeDisclosure({ ... });\n * return () => disclosure.destroy();\n * });\n */\n\ntype Init = (root: HTMLElement) => () => void;\n\nexport function mount(selector: string, init: Init): void {\n const instances = new Map<HTMLElement, () => void>();\n\n function setup() {\n document.querySelectorAll<HTMLElement>(selector).forEach((el) => {\n if (instances.has(el)) return;\n instances.set(el, init(el));\n });\n }\n\n function teardown() {\n instances.forEach((destroy) => destroy());\n instances.clear();\n }\n\n // Module scripts are deferred, so DOM is parsed by the time this runs.\n // Belt-and-braces check anyway.\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", setup, { once: true });\n } else {\n setup();\n }\n\n document.addEventListener(\"astro:before-swap\", teardown);\n document.addEventListener(\"astro:page-load\", setup);\n}\n","/**\n * Generate a unique ID with a prefix, scoped to the page.\n *\n * Used to build ARIA relationships (`aria-controls` / `aria-labelledby`)\n * between elements that don't have a stable author-provided id.\n */\n\nlet counter = 0;\n\nexport function generateId(prefix: string): string {\n counter += 1;\n return `${prefix}-${counter}`;\n}\n","/**\n * disclosure.ts — Open/close state with ARIA wiring.\n *\n * The shared module for any \"click trigger, reveals content\" pattern.\n * Owns:\n * - open/closed state (in-memory + reflected as `data-nb-state` on both\n * trigger and content)\n * - ARIA: `aria-expanded` on trigger, `aria-controls` linking to content\n * - Click handler on the trigger\n *\n * Animation is intentionally out of scope — CSS targets the `data-nb-state`\n * attribute and runs whatever transition the component wants. Returning\n * a teardown means the caller can clean up on unmount.\n *\n * Used by: Collapsible, and any future Accordion / Sidebar group /\n * dismissable Banner that wants the standard disclosure semantics.\n */\n\nimport { generateId } from \"./ids\";\n\nexport interface DisclosureOptions {\n /** The element users click to toggle. Usually a `<button>`. */\n trigger: HTMLElement;\n /** The element that's shown/hidden. Gets `id` + `data-nb-state`. */\n content: HTMLElement;\n /** Initial open state. Default `false`. */\n defaultOpen?: boolean;\n /** Called whenever open changes. */\n onOpenChange?: (open: boolean) => void;\n}\n\nexport interface DisclosureInstance {\n open(): void;\n close(): void;\n toggle(): void;\n isOpen(): boolean;\n destroy(): void;\n}\n\nexport function makeDisclosure(opts: DisclosureOptions): DisclosureInstance {\n const { trigger, content, defaultOpen = false, onOpenChange } = opts;\n\n let open = defaultOpen;\n\n // Ensure ARIA relationship exists.\n if (!content.id) {\n content.id = generateId(\"nb-disclosure\");\n }\n trigger.setAttribute(\"aria-controls\", content.id);\n\n function syncState() {\n const state = open ? \"open\" : \"closed\";\n trigger.setAttribute(\"data-nb-state\", state);\n content.setAttribute(\"data-nb-state\", state);\n trigger.setAttribute(\"aria-expanded\", String(open));\n }\n\n function setOpen(value: boolean) {\n if (open === value) return;\n open = value;\n syncState();\n onOpenChange?.(value);\n }\n\n function handleClick(e: MouseEvent) {\n e.preventDefault();\n setOpen(!open);\n }\n\n syncState();\n trigger.addEventListener(\"click\", handleClick);\n\n return {\n open() {\n setOpen(true);\n },\n close() {\n setOpen(false);\n },\n toggle() {\n setOpen(!open);\n },\n isOpen() {\n return open;\n },\n destroy() {\n trigger.removeEventListener(\"click\", handleClick);\n },\n };\n}\n","/**\n * Shared DOM constants for client-side interaction primitives.\n */\n\n/** CSS selector for focusable elements within a container. */\nexport const FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([disabled]):not([tabindex=\"-1\"])';\n","/**\n * Shared tab activation primitive.\n *\n * Handles aria-selected, panel visibility, roving tabindex,\n * keyboard navigation, sliding indicator, and cross-instance sync.\n *\n * Used by: Tabs.astro, PackageManagers.astro\n */\n\nimport { FOCUSABLE } from \"./dom\";\n\nexport interface TabsConfig {\n /** Root container holding tabs + panels */\n container: Element;\n /** CSS selector for tab trigger buttons */\n tabSelector: string;\n /** CSS selector for tab panels */\n panelSelector: string;\n /** Optional sliding indicator element */\n indicator?: HTMLElement | null;\n /** Enable roving tabindex + arrow key navigation (default: true) */\n rovingTabindex?: boolean;\n /** Cross-instance persistence config */\n sync?: {\n key: string;\n storage?: \"local\" | \"session\";\n /** Extract sync label from a tab element. Default: textContent.trim() */\n getLabel?: (tab: HTMLElement) => string;\n };\n /** Called after a tab is activated */\n onActivate?: (index: number) => void;\n}\n\nexport interface TabsInstance {\n activate(index: number, options?: { emitSync?: boolean }): void;\n readonly currentIndex: number;\n destroy(): void;\n}\n\nexport function initTabs(config: TabsConfig): TabsInstance {\n const { container, tabSelector, panelSelector, indicator = null, rovingTabindex = true, sync, onActivate } = config;\n\n const tabs = Array.from(container.querySelectorAll<HTMLElement>(tabSelector));\n const panels = Array.from(container.querySelectorAll<HTMLElement>(panelSelector));\n const tablist = container.querySelector(\"[role=tablist]\") ?? container;\n\n let currentIndex = -1;\n let isInitialActivation = true;\n\n function getStorage(kind: \"local\" | \"session\"): Storage | null {\n try {\n return kind === \"session\" ? sessionStorage : localStorage;\n } catch {\n return null;\n }\n }\n\n function getLabel(tab: HTMLElement): string {\n return sync?.getLabel?.(tab) ?? tab.textContent?.trim() ?? \"\";\n }\n\n function updateIndicator(index: number) {\n if (!indicator || !tabs[index]) return;\n indicator.style.left = `${tabs[index].offsetLeft}px`;\n indicator.style.width = `${tabs[index].offsetWidth}px`;\n }\n\n function activate(index: number, options?: { emitSync?: boolean }) {\n const emitSync = options?.emitSync ?? true;\n if (index === currentIndex) return;\n\n // Capture scroll position before DOM changes to prevent layout jump\n const rect = container.getBoundingClientRect();\n const scrollBefore = rect.top;\n\n currentIndex = index;\n\n tabs.forEach((tab, i) => {\n const active = i === index;\n tab.setAttribute(\"aria-selected\", String(active));\n if (rovingTabindex) {\n tab.setAttribute(\"tabindex\", active ? \"0\" : \"-1\");\n }\n });\n\n panels.forEach((panel, i) => {\n const visible = i === index;\n panel.hidden = !visible;\n // Panels with no focusable children need tabindex=\"0\" so keyboard\n // users can Tab into the content (WAI-ARIA Tabs pattern).\n if (visible) {\n const hasFocusable = panel.querySelector(FOCUSABLE) !== null;\n if (!hasFocusable) {\n panel.setAttribute(\"tabindex\", \"0\");\n } else {\n panel.removeAttribute(\"tabindex\");\n }\n }\n });\n\n updateIndicator(index);\n onActivate?.(index);\n\n // Compensate scroll position after panel height change (skip on first paint)\n if (emitSync && !isInitialActivation) {\n const scrollAfter = container.getBoundingClientRect().top;\n const delta = scrollAfter - scrollBefore;\n if (Math.abs(delta) > 1) {\n window.scrollTo({\n top: window.scrollY + delta,\n behavior: \"instant\",\n });\n }\n }\n isInitialActivation = false;\n\n if (sync && emitSync) {\n // `tabs[index]!`: `activate(index)` is only called with validated indices.\n const label = getLabel(tabs[index]!);\n const store = getStorage(sync.storage === \"session\" ? \"session\" : \"local\");\n store?.setItem(sync.key, label);\n window.dispatchEvent(\n new CustomEvent(\"ui-tab-sync\", {\n detail: { key: sync.key, label, origin: container },\n }),\n );\n }\n }\n\n // Resolve initial index from sync storage\n let initialIndex = 0;\n if (sync) {\n const store = getStorage(sync.storage === \"session\" ? \"session\" : \"local\");\n const saved = store?.getItem(sync.key);\n if (saved) {\n const idx = tabs.findIndex((t) => getLabel(t) === saved);\n if (idx >= 0) initialIndex = idx;\n }\n }\n\n // Click delegation on tablist\n function handleClick(e: Event) {\n const target = (e.target as HTMLElement).closest(tabSelector);\n if (!target) return;\n const idx = tabs.indexOf(target as HTMLElement);\n if (idx >= 0) {\n activate(idx);\n if (rovingTabindex) (target as HTMLElement).focus();\n }\n }\n\n // Keyboard navigation (roving tabindex)\n function handleKeydown(e: KeyboardEvent) {\n if (!rovingTabindex) return;\n const ci = tabs.indexOf(e.target as HTMLElement);\n if (ci < 0) return;\n\n let next: number;\n switch (e.key) {\n case \"ArrowRight\":\n next = ci + 1;\n break;\n case \"ArrowLeft\":\n next = ci - 1;\n break;\n case \"Home\":\n next = 0;\n break;\n case \"End\":\n next = tabs.length - 1;\n break;\n default:\n return;\n }\n // No-wrap: ignore if out of bounds\n if (!tabs[next]) return;\n e.preventDefault();\n activate(next);\n // `tabs[next]!`: guard above proves the assertion.\n tabs[next]!.focus();\n }\n\n // Cross-instance sync via CustomEvent\n function handleSync(e: Event) {\n const detail = (e as CustomEvent).detail;\n if (detail.key === sync?.key && detail.origin !== container) {\n const idx = tabs.findIndex((t) => getLabel(t) === detail.label);\n if (idx >= 0) activate(idx, { emitSync: false });\n }\n }\n\n // Wire events\n tablist.addEventListener(\"click\", handleClick);\n tablist.addEventListener(\"keydown\", handleKeydown as EventListener);\n if (sync) window.addEventListener(\"ui-tab-sync\", handleSync);\n\n // Initial activation — skip indicator transition for first paint\n if (indicator) indicator.style.transition = \"none\";\n activate(initialIndex);\n if (indicator) {\n void indicator.offsetHeight; // force reflow\n indicator.style.transition = \"\";\n }\n\n return {\n activate,\n get currentIndex() {\n return currentIndex;\n },\n destroy() {\n tablist.removeEventListener(\"click\", handleClick);\n tablist.removeEventListener(\"keydown\", handleKeydown as EventListener);\n if (sync) window.removeEventListener(\"ui-tab-sync\", handleSync);\n },\n };\n}\n","/**\n * scroll-lock.ts — Body scroll lock with scrollbar-width compensation.\n *\n * Prevents background scrolling when a modal/overlay is open.\n * Compensates for the scrollbar disappearing to avoid layout shift\n * (visible on Windows/Linux where scrollbars have width).\n *\n * Uses a data attribute + CSS for the overflow lock, and inline\n * paddingRight for the scrollbar compensation.\n *\n * Used by: Dialog (and any future overlay primitive).\n */\n\nconst ATTR = \"data-scroll-locked\";\n\nlet lockCount = 0;\nlet savedPaddingRight = \"\";\n\nexport function lockScroll(): void {\n lockCount++;\n if (lockCount > 1) return;\n\n const scrollbarW = window.innerWidth - document.documentElement.clientWidth;\n savedPaddingRight = document.body.style.paddingRight;\n\n document.body.setAttribute(ATTR, \"\");\n if (scrollbarW > 0) {\n document.body.style.paddingRight = `${scrollbarW}px`;\n }\n}\n\nexport function unlockScroll(): void {\n if (lockCount === 0) return;\n lockCount--;\n if (lockCount > 0) return;\n\n document.body.removeAttribute(ATTR);\n document.body.style.paddingRight = savedPaddingRight;\n}\n","/**\n * code-copy.ts — Injects a Nimbus-styled copy button into every Shiki\n * code block rendered by Astro's built-in `<Code>` and fenced\n * code blocks in MDX.\n *\n * Astro emits `<pre class=\"astro-code shiki ...\">` for syntax-highlighted\n * blocks. We attach a copy button positioned in the top-right corner.\n *\n * Page-wide enhancement, not tied to a single component. Call `codeCopy()`\n * once (e.g. from BaseLayout). Uses `mount` for lifecycle so the buttons\n * are torn down on view transitions and re-added against the new DOM.\n *\n * The original code text comes from the `<code>` element's textContent —\n * Shiki's wrapper spans flatten down to the raw source.\n *\n * Code blocks rendered inside [data-cg-row] (CodeGroup) are skipped\n * because CodeGroup brings its own copy button per panel.\n */\n\nimport { mount } from \"./mount\";\n\nconst COPY_ICON = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z\"/></svg>`;\nconst CHECK_ICON = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M173.66,98.34a8,8,0,0,1,0,11.32l-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35A8,8,0,0,1,173.66,98.34Z\"/></svg>`;\n\nfunction getCodeText(pre: HTMLElement): string {\n const codeEl = pre.querySelector<HTMLElement>(\"code\");\n return codeEl?.textContent ?? pre.textContent ?? \"\";\n}\n\nfunction initCodeCopy(pre: HTMLElement): () => void {\n // Skip code blocks owned by CodeGroup. `data-cg-panels-raw` is SSR'd\n // (catches pres before CodeGroup's client script reparents them);\n // `data-cg-row` catches them after reparenting.\n if (pre.closest(\"[data-cg-panels-raw], [data-cg-row]\")) return () => {};\n\n // Append the button to the figure wrapper, not the pre. The pre has\n // `overflow-x: auto`, and absolutely-positioned children of overflow:auto\n // containers slide along with horizontal scroll on iOS Safari. The figure\n // is the non-scrolling wrapper emitted by titleAndLangTransformer.\n const host = (pre.closest(\".nb-code-figure\") as HTMLElement | null) ?? pre;\n\n const btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.className = \"nb-code-copy\";\n btn.setAttribute(\"aria-label\", \"Copy code to clipboard\");\n btn.innerHTML = COPY_ICON;\n\n let resetTimer: number | undefined;\n\n async function handleClick() {\n const text = getCodeText(pre);\n if (!text) return;\n\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n return;\n }\n\n btn.innerHTML = CHECK_ICON;\n btn.dataset.state = \"copied\";\n btn.setAttribute(\"aria-label\", \"Copied!\");\n\n if (resetTimer) window.clearTimeout(resetTimer);\n resetTimer = window.setTimeout(() => {\n btn.innerHTML = COPY_ICON;\n delete btn.dataset.state;\n btn.setAttribute(\"aria-label\", \"Copy code to clipboard\");\n }, 1500);\n }\n\n btn.addEventListener(\"click\", handleClick);\n\n if (getComputedStyle(host).position === \"static\") {\n host.style.position = \"relative\";\n }\n host.appendChild(btn);\n\n return () => {\n if (resetTimer) window.clearTimeout(resetTimer);\n btn.removeEventListener(\"click\", handleClick);\n btn.remove();\n };\n}\n\n/** Wire copy buttons onto all Shiki code blocks on the page. Call once. */\nexport function codeCopy(): void {\n mount(\"pre.astro-code\", initCodeCopy);\n}\n","/** Add hoverable self-links to markdown headings with ids. */\n\nfunction applyHeadingAnchors() {\n document.querySelectorAll<HTMLElement>(\".docs-content :is(h2, h3, h4)[id]\").forEach((heading) => {\n if (heading.hasAttribute(\"data-heading-anchor-ready\")) return;\n heading.setAttribute(\"data-heading-anchor-ready\", \"true\");\n\n const link = document.createElement(\"a\");\n link.href = `#${heading.id}`;\n link.className = \"heading-anchor\";\n link.setAttribute(\"aria-label\", `Link to ${heading.textContent?.trim() ?? \"section\"}`);\n link.textContent = \"#\";\n heading.appendChild(link);\n });\n}\n\n/**\n * Add hoverable `#` self-links to all `h2`–`h4` headings in `.docs-content`.\n * Re-runs on `astro:page-load` for View Transitions. Call once (e.g. from\n * BaseLayout).\n */\nexport function headingAnchors(): void {\n applyHeadingAnchors();\n document.addEventListener(\"astro:page-load\", applyHeadingAnchors);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":[],"sources":["../src/client/mount.ts","../src/client/ids.ts","../src/client/disclosure.ts","../src/client/dom.ts","../src/client/tabs-controller.ts","../src/client/scroll-lock.ts","../src/client/code-copy.ts","../src/client/heading-anchors.ts"],"sourcesContent":["/**\n * mount.ts — Discover, mount, and unmount component instances.\n *\n * The single entry point used by every `*.client.ts` to wire its component.\n * Handles three concerns:\n *\n * 1. Initial discovery — finds elements matching `selector` and calls `init`\n * on each, storing the returned teardown.\n * 2. View transitions — on `astro:before-swap`, runs every teardown so\n * document/window listeners come down before the DOM is replaced.\n * 3. Re-mount — on `astro:page-load`, re-runs discovery against the new DOM.\n *\n * The init function receives the root element and returns a `destroy()`\n * function. The root element is the keying mechanism — calling mount again\n * against an already-tracked element is a no-op.\n *\n * Usage:\n *\n * mount(\"[data-nb-collapsible]\", (root) => {\n * const disclosure = makeDisclosure({ ... });\n * return () => disclosure.destroy();\n * });\n */\n\ntype Init = (root: HTMLElement) => () => void;\n\nexport function mount(selector: string, init: Init): void {\n const instances = new Map<HTMLElement, () => void>();\n\n function setup() {\n document.querySelectorAll<HTMLElement>(selector).forEach((el) => {\n if (instances.has(el)) return;\n instances.set(el, init(el));\n });\n }\n\n function teardown() {\n instances.forEach((destroy) => destroy());\n instances.clear();\n }\n\n // Module scripts are deferred, so DOM is parsed by the time this runs.\n // Belt-and-braces check anyway.\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", setup, { once: true });\n } else {\n setup();\n }\n\n document.addEventListener(\"astro:before-swap\", teardown);\n document.addEventListener(\"astro:page-load\", setup);\n}\n","/**\n * Generate a unique ID with a prefix, scoped to the page.\n *\n * Used to build ARIA relationships (`aria-controls` / `aria-labelledby`)\n * between elements that don't have a stable author-provided id.\n */\n\nlet counter = 0;\n\nexport function generateId(prefix: string): string {\n counter += 1;\n return `${prefix}-${counter}`;\n}\n","/**\n * disclosure.ts — Open/close state with ARIA wiring.\n *\n * The shared module for any \"click trigger, reveals content\" pattern.\n * Owns:\n * - open/closed state (in-memory + reflected as `data-nb-state` on both\n * trigger and content)\n * - ARIA: `aria-expanded` on trigger, `aria-controls` linking to content\n * - Click handler on the trigger\n *\n * Animation is intentionally out of scope — CSS targets the `data-nb-state`\n * attribute and runs whatever transition the component wants. Returning\n * a teardown means the caller can clean up on unmount.\n *\n * Used by: Collapsible, and any future Accordion / Sidebar group /\n * dismissable Banner that wants the standard disclosure semantics.\n */\n\nimport { generateId } from \"./ids\";\n\nexport interface DisclosureOptions {\n /** The element users click to toggle. Usually a `<button>`. */\n trigger: HTMLElement;\n /** The element that's shown/hidden. Gets `id` + `data-nb-state`. */\n content: HTMLElement;\n /** Initial open state. Default `false`. */\n defaultOpen?: boolean;\n /** Called whenever open changes. */\n onOpenChange?: (open: boolean) => void;\n}\n\nexport interface DisclosureInstance {\n open(): void;\n close(): void;\n toggle(): void;\n isOpen(): boolean;\n destroy(): void;\n}\n\nexport function makeDisclosure(opts: DisclosureOptions): DisclosureInstance {\n const { trigger, content, defaultOpen = false, onOpenChange } = opts;\n\n let open = defaultOpen;\n\n // Ensure ARIA relationship exists.\n if (!content.id) {\n content.id = generateId(\"nb-disclosure\");\n }\n trigger.setAttribute(\"aria-controls\", content.id);\n\n function syncState() {\n const state = open ? \"open\" : \"closed\";\n trigger.setAttribute(\"data-nb-state\", state);\n content.setAttribute(\"data-nb-state\", state);\n trigger.setAttribute(\"aria-expanded\", String(open));\n }\n\n function setOpen(value: boolean) {\n if (open === value) return;\n open = value;\n syncState();\n onOpenChange?.(value);\n }\n\n function handleClick(e: MouseEvent) {\n e.preventDefault();\n setOpen(!open);\n }\n\n syncState();\n trigger.addEventListener(\"click\", handleClick);\n\n return {\n open() {\n setOpen(true);\n },\n close() {\n setOpen(false);\n },\n toggle() {\n setOpen(!open);\n },\n isOpen() {\n return open;\n },\n destroy() {\n trigger.removeEventListener(\"click\", handleClick);\n },\n };\n}\n","/**\n * Shared DOM constants for client-side interaction primitives.\n */\n\n/** CSS selector for focusable elements within a container. */\nexport const FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([disabled]):not([tabindex=\"-1\"])';\n","/**\n * Shared tab activation primitive.\n *\n * Handles aria-selected, panel visibility, roving tabindex,\n * keyboard navigation, sliding indicator, and cross-instance sync.\n *\n * Used by: Tabs.astro, PackageManagers.astro\n */\n\nimport { FOCUSABLE } from \"./dom\";\n\nexport interface TabsConfig {\n /** Root container holding tabs + panels */\n container: Element;\n /** CSS selector for tab trigger buttons */\n tabSelector: string;\n /** CSS selector for tab panels */\n panelSelector: string;\n /**\n * Selector identifying a tab container. When set, tabs/panels are scoped\n * to this container only — a descendant belongs to it iff its nearest\n * ancestor matching `boundarySelector` is `container` itself. This keeps\n * a nested `<Tabs>`'s triggers/panels out of the parent instance. When\n * unset, all descendants match `tabSelector`/`panelSelector` are used\n * (no nesting support — the prior behaviour).\n */\n boundarySelector?: string;\n /** Optional sliding indicator element */\n indicator?: HTMLElement | null;\n /** Enable roving tabindex + arrow key navigation (default: true) */\n rovingTabindex?: boolean;\n /** Cross-instance persistence config */\n sync?: {\n key: string;\n storage?: \"local\" | \"session\";\n /** Extract sync label from a tab element. Default: textContent.trim() */\n getLabel?: (tab: HTMLElement) => string;\n };\n /** Called after a tab is activated */\n onActivate?: (index: number) => void;\n}\n\nexport interface TabsInstance {\n activate(index: number, options?: { emitSync?: boolean }): void;\n readonly currentIndex: number;\n destroy(): void;\n}\n\nexport function initTabs(config: TabsConfig): TabsInstance {\n const { container, tabSelector, panelSelector, boundarySelector, indicator = null, rovingTabindex = true, sync, onActivate } = config;\n\n // A descendant belongs to this container only if no nested tab container\n // sits between it and `container` — i.e. its nearest `boundarySelector`\n // ancestor is `container` itself. Without a boundary selector, every\n // match counts (nesting unsupported).\n const owned = (el: HTMLElement) => !boundarySelector || el.closest(boundarySelector) === container;\n const tabs = Array.from(container.querySelectorAll<HTMLElement>(tabSelector)).filter(owned);\n const panels = Array.from(container.querySelectorAll<HTMLElement>(panelSelector)).filter(owned);\n const tablist = container.querySelector(\"[role=tablist]\") ?? container;\n\n let currentIndex = -1;\n let isInitialActivation = true;\n\n function getStorage(kind: \"local\" | \"session\"): Storage | null {\n try {\n return kind === \"session\" ? sessionStorage : localStorage;\n } catch {\n return null;\n }\n }\n\n function getLabel(tab: HTMLElement): string {\n return sync?.getLabel?.(tab) ?? tab.textContent?.trim() ?? \"\";\n }\n\n function updateIndicator(index: number) {\n if (!indicator || !tabs[index]) return;\n indicator.style.left = `${tabs[index].offsetLeft}px`;\n indicator.style.width = `${tabs[index].offsetWidth}px`;\n }\n\n function activate(index: number, options?: { emitSync?: boolean }) {\n const emitSync = options?.emitSync ?? true;\n if (index === currentIndex) return;\n\n // Capture scroll position before DOM changes to prevent layout jump\n const rect = container.getBoundingClientRect();\n const scrollBefore = rect.top;\n\n currentIndex = index;\n\n tabs.forEach((tab, i) => {\n const active = i === index;\n tab.setAttribute(\"aria-selected\", String(active));\n if (rovingTabindex) {\n tab.setAttribute(\"tabindex\", active ? \"0\" : \"-1\");\n }\n });\n\n panels.forEach((panel, i) => {\n const visible = i === index;\n panel.hidden = !visible;\n // Panels with no focusable children need tabindex=\"0\" so keyboard\n // users can Tab into the content (WAI-ARIA Tabs pattern).\n if (visible) {\n const hasFocusable = panel.querySelector(FOCUSABLE) !== null;\n if (!hasFocusable) {\n panel.setAttribute(\"tabindex\", \"0\");\n } else {\n panel.removeAttribute(\"tabindex\");\n }\n }\n });\n\n updateIndicator(index);\n onActivate?.(index);\n\n // Compensate scroll position after panel height change (skip on first paint)\n if (emitSync && !isInitialActivation) {\n const scrollAfter = container.getBoundingClientRect().top;\n const delta = scrollAfter - scrollBefore;\n if (Math.abs(delta) > 1) {\n window.scrollTo({\n top: window.scrollY + delta,\n behavior: \"instant\",\n });\n }\n }\n isInitialActivation = false;\n\n if (sync && emitSync) {\n // `tabs[index]!`: `activate(index)` is only called with validated indices.\n const label = getLabel(tabs[index]!);\n const store = getStorage(sync.storage === \"session\" ? \"session\" : \"local\");\n store?.setItem(sync.key, label);\n window.dispatchEvent(\n new CustomEvent(\"ui-tab-sync\", {\n detail: { key: sync.key, label, origin: container },\n }),\n );\n }\n }\n\n // Resolve initial index from sync storage\n let initialIndex = 0;\n if (sync) {\n const store = getStorage(sync.storage === \"session\" ? \"session\" : \"local\");\n const saved = store?.getItem(sync.key);\n if (saved) {\n const idx = tabs.findIndex((t) => getLabel(t) === saved);\n if (idx >= 0) initialIndex = idx;\n }\n }\n\n // Click delegation on tablist\n function handleClick(e: Event) {\n const target = (e.target as HTMLElement).closest(tabSelector);\n if (!target) return;\n const idx = tabs.indexOf(target as HTMLElement);\n if (idx >= 0) {\n activate(idx);\n if (rovingTabindex) (target as HTMLElement).focus();\n }\n }\n\n // Keyboard navigation (roving tabindex)\n function handleKeydown(e: KeyboardEvent) {\n if (!rovingTabindex) return;\n const ci = tabs.indexOf(e.target as HTMLElement);\n if (ci < 0) return;\n\n let next: number;\n switch (e.key) {\n case \"ArrowRight\":\n next = ci + 1;\n break;\n case \"ArrowLeft\":\n next = ci - 1;\n break;\n case \"Home\":\n next = 0;\n break;\n case \"End\":\n next = tabs.length - 1;\n break;\n default:\n return;\n }\n // No-wrap: ignore if out of bounds\n if (!tabs[next]) return;\n e.preventDefault();\n activate(next);\n // `tabs[next]!`: guard above proves the assertion.\n tabs[next]!.focus();\n }\n\n // Cross-instance sync via CustomEvent\n function handleSync(e: Event) {\n const detail = (e as CustomEvent).detail;\n if (detail.key === sync?.key && detail.origin !== container) {\n const idx = tabs.findIndex((t) => getLabel(t) === detail.label);\n if (idx >= 0) activate(idx, { emitSync: false });\n }\n }\n\n // Wire events\n tablist.addEventListener(\"click\", handleClick);\n tablist.addEventListener(\"keydown\", handleKeydown as EventListener);\n if (sync) window.addEventListener(\"ui-tab-sync\", handleSync);\n\n // Initial activation — skip indicator transition for first paint\n if (indicator) indicator.style.transition = \"none\";\n activate(initialIndex);\n if (indicator) {\n void indicator.offsetHeight; // force reflow\n indicator.style.transition = \"\";\n }\n\n return {\n activate,\n get currentIndex() {\n return currentIndex;\n },\n destroy() {\n tablist.removeEventListener(\"click\", handleClick);\n tablist.removeEventListener(\"keydown\", handleKeydown as EventListener);\n if (sync) window.removeEventListener(\"ui-tab-sync\", handleSync);\n },\n };\n}\n","/**\n * scroll-lock.ts — Body scroll lock with scrollbar-width compensation.\n *\n * Prevents background scrolling when a modal/overlay is open.\n * Compensates for the scrollbar disappearing to avoid layout shift\n * (visible on Windows/Linux where scrollbars have width).\n *\n * Uses a data attribute + CSS for the overflow lock, and inline\n * paddingRight for the scrollbar compensation.\n *\n * Used by: Dialog (and any future overlay primitive).\n */\n\nconst ATTR = \"data-scroll-locked\";\n\nlet lockCount = 0;\nlet savedPaddingRight = \"\";\n\nexport function lockScroll(): void {\n lockCount++;\n if (lockCount > 1) return;\n\n const scrollbarW = window.innerWidth - document.documentElement.clientWidth;\n savedPaddingRight = document.body.style.paddingRight;\n\n document.body.setAttribute(ATTR, \"\");\n if (scrollbarW > 0) {\n document.body.style.paddingRight = `${scrollbarW}px`;\n }\n}\n\nexport function unlockScroll(): void {\n if (lockCount === 0) return;\n lockCount--;\n if (lockCount > 0) return;\n\n document.body.removeAttribute(ATTR);\n document.body.style.paddingRight = savedPaddingRight;\n}\n","/**\n * code-copy.ts — Injects a Nimbus-styled copy button into every Shiki\n * code block rendered by Astro's built-in `<Code>` and fenced\n * code blocks in MDX.\n *\n * Astro emits `<pre class=\"astro-code shiki ...\">` for syntax-highlighted\n * blocks. We attach a copy button positioned in the top-right corner.\n *\n * Page-wide enhancement, not tied to a single component. Call `codeCopy()`\n * once (e.g. from BaseLayout). Uses `mount` for lifecycle so the buttons\n * are torn down on view transitions and re-added against the new DOM.\n *\n * The original code text comes from the `<code>` element's textContent —\n * Shiki's wrapper spans flatten down to the raw source.\n *\n * Code blocks rendered inside [data-cg-row] (CodeGroup) are skipped\n * because CodeGroup brings its own copy button per panel.\n */\n\nimport { mount } from \"./mount\";\n\nconst COPY_ICON = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z\"/></svg>`;\nconst CHECK_ICON = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M173.66,98.34a8,8,0,0,1,0,11.32l-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35A8,8,0,0,1,173.66,98.34Z\"/></svg>`;\n\nfunction getCodeText(pre: HTMLElement): string {\n const codeEl = pre.querySelector<HTMLElement>(\"code\");\n return codeEl?.textContent ?? pre.textContent ?? \"\";\n}\n\nfunction initCodeCopy(pre: HTMLElement): () => void {\n // Skip code blocks owned by CodeGroup. `data-cg-panels-raw` is SSR'd\n // (catches pres before CodeGroup's client script reparents them);\n // `data-cg-row` catches them after reparenting.\n if (pre.closest(\"[data-cg-panels-raw], [data-cg-row]\")) return () => {};\n\n // Append the button to the figure wrapper, not the pre. The pre has\n // `overflow-x: auto`, and absolutely-positioned children of overflow:auto\n // containers slide along with horizontal scroll on iOS Safari. The figure\n // is the non-scrolling wrapper emitted by titleAndLangTransformer.\n const host = (pre.closest(\".nb-code-figure\") as HTMLElement | null) ?? pre;\n\n const btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.className = \"nb-code-copy\";\n btn.setAttribute(\"aria-label\", \"Copy code to clipboard\");\n btn.innerHTML = COPY_ICON;\n\n let resetTimer: number | undefined;\n\n async function handleClick() {\n const text = getCodeText(pre);\n if (!text) return;\n\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n return;\n }\n\n btn.innerHTML = CHECK_ICON;\n btn.dataset.state = \"copied\";\n btn.setAttribute(\"aria-label\", \"Copied!\");\n\n if (resetTimer) window.clearTimeout(resetTimer);\n resetTimer = window.setTimeout(() => {\n btn.innerHTML = COPY_ICON;\n delete btn.dataset.state;\n btn.setAttribute(\"aria-label\", \"Copy code to clipboard\");\n }, 1500);\n }\n\n btn.addEventListener(\"click\", handleClick);\n\n if (getComputedStyle(host).position === \"static\") {\n host.style.position = \"relative\";\n }\n host.appendChild(btn);\n\n return () => {\n if (resetTimer) window.clearTimeout(resetTimer);\n btn.removeEventListener(\"click\", handleClick);\n btn.remove();\n };\n}\n\n/** Wire copy buttons onto all Shiki code blocks on the page. Call once. */\nexport function codeCopy(): void {\n mount(\"pre.astro-code\", initCodeCopy);\n}\n","/** Add hoverable self-links to markdown headings with ids. */\n\nlet liveRegion: HTMLElement | null = null;\n\n/**\n * Singleton polite live region for the \"copied\" announcement.\n * Visually hidden via inline styles so the framework doesn't depend on\n * a starter utility class.\n */\nfunction announce(message: string) {\n if (!liveRegion || !liveRegion.isConnected) {\n liveRegion = document.createElement(\"div\");\n liveRegion.setAttribute(\"aria-live\", \"polite\");\n Object.assign(liveRegion.style, {\n position: \"absolute\",\n width: \"1px\",\n height: \"1px\",\n padding: \"0\",\n margin: \"-1px\",\n overflow: \"hidden\",\n clipPath: \"inset(50%)\",\n whiteSpace: \"nowrap\",\n border: \"0\",\n });\n document.body.appendChild(liveRegion);\n }\n // Clear first so repeating the same message re-announces.\n liveRegion.textContent = \"\";\n liveRegion.textContent = message;\n}\n\nfunction applyHeadingAnchors() {\n document.querySelectorAll<HTMLElement>(\".docs-content :is(h2, h3, h4)[id]\").forEach((heading) => {\n if (heading.hasAttribute(\"data-heading-anchor-ready\")) return;\n heading.setAttribute(\"data-heading-anchor-ready\", \"true\");\n\n const link = document.createElement(\"a\");\n link.href = `#${heading.id}`;\n link.className = \"heading-anchor\";\n link.setAttribute(\"aria-label\", `Copy link to ${heading.textContent?.trim() ?? \"section\"}`);\n link.textContent = \"#\";\n\n // Copy the deep link on click. Default navigation is preserved so\n // the URL bar updates; the clipboard write rides alongside. No-op\n // outside secure contexts.\n link.addEventListener(\"click\", () => {\n const url = new URL(link.getAttribute(\"href\") ?? `#${heading.id}`, location.href).href;\n navigator.clipboard?.writeText(url).then(\n () => announce(\"Link copied to clipboard\"),\n () => {},\n );\n });\n\n heading.appendChild(link);\n });\n}\n\n/**\n * Add hoverable `#` self-links to all `h2`–`h4` headings in `.docs-content`.\n * Clicking one navigates (hash) *and* copies the absolute deep link, with an\n * `aria-live` announcement for screen readers. Re-runs on `astro:page-load`\n * for View Transitions. Call once (e.g. from BaseLayout).\n */\nexport function headingAnchors(): void {\n applyHeadingAnchors();\n document.addEventListener(\"astro:page-load\", applyHeadingAnchors);\n}\n"],"mappings":"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"}
|
package/dist/content.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComponentProp, DefineSchemaOptions, DocSchemaConfig, componentsSchema, defineDocSchema, defineSchema, docsSchema, partialsSchema } from "./schemas.js";
|
|
1
|
+
import { ComponentProp, DefineSchemaOptions, DocSchemaConfig, componentsSchema, defineDocSchema, definePartialsSchema, defineSchema, docsSchema, partialsSchema } from "./schemas.js";
|
|
2
2
|
import { z } from "astro/zod";
|
|
3
3
|
import * as astro_loaders0 from "astro/loaders";
|
|
4
4
|
|
|
@@ -25,7 +25,7 @@ interface DocsCollectionOptions<TFields extends Record<string, z.ZodTypeAny> = R
|
|
|
25
25
|
*/
|
|
26
26
|
schemaFields?: TFields;
|
|
27
27
|
}
|
|
28
|
-
interface PartialsCollectionOptions {
|
|
28
|
+
interface PartialsCollectionOptions<TFields extends Record<string, z.ZodTypeAny> = Record<string, never>> {
|
|
29
29
|
/**
|
|
30
30
|
* Directory under `src/content/` to load partials from.
|
|
31
31
|
* Default: `"partials"`.
|
|
@@ -36,6 +36,13 @@ interface PartialsCollectionOptions {
|
|
|
36
36
|
* Default: `"** /*.{md,mdx}"`.
|
|
37
37
|
*/
|
|
38
38
|
pattern?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Extra frontmatter fields merged into the default partials schema.
|
|
41
|
+
* Useful for partials with product-specific metadata (e.g. CF's
|
|
42
|
+
* `inputParameters`). Same generic-preserving shape as
|
|
43
|
+
* `DocsCollectionOptions.schemaFields`.
|
|
44
|
+
*/
|
|
45
|
+
schemaFields?: TFields;
|
|
39
46
|
}
|
|
40
47
|
/**
|
|
41
48
|
* Returns an Astro content-collection config (`{ loader, schema }`) for the
|
|
@@ -43,7 +50,7 @@ interface PartialsCollectionOptions {
|
|
|
43
50
|
*/
|
|
44
51
|
declare function docsCollection<TFields extends Record<string, z.ZodTypeAny> = Record<string, never>>(options?: DocsCollectionOptions<TFields>): {
|
|
45
52
|
loader: astro_loaders0.Loader;
|
|
46
|
-
schema: z.ZodObject<(("prev" | "next" | "title" | "description" | "mode" | "sidebar" | "head" | "banner" | "draft" | "noindex" | "searchable" | "tableOfContents" | "lastUpdated" | "socialImage" | "previousSlug") & keyof TFields extends never ? {
|
|
53
|
+
schema: z.ZodObject<(("prev" | "next" | "title" | "description" | "mode" | "sidebar" | "head" | "banner" | "draft" | "noindex" | "searchable" | "tableOfContents" | "lastUpdated" | "socialImage" | "previousSlug" | "external_link") & keyof TFields extends never ? {
|
|
47
54
|
title: z.ZodString;
|
|
48
55
|
description: z.ZodOptional<z.ZodString>;
|
|
49
56
|
mode: z.ZodDefault<z.ZodEnum<{
|
|
@@ -68,13 +75,33 @@ declare function docsCollection<TFields extends Record<string, z.ZodTypeAny> = R
|
|
|
68
75
|
}, z.core.$strip>]>>;
|
|
69
76
|
hidden: z.ZodOptional<z.ZodBoolean>;
|
|
70
77
|
hideChildren: z.ZodOptional<z.ZodBoolean>;
|
|
78
|
+
group: z.ZodOptional<z.ZodObject<{
|
|
79
|
+
label: z.ZodOptional<z.ZodString>;
|
|
80
|
+
badge: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
81
|
+
text: z.ZodString;
|
|
82
|
+
variant: z.ZodDefault<z.ZodEnum<{
|
|
83
|
+
success: "success";
|
|
84
|
+
default: "default";
|
|
85
|
+
info: "info";
|
|
86
|
+
note: "note";
|
|
87
|
+
tip: "tip";
|
|
88
|
+
warning: "warning";
|
|
89
|
+
caution: "caution";
|
|
90
|
+
danger: "danger";
|
|
91
|
+
}>>;
|
|
92
|
+
}, z.core.$strip>]>>;
|
|
93
|
+
hideIndex: z.ZodOptional<z.ZodBoolean>;
|
|
94
|
+
}, z.core.$strip>>;
|
|
71
95
|
}, z.core.$strip>]>>;
|
|
72
96
|
head: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
73
97
|
tag: z.ZodEnum<{
|
|
98
|
+
title: "title";
|
|
74
99
|
meta: "meta";
|
|
75
100
|
link: "link";
|
|
76
101
|
script: "script";
|
|
77
102
|
style: "style";
|
|
103
|
+
noscript: "noscript";
|
|
104
|
+
base: "base";
|
|
78
105
|
}>;
|
|
79
106
|
attrs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
80
107
|
content: z.ZodOptional<z.ZodString>;
|
|
@@ -110,6 +137,7 @@ declare function docsCollection<TFields extends Record<string, z.ZodTypeAny> = R
|
|
|
110
137
|
label: z.ZodOptional<z.ZodString>;
|
|
111
138
|
}, z.core.$strip>, z.ZodLiteral<false>]>>;
|
|
112
139
|
previousSlug: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
140
|
+
external_link: z.ZodOptional<z.ZodString>;
|
|
113
141
|
} & { -readonly [P in keyof TFields]: TFields[P] } : ({
|
|
114
142
|
title: z.ZodString;
|
|
115
143
|
description: z.ZodOptional<z.ZodString>;
|
|
@@ -135,13 +163,33 @@ declare function docsCollection<TFields extends Record<string, z.ZodTypeAny> = R
|
|
|
135
163
|
}, z.core.$strip>]>>;
|
|
136
164
|
hidden: z.ZodOptional<z.ZodBoolean>;
|
|
137
165
|
hideChildren: z.ZodOptional<z.ZodBoolean>;
|
|
166
|
+
group: z.ZodOptional<z.ZodObject<{
|
|
167
|
+
label: z.ZodOptional<z.ZodString>;
|
|
168
|
+
badge: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
169
|
+
text: z.ZodString;
|
|
170
|
+
variant: z.ZodDefault<z.ZodEnum<{
|
|
171
|
+
success: "success";
|
|
172
|
+
default: "default";
|
|
173
|
+
info: "info";
|
|
174
|
+
note: "note";
|
|
175
|
+
tip: "tip";
|
|
176
|
+
warning: "warning";
|
|
177
|
+
caution: "caution";
|
|
178
|
+
danger: "danger";
|
|
179
|
+
}>>;
|
|
180
|
+
}, z.core.$strip>]>>;
|
|
181
|
+
hideIndex: z.ZodOptional<z.ZodBoolean>;
|
|
182
|
+
}, z.core.$strip>>;
|
|
138
183
|
}, z.core.$strip>]>>;
|
|
139
184
|
head: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
140
185
|
tag: z.ZodEnum<{
|
|
186
|
+
title: "title";
|
|
141
187
|
meta: "meta";
|
|
142
188
|
link: "link";
|
|
143
189
|
script: "script";
|
|
144
190
|
style: "style";
|
|
191
|
+
noscript: "noscript";
|
|
192
|
+
base: "base";
|
|
145
193
|
}>;
|
|
146
194
|
attrs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
147
195
|
content: z.ZodOptional<z.ZodString>;
|
|
@@ -177,15 +225,23 @@ declare function docsCollection<TFields extends Record<string, z.ZodTypeAny> = R
|
|
|
177
225
|
label: z.ZodOptional<z.ZodString>;
|
|
178
226
|
}, z.core.$strip>, z.ZodLiteral<false>]>>;
|
|
179
227
|
previousSlug: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
228
|
+
external_link: z.ZodOptional<z.ZodString>;
|
|
180
229
|
} extends infer T_1 extends z.core.util.SomeObject ? { [K in keyof T_1 as K extends keyof TFields ? never : K]: T_1[K] } : never) & { [K_1 in keyof { -readonly [P in keyof TFields]: TFields[P] }]: { -readonly [P in keyof TFields]: TFields[P] }[K_1] }) extends infer T ? { [k in keyof T]: T[k] } : never, z.core.$strip>;
|
|
181
230
|
};
|
|
182
231
|
/**
|
|
183
232
|
* Returns an Astro content-collection config (`{ loader, schema }`) for the
|
|
184
233
|
* partials collection. Pass to `defineCollection()`.
|
|
234
|
+
*
|
|
235
|
+
* `schemaFields` extends the default partials schema with extra
|
|
236
|
+
* frontmatter — same shape as `docsCollection({ schemaFields })`.
|
|
185
237
|
*/
|
|
186
|
-
declare function partialsCollection(options?: PartialsCollectionOptions): {
|
|
238
|
+
declare function partialsCollection<TFields extends Record<string, z.ZodTypeAny> = Record<string, never>>(options?: PartialsCollectionOptions<TFields>): {
|
|
187
239
|
loader: astro_loaders0.Loader;
|
|
188
|
-
schema: z.
|
|
240
|
+
schema: z.ZodObject<("params" & keyof TFields extends never ? {
|
|
241
|
+
params: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
242
|
+
} & { -readonly [P in keyof TFields]: TFields[P] } : ({
|
|
243
|
+
params: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
244
|
+
} extends infer T_1 extends z.core.util.SomeObject ? { [K in keyof T_1 as K extends keyof TFields ? never : K]: T_1[K] } : never) & { [K_1 in keyof { -readonly [P in keyof TFields]: TFields[P] }]: { -readonly [P in keyof TFields]: TFields[P] }[K_1] }) extends infer T ? { [k in keyof T]: T[k] } : never, z.core.$strip> | z.ZodDefault<z.ZodObject<{
|
|
189
245
|
params: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
190
246
|
}, z.core.$strip>>;
|
|
191
247
|
};
|
|
@@ -224,5 +280,5 @@ declare function componentsCollection(options?: ComponentsCollectionOptions): {
|
|
|
224
280
|
}, z.core.$strip>;
|
|
225
281
|
};
|
|
226
282
|
//#endregion
|
|
227
|
-
export { type ComponentProp, ComponentsCollectionOptions, type DefineSchemaOptions, type DocSchemaConfig, DocsCollectionOptions, PartialsCollectionOptions, componentsCollection, componentsSchema, defineDocSchema, defineSchema, docsCollection, docsSchema, partialsCollection, partialsSchema };
|
|
283
|
+
export { type ComponentProp, ComponentsCollectionOptions, type DefineSchemaOptions, type DocSchemaConfig, DocsCollectionOptions, PartialsCollectionOptions, componentsCollection, componentsSchema, defineDocSchema, definePartialsSchema, defineSchema, docsCollection, docsSchema, partialsCollection, partialsSchema };
|
|
228
284
|
//# sourceMappingURL=content.d.ts.map
|
package/dist/content.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.d.ts","names":[],"sources":["../src/content.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"content.d.ts","names":[],"sources":["../src/content.ts"],"mappings":";;;;;UA0CiB,qBAAA,iBACC,MAAA,SAAe,CAAA,CAAE,UAAA,IAAc,MAAA;EAqBzB;;AAGxB;;EAlBE,IAAA;EAmBiC;;;;EAdjC,OAAA;EAgCsB;;;;;;;;;EAtBtB,YAAA,GAAe,OAAA;AAAA;AAAA,UAGA,yBAAA,iBACC,MAAA,SAAe,CAAA,CAAE,UAAA,IAAc,MAAA;EA2BjC;;;;EArBd,IAAA;EAsB+C;;;;EAjB/C,OAAA;;;;;;;EAOA,YAAA,GAAe,OAAA;AAAA;;;;;iBASD,cAAA,iBACE,MAAA,SAAe,CAAA,CAAE,UAAA,IAAc,MAAA,gBAAA,CAC/C,OAAA,GAAS,qBAAA,CAAsB,OAAA;UAAD,cAAA,CAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkBhB,kBAAA,iBACE,MAAA,SAAe,CAAA,CAAE,UAAA,IAAc,MAAA,gBAAA,CAC/C,OAAA,GAAS,yBAAA,CAA0B,OAAA;UAAD,cAAA,CAAA,MAAA;;;;;;;;;UAgBnB,2BAAA;;;;;EAKf,IAAA;;;;;EAKA,OAAA;AAAA;;;;;;;;;iBAWc,oBAAA,CAAqB,OAAA,GAAS,2BAAA;UAAgC,cAAA,CAAA,MAAA"}
|
package/dist/content.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { componentsSchema, defineDocSchema, defineSchema, docsSchema, partialsSchema } from "./schemas.js";
|
|
1
|
+
import { componentsSchema, defineDocSchema, definePartialsSchema, defineSchema, docsSchema, partialsSchema } from "./schemas.js";
|
|
2
2
|
import { glob } from "astro/loaders";
|
|
3
3
|
|
|
4
4
|
//#region src/content.ts
|
|
@@ -41,14 +41,20 @@ function docsCollection(options = {}) {
|
|
|
41
41
|
/**
|
|
42
42
|
* Returns an Astro content-collection config (`{ loader, schema }`) for the
|
|
43
43
|
* partials collection. Pass to `defineCollection()`.
|
|
44
|
+
*
|
|
45
|
+
* `schemaFields` extends the default partials schema with extra
|
|
46
|
+
* frontmatter — same shape as `docsCollection({ schemaFields })`.
|
|
44
47
|
*/
|
|
45
48
|
function partialsCollection(options = {}) {
|
|
49
|
+
const base = `./src/content/${options.base ?? "partials"}`;
|
|
50
|
+
const pattern = options.pattern ?? DEFAULT_PATTERN;
|
|
51
|
+
const schema = options.schemaFields ? definePartialsSchema({ fields: options.schemaFields }) : partialsSchema;
|
|
46
52
|
return {
|
|
47
53
|
loader: glob({
|
|
48
|
-
base
|
|
49
|
-
pattern
|
|
54
|
+
base,
|
|
55
|
+
pattern
|
|
50
56
|
}),
|
|
51
|
-
schema
|
|
57
|
+
schema
|
|
52
58
|
};
|
|
53
59
|
}
|
|
54
60
|
/**
|
|
@@ -70,5 +76,5 @@ function componentsCollection(options = {}) {
|
|
|
70
76
|
}
|
|
71
77
|
|
|
72
78
|
//#endregion
|
|
73
|
-
export { componentsCollection, componentsSchema, defineDocSchema, defineSchema, docsCollection, docsSchema, partialsCollection, partialsSchema };
|
|
79
|
+
export { componentsCollection, componentsSchema, defineDocSchema, definePartialsSchema, defineSchema, docsCollection, docsSchema, partialsCollection, partialsSchema };
|
|
74
80
|
//# sourceMappingURL=content.js.map
|
package/dist/content.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.js","names":[],"sources":["../src/content.ts"],"sourcesContent":["/**\n * Content collection helpers for `nimbus-docs/content`.\n *\n * Users plug these into their `src/content.config.ts`:\n *\n * import { defineCollection } from \"astro:content\";\n * import { docsCollection, partialsCollection } from \"nimbus-docs/content\";\n *\n * export const collections = {\n * docs: defineCollection(docsCollection()),\n * partials: defineCollection(partialsCollection()),\n * };\n *\n * Extend the docs schema with extra frontmatter fields:\n *\n * docs: defineCollection(docsCollection({\n * schemaFields: { author: z.string(), tags: z.array(z.string()) },\n * })),\n */\n\nimport { glob } from \"astro/loaders\";\nimport type { z } from \"astro/zod\";\n\nimport {
|
|
1
|
+
{"version":3,"file":"content.js","names":[],"sources":["../src/content.ts"],"sourcesContent":["/**\n * Content collection helpers for `nimbus-docs/content`.\n *\n * Users plug these into their `src/content.config.ts`:\n *\n * import { defineCollection } from \"astro:content\";\n * import { docsCollection, partialsCollection } from \"nimbus-docs/content\";\n *\n * export const collections = {\n * docs: defineCollection(docsCollection()),\n * partials: defineCollection(partialsCollection()),\n * };\n *\n * Extend the docs schema with extra frontmatter fields:\n *\n * docs: defineCollection(docsCollection({\n * schemaFields: { author: z.string(), tags: z.array(z.string()) },\n * })),\n */\n\nimport { glob } from \"astro/loaders\";\nimport type { z } from \"astro/zod\";\n\nimport {\n componentsSchema,\n defineDocSchema,\n definePartialsSchema,\n partialsSchema,\n} from \"./schemas.js\";\n\n// Re-export the public schema factories from `nimbus-docs/content` so users\n// have a single import for content-config concerns (collections + schemas).\nexport {\n defineDocSchema,\n definePartialsSchema,\n defineSchema,\n docsSchema,\n partialsSchema,\n componentsSchema,\n} from \"./schemas.js\";\nexport type { DefineSchemaOptions, DocSchemaConfig, ComponentProp } from \"./schemas.js\";\n\nexport interface DocsCollectionOptions<\n TFields extends Record<string, z.ZodTypeAny> = Record<string, never>,\n> {\n /**\n * Directory under `src/content/` to load docs from.\n * Default: `\"docs\"`.\n */\n base?: string;\n /**\n * Glob pattern relative to `base`.\n * Default: `\"** /*.{md,mdx}\"` (space added to avoid breaking this comment).\n */\n pattern?: string;\n /**\n * Extra fields merged into the default docs schema. Lets users add\n * project-specific frontmatter (author, tags, etc.) without rebuilding\n * the whole schema.\n *\n * Generic-typed so the call-site shape (`{ author: z.string() }`) is\n * preserved through to the emitted entry data type — `entry.data.author`\n * resolves to `string`, not `unknown`.\n */\n schemaFields?: TFields;\n}\n\nexport interface PartialsCollectionOptions<\n TFields extends Record<string, z.ZodTypeAny> = Record<string, never>,\n> {\n /**\n * Directory under `src/content/` to load partials from.\n * Default: `\"partials\"`.\n */\n base?: string;\n /**\n * Glob pattern relative to `base`.\n * Default: `\"** /*.{md,mdx}\"`.\n */\n pattern?: string;\n /**\n * Extra frontmatter fields merged into the default partials schema.\n * Useful for partials with product-specific metadata (e.g. CF's\n * `inputParameters`). Same generic-preserving shape as\n * `DocsCollectionOptions.schemaFields`.\n */\n schemaFields?: TFields;\n}\n\nconst DEFAULT_PATTERN = \"**/*.{md,mdx}\";\n\n/**\n * Returns an Astro content-collection config (`{ loader, schema }`) for the\n * docs collection. Pass to `defineCollection()`.\n */\nexport function docsCollection<\n TFields extends Record<string, z.ZodTypeAny> = Record<string, never>,\n>(options: DocsCollectionOptions<TFields> = {}) {\n const base = `./src/content/${options.base ?? \"docs\"}`;\n const pattern = options.pattern ?? DEFAULT_PATTERN;\n const schema = defineDocSchema({ fields: options.schemaFields });\n\n return {\n loader: glob({ base, pattern }),\n schema,\n };\n}\n\n/**\n * Returns an Astro content-collection config (`{ loader, schema }`) for the\n * partials collection. Pass to `defineCollection()`.\n *\n * `schemaFields` extends the default partials schema with extra\n * frontmatter — same shape as `docsCollection({ schemaFields })`.\n */\nexport function partialsCollection<\n TFields extends Record<string, z.ZodTypeAny> = Record<string, never>,\n>(options: PartialsCollectionOptions<TFields> = {}) {\n const base = `./src/content/${options.base ?? \"partials\"}`;\n const pattern = options.pattern ?? DEFAULT_PATTERN;\n // Avoid re-deriving the schema when no fields were declared — keeps the\n // default behaviour (`partialsSchema` with its `.default({})`) exact for\n // existing users who don't opt in.\n const schema = options.schemaFields\n ? definePartialsSchema({ fields: options.schemaFields })\n : partialsSchema;\n\n return {\n loader: glob({ base, pattern }),\n schema,\n };\n}\n\nexport interface ComponentsCollectionOptions {\n /**\n * Directory under `src/content/` to load component entries from.\n * Default: `\"components\"`.\n */\n base?: string;\n /**\n * Glob pattern relative to `base`.\n * Default: `\"**\\/*.{md,mdx}\"`.\n */\n pattern?: string;\n}\n\n/**\n * Returns an Astro content-collection config (`{ loader, schema }`) for the\n * components collection — for sites documenting their own UI components.\n *\n * Pairs with the `component-showcase` registry recipe, which installs the\n * matching `<Showcase>` / `<Example>` MDX wrappers and the `/components`\n * route. Frontmatter shape: `{ title, tagline, props }`.\n */\nexport function componentsCollection(options: ComponentsCollectionOptions = {}) {\n const base = `./src/content/${options.base ?? \"components\"}`;\n const pattern = options.pattern ?? DEFAULT_PATTERN;\n\n return {\n loader: glob({ base, pattern }),\n schema: componentsSchema,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAyFA,MAAM,kBAAkB;;;;;AAMxB,SAAgB,eAEd,UAA0C,EAAE,EAAE;CAC9C,MAAM,OAAO,iBAAiB,QAAQ,QAAQ;CAC9C,MAAM,UAAU,QAAQ,WAAW;CACnC,MAAM,SAAS,gBAAgB,EAAE,QAAQ,QAAQ,cAAc,CAAC;AAEhE,QAAO;EACL,QAAQ,KAAK;GAAE;GAAM;GAAS,CAAC;EAC/B;EACD;;;;;;;;;AAUH,SAAgB,mBAEd,UAA8C,EAAE,EAAE;CAClD,MAAM,OAAO,iBAAiB,QAAQ,QAAQ;CAC9C,MAAM,UAAU,QAAQ,WAAW;CAInC,MAAM,SAAS,QAAQ,eACnB,qBAAqB,EAAE,QAAQ,QAAQ,cAAc,CAAC,GACtD;AAEJ,QAAO;EACL,QAAQ,KAAK;GAAE;GAAM;GAAS,CAAC;EAC/B;EACD;;;;;;;;;;AAwBH,SAAgB,qBAAqB,UAAuC,EAAE,EAAE;AAI9E,QAAO;EACL,QAAQ,KAAK;GAAE,MAJJ,iBAAiB,QAAQ,QAAQ;GAIvB,SAHP,QAAQ,WAAW;GAGH,CAAC;EAC/B,QAAQ;EACT"}
|
|
@@ -45,6 +45,9 @@ declare const RULE_CODES: {
|
|
|
45
45
|
readonly "nimbus/internal-link": {
|
|
46
46
|
readonly kind: "authoring";
|
|
47
47
|
};
|
|
48
|
+
readonly "nimbus/image-ref": {
|
|
49
|
+
readonly kind: "authoring";
|
|
50
|
+
};
|
|
48
51
|
readonly "nimbus/orphan-page": {
|
|
49
52
|
readonly kind: "authoring";
|
|
50
53
|
};
|
|
@@ -130,4 +133,4 @@ interface Diagnostic {
|
|
|
130
133
|
}
|
|
131
134
|
//#endregion
|
|
132
135
|
export { Severity as a, RuleCode as i, Diagnostic as n, SeverityConfig as o, DiagnosticFix as r, AuthoringRuleCode as t };
|
|
133
|
-
//# sourceMappingURL=diagnostic-
|
|
136
|
+
//# sourceMappingURL=diagnostic-ewiZxpSO.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostic-ewiZxpSO.d.ts","names":[],"sources":["../src/lint/diagnostic.ts"],"mappings":";;AAyBA;;;;;;;;;;;;;;;;;;;;;;;cAAa,UAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2BD,QAAA,gBAAwB,UAAA;;;;;AAgCpC;;;KAvBY,iBAAA,WACJ,QAAA,WAAmB,UAAA,EAAY,CAAA;EAAa,IAAA;AAAA,IAC9C,CAAA,WAEJ,QAAA;;;KAIU,QAAA;;KAGA,cAAA,GAAiB,QAAA;AAAA,UAEZ,aAAA;EAkBf;EAhBA,WAAA;EAoBA;;;;EAfA,KAAA,EAAO,KAAA;IAAQ,KAAA;IAAyB,IAAA;EAAA;AAAA;AAAA,UAGzB,UAAA;EACf,IAAA,EAAM,QAAA;EACN,QAAA,EAAU,QAAA;;;EAGV,MAAA;EACA,OAAA;;EAEA,IAAA;;EAEA,IAAA;;EAEA,MAAA;EACA,OAAA;EACA,SAAA;EACA,GAAA,GAAM,aAAA;AAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { o as SeverityConfig, t as AuthoringRuleCode } from "./diagnostic-
|
|
1
|
+
import { o as SeverityConfig, t as AuthoringRuleCode } from "./diagnostic-ewiZxpSO.js";
|
|
2
2
|
import { BadgeVariant, Breadcrumb, NimbusConfig, PrevNext, PrevNextLink, PrevNextOverrides, ResolvedVersions, SearchProvider, SearchResult, SidebarBadge, SidebarConfig, SidebarConfigItem, SidebarExternalLinkItem, SidebarGroupItem, SidebarItem, SidebarLinkItem, SidebarSection, TOCItem, VersionAlternateRecord, VersionAlternatesTable, VersionPageRef, VersionStatus, VersionsConfig } from "./types.js";
|
|
3
3
|
import mdx from "@astrojs/mdx";
|
|
4
4
|
import * as astro_content0 from "astro:content";
|
|
@@ -85,12 +85,83 @@ interface CollectionLintConfig {
|
|
|
85
85
|
*/
|
|
86
86
|
type CollectionsConfig = Record<string, CollectionLintConfig>;
|
|
87
87
|
//#endregion
|
|
88
|
+
//#region src/_internal/incremental/partial-refs.d.ts
|
|
89
|
+
/**
|
|
90
|
+
* Partial resolver hook. Called for every component opening tag scanner
|
|
91
|
+
* encounters in MDX content. Returns the absolute file path of the partial
|
|
92
|
+
* the component embeds, or null if the component isn't a partial-embedder
|
|
93
|
+
* (Tabs, Aside, etc.) or the props don't match a known pattern.
|
|
94
|
+
*
|
|
95
|
+
* Pattern borrowed from mvvmm's cloudflare-docs PR — supports the
|
|
96
|
+
* multi-prop case (`<Render file="setup" product="workers" />` →
|
|
97
|
+
* `partials/workers/setup.mdx`) that single-prop string regex can't
|
|
98
|
+
* capture.
|
|
99
|
+
*/
|
|
100
|
+
type PartialResolverHook = (componentName: string, props: Record<string, string>) => string | null;
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/_internal/incremental/sitemap.d.ts
|
|
103
|
+
/** Mirror of `@astrojs/sitemap`'s `SitemapItem` shape. */
|
|
104
|
+
interface SitemapItem {
|
|
105
|
+
url: string;
|
|
106
|
+
lastmod?: string;
|
|
107
|
+
changefreq?: "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
|
|
108
|
+
priority?: number;
|
|
109
|
+
links?: {
|
|
110
|
+
lang: string;
|
|
111
|
+
url: string;
|
|
112
|
+
}[];
|
|
113
|
+
}
|
|
114
|
+
type SitemapSerialize = (item: SitemapItem) => SitemapItem | undefined | null | Promise<SitemapItem | undefined | null>;
|
|
115
|
+
//#endregion
|
|
88
116
|
//#region src/integration.d.ts
|
|
117
|
+
interface SitemapOptions {
|
|
118
|
+
serialize?: SitemapSerialize;
|
|
119
|
+
customPages?: string[];
|
|
120
|
+
}
|
|
89
121
|
interface NimbusIntegrationOptions {
|
|
90
122
|
/** MDX options forwarded to `@astrojs/mdx`. */
|
|
91
123
|
mdx?: Parameters<typeof mdx>[0];
|
|
92
|
-
/**
|
|
93
|
-
|
|
124
|
+
/**
|
|
125
|
+
* Sitemap behavior. Defaults: enabled when `site.url` is set, default
|
|
126
|
+
* `@astrojs/sitemap` output. `false` disables it. Pass an object to
|
|
127
|
+
* customise — currently `serialize` and `customPages` are supported, and
|
|
128
|
+
* they apply both when incremental builds are on (we emit the sitemap
|
|
129
|
+
* ourselves so cached routes appear) and when incremental is off (we
|
|
130
|
+
* forward them to `@astrojs/sitemap`).
|
|
131
|
+
*
|
|
132
|
+
* The `serialize` callback runs once per URL and may return modified
|
|
133
|
+
* fields (e.g. `lastmod` from git) or `null`/`undefined` to drop the
|
|
134
|
+
* URL. Cloudflare-docs's pattern of git-sourced `lastmod` is the
|
|
135
|
+
* motivating case.
|
|
136
|
+
*/
|
|
137
|
+
sitemap?: boolean | SitemapOptions;
|
|
138
|
+
/**
|
|
139
|
+
* Override the markdown processor Nimbus wires into Astro's
|
|
140
|
+
* `markdown.processor`. Default is Sätteri (Rust-based, fast).
|
|
141
|
+
*
|
|
142
|
+
* Pass a different processor when you need remark/rehype plugin
|
|
143
|
+
* extensibility — Sätteri disables `mdx({ remarkPlugins })` because it
|
|
144
|
+
* replaces unified's pipeline. The escape hatch:
|
|
145
|
+
*
|
|
146
|
+
* ```ts
|
|
147
|
+
* import { unified } from "@astrojs/markdown-remark";
|
|
148
|
+
* import remarkToc from "remark-toc";
|
|
149
|
+
*
|
|
150
|
+
* nimbus(config, {
|
|
151
|
+
* markdown: {
|
|
152
|
+
* processor: unified({ remarkPlugins: [remarkToc] }),
|
|
153
|
+
* },
|
|
154
|
+
* });
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
157
|
+
* Trade-off: the Sätteri performance win goes away. Worth it for sites
|
|
158
|
+
* that depend on unified-ecosystem plugins (CF docs uses seven).
|
|
159
|
+
*
|
|
160
|
+
* @default `satteri()`
|
|
161
|
+
*/
|
|
162
|
+
markdown?: {
|
|
163
|
+
/** Custom Astro `markdown.processor`. Imported from `@astrojs/markdown-remark` (unified), `@astrojs/markdown-satteri` (default), or any compatible processor. */processor?: unknown;
|
|
164
|
+
};
|
|
94
165
|
/**
|
|
95
166
|
* Build-time MDX PascalCase tag validation.
|
|
96
167
|
*
|
|
@@ -115,6 +186,30 @@ interface NimbusIntegrationOptions {
|
|
|
115
186
|
contentDirs?: string[];
|
|
116
187
|
skip?: (filePath: string) => boolean;
|
|
117
188
|
};
|
|
189
|
+
/**
|
|
190
|
+
* Rewrite `:::type[title]` fenced directives to `<Aside>` components
|
|
191
|
+
* in MDX/MD source before the markdown compiler sees them. Built-in
|
|
192
|
+
* types: `note`, `info`, `tip`, `caution`, `warning`, `important`,
|
|
193
|
+
* `danger` (mapped to Nimbus's 4 Aside slots).
|
|
194
|
+
*
|
|
195
|
+
* - `true` (default): rewrite against `src/content/**\/*.{md,mdx}`.
|
|
196
|
+
* - `false`: skip the transform; `:::` syntax renders as literal text.
|
|
197
|
+
* - `{ typeAliases }`: extra type → Aside mappings for product
|
|
198
|
+
* synonyms (`{ heads: "tip" }`).
|
|
199
|
+
* - `{ contentDirs }`: override the scanned directories.
|
|
200
|
+
* - `{ skip }`: per-file opt-out.
|
|
201
|
+
*
|
|
202
|
+
* Runs as a Vite plugin (content pass) so it survives the
|
|
203
|
+
* `markdown.processor` swap that disables remark plugins under
|
|
204
|
+
* Sätteri. Aside must be in the user's `src/components.ts` globals
|
|
205
|
+
* registry — the default starter exports it; if your registry doesn't,
|
|
206
|
+
* the MDX validator surfaces a clean build error.
|
|
207
|
+
*/
|
|
208
|
+
admonitions?: boolean | {
|
|
209
|
+
typeAliases?: Record<string, "note" | "tip" | "caution" | "danger">;
|
|
210
|
+
contentDirs?: string[];
|
|
211
|
+
skip?: (filePath: string) => boolean;
|
|
212
|
+
};
|
|
118
213
|
/**
|
|
119
214
|
* Authoring-lint severity overrides for `nimbus-docs lint`. Maps a rule
|
|
120
215
|
* code to `"error" | "warn" | "off"` or a `[severity, options]` tuple.
|
|
@@ -138,6 +233,46 @@ interface NimbusIntegrationOptions {
|
|
|
138
233
|
* }
|
|
139
234
|
*/
|
|
140
235
|
collections?: CollectionsConfig;
|
|
236
|
+
/**
|
|
237
|
+
* Opt into per-page build caching. When `true`, Nimbus wraps Astro's
|
|
238
|
+
* prerenderer and short-circuits cache hits with previously-rendered HTML.
|
|
239
|
+
*
|
|
240
|
+
* Phase 2 MVP — preview-quality:
|
|
241
|
+
* - Per-page cache keyed on file bytes + a global hash of tracked
|
|
242
|
+
* sources (config, components, layouts, lockfile).
|
|
243
|
+
* - No partial-dependency tracking yet — editing a partial triggers a
|
|
244
|
+
* full rebuild (because it doesn't change the page's bytes but it
|
|
245
|
+
* does need to invalidate dependents). Phase 3 closes this gap.
|
|
246
|
+
* - No cache provenance / namespace isolation / trust boundary.
|
|
247
|
+
* Manual `rm -rf .nimbus/cache` between framework upgrades.
|
|
248
|
+
*
|
|
249
|
+
* Default: `false`. The bench (`apps/incremental-bench`) is the only
|
|
250
|
+
* site that should set this today.
|
|
251
|
+
*/
|
|
252
|
+
incrementalBuilds?: boolean;
|
|
253
|
+
/**
|
|
254
|
+
* Custom partial resolver for incremental builds. Called for every
|
|
255
|
+
* PascalCase component opening tag found in MDX content with string-
|
|
256
|
+
* literal props. Return the absolute file path of the partial the
|
|
257
|
+
* component embeds, or `null` to indicate this component isn't a
|
|
258
|
+
* partial-embedder.
|
|
259
|
+
*
|
|
260
|
+
* The default resolver covers the standard `<Render file="topic/slug" />`
|
|
261
|
+
* pattern shipping with Nimbus's starter. Sites with multi-prop
|
|
262
|
+
* conventions need their own — cloudflare-docs is the motivating case:
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* partialResolver: (name, props) => {
|
|
266
|
+
* if (name !== "Render" || !props.file) return null;
|
|
267
|
+
* if (props.product) {
|
|
268
|
+
* return resolve(projectRoot, `src/content/partials/${props.product}/${props.file}.mdx`);
|
|
269
|
+
* }
|
|
270
|
+
* return resolve(projectRoot, `src/content/partials/${props.file}.mdx`);
|
|
271
|
+
* }
|
|
272
|
+
*
|
|
273
|
+
* Required only when `incrementalBuilds: true`. Ignored otherwise.
|
|
274
|
+
*/
|
|
275
|
+
partialResolver?: PartialResolverHook;
|
|
141
276
|
}
|
|
142
277
|
declare function nimbus(rawConfig: NimbusConfig, options?: NimbusIntegrationOptions): AstroIntegration;
|
|
143
278
|
//#endregion
|