nimbus-docs 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +42 -28
- package/dist/cli/index.js.map +1 -1
- package/dist/content.d.ts +0 -2
- package/dist/content.d.ts.map +1 -1
- package/dist/{diagnostic-ewiZxpSO.d.ts → diagnostic-CnxJwVpT.d.ts} +5 -6
- package/dist/diagnostic-CnxJwVpT.d.ts.map +1 -0
- package/dist/index.d.ts +40 -46
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +93 -115
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +7 -7
- package/dist/react.js +6 -6
- package/dist/react.js.map +1 -1
- package/dist/{rules-DDDvKkyJ.js → rules-CzB-afEb.js} +7 -11
- package/dist/rules-CzB-afEb.js.map +1 -0
- package/dist/schemas.d.ts +0 -3
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +9 -22
- package/dist/schemas.js.map +1 -1
- package/dist/types.d.ts +11 -9
- package/dist/types.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/components/NimbusHead.astro +1 -1
- package/dist/diagnostic-ewiZxpSO.d.ts.map +0 -1
- package/dist/rules-DDDvKkyJ.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { o as validateLintOptions, r as suggest, t as IMPLEMENTED_CODES } from "./rules-
|
|
1
|
+
import { o as validateLintOptions, r as suggest, t as IMPLEMENTED_CODES } from "./rules-CzB-afEb.js";
|
|
2
2
|
import { i as toRouteKey, n as isAbsoluteUrl, r as toBrowserHref, t as withStrictKeys } from "./strict-keys-fbKKxxKL.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { execFile } from "node:child_process";
|
|
@@ -118,28 +118,16 @@ function slug(value, maintainCase) {
|
|
|
118
118
|
* Mirror of Astro's content-layer slug normalization, used by every
|
|
119
119
|
* framework URL builder that derives a URL from an `entry.id`.
|
|
120
120
|
*
|
|
121
|
-
* Astro's `glob` content loader
|
|
122
|
-
* `partialsCollection` factories) runs each path segment through
|
|
121
|
+
* Astro's `glob` content loader runs each path segment through
|
|
123
122
|
* `github-slugger.slug()` and strips a trailing `/index`. That output is
|
|
124
|
-
* what `entry.id` becomes
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* clean way to read Astro's resolved routes. The honest architectural fix
|
|
133
|
-
* is to refactor those builders to consume the route manifest at
|
|
134
|
-
* `astro:routes:resolved` (sitemap/llms) or via a build-emitted lookup
|
|
135
|
-
* table (sidebar). Until that work lands, this helper keeps the URLs
|
|
136
|
-
* correct.
|
|
137
|
-
*
|
|
138
|
-
* Mirror caveat: this matches `github-slugger.slug()` and the trailing-
|
|
139
|
-
* /index strip — the documented public-library behaviors Astro inherits
|
|
140
|
-
* — not Astro's private routing internals. If a user supplies a custom
|
|
141
|
-
* `generateId` to the content loader, or a `data.slug` override in
|
|
142
|
-
* frontmatter, this helper doesn't see it. Both are uncommon.
|
|
123
|
+
* what `entry.id` becomes and what `params.slug` substitutes into
|
|
124
|
+
* `[...slug].astro` routes, so anything building a URL from the raw
|
|
125
|
+
* filesystem path must apply the same normalization to match what Astro
|
|
126
|
+
* serves.
|
|
127
|
+
*
|
|
128
|
+
* Caveat: this matches `github-slugger.slug()` and the trailing-/index
|
|
129
|
+
* strip, not a custom loader `generateId` or a `data.slug` frontmatter
|
|
130
|
+
* override — neither of which this helper sees.
|
|
143
131
|
*/
|
|
144
132
|
/** Canonicalize one entry id the way Astro's content layer does. */
|
|
145
133
|
function canonicalSlug(entryId) {
|
|
@@ -489,12 +477,9 @@ function hasActivePage(item, currentPath) {
|
|
|
489
477
|
* URL prefix* — e.g. `Components` mounted at `/components/` —
|
|
490
478
|
* rather than a sub-directory of the primary docs collection.
|
|
491
479
|
*
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
* header rail is meant for "other collections" navigation, not for
|
|
496
|
-
* sub-sections of the default collection — those belong in the
|
|
497
|
-
* sidebar's own collapsible tree.
|
|
480
|
+
* Sub-directories of the primary collection (`wip/`, `lab/`, etc.) are
|
|
481
|
+
* deliberately excluded — the header rail is for cross-collection
|
|
482
|
+
* navigation; sub-sections belong in the sidebar's own tree.
|
|
498
483
|
*
|
|
499
484
|
* Caller must pass the *un-scoped* tree (the result of
|
|
500
485
|
* `buildSidebarTree`, not `getSidebar`); otherwise only the current
|
|
@@ -557,16 +542,13 @@ function applyDefaultCollapsed(items) {
|
|
|
557
542
|
}
|
|
558
543
|
}
|
|
559
544
|
/**
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
*
|
|
565
|
-
*
|
|
566
|
-
*
|
|
567
|
-
* Renamed only when the first link IS the group's index (matched via the
|
|
568
|
-
* `sortKeyByItem` WeakMap) — under structural separation that condition
|
|
569
|
-
* never holds, so this silently returns the input unchanged.
|
|
545
|
+
* Relabel a section's landing link to the `overviewLabel` string (default
|
|
546
|
+
* "Overview"). Applies to a `directory:` autogenerate's leading landing
|
|
547
|
+
* link wherever it surfaces (tracked via `directoryIndexLinks`), and to a
|
|
548
|
+
* group whose first child link IS the group's own index (matched via the
|
|
549
|
+
* `sortKeyByItem` WeakMap). Config groups expose their index as the group
|
|
550
|
+
* label itself (`SidebarGroupItem.indexHref`), so those aren't relabelled
|
|
551
|
+
* here — there's no separate child link to rename.
|
|
570
552
|
*/
|
|
571
553
|
function applyOverviewLabel(items, label) {
|
|
572
554
|
for (const item of items) if (item.type === "link" && directoryIndexLinks.has(item)) item.label = label;
|
|
@@ -1025,7 +1007,7 @@ async function getLastUpdatedFromGit(filePath) {
|
|
|
1025
1007
|
|
|
1026
1008
|
//#endregion
|
|
1027
1009
|
//#region src/_internal/admonition-transform.ts
|
|
1028
|
-
/** Built-in MyST / Docusaurus
|
|
1010
|
+
/** Built-in MyST / Docusaurus admonition types and their Aside mapping. */
|
|
1029
1011
|
const BUILTIN_TYPES = {
|
|
1030
1012
|
note: "note",
|
|
1031
1013
|
info: "note",
|
|
@@ -1856,9 +1838,9 @@ async function validateMdxContent(options) {
|
|
|
1856
1838
|
* Format a list of failures into a single multi-line error message
|
|
1857
1839
|
* suitable for `throw new Error(...)`.
|
|
1858
1840
|
*/
|
|
1859
|
-
function formatFailures(failures
|
|
1841
|
+
function formatFailures(failures) {
|
|
1860
1842
|
const lines = failures.map((f) => {
|
|
1861
|
-
const fix = f.hint ? `Did you mean <${f.hint} />?` :
|
|
1843
|
+
const fix = f.hint ? `Did you mean <${f.hint} />?` : `Register it in src/components.ts, or add an explicit \`import\` at the top of this file.`;
|
|
1862
1844
|
return ` ${f.filePath}:${f.line}:${f.column} <${f.tag} /> → ${fix}`;
|
|
1863
1845
|
});
|
|
1864
1846
|
return `[nimbus-docs] Unknown MDX component ${failures.length === 1 ? "tag" : "tags"}:\n` + lines.join("\n") + "\n\nA PascalCase tag in MDX must either be registered in src/components.ts (the global registry) or imported at the top of the file. Without either, MDX renders the tag as literal text on the page — a silent failure this validator turns into a build error.";
|
|
@@ -2086,7 +2068,7 @@ function validateNimbusConfig(input) {
|
|
|
2086
2068
|
const tail = received === null ? "" : `\n received: ${received}`;
|
|
2087
2069
|
return ` - ${display}: ${issue.message}${tail}`;
|
|
2088
2070
|
}).join("\n");
|
|
2089
|
-
throw new Error(`Invalid nimbus.config — fix these issues:\n${issues}\n\nSee https://nimbus-docs.
|
|
2071
|
+
throw new Error(`Invalid nimbus.config — fix these issues:\n${issues}\n\nSee https://nimbus-docs.com/config for the full config schema.`);
|
|
2090
2072
|
}
|
|
2091
2073
|
/**
|
|
2092
2074
|
* Resolve the value at `path` inside the raw input and format it for an
|
|
@@ -2134,18 +2116,11 @@ function virtualConfigPlugin(config, extras) {
|
|
|
2134
2116
|
* inside `.md` / `.mdx` files. Output feeds `shikiConfig.langs` so Shiki
|
|
2135
2117
|
* eager-loads every grammar at startup instead of lazy-loading on first use.
|
|
2136
2118
|
*
|
|
2137
|
-
*
|
|
2138
|
-
*
|
|
2139
|
-
*
|
|
2140
|
-
*
|
|
2141
|
-
*
|
|
2142
|
-
* without highlighting.
|
|
2143
|
-
*
|
|
2144
|
-
* Eager loading also gives non-incremental users a small predictability win:
|
|
2145
|
-
* the highlighter behaves the same regardless of which file is processed
|
|
2146
|
-
* first.
|
|
2147
|
-
*
|
|
2148
|
-
* Cost: ~1s on a 7k-file bench. Acceptable.
|
|
2119
|
+
* Needed because incremental builds skip cached MDX files: those never
|
|
2120
|
+
* enter the markdown pipeline, so a language appearing only in cached
|
|
2121
|
+
* files would never trigger Shiki's lazy grammar load, and a non-cached
|
|
2122
|
+
* file using it would render without highlighting. Eager loading also
|
|
2123
|
+
* keeps highlighting independent of which file is processed first.
|
|
2149
2124
|
*/
|
|
2150
2125
|
const FENCE_RE = /^[ \t]*```([a-zA-Z][a-zA-Z0-9_+\-]*)/gm;
|
|
2151
2126
|
async function* walkMdx(dir) {
|
|
@@ -2200,16 +2175,23 @@ async function scanCodeBlockLanguages(projectRoot, langAlias = {}) {
|
|
|
2200
2175
|
* pages/<aa>/<full-hash>.html — cached HTML body for a page, sharded
|
|
2201
2176
|
* by the first 2 hex chars of the hash
|
|
2202
2177
|
*
|
|
2203
|
-
*
|
|
2204
|
-
*
|
|
2205
|
-
*
|
|
2206
|
-
*
|
|
2178
|
+
* Atomic per-file writes. A manifest-level `namespace` field provides
|
|
2179
|
+
* PR-vs-main isolation; resolution lives in `namespace.ts`. Framework/Node
|
|
2180
|
+
* version is folded into `globalHash` via `computeGlobalHash` already, so
|
|
2181
|
+
* it doesn't need a separate field.
|
|
2207
2182
|
*/
|
|
2208
2183
|
const SCHEMA_VERSION = 2;
|
|
2209
2184
|
var Cache = class {
|
|
2210
2185
|
root;
|
|
2211
|
-
|
|
2212
|
-
|
|
2186
|
+
/**
|
|
2187
|
+
* @param root Absolute path to the cache directory. Callers resolve this —
|
|
2188
|
+
* by default the incremental layer roots it under Astro's own `cacheDir`
|
|
2189
|
+
* (`node_modules/.astro/nimbus`) so it travels with the framework cache
|
|
2190
|
+
* every host already persists between builds (Cloudflare, Vercel,
|
|
2191
|
+
* Netlify, GitHub Actions). Falls back to `<projectRoot>/.nimbus/cache`.
|
|
2192
|
+
*/
|
|
2193
|
+
constructor(root) {
|
|
2194
|
+
this.root = root;
|
|
2213
2195
|
}
|
|
2214
2196
|
pagePath(hash) {
|
|
2215
2197
|
return resolve(this.root, "pages", hash.slice(0, 2), `${hash}.html`);
|
|
@@ -2265,14 +2247,13 @@ var Cache = class {
|
|
|
2265
2247
|
/**
|
|
2266
2248
|
* Snapshot a *bounded subset* of `dist/_astro/` into the cache.
|
|
2267
2249
|
*
|
|
2268
|
-
*
|
|
2269
|
-
*
|
|
2270
|
-
*
|
|
2271
|
-
* the set of asset rel-paths that some cached HTML actually references —
|
|
2250
|
+
* Bounded so the cache doesn't grow forever: Vite emits new bundle
|
|
2251
|
+
* hashes whenever the module graph differs between builds. The caller
|
|
2252
|
+
* passes the asset rel-paths that some cached HTML actually references;
|
|
2272
2253
|
* anything outside that set gets dropped.
|
|
2273
2254
|
*
|
|
2274
2255
|
* `referencedRelPaths` should be the union of every `/_astro/...` URL
|
|
2275
|
-
* extracted from cached HTML — see `
|
|
2256
|
+
* extracted from cached HTML — see `collectReferencedAssets` in index.ts.
|
|
2276
2257
|
*/
|
|
2277
2258
|
async snapshotAssets(distAstroDir, referencedRelPaths) {
|
|
2278
2259
|
const target = resolve(this.root, "assets");
|
|
@@ -2441,10 +2422,9 @@ async function writeAtomic(path, data) {
|
|
|
2441
2422
|
* - pageHash: sha256(page bytes + globalHash). Determines whether a
|
|
2442
2423
|
* given page's cached HTML is still valid.
|
|
2443
2424
|
*
|
|
2444
|
-
*
|
|
2445
|
-
*
|
|
2446
|
-
*
|
|
2447
|
-
* to capture `<Render file="…">` references.
|
|
2425
|
+
* Current scope deliberately omits data-collection tracking and
|
|
2426
|
+
* component-graph tracking. Partial-dependency tracking folds the partial
|
|
2427
|
+
* registry into the page hash (see `partial-refs.ts`).
|
|
2448
2428
|
*/
|
|
2449
2429
|
const TRACKED_DIRS = ["src", "public"];
|
|
2450
2430
|
const TRACKED_FILES = [
|
|
@@ -2507,7 +2487,7 @@ async function walk$1(dir, root) {
|
|
|
2507
2487
|
* - Node major version (minor diffs occasionally affect bundling)
|
|
2508
2488
|
* - Platform + arch (some asset emission is platform-sensitive)
|
|
2509
2489
|
*
|
|
2510
|
-
* Including provenance closes
|
|
2490
|
+
* Including provenance closes a class of staleness bug: a framework upgrade
|
|
2511
2491
|
* (or Node bump, or OS change) silently changed rendered output but the
|
|
2512
2492
|
* old global hash matched, so warm builds served stale entries from a
|
|
2513
2493
|
* different version of the world.
|
|
@@ -2576,7 +2556,7 @@ async function readDepVersion(projectRoot, dep) {
|
|
|
2576
2556
|
}
|
|
2577
2557
|
}
|
|
2578
2558
|
/**
|
|
2579
|
-
*
|
|
2559
|
+
* Per-page hash with transitive partial dependencies folded in.
|
|
2580
2560
|
*
|
|
2581
2561
|
* Same shape as `computePageHash` but additionally absorbs the bytes of
|
|
2582
2562
|
* every partial the page transitively embeds. Sorted by path so two
|
|
@@ -2660,14 +2640,14 @@ async function resolveCacheNamespace(projectRoot) {
|
|
|
2660
2640
|
//#endregion
|
|
2661
2641
|
//#region src/_internal/incremental/partial-refs.ts
|
|
2662
2642
|
/**
|
|
2663
|
-
*
|
|
2643
|
+
* Partial dependency tracking.
|
|
2664
2644
|
*
|
|
2665
2645
|
* Walks MDX content to find `<Render file="…" />` and `<Render slug="…" />`
|
|
2666
2646
|
* references, then builds a per-page transitive closure: "pathname X
|
|
2667
2647
|
* embeds partials A, B, C — where A in turn embeds D, and B in turn
|
|
2668
2648
|
* embeds E and F." Folding all of those partials' bytes into the page's
|
|
2669
|
-
* hash gives us the property
|
|
2670
|
-
*
|
|
2649
|
+
* hash gives us the property we want: edit one partial, exactly the pages
|
|
2650
|
+
* that transitively embed it re-render.
|
|
2671
2651
|
*
|
|
2672
2652
|
* Scope (v1):
|
|
2673
2653
|
* - Only string-literal `file` / `slug` props get captured. Dynamic
|
|
@@ -2676,16 +2656,17 @@ async function resolveCacheNamespace(projectRoot) {
|
|
|
2676
2656
|
* v1 limitation; the `partialResolver` hook (deferred) gives sites
|
|
2677
2657
|
* an escape valve.
|
|
2678
2658
|
* - Default resolver: `<Render file="topic/slug" />` resolves to
|
|
2679
|
-
* `src/content/partials/topic/slug.mdx`.
|
|
2680
|
-
*
|
|
2681
|
-
*
|
|
2659
|
+
* `src/content/partials/topic/slug.mdx`. Sites with a multi-prop
|
|
2660
|
+
* convention (e.g. a resolver that prepends a `product` prop) need a
|
|
2661
|
+
* custom resolver.
|
|
2682
2662
|
* - Cycles in the partial graph are handled (visited set).
|
|
2683
2663
|
*/
|
|
2684
2664
|
/**
|
|
2685
2665
|
* Check `candidate` is a normalised path under `rootWithSep`. Cheap
|
|
2686
2666
|
* defense against `../` traversal escaping the partials root. We use a
|
|
2687
2667
|
* trailing-sep marker on root to avoid false-matching `partialsRoot` with
|
|
2688
|
-
*
|
|
2668
|
+
* sibling directories that share its name as a prefix (e.g.
|
|
2669
|
+
* `partialsRoot-shared/`).
|
|
2689
2670
|
*/
|
|
2690
2671
|
function isInside(candidate, rootWithSep) {
|
|
2691
2672
|
return candidate.startsWith(rootWithSep) || candidate === rootWithSep.slice(0, -1);
|
|
@@ -2708,7 +2689,7 @@ const ATTR_RE = /([a-zA-Z][a-zA-Z0-9_]*)\s*=\s*["']([^"']*)["']/g;
|
|
|
2708
2689
|
* extensions or use plain Markdown for partials.
|
|
2709
2690
|
*
|
|
2710
2691
|
* `partialsBase` lets callers point the resolver at a non-default partials
|
|
2711
|
-
* collection base
|
|
2692
|
+
* collection base. Default: `src/content/partials`.
|
|
2712
2693
|
*/
|
|
2713
2694
|
function makeDefaultPartialResolver(projectRoot, partialsBase = "src/content/partials") {
|
|
2714
2695
|
const partialsRoot = resolve(projectRoot, partialsBase);
|
|
@@ -2877,7 +2858,7 @@ async function partialsDirExists(projectRoot, partialsBase = "src/content/partia
|
|
|
2877
2858
|
//#endregion
|
|
2878
2859
|
//#region src/_internal/incremental/index.ts
|
|
2879
2860
|
/**
|
|
2880
|
-
* Incremental builds
|
|
2861
|
+
* Incremental builds.
|
|
2881
2862
|
*
|
|
2882
2863
|
* Wires the cache layer into Astro's prerenderer. On warm build, pages whose
|
|
2883
2864
|
* source bytes (and the global hash) haven't changed since the last build
|
|
@@ -2886,16 +2867,14 @@ async function partialsDirExists(projectRoot, partialsBase = "src/content/partia
|
|
|
2886
2867
|
*
|
|
2887
2868
|
* Astro sees every route in `getStaticPaths` either way — cache hits flow
|
|
2888
2869
|
* through `astro:build:generated`, adapter writers, route-headers accounting
|
|
2889
|
-
* exactly like fresh renders. This is
|
|
2890
|
-
* `getStaticPaths
|
|
2891
|
-
*
|
|
2870
|
+
* exactly like fresh renders. This is by design — rather than filtering
|
|
2871
|
+
* cached routes out of `getStaticPaths`, which would hide them from
|
|
2872
|
+
* downstream hooks.
|
|
2892
2873
|
*
|
|
2893
|
-
*
|
|
2894
|
-
* - Partial-dependency tracking. Edit a partial → still full rebuild today.
|
|
2874
|
+
* Out of scope for now:
|
|
2895
2875
|
* - Data-collection scoping.
|
|
2896
2876
|
* - Component-graph tracking. Any tracked-file change → full rebuild.
|
|
2897
|
-
* -
|
|
2898
|
-
* - `nimbus build --explain` and structured build reports. Console log only.
|
|
2877
|
+
* - `nimbus build --explain` and structured build reports.
|
|
2899
2878
|
*/
|
|
2900
2879
|
/**
|
|
2901
2880
|
* Normalise a request URL to its canonical pathname (no trailing slash,
|
|
@@ -2914,7 +2893,7 @@ function canonicalisePathname(input) {
|
|
|
2914
2893
|
}
|
|
2915
2894
|
/**
|
|
2916
2895
|
* Build a map from pathname → MDX file bytes by walking the docs collection
|
|
2917
|
-
* directory.
|
|
2896
|
+
* directory. Only the primary `docs` collection is handled.
|
|
2918
2897
|
*
|
|
2919
2898
|
* Pathname derivation: `src/content/docs/<entry.id>.mdx` → `/<entry.id>`,
|
|
2920
2899
|
* mirroring `getDocsStaticPaths` which uses `entry.id` verbatim as slug.
|
|
@@ -3012,12 +2991,12 @@ async function collectDocsPages(projectRoot, docsBase = "src/content/docs") {
|
|
|
3012
2991
|
* Computes per-page hashes, reads prior manifest, determines which pages
|
|
3013
2992
|
* are cache-hits.
|
|
3014
2993
|
*
|
|
3015
|
-
*
|
|
3016
|
-
*
|
|
3017
|
-
*
|
|
2994
|
+
* The page hash includes the bytes of every partial the page transitively
|
|
2995
|
+
* embeds, so editing a partial invalidates exactly the pages that reference
|
|
2996
|
+
* it (directly or transitively) and nothing else.
|
|
3018
2997
|
*/
|
|
3019
|
-
async function setupIncrementalContext(projectRoot, logger, partialResolver) {
|
|
3020
|
-
const cache = new Cache(projectRoot);
|
|
2998
|
+
async function setupIncrementalContext(projectRoot, cacheDir, logger, partialResolver) {
|
|
2999
|
+
const cache = new Cache(cacheDir ? resolve(cacheDir, "nimbus") : resolve(projectRoot, ".nimbus/cache"));
|
|
3021
3000
|
const globalHash = await computeGlobalHash(projectRoot);
|
|
3022
3001
|
const namespace = await resolveCacheNamespace(projectRoot);
|
|
3023
3002
|
const priorManifest = await cache.readManifest();
|
|
@@ -3074,7 +3053,7 @@ async function setupIncrementalContext(projectRoot, logger, partialResolver) {
|
|
|
3074
3053
|
/**
|
|
3075
3054
|
* Wrap an Astro prerenderer with the cache.
|
|
3076
3055
|
*
|
|
3077
|
-
* Strategy (
|
|
3056
|
+
* Strategy (chosen empirically over the "wrap Response" approach
|
|
3078
3057
|
* because Astro's per-route work outside `render` is the actual dominant cost,
|
|
3079
3058
|
* not MDX→HTML conversion):
|
|
3080
3059
|
*
|
|
@@ -3087,12 +3066,12 @@ async function setupIncrementalContext(projectRoot, logger, partialResolver) {
|
|
|
3087
3066
|
* `dist/<pathname>/index.html` for the filtered cached routes — Astro
|
|
3088
3067
|
* never wrote them, so we do.
|
|
3089
3068
|
*
|
|
3090
|
-
* Trade-off vs. the
|
|
3069
|
+
* Trade-off vs. the "wrap Response in render" design: downstream
|
|
3091
3070
|
* Astro hooks (`astro:build:generated`, adapter writers, route accounting)
|
|
3092
3071
|
* don't see cached routes. For Cloudflare adapter sites or anything that
|
|
3093
3072
|
* depends on every route being visible to those hooks, this matters.
|
|
3094
3073
|
* For static SSG sites where the rendered HTML *is* the output, it's fine.
|
|
3095
|
-
* Documented as a limitation
|
|
3074
|
+
* Documented as a known limitation.
|
|
3096
3075
|
*/
|
|
3097
3076
|
function wrapPrerenderer(defaultPrerenderer, ctx) {
|
|
3098
3077
|
return {
|
|
@@ -3169,7 +3148,7 @@ async function restoreCachedPagesToDist(ctx, outDir) {
|
|
|
3169
3148
|
* (so the snapshot is the union of fresh + previously-cached assets the
|
|
3170
3149
|
* cached HTML still references).
|
|
3171
3150
|
*
|
|
3172
|
-
*
|
|
3151
|
+
* Bounded to assets actually referenced by cached HTML. We
|
|
3173
3152
|
* walk every cached page's bytes, regex-extract `/_astro/...` URLs,
|
|
3174
3153
|
* dedupe — and only persist those. Without this the snapshot grew
|
|
3175
3154
|
* unboundedly because vite produces new bundle hashes on every warm
|
|
@@ -3186,7 +3165,7 @@ const ASSET_REF_RE = /\/_astro\/([^"')\s>]+)/g;
|
|
|
3186
3165
|
* Strip query string and hash from an extracted asset path. Without
|
|
3187
3166
|
* this, `/_astro/foo.js?v=1` would record `foo.js?v=1` as the file
|
|
3188
3167
|
* name — the snapshot would skip it because no such file exists in
|
|
3189
|
-
* `_astro/`, leaving the warm build with a broken reference
|
|
3168
|
+
* `_astro/`, leaving the warm build with a broken reference.
|
|
3190
3169
|
*/
|
|
3191
3170
|
function normaliseAssetRef(raw) {
|
|
3192
3171
|
if (!raw) return null;
|
|
@@ -3206,10 +3185,9 @@ function normaliseAssetRef(raw) {
|
|
|
3206
3185
|
*
|
|
3207
3186
|
* The single regex matches `/_astro/...` anywhere in the HTML —
|
|
3208
3187
|
* straightforward for `href="..."`, `src="..."`, `url(...)` in inline
|
|
3209
|
-
* styles, and individual `srcset` URLs alike. (
|
|
3210
|
-
*
|
|
3211
|
-
*
|
|
3212
|
-
* catches them all.)
|
|
3188
|
+
* styles, and individual `srcset` URLs alike. (An earlier regex
|
|
3189
|
+
* anchored on a quote/paren prefix and missed the second+nth URL
|
|
3190
|
+
* inside a `srcset` value; the unanchored form here catches them all.)
|
|
3213
3191
|
*
|
|
3214
3192
|
* We scan the dist output rather than the in-memory cache because dist
|
|
3215
3193
|
* is the source of truth for what's currently referenced — after the
|
|
@@ -3328,8 +3306,8 @@ function mdxSkipPlugin(ctx) {
|
|
|
3328
3306
|
* - sitemap-0.xml carries all entries (we don't split until >45k urls)
|
|
3329
3307
|
* - sitemap-index.xml lists sitemap-0.xml only
|
|
3330
3308
|
*
|
|
3331
|
-
*
|
|
3332
|
-
*
|
|
3309
|
+
* Scope: an optional `serialize` hook per URL, but no `lastmod`,
|
|
3310
|
+
* `changefreq`, `priority`, and no image/video sitemaps. Matches
|
|
3333
3311
|
* `@astrojs/sitemap` *default* output for sites that don't override.
|
|
3334
3312
|
*/
|
|
3335
3313
|
const URLSET_XMLNS = "xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" xmlns:news=\"http://www.google.com/schemas/sitemap-news/0.9\" xmlns:xhtml=\"http://www.w3.org/1999/xhtml\" xmlns:image=\"http://www.google.com/schemas/sitemap-image/1.1\" xmlns:video=\"http://www.google.com/schemas/sitemap-video/1.1\"";
|
|
@@ -3480,8 +3458,7 @@ function extractFrontmatter(source) {
|
|
|
3480
3458
|
const rest = source.slice(afterFirstMarker + 1);
|
|
3481
3459
|
const closingMatch = rest.match(/(^|\n)---\s*(\n|$)/);
|
|
3482
3460
|
if (!closingMatch || closingMatch.index === void 0) return null;
|
|
3483
|
-
|
|
3484
|
-
return rest.slice(0, endIndex);
|
|
3461
|
+
return rest.slice(0, closingMatch.index);
|
|
3485
3462
|
}
|
|
3486
3463
|
/**
|
|
3487
3464
|
* Find a top-level boolean field in YAML frontmatter. Returns the
|
|
@@ -3512,9 +3489,8 @@ function parseBoolField(yaml, field) {
|
|
|
3512
3489
|
* - `string[]` for either array form
|
|
3513
3490
|
* - `undefined` if absent
|
|
3514
3491
|
*
|
|
3515
|
-
*
|
|
3516
|
-
*
|
|
3517
|
-
* dropped valid block lists at build time. The schema validates the
|
|
3492
|
+
* All three forms are accepted: scalar, inline array, and the multiline
|
|
3493
|
+
* block list (canonical YAML list syntax). The schema validates the
|
|
3518
3494
|
* post-parse shape; the scanner has to match it.
|
|
3519
3495
|
*/
|
|
3520
3496
|
function parsePreviousSlugField(yaml) {
|
|
@@ -3792,6 +3768,7 @@ function nimbus(rawConfig, options = {}) {
|
|
|
3792
3768
|
collections: options.collections
|
|
3793
3769
|
}, IMPLEMENTED_CODES);
|
|
3794
3770
|
let projectRootForBuild = "";
|
|
3771
|
+
let cacheDirForBuild = "";
|
|
3795
3772
|
let astroBaseForBuild = "";
|
|
3796
3773
|
let incrementalCtx = null;
|
|
3797
3774
|
const mdxSkipCtx = createMdxSkipContext();
|
|
@@ -3816,12 +3793,13 @@ function nimbus(rawConfig, options = {}) {
|
|
|
3816
3793
|
skip: validateOpts.skip,
|
|
3817
3794
|
projectRoot
|
|
3818
3795
|
});
|
|
3819
|
-
if (failures.length > 0) throw new Error(formatFailures(failures
|
|
3796
|
+
if (failures.length > 0) throw new Error(formatFailures(failures));
|
|
3820
3797
|
logger.info(`MDX validation passed — ${globals.length} global component${globals.length === 1 ? "" : "s"} registered, ${contentDirs.length} content dir${contentDirs.length === 1 ? "" : "s"} scanned.`);
|
|
3821
3798
|
}
|
|
3822
3799
|
}
|
|
3823
3800
|
const projectRoot = fileURLToPath(astroConfig.root);
|
|
3824
3801
|
projectRootForBuild = projectRoot;
|
|
3802
|
+
cacheDirForBuild = fileURLToPath(astroConfig.cacheDir);
|
|
3825
3803
|
astroBaseForBuild = astroConfig.base ?? "";
|
|
3826
3804
|
const codeBlockLangs = await scanCodeBlockLanguages(projectRoot, SHIKI_LANG_ALIAS);
|
|
3827
3805
|
const contentConfigPath = path.join(projectRoot, "src/content.config.ts");
|
|
@@ -3936,7 +3914,7 @@ function nimbus(rawConfig, options = {}) {
|
|
|
3936
3914
|
logger.warn("[incremental] project root unknown at build:start; cache disabled this run");
|
|
3937
3915
|
return;
|
|
3938
3916
|
}
|
|
3939
|
-
incrementalCtx = await setupIncrementalContext(projectRootForBuild, logger, options.partialResolver);
|
|
3917
|
+
incrementalCtx = await setupIncrementalContext(projectRootForBuild, cacheDirForBuild || void 0, logger, options.partialResolver);
|
|
3940
3918
|
mdxSkipCtx.cachedAbsolutePaths.clear();
|
|
3941
3919
|
for (const pathname of incrementalCtx.cacheableHits) {
|
|
3942
3920
|
const filePath = incrementalCtx.filePathByPathname.get(pathname);
|
|
@@ -4066,9 +4044,9 @@ function runPagefind(siteDir) {
|
|
|
4066
4044
|
/**
|
|
4067
4045
|
* Main entry for `nimbus-docs`.
|
|
4068
4046
|
*
|
|
4069
|
-
* Exports the Astro integration (default), config helper,
|
|
4070
|
-
*
|
|
4071
|
-
*
|
|
4047
|
+
* Exports the Astro integration (default), config helper, the data helpers
|
|
4048
|
+
* (sidebar, prev/next, breadcrumbs, TOC), and the page composition helpers
|
|
4049
|
+
* (`getDocsStaticPaths`, `getDocsPageProps`).
|
|
4072
4050
|
*
|
|
4073
4051
|
* Helpers read the user's config from `virtual:nimbus/config` (provided
|
|
4074
4052
|
* by our Vite plugin) and content entries from `astro:content`. Both
|
|
@@ -4317,7 +4295,7 @@ async function getPrevNext(currentSlug, options) {
|
|
|
4317
4295
|
/**
|
|
4318
4296
|
* Build breadcrumb trail from "/" to the current page.
|
|
4319
4297
|
*
|
|
4320
|
-
*
|
|
4298
|
+
* Simple URL-segment derivation. A later iteration may enrich this with
|
|
4321
4299
|
* sidebar-aware labels.
|
|
4322
4300
|
*/
|
|
4323
4301
|
async function getBreadcrumbs(currentSlug, options) {
|