@dogsbay/ssg 0.2.0-beta.144 → 0.2.0-beta.146
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.
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
Third-party software in @dogsbay/ssg (dist/package/)
|
|
2
2
|
|
|
3
3
|
========================================================================
|
|
4
|
-
@dogsbay/elements@0.2.0-beta.
|
|
4
|
+
@dogsbay/elements@0.2.0-beta.146 (MIT)
|
|
5
5
|
https://github.com/dogsbay/dogsbay.git
|
|
6
6
|
|
|
7
7
|
Licensed under MIT; the package ships no licence file.
|
|
8
8
|
|
|
9
9
|
========================================================================
|
|
10
|
-
@dogsbay/primitives@0.2.0-beta.
|
|
10
|
+
@dogsbay/primitives@0.2.0-beta.146 (MIT)
|
|
11
11
|
https://github.com/dogsbay/dogsbay.git
|
|
12
12
|
|
|
13
13
|
Licensed under MIT; the package ships no licence file.
|
|
14
14
|
|
|
15
15
|
========================================================================
|
|
16
|
-
@dogsbay/render-html@0.2.0-beta.
|
|
16
|
+
@dogsbay/render-html@0.2.0-beta.146 (MIT)
|
|
17
17
|
https://github.com/dogsbay/dogsbay.git
|
|
18
18
|
|
|
19
19
|
Licensed under MIT; the package ships no licence file.
|
|
20
20
|
|
|
21
21
|
========================================================================
|
|
22
|
-
@dogsbay/search@0.2.0-beta.
|
|
22
|
+
@dogsbay/search@0.2.0-beta.146 (MIT)
|
|
23
23
|
https://github.com/dogsbay/dogsbay.git
|
|
24
24
|
|
|
25
25
|
Licensed under MIT; the package ships no licence file.
|
|
26
26
|
|
|
27
27
|
========================================================================
|
|
28
|
-
@dogsbay/ui@0.2.0-beta.
|
|
28
|
+
@dogsbay/ui@0.2.0-beta.146 (MIT)
|
|
29
29
|
https://github.com/dogsbay/dogsbay.git
|
|
30
30
|
|
|
31
31
|
Licensed under MIT; the package ships no licence file.
|
package/dist/package/browser.mjs
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
|
|
19
19
|
// src/core/build.ts
|
|
20
20
|
import { dogsbayMdToTree, splitFrontmatter as splitFrontmatter2, treeToDogsbayMd } from "@dogsbay/format-dogsbay-md/browser";
|
|
21
|
+
import { mergeHeaders, mergeRedirects, productRootRedirects, siteFiles, siteRootTarget, toScript, unitOf } from "@dogsbay/site-files";
|
|
21
22
|
import { buildHreflangLinks, isMountRoot, missingTranslations, mountRefs, mountRootNote, namespaceNavGroup, namespacePrefixes, placeMountedNav, prefixSlug as prefixSlug2, rewriteContentRefs } from "@dogsbay/site-files";
|
|
22
23
|
|
|
23
24
|
// src/core/canonical.ts
|
|
@@ -26,7 +27,7 @@ import { declaresParams, splitFrontmatter } from "@dogsbay/format-dogsbay-md/bro
|
|
|
26
27
|
|
|
27
28
|
// src/core/config.ts
|
|
28
29
|
import { scriptUrl } from "@dogsbay/render-html";
|
|
29
|
-
import { assertLeafSitemap, checkVersionSeo, isNamespaceAxisActive, namespaceSegments, parseMount } from "@dogsbay/site-files";
|
|
30
|
+
import { assertLeafSitemap, checkVersionSeo, isNamespaceAxisActive, namespaceSegments, parseMount, ProductConfigError, productModel, productOf, sourceNamespace, sourceUnit, unitSegments } from "@dogsbay/site-files";
|
|
30
31
|
|
|
31
32
|
// src/core/yaml.ts
|
|
32
33
|
import { load } from "js-yaml";
|
|
@@ -36,6 +37,17 @@ function loadYaml(text) {
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
// src/core/config.ts
|
|
40
|
+
function shared(f) {
|
|
41
|
+
try {
|
|
42
|
+
return f();
|
|
43
|
+
} catch (e) {
|
|
44
|
+
if (e instanceof ProductConfigError) throw new ConfigError(e.message);
|
|
45
|
+
throw e;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function versionsOf(cfg, product) {
|
|
49
|
+
return cfg.productVersions?.get(product ?? "") ?? { versions: cfg.versions, defaultVersion: cfg.defaultVersion };
|
|
50
|
+
}
|
|
39
51
|
var ConfigError = class extends Error {
|
|
40
52
|
};
|
|
41
53
|
function sourceTemplates(v, path) {
|
|
@@ -67,10 +79,10 @@ function unitId(kind, v) {
|
|
|
67
79
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(id)) throw new ConfigError(`${kind}: id "${id.slice(0, 80)}" must be one URL segment of letters, digits, dots, dashes and underscores`);
|
|
68
80
|
return id;
|
|
69
81
|
}
|
|
70
|
-
function sourceMount(s) {
|
|
82
|
+
function sourceMount(s, products) {
|
|
71
83
|
const at = `content.sources[${String(s.path)}]`;
|
|
72
84
|
if (s.from !== "openapi") throw new ConfigError(`${at}: mount is only for a "from: openapi" source`);
|
|
73
|
-
if (s.name != null) throw new ConfigError(`${at} has both name and mount: a mounted source goes inside its version, so it takes no name`);
|
|
85
|
+
if (s.name != null && !products) throw new ConfigError(`${at} has both name and mount: a mounted source goes inside its version, so it takes no name (with content.products:, it names its product)`);
|
|
74
86
|
const parsed = parseMount(s.mount);
|
|
75
87
|
if ("error" in parsed) throw new ConfigError(`${at}: ${parsed.error}`);
|
|
76
88
|
return parsed.segments.join("/");
|
|
@@ -140,6 +152,7 @@ function parseConfig(text, overrides = {}) {
|
|
|
140
152
|
if (navMode !== void 0 && navMode !== "client" && navMode !== "ssr-full") throw new ConfigError(`build.navMode must be "client" or "ssr-full"; got ${JSON.stringify(navMode)}`);
|
|
141
153
|
const site = raw.site ?? {};
|
|
142
154
|
const content = raw.content ?? {};
|
|
155
|
+
const productsBlock = content.products != null;
|
|
143
156
|
const ssg = raw.ssg ?? {};
|
|
144
157
|
const agent = raw.agent ?? {};
|
|
145
158
|
const signal = agent.contentSignal ?? {};
|
|
@@ -147,7 +160,7 @@ function parseConfig(text, overrides = {}) {
|
|
|
147
160
|
path: sourcePath(s),
|
|
148
161
|
...s.name != null ? { name: sourceName(s.name) } : {},
|
|
149
162
|
...s.from != null ? { from: sourceFrom(s.from, String(s.path)) } : {},
|
|
150
|
-
...s.mount != null ? { mount: sourceMount(s) } : {},
|
|
163
|
+
...s.mount != null ? { mount: sourceMount(s, productsBlock) } : {},
|
|
151
164
|
version: s.version != null ? unitId("version", s.version) : void 0,
|
|
152
165
|
locale: s.locale != null ? unitId("locale", s.locale) : void 0,
|
|
153
166
|
attributes: s.attributes ?? void 0,
|
|
@@ -164,7 +177,7 @@ function parseConfig(text, overrides = {}) {
|
|
|
164
177
|
hidden: v.hidden || void 0,
|
|
165
178
|
removed: removedOf(v.removed, String(v.id)),
|
|
166
179
|
...versionSeoOf(v, String(v.id)),
|
|
167
|
-
...versionPathOf(v, String(v.id))
|
|
180
|
+
...versionPathOf(v, String(v.id), productsBlock)
|
|
168
181
|
}));
|
|
169
182
|
const locales = (content.locales ?? raw.locales ?? []).map((l) => ({
|
|
170
183
|
id: unitId("locales", l.id),
|
|
@@ -267,6 +280,7 @@ function parseConfig(text, overrides = {}) {
|
|
|
267
280
|
}
|
|
268
281
|
if (dv.noindex) throw new ConfigError(`versions: "${dv.id}" is the defaultVersion and has noindex: true; older versions' pages name it as their canonical`);
|
|
269
282
|
}
|
|
283
|
+
if (productsBlock) Object.assign(cfg, productsOf(content, raw, cfg));
|
|
270
284
|
return cfg;
|
|
271
285
|
}
|
|
272
286
|
var TAG_COLORS = /* @__PURE__ */ new Set(["blue", "amber", "emerald", "violet", "rose", "slate"]);
|
|
@@ -392,11 +406,41 @@ function versionSeoOf(v, id) {
|
|
|
392
406
|
...typeof v.sitemap === "boolean" ? { sitemap: v.sitemap } : {}
|
|
393
407
|
};
|
|
394
408
|
}
|
|
395
|
-
function versionPathOf(v, id) {
|
|
409
|
+
function versionPathOf(v, id, products = false) {
|
|
396
410
|
if (v.path === void 0 || v.path === null) return {};
|
|
397
|
-
if (v.path !== "")
|
|
411
|
+
if (products && v.path !== "") return { path: String(v.path) };
|
|
412
|
+
if (v.path !== "") throw new ConfigError(`versions: "${id}".path can only be "" (serve the version at the root); another segment needs content.products:`);
|
|
398
413
|
return { path: "" };
|
|
399
414
|
}
|
|
415
|
+
function productsOf(content, raw, cfg) {
|
|
416
|
+
const siteVersions = content.versions ?? raw.versions;
|
|
417
|
+
const written = (Array.isArray(content.sources) ? content.sources : []).filter((s) => typeof s?.path === "string");
|
|
418
|
+
const sources = written.length ? written : [{ path: "content" }];
|
|
419
|
+
const model = shared(() => productModel({ products: content.products, sources, versions: siteVersions, defaultVersion: content.defaultVersion ?? raw.defaultVersion, locales: cfg.locales, defaultLocale: cfg.defaultLocale }));
|
|
420
|
+
if (!model) return {};
|
|
421
|
+
const productVersions = /* @__PURE__ */ new Map();
|
|
422
|
+
for (const p of model.products) {
|
|
423
|
+
const rawList = (p.name ? content.products[p.name]?.versions : void 0) ?? siteVersions ?? [];
|
|
424
|
+
const versions = p.versions.map((v) => {
|
|
425
|
+
const r = rawList.find((x) => String(x?.id) === v.id) ?? {};
|
|
426
|
+
return {
|
|
427
|
+
id: v.id,
|
|
428
|
+
label: v.label,
|
|
429
|
+
...v.eol ? { eol: true } : {},
|
|
430
|
+
...v.prerelease ? { prerelease: true } : {},
|
|
431
|
+
...v.hidden ? { hidden: true } : {},
|
|
432
|
+
...r.removed != null ? { removed: removedOf(r.removed, v.id) } : {},
|
|
433
|
+
...v.canonical ? { canonical: v.canonical } : {},
|
|
434
|
+
...v.noindex !== void 0 ? { noindex: v.noindex } : {},
|
|
435
|
+
...v.sitemap !== void 0 ? { sitemap: v.sitemap } : {},
|
|
436
|
+
...v.path !== v.id ? { path: v.path } : {},
|
|
437
|
+
...v.banner ? { banner: v.banner } : {}
|
|
438
|
+
};
|
|
439
|
+
});
|
|
440
|
+
productVersions.set(p.name ?? "", { versions, ...p.defaultVersion ? { defaultVersion: p.defaultVersion } : {} });
|
|
441
|
+
}
|
|
442
|
+
return { products: model, productVersions };
|
|
443
|
+
}
|
|
400
444
|
function unitOfPath(units, sitePath2) {
|
|
401
445
|
let best;
|
|
402
446
|
for (const u of units) {
|
|
@@ -406,7 +450,12 @@ function unitOfPath(units, sitePath2) {
|
|
|
406
450
|
}
|
|
407
451
|
return best;
|
|
408
452
|
}
|
|
453
|
+
function groupPrefix(u) {
|
|
454
|
+
return [u.product, u.locale].filter(Boolean).join("/");
|
|
455
|
+
}
|
|
456
|
+
var sameProduct = (a, b) => (a.product ?? "") === (b.product ?? "");
|
|
409
457
|
function buildUnits(cfg) {
|
|
458
|
+
if (cfg.products) return productUnits(cfg, cfg.products);
|
|
410
459
|
const withDefaults2 = cfg.sources.map((s) => ({
|
|
411
460
|
source: s,
|
|
412
461
|
version: s.version ?? cfg.defaultVersion,
|
|
@@ -424,26 +473,26 @@ function buildUnits(cfg) {
|
|
|
424
473
|
}
|
|
425
474
|
}
|
|
426
475
|
const namespaces = isNamespaceAxisActive(cfg.sources.filter((s) => !s.mount));
|
|
427
|
-
|
|
428
|
-
throw new ConfigError("named sources (content.sources name:) cannot be combined with versions or locales yet (plans/openapi-sources.md)");
|
|
429
|
-
}
|
|
476
|
+
const products = namespaces && (versionAxis || localeAxis);
|
|
430
477
|
for (const s of cfg.sources) {
|
|
431
478
|
if (s.from === "openapi" && cfg.sources.length > 1 && !s.name && !s.mount) throw new ConfigError(`content.sources[${s.path}]: an OpenAPI source beside other sources needs a name: or a mount:, so its pages do not land on theirs`);
|
|
432
479
|
}
|
|
433
480
|
const units = /* @__PURE__ */ new Map();
|
|
434
481
|
for (const u of withDefaults2) {
|
|
435
482
|
const atRoot = cfg.versions.find((v) => v.id === u.version)?.path === "";
|
|
436
|
-
const
|
|
437
|
-
const
|
|
483
|
+
const product = products && !u.source.mount ? sourceNamespace(u.source) : void 0;
|
|
484
|
+
const prefix = [product, localeAxis ? u.locale : void 0, versionAxis && !atRoot ? u.version : void 0].filter(Boolean).join("/");
|
|
485
|
+
const member = u.source.mount ? { source: u.source, namespace: "", mount: u.source.mount } : { source: u.source, namespace: products ? "" : namespaceSegments(u.source, cfg.sources).join("/") };
|
|
438
486
|
const unit = units.get(prefix);
|
|
439
487
|
if (!unit) {
|
|
440
|
-
units.set(prefix, { source: u.source, members: [member], version: versionAxis ? u.version : void 0, locale: localeAxis ? u.locale : void 0, prefix });
|
|
488
|
+
units.set(prefix, { source: u.source, members: [member], version: versionAxis ? u.version : void 0, ...versionAxis && u.version ? { versionPath: atRoot ? "" : u.version } : {}, locale: localeAxis ? u.locale : void 0, ...product ? { product } : {}, prefix });
|
|
441
489
|
continue;
|
|
442
490
|
}
|
|
443
491
|
if (member.mount) {
|
|
444
492
|
const taken = unit.members.find((m) => m.mount === member.mount);
|
|
445
493
|
if (taken) throw new ConfigError(`two sources are mounted at "${member.mount}" in the same version and locale (${taken.source.path}, ${u.source.path})`);
|
|
446
494
|
} else if (unit.members.some((m) => !m.mount)) {
|
|
495
|
+
if (products) throw new ConfigError(`two sources publish to "${prefix || "/"}" (${unit.members.find((m) => !m.mount).source.path}, ${u.source.path}): give each its own name, version or locale`);
|
|
447
496
|
if (!namespaces) throw new ConfigError(`two sources publish to the same prefix "${prefix || "/"}"`);
|
|
448
497
|
if (unit.members.some((m) => !m.mount && m.namespace === member.namespace)) {
|
|
449
498
|
throw new ConfigError(member.namespace ? `two sources are named "${member.namespace}"` : `two unnamed sources publish to the same prefix "${prefix || "/"}"`);
|
|
@@ -453,6 +502,16 @@ function buildUnits(cfg) {
|
|
|
453
502
|
const main = unit.members.find((m) => m.source === unit.source);
|
|
454
503
|
if (!member.namespace && !member.mount && (main.namespace || main.mount)) unit.source = u.source;
|
|
455
504
|
}
|
|
505
|
+
if (products) {
|
|
506
|
+
const names = new Set([...units.values()].map((u) => u.product).filter(Boolean));
|
|
507
|
+
for (const unit of units.values()) {
|
|
508
|
+
const main = unit.members.find((m) => !m.mount);
|
|
509
|
+
for (const m of unit.members.filter((x) => x.mount)) {
|
|
510
|
+
if (!main) throw new ConfigError(`content.sources[${m.source.path}]: a mounted source goes beside the unnamed source of its version and locale, and there is none at "${unit.prefix || "/"}"; a mount inside a named source's version is not supported yet`);
|
|
511
|
+
if (names.has(m.mount.split("/")[0])) throw new ConfigError(`content.sources[${m.source.path}]: mount "${m.mount}" starts with the name of a source, where that source's pages are; mount it elsewhere`);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
456
515
|
for (const unit of units.values()) {
|
|
457
516
|
for (const m of unit.members) {
|
|
458
517
|
const ns = m.mount && unit.members.find((o) => o.namespace && m.mount.split("/")[0] === o.namespace);
|
|
@@ -461,6 +520,43 @@ function buildUnits(cfg) {
|
|
|
461
520
|
}
|
|
462
521
|
return [...units.values()];
|
|
463
522
|
}
|
|
523
|
+
function productUnits(cfg, model) {
|
|
524
|
+
const units = /* @__PURE__ */ new Map();
|
|
525
|
+
for (const s of cfg.sources) {
|
|
526
|
+
const key = shared(() => sourceUnit(model, s, cfg.defaultLocale));
|
|
527
|
+
const prefix = shared(() => unitSegments(model, key)).join("/");
|
|
528
|
+
const member = s.mount ? { source: s, namespace: "", mount: s.mount } : { source: s, namespace: "" };
|
|
529
|
+
const unit = units.get(prefix);
|
|
530
|
+
if (!unit) {
|
|
531
|
+
const versionPath = key.version === void 0 ? void 0 : shared(() => productOf(model, key.product)).versions.find((v) => v.id === key.version)?.path;
|
|
532
|
+
units.set(prefix, {
|
|
533
|
+
source: s,
|
|
534
|
+
members: [member],
|
|
535
|
+
...key.version !== void 0 ? { version: key.version, versionPath } : {},
|
|
536
|
+
...key.locale !== void 0 ? { locale: key.locale } : {},
|
|
537
|
+
...key.product ? { product: key.product } : {},
|
|
538
|
+
prefix
|
|
539
|
+
});
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
if (member.mount) {
|
|
543
|
+
const taken = unit.members.find((m) => m.mount === member.mount);
|
|
544
|
+
if (taken) throw new ConfigError(`two sources are mounted at "${member.mount}" in the same version and locale (${taken.source.path}, ${s.path})`);
|
|
545
|
+
} else if (unit.members.some((m) => !m.mount)) {
|
|
546
|
+
throw new ConfigError(`two sources publish to "${prefix || "/"}" (${unit.members.find((m) => !m.mount).source.path}, ${s.path}): give each its own name, version or locale`);
|
|
547
|
+
}
|
|
548
|
+
unit.members.push(member);
|
|
549
|
+
if (!member.mount) unit.source = s;
|
|
550
|
+
}
|
|
551
|
+
const names = new Set(model.products.map((p) => p.name).filter(Boolean));
|
|
552
|
+
for (const unit of units.values()) {
|
|
553
|
+
if (unit.prefix !== "") continue;
|
|
554
|
+
for (const m of unit.members) {
|
|
555
|
+
if (m.mount && names.has(m.mount.split("/")[0])) throw new ConfigError(`content.sources[${m.source.path}]: mount "${m.mount}" starts with the name of a product, where that product's pages are; mount it elsewhere`);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
return [...units.values()];
|
|
559
|
+
}
|
|
464
560
|
function memberPath(unit, projectPath2) {
|
|
465
561
|
let best;
|
|
466
562
|
for (const m of unit.members) {
|
|
@@ -1069,16 +1165,19 @@ function parseFrontMatter(text) {
|
|
|
1069
1165
|
return {};
|
|
1070
1166
|
}
|
|
1071
1167
|
}
|
|
1168
|
+
var tableKey = (u) => u.product ? `${u.product}\0${u.locale ?? ""}` : u.locale ?? "";
|
|
1072
1169
|
async function defaultTables(cfg, units, built, files, read, warn = () => {
|
|
1073
1170
|
}, fm) {
|
|
1074
1171
|
const tables = /* @__PURE__ */ new Map();
|
|
1075
|
-
|
|
1076
|
-
|
|
1172
|
+
const dv = (u) => versionsOf(cfg, u.product).defaultVersion;
|
|
1173
|
+
const older = (u) => !!u.version && !!dv(u) && u.version !== dv(u);
|
|
1174
|
+
if (!built.some(older)) return tables;
|
|
1175
|
+
for (const unit of units.filter((u) => u.version !== void 0 && u.version === dv(u))) {
|
|
1077
1176
|
const t = await scan(cfg, unit, units, files, fm ?? frontMatterCache(read), read);
|
|
1078
|
-
if (!t.pages.size && built.some((u) => u
|
|
1079
|
-
warn(`[canonical] the default version "${
|
|
1177
|
+
if (!t.pages.size && built.some((u) => older(u) && u.locale === unit.locale && sameProduct(u, unit))) {
|
|
1178
|
+
warn(`[canonical] the default version "${dv(unit)}" has no pages under ${unit.source.path}, so older versions' pages keep themselves as canonical`);
|
|
1080
1179
|
}
|
|
1081
|
-
tables.set(unit
|
|
1180
|
+
tables.set(tableKey(unit), t);
|
|
1082
1181
|
}
|
|
1083
1182
|
return tables;
|
|
1084
1183
|
}
|
|
@@ -1163,11 +1262,12 @@ async function scan(cfg, unit, units, files, frontMatterOf, read, mode = { kind:
|
|
|
1163
1262
|
return { prefix: unit.prefix, pages, redirects };
|
|
1164
1263
|
}
|
|
1165
1264
|
function pageCanonical(cfg, unit, tables, page, urls) {
|
|
1166
|
-
const table = tables.get(unit
|
|
1167
|
-
const
|
|
1265
|
+
const table = tables.get(tableKey(unit));
|
|
1266
|
+
const { versions, defaultVersion } = versionsOf(cfg, unit.product);
|
|
1267
|
+
const version = versions.find((v) => v.id === unit.version);
|
|
1168
1268
|
const fmCanonical = typeof page.frontmatter.canonicalUrl === "string" ? page.frontmatter.canonicalUrl : void 0;
|
|
1169
1269
|
const d = decideCanonical({
|
|
1170
|
-
isDefault: !unit.version || unit.version ===
|
|
1270
|
+
isDefault: !unit.version || unit.version === defaultVersion || !table,
|
|
1171
1271
|
path: page.slug || "index",
|
|
1172
1272
|
version,
|
|
1173
1273
|
frontmatter: fmCanonical,
|
|
@@ -1312,31 +1412,31 @@ var CLIENT_CANDIDATES = ['""', '"&"', '"\\\\$&")).join("|")})', '"\\\\$&")}"', '
|
|
|
1312
1412
|
var SITE_NOTICES = `Third-party software in this site's _dogsbay/ files (dogsbay.js, site.css) and pages
|
|
1313
1413
|
|
|
1314
1414
|
========================================================================
|
|
1315
|
-
@dogsbay/elements@0.2.0-beta.
|
|
1415
|
+
@dogsbay/elements@0.2.0-beta.146 (MIT)
|
|
1316
1416
|
https://github.com/dogsbay/dogsbay.git
|
|
1317
1417
|
|
|
1318
1418
|
Licensed under MIT; the package ships no licence file.
|
|
1319
1419
|
|
|
1320
1420
|
========================================================================
|
|
1321
|
-
@dogsbay/primitives@0.2.0-beta.
|
|
1421
|
+
@dogsbay/primitives@0.2.0-beta.146 (MIT)
|
|
1322
1422
|
https://github.com/dogsbay/dogsbay.git
|
|
1323
1423
|
|
|
1324
1424
|
Licensed under MIT; the package ships no licence file.
|
|
1325
1425
|
|
|
1326
1426
|
========================================================================
|
|
1327
|
-
@dogsbay/render-html@0.2.0-beta.
|
|
1427
|
+
@dogsbay/render-html@0.2.0-beta.146 (MIT)
|
|
1328
1428
|
https://github.com/dogsbay/dogsbay.git
|
|
1329
1429
|
|
|
1330
1430
|
Licensed under MIT; the package ships no licence file.
|
|
1331
1431
|
|
|
1332
1432
|
========================================================================
|
|
1333
|
-
@dogsbay/search@0.2.0-beta.
|
|
1433
|
+
@dogsbay/search@0.2.0-beta.146 (MIT)
|
|
1334
1434
|
https://github.com/dogsbay/dogsbay.git
|
|
1335
1435
|
|
|
1336
1436
|
Licensed under MIT; the package ships no licence file.
|
|
1337
1437
|
|
|
1338
1438
|
========================================================================
|
|
1339
|
-
@dogsbay/ui@0.2.0-beta.
|
|
1439
|
+
@dogsbay/ui@0.2.0-beta.146 (MIT)
|
|
1340
1440
|
https://github.com/dogsbay/dogsbay.git
|
|
1341
1441
|
|
|
1342
1442
|
Licensed under MIT; the package ships no licence file.
|
|
@@ -2498,6 +2598,8 @@ var EN = {
|
|
|
2498
2598
|
prerelease: "pre-release",
|
|
2499
2599
|
latest: "latest",
|
|
2500
2600
|
oldVersion: "You are viewing documentation for an older version.",
|
|
2601
|
+
eolVersion: "This version is no longer maintained.",
|
|
2602
|
+
prereleaseVersion: "This version is not released yet.",
|
|
2501
2603
|
goLatest: "Go to the latest version",
|
|
2502
2604
|
notFound: "Page not found",
|
|
2503
2605
|
notFoundBody: "The page you asked for does not exist in this version of the documentation.",
|
|
@@ -3064,7 +3166,8 @@ function diagramStore(input, cfg) {
|
|
|
3064
3166
|
async function siteCssBuilder(input) {
|
|
3065
3167
|
return input.css ?? (await import("./chunks/tailwind-fallback-KPRFHW3C.mjs")).buildSiteCss;
|
|
3066
3168
|
}
|
|
3067
|
-
var SITE_FILES = /* @__PURE__ */ new Set(["robots.txt", "
|
|
3169
|
+
var SITE_FILES = /* @__PURE__ */ new Set(["robots.txt", "sitemap-index.xml"]);
|
|
3170
|
+
var MERGED_FILES = /* @__PURE__ */ new Set(["_headers", "_redirects"]);
|
|
3068
3171
|
function reporter(warnings, problems) {
|
|
3069
3172
|
return (code, text, at = {}) => {
|
|
3070
3173
|
const t = detach(text);
|
|
@@ -3210,6 +3313,7 @@ async function build(input, hooks = {}) {
|
|
|
3210
3313
|
const allUnits = buildUnits(cfg);
|
|
3211
3314
|
const units = selectUnits(allUnits, input.units);
|
|
3212
3315
|
checkRootVersion(allUnits, input.files);
|
|
3316
|
+
checkProductFolders(allUnits, input.files);
|
|
3213
3317
|
const out = /* @__PURE__ */ new Map();
|
|
3214
3318
|
const sink = input.sink;
|
|
3215
3319
|
let classes = new Set(CLIENT_CANDIDATES);
|
|
@@ -3238,7 +3342,7 @@ async function build(input, hooks = {}) {
|
|
|
3238
3342
|
phase.init = now() - t0;
|
|
3239
3343
|
let pages = 0;
|
|
3240
3344
|
let assets = 0;
|
|
3241
|
-
const state = { redirects: [], notes: /* @__PURE__ */ new Map(), navCache: navCache(), written: /* @__PURE__ */ new Set(), stubs: [], pageOut: /* @__PURE__ */ new Map(), sitemaps: /* @__PURE__ */ new Map(), supplied: /* @__PURE__ */ new Set(), usedMath: false, diagrams: diagramStore(input, cfg), scan: hooks.keep || hooks.lazy ? new ScanCache() : void 0, parseCache: input.parseCacheBytes === 0 ? false : new ParseCache(input.parseCacheBytes ?? DEFAULT_PARSE_CACHE_BYTES), templateBudget: templateBudget(input.untrusted === true, input.templateMs), dataCache: new DataCache(input.dataCacheBytes ?? DEFAULT_DATA_CACHE_BYTES) };
|
|
3345
|
+
const state = { redirects: [], notes: /* @__PURE__ */ new Map(), navCache: navCache(), written: /* @__PURE__ */ new Set(), stubs: [], pageOut: /* @__PURE__ */ new Map(), sitemaps: /* @__PURE__ */ new Map(), supplied: /* @__PURE__ */ new Set(), hostFiles: /* @__PURE__ */ new Map(), usedMath: false, diagrams: diagramStore(input, cfg), scan: hooks.keep || hooks.lazy ? new ScanCache() : void 0, parseCache: input.parseCacheBytes === 0 ? false : new ParseCache(input.parseCacheBytes ?? DEFAULT_PARSE_CACHE_BYTES), templateBudget: templateBudget(input.untrusted === true, input.templateMs), dataCache: new DataCache(input.dataCacheBytes ?? DEFAULT_DATA_CACHE_BYTES) };
|
|
3242
3346
|
for (const r of cfg.redirects) {
|
|
3243
3347
|
const from = sitePath(r.from, cfg.basePath);
|
|
3244
3348
|
if (!from) {
|
|
@@ -3292,20 +3396,36 @@ async function build(input, hooks = {}) {
|
|
|
3292
3396
|
defaultLocale: cfg.defaultLocale,
|
|
3293
3397
|
versions: cfg.versions,
|
|
3294
3398
|
locales: cfg.locales,
|
|
3295
|
-
units: allUnits.map((u) => ({ prefix: u.prefix, version: u.version, locale: u.locale }))
|
|
3399
|
+
units: allUnits.map((u) => ({ prefix: u.prefix, version: u.version, locale: u.locale, ...u.product ? { product: u.product } : {}, ...cfg.products && u.versionPath !== u.version ? { versionPath: u.versionPath } : {} })),
|
|
3400
|
+
// With content.products, each product's own versions and default (key "" for the unnamed source's).
|
|
3401
|
+
...cfg.productVersions ? { products: Object.fromEntries(cfg.productVersions) } : {}
|
|
3296
3402
|
// As nav.js: a host may inline the script, and a name with "<\/script>" must not close it.
|
|
3297
3403
|
}).replace(/<\//g, "<\\/")};
|
|
3298
3404
|
`
|
|
3299
3405
|
);
|
|
3406
|
+
if (cfg.products) await emit("_dogsbay/versions.js", `${toScript("__DOGSBAY_VERSIONS__", siteFiles(cfg.products, []).versions)}
|
|
3407
|
+
`);
|
|
3300
3408
|
const def = defaultUnit(allUnits, cfg);
|
|
3301
3409
|
const tSite = now();
|
|
3410
|
+
const rootUnit = allUnits.find((u) => u.prefix === "");
|
|
3411
|
+
if (rootUnit && !input.untrusted) {
|
|
3412
|
+
for (const n of MERGED_FILES) {
|
|
3413
|
+
const own = input.files.get(sourceRoot(rootUnit.source) + n);
|
|
3414
|
+
if (own !== void 0) state.hostFiles.set(n, own);
|
|
3415
|
+
}
|
|
3416
|
+
}
|
|
3302
3417
|
await emitSiteFiles(cfg, allUnits, units, def, state, emit, report, input.onRedirects);
|
|
3303
3418
|
phase.site = (phase.site ?? 0) + now() - tSite;
|
|
3304
3419
|
if (def && def.prefix) {
|
|
3305
3420
|
await emit("index.html", redirectPage(`${def.prefix}/index.html`, cfg.name));
|
|
3306
3421
|
await emit("404.html", redirectPage(`${def.prefix}/404.html`, cfg.name));
|
|
3422
|
+
}
|
|
3423
|
+
if (cfg.products) {
|
|
3424
|
+
for (const [from, to] of productRootRedirects(cfg.products)) await emit(`${from.slice(1)}index.html`, redirectPage(`${relativeHome(from, to)}index.html`, cfg.name));
|
|
3425
|
+
} else if (def && def.prefix) {
|
|
3307
3426
|
for (const u of allUnits) {
|
|
3308
|
-
|
|
3427
|
+
const root = groupPrefix(u);
|
|
3428
|
+
if (root && u.version && u.version === cfg.defaultVersion && u.prefix !== root) await emit(`${root}/index.html`, redirectPage(`${u.version}/index.html`, cfg.name));
|
|
3309
3429
|
}
|
|
3310
3430
|
}
|
|
3311
3431
|
state.stubs = await writeTranslationStubs(cfg, allUnits, units, translations, state, emit);
|
|
@@ -3322,7 +3442,10 @@ async function build(input, hooks = {}) {
|
|
|
3322
3442
|
}
|
|
3323
3443
|
function selectUnits(allUnits, names) {
|
|
3324
3444
|
if (!names) return allUnits;
|
|
3325
|
-
const named = (u, name) =>
|
|
3445
|
+
const named = (u, name) => {
|
|
3446
|
+
if (u.product) return u.product === name || u.prefix === name && u.prefix !== groupPrefix(u) || u.version !== void 0 && name === `${groupPrefix(u)}/${u.version}`;
|
|
3447
|
+
return u.prefix === name || u.version !== void 0 && (u.version === name && u.prefix === groupPrefix(u) || [groupPrefix(u), u.version].filter(Boolean).join("/") === name);
|
|
3448
|
+
};
|
|
3326
3449
|
const unknown = names.filter((p) => !allUnits.some((u) => named(u, p)));
|
|
3327
3450
|
if (unknown.length) {
|
|
3328
3451
|
const list = allUnits.map((u) => u.prefix ? `"${u.prefix}"` : `"${u.version ?? ""}" (at the root)`).join(", ");
|
|
@@ -3332,13 +3455,13 @@ function selectUnits(allUnits, names) {
|
|
|
3332
3455
|
}
|
|
3333
3456
|
function checkRootVersion(allUnits, files) {
|
|
3334
3457
|
const rootOf = (x) => x.source.path === "." ? "" : x.source.path.replace(/^\.\//, "").replace(/\/+$/, "") + "/";
|
|
3335
|
-
for (const u of allUnits.filter((x) => x.version && x.prefix === (x
|
|
3458
|
+
for (const u of allUnits.filter((x) => x.version && x.prefix === groupPrefix(x))) {
|
|
3336
3459
|
const root = rootOf(u);
|
|
3337
3460
|
const nested = allUnits.find((x) => x !== u && rootOf(x).startsWith(root) && rootOf(x) !== root);
|
|
3338
3461
|
if (nested) {
|
|
3339
3462
|
throw new ConfigError(`source "${nested.source.path}" is inside "${u.source.path}", the source of version "${u.version}" served at the root; give each version its own folder`);
|
|
3340
3463
|
}
|
|
3341
|
-
const segs = new Set(allUnits.filter((x) => x !== u && x.locale === u.locale && x.
|
|
3464
|
+
const segs = new Set(allUnits.filter((x) => x !== u && x.locale === u.locale && sameProduct(x, u) && x.versionPath).map((x) => x.versionPath));
|
|
3342
3465
|
if (!segs.size) continue;
|
|
3343
3466
|
for (const k of files.keys()) {
|
|
3344
3467
|
if (!k.startsWith(root)) continue;
|
|
@@ -3346,7 +3469,26 @@ function checkRootVersion(allUnits, files) {
|
|
|
3346
3469
|
if (rel.split("/").some((s) => s.startsWith("_") || s.startsWith("."))) continue;
|
|
3347
3470
|
const first = rel.split("/")[0].replace(/\.(md|markdown)$/i, "");
|
|
3348
3471
|
if (segs.has(first) && (rel.includes("/") || /\.(md|markdown)$/i.test(rel))) {
|
|
3349
|
-
|
|
3472
|
+
const other = allUnits.find((x) => x.versionPath === first && x.locale === u.locale && sameProduct(x, u));
|
|
3473
|
+
throw new ConfigError(`${k} is at ${[u.prefix, first].filter(Boolean).join("/")}/\u2026, where version "${other.version}" is served (version "${u.version}" is at the root); rename the folder or the page`);
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
}
|
|
3477
|
+
}
|
|
3478
|
+
function checkProductFolders(allUnits, files) {
|
|
3479
|
+
const names = new Set(allUnits.map((u) => u.product).filter((p) => !!p));
|
|
3480
|
+
if (!names.size) return;
|
|
3481
|
+
for (const u of allUnits.filter((x) => !x.product && x.prefix === "")) {
|
|
3482
|
+
const roots = u.members.filter((m) => !m.mount && m.source.from !== "openapi").map((m) => sourceRoot(m.source));
|
|
3483
|
+
const others = allUnits.filter((x) => x !== u).flatMap((x) => x.members.map((m) => sourceRoot(m.source))).filter(Boolean);
|
|
3484
|
+
for (const k of files.keys()) {
|
|
3485
|
+
const root = roots.find((r) => k.startsWith(r));
|
|
3486
|
+
if (root === void 0 || others.some((o) => k.startsWith(o) && o.length > root.length)) continue;
|
|
3487
|
+
const rel = k.slice(root.length);
|
|
3488
|
+
if (rel.split("/").some((seg) => seg.startsWith("_") || seg.startsWith("."))) continue;
|
|
3489
|
+
const first = rel.split("/")[0].replace(/\.(md|markdown)$/i, "");
|
|
3490
|
+
if (names.has(first) && (rel.includes("/") || /\.(md|markdown)$/i.test(rel))) {
|
|
3491
|
+
throw new ConfigError(`${k} is at ${first}/\u2026, where the source named "${first}" is published; rename the folder or the page`);
|
|
3350
3492
|
}
|
|
3351
3493
|
}
|
|
3352
3494
|
}
|
|
@@ -3357,15 +3499,23 @@ async function emitSiteFiles(cfg, all, built, def, state, emit, report, onRedire
|
|
|
3357
3499
|
if (state.supplied.has(p)) report("site", `[site] ${p} comes from the content, so the generated one is not written`);
|
|
3358
3500
|
else await emit(p, content);
|
|
3359
3501
|
};
|
|
3502
|
+
const cloudflare = cfg.deployTarget === "cloudflare-workers";
|
|
3503
|
+
const merged = async (p, generated, merge) => {
|
|
3504
|
+
const own = state.hostFiles.get(p);
|
|
3505
|
+
if (own === void 0 && generated === void 0) return;
|
|
3506
|
+
const { text, notes } = merge(own === void 0 ? "" : await readText(own), generated, cloudflare);
|
|
3507
|
+
for (const n of notes) report("site", `[site] ${n}`);
|
|
3508
|
+
await emit(p, text);
|
|
3509
|
+
};
|
|
3360
3510
|
await put("robots.txt", buildRobotsTxt(cfg, defPrefix));
|
|
3361
|
-
|
|
3511
|
+
await merged("_headers", cfg.llmsTxt ? buildHeadersFile(cfg, defPrefix) : void 0, mergeHeaders);
|
|
3362
3512
|
if (siteBase(cfg)) {
|
|
3363
3513
|
const maps = all.flatMap((u) => state.sitemaps.get(u.prefix) ?? [[u.prefix, "sitemap-0.xml"].filter(Boolean).join("/")]);
|
|
3364
3514
|
await put("sitemap-index.xml", buildSitemapIndex(cfg, maps));
|
|
3365
3515
|
} else if (cfg.url) {
|
|
3366
3516
|
report("config", `[site] site.url "${cfg.url}" has no http:// or https://, so canonical links, the sitemap and absolute llms.txt links are left out`);
|
|
3367
3517
|
}
|
|
3368
|
-
if (!state.redirects.length) return;
|
|
3518
|
+
if (!state.redirects.length) return merged("_redirects", void 0, mergeRedirects);
|
|
3369
3519
|
const known = (p) => {
|
|
3370
3520
|
const u = unitOfPath(all, p);
|
|
3371
3521
|
return !!u && built.includes(u);
|
|
@@ -3375,9 +3525,15 @@ async function emitSiteFiles(cfg, all, built, def, state, emit, report, onRedire
|
|
|
3375
3525
|
for (const m of w) report("redirects", `[redirects] ${m}`);
|
|
3376
3526
|
onRedirects?.(rules);
|
|
3377
3527
|
for (const r of rules) await emit(stubFile(r), renderRedirectPage(r, cfg));
|
|
3378
|
-
|
|
3528
|
+
const ownRedirects = state.hostFiles.has("_redirects");
|
|
3529
|
+
await merged("_redirects", (cloudflare || ownRedirects) && rules.length ? renderRedirectsFile(rules, cfg) : void 0, mergeRedirects);
|
|
3379
3530
|
}
|
|
3380
3531
|
function defaultUnit(units, cfg) {
|
|
3532
|
+
if (cfg.products) {
|
|
3533
|
+
const target = siteRootTarget(cfg.products);
|
|
3534
|
+
if (target) return units.find((u) => `/${u.prefix}/` === target || u.prefix === "" && target === "/") ?? units[0];
|
|
3535
|
+
units = units.filter((u) => !u.product);
|
|
3536
|
+
}
|
|
3381
3537
|
return units.find((u) => (u.version ?? cfg.defaultVersion) === cfg.defaultVersion && (u.locale ?? cfg.defaultLocale) === cfg.defaultLocale) ?? units[0];
|
|
3382
3538
|
}
|
|
3383
3539
|
var mathLoad;
|
|
@@ -4351,6 +4507,8 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path, read2),
|
|
|
4351
4507
|
t = now();
|
|
4352
4508
|
for (const a of assetPaths) {
|
|
4353
4509
|
if (SITE_FILES.has(prefix + a)) state.supplied.add(prefix + a);
|
|
4510
|
+
if (MERGED_FILES.has(prefix + a)) continue;
|
|
4511
|
+
if (MERGED_FILES.has(a)) warn("site", `${a} is copied to ${prefix}${a}, where hosts do not read it: they read _headers and _redirects at the site root only, from the unit served there`, { file: abs(a) });
|
|
4354
4512
|
await emit(prefix + a, files.get(a));
|
|
4355
4513
|
}
|
|
4356
4514
|
const pagesJs = `(window.__DOGSBAY_PAGES__=window.__DOGSBAY_PAGES__||{})[${JSON.stringify(unit.prefix)}]=${JSON.stringify([...[...infos.values()].filter((i) => i.slug !== replaced).map((i) => i.out), ...generatedOuts])};
|
|
@@ -4863,13 +5021,14 @@ function switchOptions(kind, unit, all, cfg, out, siteRoot, t) {
|
|
|
4863
5021
|
const axis = kind === "version" ? "version" : "locale";
|
|
4864
5022
|
const other = kind === "version" ? "locale" : "version";
|
|
4865
5023
|
if (!unit[axis]) return [];
|
|
4866
|
-
const peers = all.filter((u) => u[other] === unit[other] && u[axis]);
|
|
4867
|
-
const
|
|
5024
|
+
const peers = all.filter((u) => u[other] === unit[other] && sameProduct(u, unit) && u[axis]);
|
|
5025
|
+
const { versions, defaultVersion } = versionsOf(cfg, unit.product);
|
|
5026
|
+
const defs = kind === "version" ? versions : cfg.locales;
|
|
4868
5027
|
const ordered = defs.length ? defs.map((d) => peers.find((u) => u[axis] === d.id)).filter((u) => !!u) : peers;
|
|
4869
|
-
return ordered.filter((u) => !(kind === "version" &&
|
|
4870
|
-
const v = kind === "version" ?
|
|
5028
|
+
return ordered.filter((u) => !(kind === "version" && versions.find((v) => v.id === u.version)?.hidden && u !== unit)).map((u) => {
|
|
5029
|
+
const v = kind === "version" ? versions.find((d) => d.id === u.version) : void 0;
|
|
4871
5030
|
const l = kind === "locale" ? cfg.locales.find((d) => d.id === u.locale) : void 0;
|
|
4872
|
-
const note = v?.eol ? t("eol") : v?.prerelease ? t("prerelease") : v && v.id ===
|
|
5031
|
+
const note = v?.eol ? t("eol") : v?.prerelease ? t("prerelease") : v && v.id === defaultVersion && v.id !== "latest" ? t("latest") : void 0;
|
|
4873
5032
|
return {
|
|
4874
5033
|
label: v?.label ?? l?.label ?? String(u[axis]),
|
|
4875
5034
|
href: `${siteRoot}${u.prefix ? u.prefix + "/" : ""}${out}`,
|
|
@@ -4880,19 +5039,28 @@ function switchOptions(kind, unit, all, cfg, out, siteRoot, t) {
|
|
|
4880
5039
|
});
|
|
4881
5040
|
}
|
|
4882
5041
|
function versionBanner(unit, all, cfg, out, siteRoot, t) {
|
|
5042
|
+
const link = (latest2) => ` <a href="${esc3(`${siteRoot}${latest2.prefix ? latest2.prefix + "/" : ""}${out}`)}" data-db-version-link data-prefix="${esc3(latest2.prefix)}">${esc3(t("goLatest"))}</a>`;
|
|
5043
|
+
if (cfg.products) {
|
|
5044
|
+
if (unit.version === void 0 || versionsOf(cfg, unit.product).versions.find((d) => d.id === unit.version)?.hidden) return void 0;
|
|
5045
|
+
const b = shared(() => unitOf(cfg.products, { product: unit.product, locale: unit.locale, version: unit.version })).banner;
|
|
5046
|
+
if (!b) return void 0;
|
|
5047
|
+
const text = esc3(b.kind === "custom" ? b.text : t(b.kind === "eol" ? "eolVersion" : b.kind === "prerelease" ? "prereleaseVersion" : "oldVersion"));
|
|
5048
|
+
const latest2 = b.latest && all.find((u) => `/${u.prefix ? u.prefix + "/" : ""}` === b.latest.home);
|
|
5049
|
+
return latest2 ? text + link(latest2) : text;
|
|
5050
|
+
}
|
|
4883
5051
|
if (!unit.version || !cfg.defaultVersion || unit.version === cfg.defaultVersion) return void 0;
|
|
4884
5052
|
const v = cfg.versions.find((d) => d.id === unit.version);
|
|
4885
5053
|
if (v?.hidden) return void 0;
|
|
4886
|
-
const latest = all.find((u) => u.version === cfg.defaultVersion && u.locale === unit.locale);
|
|
5054
|
+
const latest = all.find((u) => u.version === cfg.defaultVersion && u.locale === unit.locale && sameProduct(u, unit));
|
|
4887
5055
|
if (!latest) return void 0;
|
|
4888
|
-
return
|
|
5056
|
+
return esc3(t("oldVersion")) + link(latest);
|
|
4889
5057
|
}
|
|
4890
5058
|
async function writeTranslationStubs(cfg, all, built, tables, state, emit, exists = () => false) {
|
|
4891
5059
|
const def = cfg.defaultLocale;
|
|
4892
5060
|
if (!def || !tables.size) return [];
|
|
4893
|
-
const
|
|
5061
|
+
const unitOf2 = (locale, version) => all.find((u) => u.locale === locale && u.version === version && !u.product);
|
|
4894
5062
|
const missing = missingTranslations(
|
|
4895
|
-
all.filter((u) => u.locale).map((u) => {
|
|
5063
|
+
all.filter((u) => u.locale && !u.product).map((u) => {
|
|
4896
5064
|
const t = tables.get(u.prefix);
|
|
4897
5065
|
return { locale: u.locale, version: u.version, pages: !t ? [] : u.locale === def ? t.pages.keys() : [...t.pages.keys(), ...t.redirects.keys()] };
|
|
4898
5066
|
}),
|
|
@@ -4903,9 +5071,9 @@ async function writeTranslationStubs(cfg, all, built, tables, state, emit, exist
|
|
|
4903
5071
|
const written = [];
|
|
4904
5072
|
for (const m of missing) {
|
|
4905
5073
|
if (m.page === "404") continue;
|
|
4906
|
-
const home =
|
|
5074
|
+
const home = unitOf2(def, m.version);
|
|
4907
5075
|
const out = tables.get(home.prefix).pages.get(m.page);
|
|
4908
|
-
const target =
|
|
5076
|
+
const target = unitOf2(m.locale, m.version);
|
|
4909
5077
|
if (!built.includes(target ?? home)) continue;
|
|
4910
5078
|
const to = join(home.prefix, out);
|
|
4911
5079
|
if (built.includes(home) && !pageFiles.has(to)) continue;
|
|
@@ -4916,6 +5084,10 @@ async function writeTranslationStubs(cfg, all, built, tables, state, emit, exist
|
|
|
4916
5084
|
}
|
|
4917
5085
|
return written;
|
|
4918
5086
|
}
|
|
5087
|
+
function relativeHome(from, to) {
|
|
5088
|
+
if (to.startsWith(from)) return to.slice(from.length);
|
|
5089
|
+
return "../".repeat(from.split("/").filter(Boolean).length) + to.slice(1);
|
|
5090
|
+
}
|
|
4919
5091
|
function redirectPage(target, name) {
|
|
4920
5092
|
const u = esc3(target);
|
|
4921
5093
|
return `<!doctype html><html><head><meta charset="utf-8"><title>${esc3(name)}</title><meta name="robots" content="noindex"><meta http-equiv="refresh" content="0; url=${u}"><link rel="canonical" href="${u}"><link rel="icon" href="data:,"></head><body><p><a href="${u}">${esc3(name)}</a></p></body></html>
|
|
@@ -4991,7 +5163,7 @@ function hreflangFor(cfg, unit, all, languages, slug) {
|
|
|
4991
5163
|
const path = slug || "index";
|
|
4992
5164
|
const alts = [];
|
|
4993
5165
|
for (const u of all) {
|
|
4994
|
-
if (!u.locale || u.version !== unit.version) continue;
|
|
5166
|
+
if (!u.locale || u.version !== unit.version || !sameProduct(u, unit)) continue;
|
|
4995
5167
|
const out = languages.get(u.prefix)?.get(path);
|
|
4996
5168
|
const url = out ? absoluteUrl(cfg, u.prefix, servedPath(out, cfg.linkStyle)) : void 0;
|
|
4997
5169
|
if (url) alts.push({ lang: u.locale, url });
|
|
@@ -5003,7 +5175,7 @@ function hreflangFor(cfg, unit, all, languages, slug) {
|
|
|
5003
5175
|
var CONFIG_FILES = /* @__PURE__ */ new Set(["dogsbay.config.yml", "dogsbay.config.yaml"]);
|
|
5004
5176
|
var NAV_FILES2 = /(^|\/)nav\.(ya?ml|json)$/;
|
|
5005
5177
|
var START_ONLY = /(^|\/)(_dogsbay\/search\/|llms(-full)?\.txt$)/;
|
|
5006
|
-
var SITE_WIDE = /^(_dogsbay\/assets\/|_dogsbay\/site\.js$|robots\.txt$|_headers$|_redirects$|sitemap-index\.xml$)/;
|
|
5178
|
+
var SITE_WIDE = /^(_dogsbay\/assets\/|_dogsbay\/(site|versions)\.js$|robots\.txt$|_headers$|_redirects$|sitemap-index\.xml$)/;
|
|
5007
5179
|
var UNIT_CSS = /(^|\/)_dogsbay\/site\.css$/;
|
|
5008
5180
|
async function openDevSession(input, o = {}) {
|
|
5009
5181
|
let out = /* @__PURE__ */ new Map();
|
|
@@ -5082,7 +5254,7 @@ async function openDevSession(input, o = {}) {
|
|
|
5082
5254
|
if (o.lazy) for (const u of units.values()) for (const p of u.handle.pageOuts) stale.add(p);
|
|
5083
5255
|
};
|
|
5084
5256
|
const noteItems = () => [...ctx?.state.notes.values() ?? []].flat().map((n) => ({ ...n }));
|
|
5085
|
-
const
|
|
5257
|
+
const unitOf2 = (path) => {
|
|
5086
5258
|
let best;
|
|
5087
5259
|
let bestLen = -1;
|
|
5088
5260
|
for (const u of units.values()) {
|
|
@@ -5167,7 +5339,7 @@ async function openDevSession(input, o = {}) {
|
|
|
5167
5339
|
const lazy = await textOf(c);
|
|
5168
5340
|
return lazy ?? c;
|
|
5169
5341
|
};
|
|
5170
|
-
const pageFor = (source) =>
|
|
5342
|
+
const pageFor = (source) => unitOf2(source)?.handle.pageForSource(source);
|
|
5171
5343
|
return {
|
|
5172
5344
|
get config() {
|
|
5173
5345
|
return config;
|
|
@@ -5278,7 +5450,7 @@ async function openDevSession(input, o = {}) {
|
|
|
5278
5450
|
if (CONFIG_FILES.has(p)) continue;
|
|
5279
5451
|
const readers = [...units.values()].filter((u2) => u2.handle.navInputs.includes(p) || u2.unit.members.some((m) => m.source.nav === p));
|
|
5280
5452
|
if (readers.length) {
|
|
5281
|
-
for (const u2 of [...readers,
|
|
5453
|
+
for (const u2 of [...readers, unitOf2(p)]) if (u2) lazy.add(u2.unit.prefix);
|
|
5282
5454
|
mark("unit");
|
|
5283
5455
|
continue;
|
|
5284
5456
|
}
|
|
@@ -5300,7 +5472,7 @@ async function openDevSession(input, o = {}) {
|
|
|
5300
5472
|
}
|
|
5301
5473
|
continue;
|
|
5302
5474
|
}
|
|
5303
|
-
const u =
|
|
5475
|
+
const u = unitOf2(p);
|
|
5304
5476
|
if (!u) continue;
|
|
5305
5477
|
const content = input.files.get(p);
|
|
5306
5478
|
if (/\.(md|markdown)$/i.test(p)) {
|
|
@@ -5326,6 +5498,7 @@ async function openDevSession(input, o = {}) {
|
|
|
5326
5498
|
const at = memberPath(u.unit, p)?.path ?? p.slice(sourceRoot(u.unit.source).length);
|
|
5327
5499
|
const key = u.unit.prefix ? `${u.unit.prefix}/${at}` : at;
|
|
5328
5500
|
const sanitizing = (config.html ?? input.defaultHtml ?? "keep") === "sanitize";
|
|
5501
|
+
if (key === "_headers" || key === "_redirects") continue;
|
|
5329
5502
|
if (copiedPath(at) && await assetVerdict(at, content, input.untrusted === true, sanitizing) === "copy") out.set(key, content);
|
|
5330
5503
|
else out.delete(key);
|
|
5331
5504
|
}
|
|
@@ -5352,10 +5525,12 @@ async function openDevSession(input, o = {}) {
|
|
|
5352
5525
|
units.set(prefix, next);
|
|
5353
5526
|
for (const o2 of handle.pageOuts) markStale(o2, next, true);
|
|
5354
5527
|
}
|
|
5355
|
-
|
|
5528
|
+
const isDefault = (u) => u.version !== void 0 && u.version === versionsOf(config, u.product).defaultVersion;
|
|
5529
|
+
const changedDefaults = [...lazy].map((prefix) => units.get(prefix)?.unit).filter((u) => !!u && isDefault(u));
|
|
5530
|
+
if (changedDefaults.length) {
|
|
5356
5531
|
const all = [...units.values()].map((u) => u.unit);
|
|
5357
5532
|
ctx.state.canonical = await defaultTables(config, all, all, input.files, readText);
|
|
5358
|
-
for (const u of units.values()) if (u.unit.version !==
|
|
5533
|
+
for (const u of units.values()) if (u.unit.version !== void 0 && !isDefault(u.unit) && changedDefaults.some((d) => (d.product ?? "") === (u.unit.product ?? ""))) for (const o2 of u.handle.pageOuts) markStale(o2, u);
|
|
5359
5534
|
}
|
|
5360
5535
|
if (lazy.size && ctx.state.languages) {
|
|
5361
5536
|
const all = [...units.values()].map((u) => u.unit);
|
|
@@ -220,8 +220,10 @@ export interface SiteState {
|
|
|
220
220
|
pageOut: Map<string, string>;
|
|
221
221
|
/** Sitemap files, relative to the site root, by unit prefix. */
|
|
222
222
|
sitemaps: Map<string, string[]>;
|
|
223
|
-
/** Site-level files a content root supplies itself (robots.txt,
|
|
223
|
+
/** Site-level files a content root supplies itself (robots.txt, the sitemap index); they win over generated ones. */
|
|
224
224
|
supplied: Set<string>;
|
|
225
|
+
/** The root's own `_headers` and `_redirects`, merged with the generated ones (@dogsbay/site-files host-files.ts). */
|
|
226
|
+
hostFiles: Map<string, FileContent>;
|
|
225
227
|
/** A page rendered math, so the KaTeX stylesheet and fonts are written. */
|
|
226
228
|
usedMath: boolean;
|
|
227
229
|
/** Rendered diagrams, shared by the units of the build. */
|
|
@@ -423,10 +425,10 @@ export interface BuildHooks {
|
|
|
423
425
|
/** Build one unit again without rendering its pages (they are rendered on request). */
|
|
424
426
|
export declare function rebuildUnitLazy(ctx: BuildContext, unit: BuildUnit): Promise<UnitHandle>;
|
|
425
427
|
export declare function build(input: BuildInput, hooks?: BuildHooks): Promise<BuildResult>;
|
|
426
|
-
/** robots.txt, _headers, the sitemap index and redirects: the files that belong to the whole site. */
|
|
427
428
|
/**
|
|
428
|
-
* The units `--unit` names: by prefix
|
|
429
|
-
*
|
|
429
|
+
* The units `--unit` names: by prefix; a version served at the root (prefix "", the locale or
|
|
430
|
+
* the product) also by its id, and inside a product by `<product>/<id>`; and a product by its
|
|
431
|
+
* name, which is all its versions and locales. Throws on a name that is no unit.
|
|
430
432
|
*/
|
|
431
433
|
export declare function selectUnits(allUnits: BuildUnit[], names: string[] | undefined): BuildUnit[];
|
|
432
434
|
/**
|
|
@@ -31,8 +31,7 @@ export type FrontMatterOf = (path: string, c: FileContent) => Promise<Record<str
|
|
|
31
31
|
*/
|
|
32
32
|
export declare function frontMatterCache(read: Read): FrontMatterOf;
|
|
33
33
|
/**
|
|
34
|
-
* One table per language of the default version, keyed by
|
|
35
|
-
* without a locale axis). Empty when none of the units being built is an
|
|
34
|
+
* One table per language of the default version and per product, keyed by `tableKey`. Empty when none of the units being built is an
|
|
36
35
|
* older version (then nothing points elsewhere, and nothing is read).
|
|
37
36
|
*/
|
|
38
37
|
export declare function defaultTables(cfg: SiteConfig, units: BuildUnit[], built: BuildUnit[], files: Map<string, FileContent>, read: Read, warn?: (m: string) => void, fm?: FrontMatterOf): Promise<Map<string, DefaultTable>>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ProductModel } from "@dogsbay/site-files";
|
|
1
2
|
export type LinkStyle = "html" | "pretty";
|
|
2
3
|
export type TocMode = "top" | "popover" | "rail" | "off";
|
|
3
4
|
export interface VersionDef {
|
|
@@ -14,9 +15,26 @@ export interface VersionDef {
|
|
|
14
15
|
noindex?: boolean;
|
|
15
16
|
/** Override whether the version's pages are in the sitemap. */
|
|
16
17
|
sitemap?: boolean;
|
|
17
|
-
/**
|
|
18
|
-
|
|
18
|
+
/**
|
|
19
|
+
* The version's URL segment when it is not its id. `""`: served at the root (no version segment),
|
|
20
|
+
* only on the default version. Any other segment (`latest`) only inside `content.products:`.
|
|
21
|
+
*/
|
|
22
|
+
path?: string;
|
|
23
|
+
/** The version's own banner text (`content.products:` only), instead of the standard one. */
|
|
24
|
+
banner?: string;
|
|
25
|
+
}
|
|
26
|
+
/** A call into @dogsbay/site-files' product model, its config errors reported as ours (dev and the CLI tell them apart). */
|
|
27
|
+
export declare function shared<T>(f: () => T): T;
|
|
28
|
+
/** The versions a unit's product has, and its default. */
|
|
29
|
+
export interface ProductVersions {
|
|
30
|
+
versions: VersionDef[];
|
|
31
|
+
defaultVersion?: string;
|
|
19
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* A product's versions and default: its own with `content.products:`, else the site-wide `versions:`
|
|
35
|
+
* and `defaultVersion` (the unnamed source's, and every product's without the block).
|
|
36
|
+
*/
|
|
37
|
+
export declare function versionsOf(cfg: Pick<SiteConfig, "versions" | "defaultVersion" | "productVersions">, product: string | undefined): ProductVersions;
|
|
20
38
|
export interface LocaleDef {
|
|
21
39
|
id: string;
|
|
22
40
|
label: string;
|
|
@@ -72,6 +90,10 @@ export interface SiteConfig {
|
|
|
72
90
|
routablesFrom: "all" | "nav";
|
|
73
91
|
versions: VersionDef[];
|
|
74
92
|
defaultVersion?: string;
|
|
93
|
+
/** `content.products:`, read by @dogsbay/site-files' `productModel` (plans/product-versions-ssg.md). Undefined without the block. */
|
|
94
|
+
products?: ProductModel;
|
|
95
|
+
/** With `products`: each product's versions and default (key `""` for the unnamed source's), read through `versionsOf`. */
|
|
96
|
+
productVersions?: Map<string, ProductVersions>;
|
|
75
97
|
locales: LocaleDef[];
|
|
76
98
|
defaultLocale?: string;
|
|
77
99
|
search: boolean;
|
|
@@ -274,10 +296,26 @@ export interface BuildUnit {
|
|
|
274
296
|
/** Every source the unit builds, the main one included, in config order. */
|
|
275
297
|
members: UnitMember[];
|
|
276
298
|
version?: string;
|
|
299
|
+
/** The version's URL segment: its id, its `path` (`latest`), or `""` when served without one. */
|
|
300
|
+
versionPath?: string;
|
|
277
301
|
locale?: string;
|
|
278
|
-
/**
|
|
302
|
+
/**
|
|
303
|
+
* The named source the unit publishes, when named sources are combined with versions or locales
|
|
304
|
+
* (a product): its first prefix segment, as the CLI's `/<name>/<locale>/<version>/` order.
|
|
305
|
+
* Units of one product share it; the unnamed source's units have none.
|
|
306
|
+
*/
|
|
307
|
+
product?: string;
|
|
308
|
+
/** Output prefix inside the site, e.g. "en/3.31", "calico/3.31", or "" when no axis is active. */
|
|
279
309
|
prefix: string;
|
|
280
310
|
}
|
|
311
|
+
/**
|
|
312
|
+
* The prefix of a unit's product and locale, without its version: where the unit's
|
|
313
|
+
* versions sit side by side ("calico/en", "en", or ""). A version served at the root
|
|
314
|
+
* (`path: ""`) has this as its prefix.
|
|
315
|
+
*/
|
|
316
|
+
export declare function groupPrefix(u: Pick<BuildUnit, "product" | "locale">): string;
|
|
317
|
+
/** Whether two units are versions or languages of the same product (or both of no product). */
|
|
318
|
+
export declare const sameProduct: (a: Pick<BuildUnit, "product">, b: Pick<BuildUnit, "product">) => boolean;
|
|
281
319
|
/**
|
|
282
320
|
* Expand sources into units. An axis is "active" (adds a URL segment)
|
|
283
321
|
* when the sources carry two or more distinct values for it, or when
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dogsbay/ssg",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.146",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Documentation static site generator for Dogsbay-MD that builds inside Cloudflare Workers and publishes sites that work offline",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -49,38 +49,38 @@
|
|
|
49
49
|
"tailwindcss": "^4.3.2"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@dogsbay/elements": "0.2.0-beta.
|
|
53
|
-
"@dogsbay/format-dogsbay-md": "0.2.0-beta.
|
|
54
|
-
"@dogsbay/format-openapi": "0.2.0-beta.
|
|
55
|
-
"@dogsbay/format-topicmap": "0.2.0-beta.
|
|
56
|
-
"@dogsbay/highlight": "0.2.0-beta.
|
|
57
|
-
"@dogsbay/minja": "0.2.0-beta.
|
|
58
|
-
"@dogsbay/primitives": "0.2.0-beta.
|
|
59
|
-
"@dogsbay/render-html": "0.2.0-beta.
|
|
60
|
-
"@dogsbay/search": "0.2.0-beta.
|
|
61
|
-
"@dogsbay/serialize-core": "0.2.0-beta.
|
|
62
|
-
"@dogsbay/site-check": "0.2.0-beta.
|
|
63
|
-
"@dogsbay/site-files": "0.2.0-beta.
|
|
64
|
-
"@dogsbay/types": "0.2.0-beta.
|
|
52
|
+
"@dogsbay/elements": "0.2.0-beta.146",
|
|
53
|
+
"@dogsbay/format-dogsbay-md": "0.2.0-beta.146",
|
|
54
|
+
"@dogsbay/format-openapi": "0.2.0-beta.146",
|
|
55
|
+
"@dogsbay/format-topicmap": "0.2.0-beta.146",
|
|
56
|
+
"@dogsbay/highlight": "0.2.0-beta.146",
|
|
57
|
+
"@dogsbay/minja": "0.2.0-beta.146",
|
|
58
|
+
"@dogsbay/primitives": "0.2.0-beta.146",
|
|
59
|
+
"@dogsbay/render-html": "0.2.0-beta.146",
|
|
60
|
+
"@dogsbay/search": "0.2.0-beta.146",
|
|
61
|
+
"@dogsbay/serialize-core": "0.2.0-beta.146",
|
|
62
|
+
"@dogsbay/site-check": "0.2.0-beta.146",
|
|
63
|
+
"@dogsbay/site-files": "0.2.0-beta.146",
|
|
64
|
+
"@dogsbay/types": "0.2.0-beta.146"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@axe-core/playwright": "^4.12.1",
|
|
68
68
|
"@cloudflare/workers-types": "^5.20260921.1",
|
|
69
|
-
"@dogsbay/elements": "0.2.0-beta.
|
|
70
|
-
"@dogsbay/format-dogsbay-md": "0.2.0-beta.
|
|
71
|
-
"@dogsbay/format-openapi": "0.2.0-beta.
|
|
72
|
-
"@dogsbay/format-topicmap": "0.2.0-beta.
|
|
73
|
-
"@dogsbay/highlight": "0.2.0-beta.
|
|
74
|
-
"@dogsbay/icons": "0.2.0-beta.
|
|
75
|
-
"@dogsbay/minja": "0.2.0-beta.
|
|
76
|
-
"@dogsbay/primitives": "0.2.0-beta.
|
|
77
|
-
"@dogsbay/render-html": "0.2.0-beta.
|
|
78
|
-
"@dogsbay/search": "0.2.0-beta.
|
|
79
|
-
"@dogsbay/serialize-core": "0.2.0-beta.
|
|
80
|
-
"@dogsbay/site-check": "0.2.0-beta.
|
|
81
|
-
"@dogsbay/site-files": "0.2.0-beta.
|
|
82
|
-
"@dogsbay/types": "0.2.0-beta.
|
|
83
|
-
"@dogsbay/ui": "0.2.0-beta.
|
|
69
|
+
"@dogsbay/elements": "0.2.0-beta.146",
|
|
70
|
+
"@dogsbay/format-dogsbay-md": "0.2.0-beta.146",
|
|
71
|
+
"@dogsbay/format-openapi": "0.2.0-beta.146",
|
|
72
|
+
"@dogsbay/format-topicmap": "0.2.0-beta.146",
|
|
73
|
+
"@dogsbay/highlight": "0.2.0-beta.146",
|
|
74
|
+
"@dogsbay/icons": "0.2.0-beta.146",
|
|
75
|
+
"@dogsbay/minja": "0.2.0-beta.146",
|
|
76
|
+
"@dogsbay/primitives": "0.2.0-beta.146",
|
|
77
|
+
"@dogsbay/render-html": "0.2.0-beta.146",
|
|
78
|
+
"@dogsbay/search": "0.2.0-beta.146",
|
|
79
|
+
"@dogsbay/serialize-core": "0.2.0-beta.146",
|
|
80
|
+
"@dogsbay/site-check": "0.2.0-beta.146",
|
|
81
|
+
"@dogsbay/site-files": "0.2.0-beta.146",
|
|
82
|
+
"@dogsbay/types": "0.2.0-beta.146",
|
|
83
|
+
"@dogsbay/ui": "0.2.0-beta.146",
|
|
84
84
|
"@mermanjs/web": "0.7.0",
|
|
85
85
|
"@playwright/test": "1.61.1",
|
|
86
86
|
"@types/node": "^22.10.0",
|