dogsbay 0.2.0-beta.55 → 0.2.0-beta.57
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/commands/migrate-asciidoc.js +10 -1
- package/dist/commands/site-build.js +78 -0
- package/dist/config/load.js +8 -0
- package/dist/index.js +3 -0
- package/package.json +13 -13
|
@@ -367,7 +367,16 @@ function buildDogsbayConfig(opts) {
|
|
|
367
367
|
// them so format-astro skips emitting routes — the .md files
|
|
368
368
|
// stay on disk so includes resolve, but they don't become
|
|
369
369
|
// URLs. See plans/build-at-scale.md.
|
|
370
|
-
` excludeFromRoutes:`, ` - _attributes`, ` - modules`, ` - snippets`, ` - includes
|
|
370
|
+
` excludeFromRoutes:`, ` - _attributes`, ` - modules`, ` - snippets`, ` - includes`,
|
|
371
|
+
// The AsciiBinder topic_map → nav.yml is the authoritative page
|
|
372
|
+
// list. routablesFrom: nav restricts the page set to pages the nav
|
|
373
|
+
// names; everything else (modules, fragments) is pulled into
|
|
374
|
+
// assemblies via `{% include %}` and never emitted standalone — so
|
|
375
|
+
// no fragment leaks into routes / llms.txt / search, and the build
|
|
376
|
+
// skips the ~85% of files that are includes (10.7k → ~1.7k on
|
|
377
|
+
// OpenShift). excludeFromRoutes above stays as the fallback for
|
|
378
|
+
// `routablesFrom: all`. See plans/nav-scoped-processing.md.
|
|
379
|
+
` routablesFrom: nav`);
|
|
371
380
|
// Persist the migration-time --attribute values so subsequent
|
|
372
381
|
// `dogsbay site build` runs resolve {{ var }} / {% if %}
|
|
373
382
|
// without re-passing flags. The build-time preprocessor
|
|
@@ -196,6 +196,14 @@ export async function siteBuild(cwd, options) {
|
|
|
196
196
|
console.log(` Preprocessor: ${changes.join(", ")} → ${mirrorRoot}`);
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
|
+
// --no-astro: stop after the preprocessor. The resolved-Minja mirror under
|
|
200
|
+
// <siteRoot>/.dogsbay/build-content/ IS the artifact ("preprocessed
|
|
201
|
+
// markdown"); skip content import + Astro emission. Powers the Docker
|
|
202
|
+
// `preprocess` stage and serves as a debug aid.
|
|
203
|
+
if (options.astro === false) {
|
|
204
|
+
console.log(" --no-astro: stopped after preprocess (resolved MD in .dogsbay/build-content/)");
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
199
207
|
// 7. Import content
|
|
200
208
|
//
|
|
201
209
|
// Reads from `importPaths` — either the source paths (no-preprocess)
|
|
@@ -216,6 +224,23 @@ export async function siteBuild(cwd, options) {
|
|
|
216
224
|
// local preview. Nav entries pointing at filtered pages are pruned
|
|
217
225
|
// recursively so the sidebar doesn't have dead links.
|
|
218
226
|
let { pages, nav, draftCount } = filterDrafts(importResult.pages, importResult.nav, options.includeDrafts === true, config.site.basePath);
|
|
227
|
+
// 7a. routablesFrom: "nav" — restrict the page set to pages the nav
|
|
228
|
+
// lists (the whitelist). Include-only fragments (modules/, _attributes/,
|
|
229
|
+
// etc.) are inlined into their assemblies by the preprocessor, so they
|
|
230
|
+
// never need to be standalone pages; dropping them here keeps them out
|
|
231
|
+
// of autodoc, ref-validation, llms.txt, the sitemap, and emit — no
|
|
232
|
+
// fragment-detection needed. Self-safe: a no-op when the nav is
|
|
233
|
+
// auto-derived (it already covers every page) or routablesFrom is
|
|
234
|
+
// "all". See plans/nav-scoped-processing.md.
|
|
235
|
+
if (config.content.routablesFrom === "nav") {
|
|
236
|
+
const before = pages.length;
|
|
237
|
+
const { kept, dropped } = filterPagesToNav(pages, nav, config.site.basePath);
|
|
238
|
+
if (dropped.length > 0) {
|
|
239
|
+
pages = kept;
|
|
240
|
+
console.log(` routablesFrom: nav — excluded ${dropped.length} non-nav page(s) of ${before}` +
|
|
241
|
+
` (e.g. ${dropped.slice(0, 5).join(", ")})`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
219
244
|
// 7b. onContentImported — let plugins mutate the page set + nav.
|
|
220
245
|
if (resolvedPlugins.some((p) => p.plugin.onContentImported)) {
|
|
221
246
|
const after = await runOnContentImported(resolvedPlugins, baseCtx, pages, nav);
|
|
@@ -669,3 +694,56 @@ function hrefMatchesDroppedSlug(href, droppedSlugs, basePath) {
|
|
|
669
694
|
}
|
|
670
695
|
return droppedSlugs.has(normalized) || droppedSlugs.has(normalized || "index");
|
|
671
696
|
}
|
|
697
|
+
/**
|
|
698
|
+
* Collect the slug of every nav leaf (recursively), normalized the same
|
|
699
|
+
* way `hrefMatchesDroppedSlug` normalizes a single href — strip
|
|
700
|
+
* leading/trailing slashes, strip leading basePath segments; an empty
|
|
701
|
+
* result (the home href `/`) maps to `index`. Used by
|
|
702
|
+
* `content.routablesFrom: "nav"` to restrict the page set to
|
|
703
|
+
* nav-reachable pages.
|
|
704
|
+
*/
|
|
705
|
+
function collectNavSlugs(items, basePath) {
|
|
706
|
+
const out = new Set();
|
|
707
|
+
const bp = normalizeBasePath(basePath);
|
|
708
|
+
const segs = basePathSegments(bp);
|
|
709
|
+
const walk = (nodes) => {
|
|
710
|
+
for (const item of nodes) {
|
|
711
|
+
if (item.href) {
|
|
712
|
+
let normalized = item.href.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
713
|
+
for (const seg of segs) {
|
|
714
|
+
if (normalized === seg) {
|
|
715
|
+
normalized = "";
|
|
716
|
+
break;
|
|
717
|
+
}
|
|
718
|
+
if (normalized.startsWith(`${seg}/`)) {
|
|
719
|
+
normalized = normalized.slice(seg.length + 1);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
out.add(normalized || "index");
|
|
723
|
+
}
|
|
724
|
+
if (item.children && item.children.length > 0)
|
|
725
|
+
walk(item.children);
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
walk(items);
|
|
729
|
+
return out;
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Partition pages by nav membership for `content.routablesFrom: "nav"`.
|
|
733
|
+
* `kept` = pages whose slug is reachable from the nav; `dropped` = the
|
|
734
|
+
* slugs of pages the nav omits (include-only fragments — their content
|
|
735
|
+
* is already inlined into the assemblies that include them). Pure +
|
|
736
|
+
* exported for unit testing.
|
|
737
|
+
*/
|
|
738
|
+
export function filterPagesToNav(pages, nav, basePath) {
|
|
739
|
+
const navSlugs = collectNavSlugs(nav, basePath);
|
|
740
|
+
const kept = [];
|
|
741
|
+
const dropped = [];
|
|
742
|
+
for (const page of pages) {
|
|
743
|
+
if (navSlugs.has(page.slug))
|
|
744
|
+
kept.push(page);
|
|
745
|
+
else
|
|
746
|
+
dropped.push(page.slug);
|
|
747
|
+
}
|
|
748
|
+
return { kept, dropped };
|
|
749
|
+
}
|
package/dist/config/load.js
CHANGED
|
@@ -466,6 +466,13 @@ function validateContent(content, sourcePath) {
|
|
|
466
466
|
}
|
|
467
467
|
excludeFromRoutes = c.excludeFromRoutes;
|
|
468
468
|
}
|
|
469
|
+
let routablesFrom;
|
|
470
|
+
if (c.routablesFrom !== undefined) {
|
|
471
|
+
if (c.routablesFrom !== "all" && c.routablesFrom !== "nav") {
|
|
472
|
+
throw new Error(`content.routablesFrom must be "all" or "nav" in ${sourcePath}`);
|
|
473
|
+
}
|
|
474
|
+
routablesFrom = c.routablesFrom;
|
|
475
|
+
}
|
|
469
476
|
return {
|
|
470
477
|
sources: validatedSources,
|
|
471
478
|
section: c.section,
|
|
@@ -476,6 +483,7 @@ function validateContent(content, sourcePath) {
|
|
|
476
483
|
locales,
|
|
477
484
|
defaultLocale,
|
|
478
485
|
excludeFromRoutes,
|
|
486
|
+
routablesFrom,
|
|
479
487
|
};
|
|
480
488
|
}
|
|
481
489
|
function validateLocales(raw, sourcePath) {
|
package/dist/index.js
CHANGED
|
@@ -130,6 +130,9 @@ site
|
|
|
130
130
|
.option("--no-preprocess", "Skip the build-time Minja preprocessor pass even when " +
|
|
131
131
|
"`attributes:` are declared. Debug aid — shows the raw " +
|
|
132
132
|
"`{{ var }}` directives the importer left unresolved.")
|
|
133
|
+
.option("--no-astro", "Stop after the Minja preprocessor — write the resolved-Markdown " +
|
|
134
|
+
"mirror to .dogsbay/build-content/ but skip content import + Astro " +
|
|
135
|
+
"page emission. The mirror is the 'preprocessed markdown' artifact.")
|
|
133
136
|
.action((dir, options) => siteBuild(dir, options));
|
|
134
137
|
site
|
|
135
138
|
.command("dev")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dogsbay",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.57",
|
|
4
4
|
"description": "CLI for Dogsbay — scaffold, build, and serve documentation sites with markdown / MkDocs / Obsidian / OpenAPI sources",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,18 +33,18 @@
|
|
|
33
33
|
"picocolors": "^1.1.0",
|
|
34
34
|
"prompts": "^2.4.2",
|
|
35
35
|
"yaml": "^2.8.3",
|
|
36
|
-
"@dogsbay/
|
|
37
|
-
"@dogsbay/format-
|
|
38
|
-
"@dogsbay/
|
|
39
|
-
"@dogsbay/format-
|
|
40
|
-
"@dogsbay/format-
|
|
41
|
-
"@dogsbay/format-starlight": "0.2.0-beta.
|
|
42
|
-
"@dogsbay/format-dogsbay-md": "0.2.0-beta.
|
|
43
|
-
"@dogsbay/format-openapi": "0.2.0-beta.
|
|
44
|
-
"@dogsbay/adoc2md-modular": "0.2.0-beta.
|
|
45
|
-
"@dogsbay/format-asciidoc": "0.2.0-beta.
|
|
46
|
-
"@dogsbay/minja": "0.2.0-beta.
|
|
47
|
-
"@dogsbay/types": "0.2.0-beta.
|
|
36
|
+
"@dogsbay/format-mkdocs": "0.2.0-beta.57",
|
|
37
|
+
"@dogsbay/format-astro": "0.2.0-beta.57",
|
|
38
|
+
"@dogsbay/autodoc-python": "0.2.0-beta.57",
|
|
39
|
+
"@dogsbay/format-obsidian": "0.2.0-beta.57",
|
|
40
|
+
"@dogsbay/format-mdx": "0.2.0-beta.57",
|
|
41
|
+
"@dogsbay/format-starlight": "0.2.0-beta.57",
|
|
42
|
+
"@dogsbay/format-dogsbay-md": "0.2.0-beta.57",
|
|
43
|
+
"@dogsbay/format-openapi": "0.2.0-beta.57",
|
|
44
|
+
"@dogsbay/adoc2md-modular": "0.2.0-beta.57",
|
|
45
|
+
"@dogsbay/format-asciidoc": "0.2.0-beta.57",
|
|
46
|
+
"@dogsbay/minja": "0.2.0-beta.57",
|
|
47
|
+
"@dogsbay/types": "0.2.0-beta.57"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/markdown-it": "^14.1.0",
|