@dogsbay/ssg 0.2.0-beta.132 → 0.2.0-beta.134
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/package/THIRD-PARTY-NOTICES.txt +5 -5
- package/dist/package/browser.mjs +336 -49
- package/dist/package/types/core/build.d.ts +30 -0
- package/dist/package/types/core/dev.d.ts +18 -6
- package/dist/package/types/core/nav.d.ts +2 -1
- package/dist/package/types/core/preprocess.d.ts +54 -1
- package/dist/package/types/core/scan-cache.d.ts +51 -0
- package/dist/package/types/package/browser.d.ts +2 -2
- package/package.json +29 -29
|
@@ -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.134 (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.134 (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.134 (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.134 (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.134 (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
|
@@ -462,6 +462,12 @@ function sourceNav(v, path, from) {
|
|
|
462
462
|
if (!/\.(ya?ml|json)$/i.test(p)) throw new ConfigError(`content.sources (${path}): nav must be a .topicmap.yml topic map or a .yml or .json nav file; got ${JSON.stringify(v)}`);
|
|
463
463
|
return p;
|
|
464
464
|
}
|
|
465
|
+
function projectRoots(cfg) {
|
|
466
|
+
const roots = cfg.sources.map((s) => s.path === "." ? "" : s.path);
|
|
467
|
+
if (roots.includes("")) return [""];
|
|
468
|
+
const navDirs = cfg.sources.flatMap((s) => s.nav ? [s.nav.includes("/") ? s.nav.slice(0, s.nav.lastIndexOf("/")) : s.nav] : []);
|
|
469
|
+
return [.../* @__PURE__ */ new Set([...roots, cfg.themeDir, ...cfg.css, ...navDirs])].filter(Boolean);
|
|
470
|
+
}
|
|
465
471
|
function sourceRoot(s) {
|
|
466
472
|
return s.path === "." ? "" : s.path.replace(/^\.\//, "").replace(/\/+$/, "") + "/";
|
|
467
473
|
}
|
|
@@ -548,8 +554,8 @@ function slugFromPath(p) {
|
|
|
548
554
|
if (s.endsWith("/index")) s = s.slice(0, -"/index".length);
|
|
549
555
|
return s;
|
|
550
556
|
}
|
|
551
|
-
function parseNavYaml(text, labelFor, baseDir = "") {
|
|
552
|
-
const data =
|
|
557
|
+
function parseNavYaml(text, labelFor, baseDir = "", load2 = loadYaml) {
|
|
558
|
+
const data = load2(text);
|
|
553
559
|
if (!Array.isArray(data)) return [];
|
|
554
560
|
return data.flatMap((e) => yamlEntry(e, labelFor, baseDir, false));
|
|
555
561
|
}
|
|
@@ -1066,31 +1072,31 @@ var CLIENT_CANDIDATES = ['""', '"&"', '"\\\\$&")).join("|")})', '"\\\\$&")}"', '
|
|
|
1066
1072
|
var SITE_NOTICES = `Third-party software in this site's _dogsbay/ files (dogsbay.js, site.css) and pages
|
|
1067
1073
|
|
|
1068
1074
|
========================================================================
|
|
1069
|
-
@dogsbay/elements@0.2.0-beta.
|
|
1075
|
+
@dogsbay/elements@0.2.0-beta.134 (MIT)
|
|
1070
1076
|
https://github.com/dogsbay/dogsbay.git
|
|
1071
1077
|
|
|
1072
1078
|
Licensed under MIT; the package ships no licence file.
|
|
1073
1079
|
|
|
1074
1080
|
========================================================================
|
|
1075
|
-
@dogsbay/primitives@0.2.0-beta.
|
|
1081
|
+
@dogsbay/primitives@0.2.0-beta.134 (MIT)
|
|
1076
1082
|
https://github.com/dogsbay/dogsbay.git
|
|
1077
1083
|
|
|
1078
1084
|
Licensed under MIT; the package ships no licence file.
|
|
1079
1085
|
|
|
1080
1086
|
========================================================================
|
|
1081
|
-
@dogsbay/render-html@0.2.0-beta.
|
|
1087
|
+
@dogsbay/render-html@0.2.0-beta.134 (MIT)
|
|
1082
1088
|
https://github.com/dogsbay/dogsbay.git
|
|
1083
1089
|
|
|
1084
1090
|
Licensed under MIT; the package ships no licence file.
|
|
1085
1091
|
|
|
1086
1092
|
========================================================================
|
|
1087
|
-
@dogsbay/search@0.2.0-beta.
|
|
1093
|
+
@dogsbay/search@0.2.0-beta.134 (MIT)
|
|
1088
1094
|
https://github.com/dogsbay/dogsbay.git
|
|
1089
1095
|
|
|
1090
1096
|
Licensed under MIT; the package ships no licence file.
|
|
1091
1097
|
|
|
1092
1098
|
========================================================================
|
|
1093
|
-
@dogsbay/ui@0.2.0-beta.
|
|
1099
|
+
@dogsbay/ui@0.2.0-beta.134 (MIT)
|
|
1094
1100
|
https://github.com/dogsbay/dogsbay.git
|
|
1095
1101
|
|
|
1096
1102
|
Licensed under MIT; the package ships no licence file.
|
|
@@ -2164,7 +2170,7 @@ var ThemeTemplates = class {
|
|
|
2164
2170
|
};
|
|
2165
2171
|
|
|
2166
2172
|
// src/core/preprocess.ts
|
|
2167
|
-
import { render } from "@dogsbay/minja/browser";
|
|
2173
|
+
import { render, RenderLimitError } from "@dogsbay/minja/browser";
|
|
2168
2174
|
import {
|
|
2169
2175
|
maskMinjaInCode,
|
|
2170
2176
|
unmaskMinjaInCode,
|
|
@@ -2194,11 +2200,59 @@ var MapLoader = class {
|
|
|
2194
2200
|
throw new Error(`include not found: ${path}${basePath ? ` (from ${basePath})` : ""}`);
|
|
2195
2201
|
}
|
|
2196
2202
|
};
|
|
2203
|
+
var TemplateBudget = class {
|
|
2204
|
+
constructor(renderMs, buildMs, now2 = () => Date.now()) {
|
|
2205
|
+
this.renderMs = renderMs;
|
|
2206
|
+
this.buildMs = buildMs;
|
|
2207
|
+
this.now = now2;
|
|
2208
|
+
}
|
|
2209
|
+
spentMs = 0;
|
|
2210
|
+
active = 0;
|
|
2211
|
+
since = 0;
|
|
2212
|
+
/** Renders not run because the budget was spent, by what they were for. */
|
|
2213
|
+
skipped = { pages: 0, titles: 0 };
|
|
2214
|
+
get spent() {
|
|
2215
|
+
return this.spentMs + (this.active ? this.now() - this.since : 0);
|
|
2216
|
+
}
|
|
2217
|
+
/** The time the next render may take; 0 when the budget is spent. */
|
|
2218
|
+
next() {
|
|
2219
|
+
return Math.max(0, Math.min(this.renderMs, this.buildMs - this.spent));
|
|
2220
|
+
}
|
|
2221
|
+
start() {
|
|
2222
|
+
if (this.active++ === 0) this.since = this.now();
|
|
2223
|
+
}
|
|
2224
|
+
end() {
|
|
2225
|
+
if (--this.active === 0) this.spentMs += this.now() - this.since;
|
|
2226
|
+
}
|
|
2227
|
+
reset() {
|
|
2228
|
+
this.spentMs = 0;
|
|
2229
|
+
this.since = this.now();
|
|
2230
|
+
this.skipped = { pages: 0, titles: 0 };
|
|
2231
|
+
}
|
|
2232
|
+
/** The problem to report when renders were skipped since the last reset, else undefined. */
|
|
2233
|
+
problem() {
|
|
2234
|
+
const { pages, titles } = this.skipped;
|
|
2235
|
+
if (!pages && !titles) return void 0;
|
|
2236
|
+
const what = [pages && `${pages} page(s)`, titles && `${titles} title(s)`].filter(Boolean).join(" and ");
|
|
2237
|
+
return `[template] the template time budget (${this.buildMs / 1e3} s) ran out: ${what} shown without their templates rendered`;
|
|
2238
|
+
}
|
|
2239
|
+
};
|
|
2240
|
+
function templateBudget(untrusted, given) {
|
|
2241
|
+
return new TemplateBudget(given?.renderMs ?? (untrusted ? 2e3 : 1e4), given?.buildMs ?? (untrusted ? 3e4 : 6e5));
|
|
2242
|
+
}
|
|
2197
2243
|
function needsTemplating(text) {
|
|
2198
2244
|
return text.includes("{{") || text.includes("{%");
|
|
2199
2245
|
}
|
|
2200
|
-
async function preprocess(text, path, attributes, files, undefinedRefs = "preserve") {
|
|
2246
|
+
async function preprocess(text, path, attributes, files, undefinedRefs = "preserve", run = {}) {
|
|
2201
2247
|
if (!needsTemplating(text)) return { text };
|
|
2248
|
+
const budget = run.budget;
|
|
2249
|
+
const timeout = budget ? budget.next() : 1e4;
|
|
2250
|
+
const skip = () => {
|
|
2251
|
+
if (run.kind !== "copy") budget.skipped[run.kind === "title" ? "titles" : "pages"]++;
|
|
2252
|
+
return { text, skipped: true };
|
|
2253
|
+
};
|
|
2254
|
+
if (budget && timeout <= 0) return skip();
|
|
2255
|
+
budget?.start();
|
|
2202
2256
|
try {
|
|
2203
2257
|
const out = await render(mask(text), {
|
|
2204
2258
|
context: withUnderscoreAliases(attributes),
|
|
@@ -2207,11 +2261,15 @@ async function preprocess(text, path, attributes, files, undefinedRefs = "preser
|
|
|
2207
2261
|
hyphenToUnderscore: true,
|
|
2208
2262
|
basePath: dirname(path),
|
|
2209
2263
|
loader: new MapLoader(files),
|
|
2210
|
-
timeout
|
|
2264
|
+
timeout,
|
|
2265
|
+
...run.parseCache !== void 0 ? { parseCache: run.parseCache } : {}
|
|
2211
2266
|
});
|
|
2212
2267
|
return { text: stripFenceMinjaMarkers(stripInlineMinjaMarkers(unmask(out))) };
|
|
2213
2268
|
} catch (err) {
|
|
2269
|
+
if (budget && timeout < budget.renderMs && err instanceof RenderLimitError && budget.next() <= 0) return skip();
|
|
2214
2270
|
return { text, error: err instanceof Error ? err.message : String(err) };
|
|
2271
|
+
} finally {
|
|
2272
|
+
budget?.end();
|
|
2215
2273
|
}
|
|
2216
2274
|
}
|
|
2217
2275
|
function withUnderscoreAliases(attrs2) {
|
|
@@ -2223,6 +2281,84 @@ function withUnderscoreAliases(attrs2) {
|
|
|
2223
2281
|
return out;
|
|
2224
2282
|
}
|
|
2225
2283
|
|
|
2284
|
+
// src/core/build.ts
|
|
2285
|
+
import { ParseCache, DEFAULT_PARSE_CACHE_BYTES } from "@dogsbay/minja/browser";
|
|
2286
|
+
|
|
2287
|
+
// src/core/scan-cache.ts
|
|
2288
|
+
var ScanCache = class {
|
|
2289
|
+
entries = /* @__PURE__ */ new Map();
|
|
2290
|
+
/** Project path of a file read while resolving titles → the pages whose entries read it. */
|
|
2291
|
+
readers = /* @__PURE__ */ new Map();
|
|
2292
|
+
/** The last nav YAML loaded, by its text: an unchanged nav.yml is not parsed again. */
|
|
2293
|
+
navText;
|
|
2294
|
+
navData;
|
|
2295
|
+
/** Resolved topic maps, with what they were resolved with and the file map's value of every file read. */
|
|
2296
|
+
maps = /* @__PURE__ */ new Map();
|
|
2297
|
+
/** The page's entry when it was made from this content, else a new empty one for it. */
|
|
2298
|
+
entry(path, content) {
|
|
2299
|
+
const had = this.entries.get(path);
|
|
2300
|
+
if (had && had.content === content) return had;
|
|
2301
|
+
if (had) this.dropDeps(path, had);
|
|
2302
|
+
const e = { content };
|
|
2303
|
+
this.entries.set(path, e);
|
|
2304
|
+
return e;
|
|
2305
|
+
}
|
|
2306
|
+
/** Records that a page's title or description read a file, so a change to that file drops them. */
|
|
2307
|
+
read(page, file) {
|
|
2308
|
+
const e = this.entries.get(page);
|
|
2309
|
+
if (!e) return;
|
|
2310
|
+
(e.deps ??= /* @__PURE__ */ new Set()).add(file);
|
|
2311
|
+
let r = this.readers.get(file);
|
|
2312
|
+
if (!r) this.readers.set(file, r = /* @__PURE__ */ new Set());
|
|
2313
|
+
r.add(page);
|
|
2314
|
+
}
|
|
2315
|
+
/** A file changed, was added or was removed: its own entry goes, and the titles that read it. */
|
|
2316
|
+
changed(path) {
|
|
2317
|
+
const own = this.entries.get(path);
|
|
2318
|
+
if (own) {
|
|
2319
|
+
this.dropDeps(path, own);
|
|
2320
|
+
this.entries.delete(path);
|
|
2321
|
+
}
|
|
2322
|
+
const readers = this.readers.get(path);
|
|
2323
|
+
if (!readers) return;
|
|
2324
|
+
this.readers.delete(path);
|
|
2325
|
+
for (const page of readers) {
|
|
2326
|
+
const e = this.entries.get(page);
|
|
2327
|
+
if (!e) continue;
|
|
2328
|
+
this.dropDeps(page, e);
|
|
2329
|
+
delete e.title;
|
|
2330
|
+
delete e.description;
|
|
2331
|
+
delete e.resolvedWith;
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
/** `load(text)`, or the value it gave for the same text last time (the caller must not change it). */
|
|
2335
|
+
yaml(text, load2) {
|
|
2336
|
+
if (this.navText !== text) {
|
|
2337
|
+
this.navData = load2(text);
|
|
2338
|
+
this.navText = text;
|
|
2339
|
+
}
|
|
2340
|
+
return this.navData;
|
|
2341
|
+
}
|
|
2342
|
+
/** A topic map resolved with `key` (its variables), if no file it read has changed since. */
|
|
2343
|
+
topicMap(path, key, files) {
|
|
2344
|
+
const m = this.maps.get(path);
|
|
2345
|
+
if (!m || m.key !== key) return void 0;
|
|
2346
|
+
for (const [p, c] of m.reads) if (files.get(p) !== c) return void 0;
|
|
2347
|
+
return m.nav;
|
|
2348
|
+
}
|
|
2349
|
+
/** Keeps a resolved topic map (not one with errors: the build stops on those) and the files it read. */
|
|
2350
|
+
keepTopicMap(path, key, reads, nav) {
|
|
2351
|
+
if (!nav.errors.length) this.maps.set(path, { key, reads, nav });
|
|
2352
|
+
}
|
|
2353
|
+
get size() {
|
|
2354
|
+
return this.entries.size;
|
|
2355
|
+
}
|
|
2356
|
+
dropDeps(page, e) {
|
|
2357
|
+
for (const f of e.deps ?? []) this.readers.get(f)?.delete(page);
|
|
2358
|
+
e.deps = void 0;
|
|
2359
|
+
}
|
|
2360
|
+
};
|
|
2361
|
+
|
|
2226
2362
|
// src/core/build.ts
|
|
2227
2363
|
import { TemplatePages } from "@dogsbay/format-dogsbay-md/browser";
|
|
2228
2364
|
import { extractText, SearchIndexBuilder } from "@dogsbay/search/index";
|
|
@@ -2896,6 +3032,16 @@ function fmKey(src) {
|
|
|
2896
3032
|
return detach(`${m ? m[0] : ""}
|
|
2897
3033
|
${firstH1(src) ?? ""}`);
|
|
2898
3034
|
}
|
|
3035
|
+
function detachValue(v) {
|
|
3036
|
+
if (typeof v === "string") return detach(v);
|
|
3037
|
+
if (Array.isArray(v)) return v.map(detachValue);
|
|
3038
|
+
if (v && typeof v === "object" && Object.getPrototypeOf(v) === Object.prototype) {
|
|
3039
|
+
const o = {};
|
|
3040
|
+
for (const [k, x] of Object.entries(v)) o[detach(k)] = detachValue(x);
|
|
3041
|
+
return o;
|
|
3042
|
+
}
|
|
3043
|
+
return v;
|
|
3044
|
+
}
|
|
2899
3045
|
function frontMatterCopy(fm) {
|
|
2900
3046
|
try {
|
|
2901
3047
|
const copy = JSON.parse(JSON.stringify(fm));
|
|
@@ -2942,7 +3088,7 @@ async function build(input, hooks = {}) {
|
|
|
2942
3088
|
phase.init = now() - t0;
|
|
2943
3089
|
let pages = 0;
|
|
2944
3090
|
let assets = 0;
|
|
2945
|
-
const state = { redirects: [], 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) };
|
|
3091
|
+
const state = { redirects: [], 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) };
|
|
2946
3092
|
for (const r of cfg.redirects) {
|
|
2947
3093
|
const from = sitePath(r.from, cfg.basePath);
|
|
2948
3094
|
if (!from) {
|
|
@@ -3013,12 +3159,14 @@ async function build(input, hooks = {}) {
|
|
|
3013
3159
|
}
|
|
3014
3160
|
}
|
|
3015
3161
|
state.stubs = await writeTranslationStubs(cfg, allUnits, units, translations, state, emit);
|
|
3162
|
+
const spent = state.templateBudget.problem();
|
|
3163
|
+
if (spent) report("template", spent);
|
|
3016
3164
|
return {
|
|
3017
3165
|
files: out,
|
|
3018
3166
|
warnings,
|
|
3019
3167
|
problems,
|
|
3020
3168
|
config: cfg,
|
|
3021
|
-
stats: { pages, assets, units: units.length, ms: Math.round(now() - t0), msByPhase: roundAll(phase), highlightCache: highlighter.cacheStats() }
|
|
3169
|
+
stats: { pages, assets, units: units.length, ms: Math.round(now() - t0), msByPhase: roundAll(phase), highlightCache: highlighter.cacheStats(), ...state.parseCache ? { parseCache: state.parseCache.stats() } : {} }
|
|
3022
3170
|
};
|
|
3023
3171
|
}
|
|
3024
3172
|
function selectUnits(allUnits, names) {
|
|
@@ -3116,9 +3264,14 @@ async function buildUnit(unit, allUnits, cfg, input, highlighter, emit, report,
|
|
|
3116
3264
|
const ns = named.length ? namespaceOf(src) : "";
|
|
3117
3265
|
return ns ? (p) => p === ns || p.startsWith(ns + "/") ? p : `${ns}/${p}` : void 0;
|
|
3118
3266
|
};
|
|
3119
|
-
const includesFor = (src) => {
|
|
3267
|
+
const includesFor = (src, read2) => {
|
|
3120
3268
|
const at = scoped(src);
|
|
3121
|
-
return at ? (p) => readInclude(at(p)) : readInclude;
|
|
3269
|
+
if (!read2) return at ? (p) => readInclude(at(p)) : readInclude;
|
|
3270
|
+
return (p) => {
|
|
3271
|
+
const q = at ? at(p) : p;
|
|
3272
|
+
read2(abs(q));
|
|
3273
|
+
return readInclude(q);
|
|
3274
|
+
};
|
|
3122
3275
|
};
|
|
3123
3276
|
const namespaceOf = (p) => named.find((m) => p === m.namespace || p.startsWith(m.namespace + "/"))?.namespace ?? "";
|
|
3124
3277
|
const globalPrefixes = new Set(cfg.taxonomies.map((t2) => t2.path.split("/")[0]).filter(Boolean));
|
|
@@ -3156,6 +3309,7 @@ async function buildUnit(unit, allUnits, cfg, input, highlighter, emit, report,
|
|
|
3156
3309
|
return c == null ? void 0 : readText(c);
|
|
3157
3310
|
};
|
|
3158
3311
|
const includedPaths = /* @__PURE__ */ new Set();
|
|
3312
|
+
const includedProject = /* @__PURE__ */ new Set();
|
|
3159
3313
|
const readInclude = async (p) => {
|
|
3160
3314
|
if (mode.keep || mode.lazy) includedPaths.add(p);
|
|
3161
3315
|
const hit = cache.get(p);
|
|
@@ -3168,7 +3322,8 @@ async function buildUnit(unit, allUnits, cfg, input, highlighter, emit, report,
|
|
|
3168
3322
|
};
|
|
3169
3323
|
const resolvers = [openApiResolver(read, input.openApiChars), autodocUnresolved, ...input.resolvers?.(unit) ?? []];
|
|
3170
3324
|
const hasContent = (p) => !buildOnly(p) && input.files.has(abs(p));
|
|
3171
|
-
const
|
|
3325
|
+
const templateRun = { parseCache: state.parseCache, budget: state.templateBudget, kind: "page" };
|
|
3326
|
+
const resolveTitle = async (title, src, path, pageFm, read2) => {
|
|
3172
3327
|
if (!isTemplated(title)) return title;
|
|
3173
3328
|
if (pageFm && templatesOf(path).isTemplatePage(pageFm)) {
|
|
3174
3329
|
return (await templatesOf(path).renderField(title, path, pageFm)).trim();
|
|
@@ -3178,7 +3333,7 @@ async function buildUnit(unit, allUnits, cfg, input, highlighter, emit, report,
|
|
|
3178
3333
|
const preamble = head.split("\n").filter((l) => /^\s*\{%-?\s*(include|set)\b/.test(l)).join("\n");
|
|
3179
3334
|
const marker = "DBTITLEMARKER";
|
|
3180
3335
|
const r = await preprocess(`${preamble}
|
|
3181
|
-
${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.undefinedRefs);
|
|
3336
|
+
${marker}${title}${marker}`, path, attributesOf(path), includesFor(path, read2), cfg.undefinedRefs, { parseCache: state.parseCache, budget: state.templateBudget, kind: "title" });
|
|
3182
3337
|
const m = r.text.split(marker);
|
|
3183
3338
|
return (m.length >= 3 ? m[1] : title).trim();
|
|
3184
3339
|
};
|
|
@@ -3186,13 +3341,23 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3186
3341
|
for (const m of unit.members) {
|
|
3187
3342
|
const path = m.source.nav;
|
|
3188
3343
|
if (!path || !TOPIC_MAP.test(path) || topicMaps.has(path)) continue;
|
|
3344
|
+
const variables = withUnderscoreAliases({ ...cfg.attributes, ...m.source.attributes ?? {} });
|
|
3345
|
+
const key = state.scan ? JSON.stringify([sourceRoot(m.source), variables]) : "";
|
|
3346
|
+
const kept = state.scan?.topicMap(path, key, input.files);
|
|
3347
|
+
if (kept) {
|
|
3348
|
+
topicMaps.set(path, kept);
|
|
3349
|
+
continue;
|
|
3350
|
+
}
|
|
3189
3351
|
const { topicMapError, topicMapNav } = await import("./chunks/topicmap-PY3WDCSI.mjs");
|
|
3352
|
+
const reads = /* @__PURE__ */ new Map();
|
|
3190
3353
|
const projectText = async (p) => {
|
|
3191
3354
|
const c = input.files.get(p);
|
|
3355
|
+
reads.set(p, c);
|
|
3192
3356
|
return c == null ? void 0 : readText(c);
|
|
3193
3357
|
};
|
|
3194
|
-
const got = await topicMapNav(path, sourceRoot(m.source), projectText,
|
|
3358
|
+
const got = await topicMapNav(path, sourceRoot(m.source), projectText, variables);
|
|
3195
3359
|
if (got.errors.length) throw topicMapError(path, got.errors);
|
|
3360
|
+
state.scan?.keepTopicMap(path, key, reads, got);
|
|
3196
3361
|
topicMaps.set(path, got);
|
|
3197
3362
|
}
|
|
3198
3363
|
const navInputs = /* @__PURE__ */ new Set([...unit.members.flatMap((m) => m.source.nav ? [m.source.nav] : []), ...[...topicMaps.values()].flatMap((t2) => t2.maps)]);
|
|
@@ -3213,6 +3378,13 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3213
3378
|
}
|
|
3214
3379
|
return a;
|
|
3215
3380
|
};
|
|
3381
|
+
const resolvedKeys = /* @__PURE__ */ new Map();
|
|
3382
|
+
const resolvedKey = (p) => {
|
|
3383
|
+
const key = named.length ? namespaceOf(p) : "";
|
|
3384
|
+
let k = resolvedKeys.get(key);
|
|
3385
|
+
if (k === void 0) resolvedKeys.set(key, k = JSON.stringify([label, key, sourceOf(p).templates ?? null, cfg.name, cfg.undefinedRefs, attributesOf(p)]));
|
|
3386
|
+
return k;
|
|
3387
|
+
};
|
|
3216
3388
|
const templatesBy = /* @__PURE__ */ new Map();
|
|
3217
3389
|
const templatesOf = (p) => {
|
|
3218
3390
|
const key = named.length ? namespaceOf(p) : "";
|
|
@@ -3234,18 +3406,31 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3234
3406
|
const sanitizing = (cfg.html ?? input.defaultHtml ?? "keep") === "sanitize";
|
|
3235
3407
|
const activeFiles = [];
|
|
3236
3408
|
const untrustedFiles = [];
|
|
3409
|
+
const leftOut = /* @__PURE__ */ new Map();
|
|
3237
3410
|
for (const [p, c] of files) {
|
|
3238
3411
|
if (buildOnly(p)) continue;
|
|
3239
3412
|
if (/\.(md|markdown)$/i.test(p)) {
|
|
3240
|
-
if (excluded(p))
|
|
3413
|
+
if (excluded(p)) {
|
|
3414
|
+
leftOut.set(slugFromPath(p), cfg.excludeFromRoutes.find((d) => p === d || p.startsWith(d.replace(/\/+$/, "") + "/")) ?? "_ or . files");
|
|
3415
|
+
continue;
|
|
3416
|
+
}
|
|
3241
3417
|
const slug = slugFromPath(p);
|
|
3242
|
-
const
|
|
3418
|
+
const memo2 = state.scan?.entry(abs(p), c);
|
|
3419
|
+
let text;
|
|
3420
|
+
const source = async () => text ??= await readText(c);
|
|
3243
3421
|
let fm = {};
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3422
|
+
if (memo2?.fm) fm = memo2.fm;
|
|
3423
|
+
else {
|
|
3424
|
+
try {
|
|
3425
|
+
fm = splitFrontmatter2(await source()).data ?? {};
|
|
3426
|
+
} catch {
|
|
3427
|
+
}
|
|
3428
|
+
if (memo2) memo2.fm = detachValue(fm);
|
|
3429
|
+
}
|
|
3430
|
+
if (fm.status === "draft" && !input.includeDrafts) {
|
|
3431
|
+
leftOut.set(slug, "draft");
|
|
3432
|
+
continue;
|
|
3247
3433
|
}
|
|
3248
|
-
if (fm.status === "draft" && !input.includeDrafts) continue;
|
|
3249
3434
|
if (templatesOf(p).isPartial(fm, p)) continue;
|
|
3250
3435
|
const inUnit = (s) => unit.prefix && (s === unit.prefix || s.startsWith(unit.prefix + "/")) ? s : [unit.prefix, s].filter(Boolean).join("/");
|
|
3251
3436
|
const pageNs = named.length ? namespaceOf(p) : "";
|
|
@@ -3279,20 +3464,35 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3279
3464
|
warn("duplicate-page", `two sources map to the page "${slug || "/"}"; keeping ${srcOf(infos.get(slug))}, ignoring ${abs(p)}`, { file: abs(p) });
|
|
3280
3465
|
continue;
|
|
3281
3466
|
}
|
|
3467
|
+
const resolvedWith = memo2 ? resolvedKey(p) : void 0;
|
|
3468
|
+
let title;
|
|
3469
|
+
let description;
|
|
3470
|
+
if (memo2 && memo2.title !== void 0 && memo2.resolvedWith === resolvedWith) {
|
|
3471
|
+
title = memo2.title;
|
|
3472
|
+
description = memo2.description;
|
|
3473
|
+
for (const f of memo2.deps ?? []) includedProject.add(f);
|
|
3474
|
+
} else {
|
|
3475
|
+
const keep = memo2 && !templatesOf(p).isTemplatePage(fm);
|
|
3476
|
+
const reads = keep ? (f) => state.scan.read(abs(p), f) : void 0;
|
|
3477
|
+
const skippedBefore = state.templateBudget.skipped.titles;
|
|
3478
|
+
title = detach(await resolveTitle(str(fm.title) ?? firstH1(await source()) ?? humanize2(slug.split("/").pop() || cfg.name), await source(), p, fm, reads));
|
|
3479
|
+
description = fm.description != null ? detach(await resolveTitle(String(fm.description), await source(), p, fm, reads)) : void 0;
|
|
3480
|
+
if (keep && state.templateBudget.skipped.titles === skippedBefore) Object.assign(memo2, { title, description, resolvedWith });
|
|
3481
|
+
}
|
|
3282
3482
|
infos.set(slug, {
|
|
3283
3483
|
slug,
|
|
3284
3484
|
source: p,
|
|
3285
3485
|
out: outFileFor(slug, isIndexFile),
|
|
3286
|
-
title
|
|
3486
|
+
title,
|
|
3287
3487
|
order: typeof fm.order === "number" ? fm.order : typeof fm.weight === "number" ? fm.weight : void 0,
|
|
3288
3488
|
draft: fm.draft === true || fm.status === "draft",
|
|
3289
|
-
description
|
|
3489
|
+
description,
|
|
3290
3490
|
data: frontMatterCopy(fm)
|
|
3291
3491
|
});
|
|
3292
|
-
if (diagrams) for (const code of fencedDiagrams(
|
|
3492
|
+
if (diagrams) for (const code of memo2 ? memo2.diagrams ??= fencedDiagrams(await source()).map(detach) : fencedDiagrams(await source())) diagrams.note(detach(code), p);
|
|
3293
3493
|
taxonomies?.add(slug, fm);
|
|
3294
3494
|
blog?.add(slug, infos.get(slug).title, fm);
|
|
3295
|
-
if (mode.keep || mode.lazy) frontMatter.set(p, fmKey(
|
|
3495
|
+
if (mode.keep || mode.lazy) frontMatter.set(p, memo2 ? memo2.fmKey ??= fmKey(await source()) : fmKey(await source()));
|
|
3296
3496
|
} else if (!SKIP_FILES.has(memberRel(p)) && copiedPath(p)) {
|
|
3297
3497
|
const verdict = await assetVerdict(p, c, input.untrusted === true, sanitizing);
|
|
3298
3498
|
if (verdict === "untrusted") untrustedFiles.push(p);
|
|
@@ -3353,6 +3553,7 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3353
3553
|
if (strays.length) warn("openapi", `${strays.length} page(s) are in the folder of the OpenAPI source "${ns}", and are left out of the nav: ${strays.slice(0, 5).map(srcOf).join(", ")}${strays.length > 5 ? ", \u2026" : ""}`);
|
|
3354
3554
|
}
|
|
3355
3555
|
const labelFor = (slug) => infos.get(slug)?.title;
|
|
3556
|
+
const navLoad = state.scan ? (text) => state.scan.yaml(text, loadYaml) : void 0;
|
|
3356
3557
|
const memberNav = async (ns) => {
|
|
3357
3558
|
const dir2 = ns ? ns + "/" : "";
|
|
3358
3559
|
const member = unit.members.find((m) => m.namespace === ns);
|
|
@@ -3364,7 +3565,7 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3364
3565
|
if (!file) return { nav: fromPages() };
|
|
3365
3566
|
try {
|
|
3366
3567
|
const text = await read(file);
|
|
3367
|
-
return { nav: file.endsWith(".json") ? prefixNav(parseNavJson(text, (slug) => labelFor(ns ? prefixSlug([ns], slug) : slug)), ns) : parseNavYaml(text, labelFor, ns), file, project: abs(file) };
|
|
3568
|
+
return { nav: file.endsWith(".json") ? prefixNav(parseNavJson(text, (slug) => labelFor(ns ? prefixSlug([ns], slug) : slug)), ns) : parseNavYaml(text, labelFor, ns, navLoad), file, project: abs(file) };
|
|
3368
3569
|
} catch (e) {
|
|
3369
3570
|
const mark = e.mark;
|
|
3370
3571
|
warn("nav", `could not read ${file}: ${e.message}; using the directory layout`, {
|
|
@@ -3382,7 +3583,7 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3382
3583
|
const c = input.files.get(path);
|
|
3383
3584
|
const text = c == null ? void 0 : await readText(c);
|
|
3384
3585
|
if (text === void 0) throw new ConfigError(`content.sources (${src.path}): its nav file ${path} does not exist`);
|
|
3385
|
-
return { nav: path.endsWith(".json") ? prefixNav(parseNavJson(text, nsLabel), ns) : parseNavYaml(text, labelFor, ns), file: path, project: path, files: [path] };
|
|
3586
|
+
return { nav: path.endsWith(".json") ? prefixNav(parseNavJson(text, nsLabel), ns) : parseNavYaml(text, labelFor, ns, navLoad), file: path, project: path, files: [path] };
|
|
3386
3587
|
};
|
|
3387
3588
|
let nav = [];
|
|
3388
3589
|
const navFiles = [];
|
|
@@ -3416,12 +3617,27 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3416
3617
|
const childLinkNav = (nodes) => nodes.map((n) => ({ label: n.label, href: n.slug != null ? `/${n.slug}` : n.href, children: childLinkNav(n.children) }));
|
|
3417
3618
|
let childLinkItems;
|
|
3418
3619
|
let childLinkDirs;
|
|
3419
|
-
|
|
3620
|
+
const isLeftOut = (s) => !infos.has(s) && !stubTargets.has(s) && leftOut.has(s);
|
|
3621
|
+
for (const s of order) if (!infos.has(s) && !stubTargets.has(s) && !leftOut.has(s)) warn("nav", `nav entry "${s}" has no page`, navFileAt());
|
|
3420
3622
|
if (cfg.routablesFrom === "nav") {
|
|
3421
3623
|
const keep = new Set(order);
|
|
3422
3624
|
for (const s of [...infos.keys()]) if (s !== "" && !keep.has(s)) infos.delete(s);
|
|
3423
3625
|
}
|
|
3626
|
+
const excludedEntries = /* @__PURE__ */ new Map();
|
|
3424
3627
|
const dropMissing = (nodes) => {
|
|
3628
|
+
const kept = nodes.filter((n) => {
|
|
3629
|
+
const had = n.children.length;
|
|
3630
|
+
dropMissing(n.children);
|
|
3631
|
+
if (n.slug != null && isLeftOut(n.slug)) {
|
|
3632
|
+
const why = leftOut.get(n.slug);
|
|
3633
|
+
if (why !== "draft") excludedEntries.set(why, (excludedEntries.get(why) ?? 0) + 1);
|
|
3634
|
+
delete n.slug;
|
|
3635
|
+
delete n.fragment;
|
|
3636
|
+
return n.children.length > 0;
|
|
3637
|
+
}
|
|
3638
|
+
return !(had > 0 && n.children.length === 0 && n.slug == null && n.href == null);
|
|
3639
|
+
});
|
|
3640
|
+
nodes.splice(0, nodes.length, ...kept);
|
|
3425
3641
|
for (const n of nodes) {
|
|
3426
3642
|
if (n.slug != null && !infos.has(n.slug)) {
|
|
3427
3643
|
const stub = stubTargets.get(n.slug);
|
|
@@ -3442,10 +3658,14 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3442
3658
|
} else warn("nav", `nav entry "${from}" redirects to /${stub.to}, which is not a page of this build; it keeps its label without a link`);
|
|
3443
3659
|
}
|
|
3444
3660
|
}
|
|
3445
|
-
dropMissing(n.children);
|
|
3446
3661
|
}
|
|
3447
3662
|
};
|
|
3448
3663
|
dropMissing(nav);
|
|
3664
|
+
if (excludedEntries.size) {
|
|
3665
|
+
const n = [...excludedEntries.values()].reduce((a, b) => a + b, 0);
|
|
3666
|
+
const why = [...excludedEntries.keys()].slice(0, 5).join(", ");
|
|
3667
|
+
warn("nav", n === 1 ? `1 nav entry left out: its page is excluded from routes (${why})` : `${n} nav entries left out: their pages are excluded from routes (${why})`, navFileAt());
|
|
3668
|
+
}
|
|
3449
3669
|
const blogIndex = cfg.blog?.path;
|
|
3450
3670
|
const replaced = blogIndex === "" ? "" : void 0;
|
|
3451
3671
|
if (blogIndex && infos.has(blogIndex)) warn("duplicate-page", `the page ${infos.get(blogIndex).source} and the blog index both serve /${blogIndex} on hosts that drop .html; rename one`);
|
|
@@ -3469,7 +3689,7 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3469
3689
|
const t_ = strings(unit.locale ?? cfg.defaultLocale, void 0);
|
|
3470
3690
|
const lang = unit.locale ?? cfg.defaultLocale ?? "en";
|
|
3471
3691
|
const dir = /^(ar|he|fa|ur)(-|$)/.test(unit.locale ?? "") ? "rtl" : "ltr";
|
|
3472
|
-
|
|
3692
|
+
let search = cfg.search && cfg.searchEngine !== "pagefind" ? new SearchIndexBuilder({ lang: unit.locale ?? cfg.defaultLocale ?? "en" }) : void 0;
|
|
3473
3693
|
const siteDepthPrefix = unit.prefix ? "../".repeat(unit.prefix.split("/").length) : "";
|
|
3474
3694
|
phase.scan = (phase.scan ?? 0) + now() - t;
|
|
3475
3695
|
input.onUnitAssets?.(unit.prefix, assetPaths);
|
|
@@ -3510,7 +3730,7 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3510
3730
|
warn2("front-matter", `front matter does not parse${line ? ` (line ${line})` : ""}: ${reason}`, line);
|
|
3511
3731
|
if (mode.diagnostics) diagnostics = [{ code: "front-matter", message: detach(`front matter does not parse: ${reason}`), ...line ? { line } : {} }];
|
|
3512
3732
|
}
|
|
3513
|
-
const pre = templatesOf(info.source).isTemplatePage(fm) ? { text: await templatesOf(info.source).render(bodySrc, info.source, fm, { firstLine: raw.slice(0, raw.length - bodySrc.length).split("\n").length }) } : await preprocess(bodySrc, info.source, attributesOf(info.source), includesFor(info.source), cfg.undefinedRefs);
|
|
3733
|
+
const pre = templatesOf(info.source).isTemplatePage(fm) ? { text: await templatesOf(info.source).render(bodySrc, info.source, fm, { firstLine: raw.slice(0, raw.length - bodySrc.length).split("\n").length }) } : await preprocess(bodySrc, info.source, attributesOf(info.source), includesFor(info.source), cfg.undefinedRefs, templateRun);
|
|
3514
3734
|
if (pre.error) {
|
|
3515
3735
|
warn2("template", `template error: ${pre.error}`);
|
|
3516
3736
|
if (mode.diagnostics) (diagnostics ??= []).push({ code: "template", message: detach(`template error: ${pre.error}`) });
|
|
@@ -3830,7 +4050,11 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3830
4050
|
const unitHref = (slug) => pageRefs.get(slug)?.out;
|
|
3831
4051
|
await emit(prefix + "_dogsbay/nav.js", `window.__DOGSBAY_NAV__=${JSON.stringify(compactNav(nav, unitHref)).replace(/<\//g, "<\\/")};
|
|
3832
4052
|
`);
|
|
3833
|
-
if (search)
|
|
4053
|
+
if (search) {
|
|
4054
|
+
const written = search;
|
|
4055
|
+
search = void 0;
|
|
4056
|
+
for (const [f, c] of written.emitFiles()) await emit(`${prefix}_dogsbay/search/${f}`, c);
|
|
4057
|
+
}
|
|
3834
4058
|
if (!infos.has("") && blogIndex !== "") {
|
|
3835
4059
|
const first = readingOrder[0] ?? [...infos.keys()][0];
|
|
3836
4060
|
if (first != null) await emit(prefix + "index.html", redirectPage(pageRefs.get(first).out, cfg.name));
|
|
@@ -3857,7 +4081,7 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3857
4081
|
body = sp.content;
|
|
3858
4082
|
} catch {
|
|
3859
4083
|
}
|
|
3860
|
-
const text = templatesOf(info.source).isTemplatePage(pageFm) ? await templatesOf(info.source).render(body, info.source, pageFm) : (await preprocess(body, info.source, attributesOf(info.source), includesFor(info.source), cfg.undefinedRefs)).text;
|
|
4084
|
+
const text = templatesOf(info.source).isTemplatePage(pageFm) ? await templatesOf(info.source).render(body, info.source, pageFm) : (await preprocess(body, info.source, attributesOf(info.source), includesFor(info.source), cfg.undefinedRefs, { ...templateRun, kind: "copy" })).text;
|
|
3861
4085
|
const ns = named.length ? namespaceOf(info.source) : "";
|
|
3862
4086
|
if (!ns && !PLACEHOLDER_DIRECTIVE.test(text)) return text;
|
|
3863
4087
|
const tree = dogsbayMdToTree(text).tree;
|
|
@@ -3920,7 +4144,7 @@ ${marker}${title}${marker}`, path, attributesOf(path), includesFor(path), cfg.un
|
|
|
3920
4144
|
},
|
|
3921
4145
|
included(path) {
|
|
3922
4146
|
const r = rel(path);
|
|
3923
|
-
return r !== void 0 && includedPaths.has(r);
|
|
4147
|
+
return r !== void 0 && includedPaths.has(r) || includedProject.has(path);
|
|
3924
4148
|
}
|
|
3925
4149
|
};
|
|
3926
4150
|
async function emitGenerated() {
|
|
@@ -4450,6 +4674,7 @@ async function openDevSession(input, o = {}) {
|
|
|
4450
4674
|
const rendering = /* @__PURE__ */ new Map();
|
|
4451
4675
|
let ctx;
|
|
4452
4676
|
let config;
|
|
4677
|
+
let parsedConfig;
|
|
4453
4678
|
let taken = 0;
|
|
4454
4679
|
let takenProblems = 0;
|
|
4455
4680
|
let buildError;
|
|
@@ -4493,6 +4718,7 @@ async function openDevSession(input, o = {}) {
|
|
|
4493
4718
|
} catch (e) {
|
|
4494
4719
|
throw e instanceof ConfigError ? inConfig(e, name) : e;
|
|
4495
4720
|
}
|
|
4721
|
+
parsedConfig = parsed;
|
|
4496
4722
|
out = next;
|
|
4497
4723
|
units = nextUnits;
|
|
4498
4724
|
ctx = nextCtx;
|
|
@@ -4534,8 +4760,23 @@ async function openDevSession(input, o = {}) {
|
|
|
4534
4760
|
const css = await (await siteCssBuilder(input))({ theme: config.theme, themeCss: ctx.theme.themeCss, extra: ctx.theme.extraCss, candidates: u.classes });
|
|
4535
4761
|
out.set(`${u.unit.prefix ? u.unit.prefix + "/" : ""}_dogsbay/site.css`, css);
|
|
4536
4762
|
};
|
|
4763
|
+
let requests = Promise.resolve();
|
|
4764
|
+
const budgeted = (work) => {
|
|
4765
|
+
const run = requests.then(async () => {
|
|
4766
|
+
const budget = ctx?.state.templateBudget;
|
|
4767
|
+
budget?.reset();
|
|
4768
|
+
try {
|
|
4769
|
+
return await work();
|
|
4770
|
+
} finally {
|
|
4771
|
+
const spent = ctx?.state.templateBudget === budget ? budget?.problem() : void 0;
|
|
4772
|
+
if (spent) ctx.report("template", spent);
|
|
4773
|
+
}
|
|
4774
|
+
});
|
|
4775
|
+
requests = run.catch(() => void 0);
|
|
4776
|
+
return run;
|
|
4777
|
+
};
|
|
4537
4778
|
const renderStale = async (path, u) => {
|
|
4538
|
-
await u.handle.render(path);
|
|
4779
|
+
await budgeted(() => u.handle.render(path));
|
|
4539
4780
|
stale.delete(path);
|
|
4540
4781
|
const html = out.get(path);
|
|
4541
4782
|
if (typeof html === "string") {
|
|
@@ -4611,48 +4852,80 @@ async function openDevSession(input, o = {}) {
|
|
|
4611
4852
|
},
|
|
4612
4853
|
get,
|
|
4613
4854
|
async change(paths) {
|
|
4855
|
+
const t0 = Date.now();
|
|
4856
|
+
const done = (r) => ({ ...r, ms: Date.now() - t0 });
|
|
4614
4857
|
try {
|
|
4615
4858
|
if (buildError !== void 0) {
|
|
4616
4859
|
await full();
|
|
4617
4860
|
buildError = void 0;
|
|
4618
4861
|
buildProblem = void 0;
|
|
4619
|
-
return { css: true };
|
|
4862
|
+
return done({ css: true, handled: "full" });
|
|
4620
4863
|
}
|
|
4621
|
-
return await changeParts(paths);
|
|
4864
|
+
return done(await budgeted(() => changeParts(paths)));
|
|
4622
4865
|
} catch (e) {
|
|
4623
4866
|
failed(e);
|
|
4624
|
-
return { css: false };
|
|
4867
|
+
return done({ css: false, handled: "full" });
|
|
4625
4868
|
}
|
|
4626
4869
|
}
|
|
4627
4870
|
};
|
|
4628
4871
|
async function changeParts(paths) {
|
|
4629
4872
|
const themeDir = config.themeDir ? config.themeDir.replace(/\/+$/, "") + "/" : void 0;
|
|
4630
4873
|
const extraCss = new Set(config.css.map((c) => c.replace(/^\.\//, "")));
|
|
4631
|
-
const
|
|
4632
|
-
|
|
4633
|
-
|
|
4874
|
+
const lazy = /* @__PURE__ */ new Set();
|
|
4875
|
+
if (paths.some((p) => CONFIG_FILES.has(p))) {
|
|
4876
|
+
const next = await attributesOnly();
|
|
4877
|
+
if (!next) {
|
|
4878
|
+
await full();
|
|
4879
|
+
return { css: true, handled: "full" };
|
|
4880
|
+
}
|
|
4881
|
+
ctx.cfg = { ...ctx.cfg, attributes: next.attributes };
|
|
4882
|
+
config = { ...config, attributes: next.attributes };
|
|
4883
|
+
const same = JSON.stringify(next.attributes) === JSON.stringify(parsedConfig?.attributes);
|
|
4884
|
+
parsedConfig = next;
|
|
4885
|
+
if (!same) for (const prefix of units.keys()) lazy.add(prefix);
|
|
4886
|
+
}
|
|
4887
|
+
if (paths.some((p) => themeDir && p.startsWith(themeDir) || extraCss.has(p))) {
|
|
4634
4888
|
await full();
|
|
4635
|
-
return { css: true };
|
|
4889
|
+
return { css: true, handled: "full" };
|
|
4636
4890
|
}
|
|
4637
|
-
const
|
|
4891
|
+
for (const p of paths) ctx.state.scan?.changed(p);
|
|
4892
|
+
let handled = lazy.size ? "unit" : "none";
|
|
4893
|
+
const mark = (h) => {
|
|
4894
|
+
const rank = ["none", "asset", "page", "unit", "full"];
|
|
4895
|
+
if (rank.indexOf(h) > rank.indexOf(handled)) handled = h;
|
|
4896
|
+
};
|
|
4638
4897
|
for (const p of paths) {
|
|
4898
|
+
if (CONFIG_FILES.has(p)) continue;
|
|
4899
|
+
const readers = [...units.values()].filter((u2) => u2.handle.navInputs.includes(p) || u2.unit.members.some((m) => m.source.nav === p));
|
|
4900
|
+
if (readers.length) {
|
|
4901
|
+
for (const u2 of [...readers, unitOf(p)]) if (u2) lazy.add(u2.unit.prefix);
|
|
4902
|
+
mark("unit");
|
|
4903
|
+
continue;
|
|
4904
|
+
}
|
|
4905
|
+
if (TOPIC_MAP.test(p)) continue;
|
|
4639
4906
|
const u = unitOf(p);
|
|
4640
4907
|
if (!u) continue;
|
|
4641
4908
|
const content = input.files.get(p);
|
|
4642
4909
|
if (/\.(md|markdown)$/i.test(p)) {
|
|
4643
4910
|
const page = u.handle.pageForSource(p);
|
|
4644
4911
|
const text = content === void 0 ? void 0 : await textOf(content);
|
|
4645
|
-
if (page && text !== void 0 && u.handle.sameFrontMatter(p, text) && !u.handle.included(p))
|
|
4646
|
-
|
|
4912
|
+
if (page && text !== void 0 && u.handle.sameFrontMatter(p, text) && !u.handle.included(p)) {
|
|
4913
|
+
stale.add(page);
|
|
4914
|
+
mark("page");
|
|
4915
|
+
} else {
|
|
4647
4916
|
u.handle.forget(p);
|
|
4648
4917
|
lazy.add(u.unit.prefix);
|
|
4918
|
+
mark("unit");
|
|
4649
4919
|
}
|
|
4650
4920
|
} else if (NAV_FILES2.test(p)) {
|
|
4651
4921
|
lazy.add(u.unit.prefix);
|
|
4922
|
+
mark("unit");
|
|
4652
4923
|
} else if (content === void 0 || /\.(md|markdown|ya?ml|json|txt|html?|csv)$/i.test(p)) {
|
|
4653
4924
|
u.handle.forget(p);
|
|
4654
4925
|
lazy.add(u.unit.prefix);
|
|
4926
|
+
mark("unit");
|
|
4655
4927
|
} else {
|
|
4928
|
+
mark("asset");
|
|
4656
4929
|
const at = memberPath(u.unit, p)?.path ?? p.slice(sourceRoot(u.unit.source).length);
|
|
4657
4930
|
const key = u.unit.prefix ? `${u.unit.prefix}/${at}` : at;
|
|
4658
4931
|
const sanitizing = (config.html ?? input.defaultHtml ?? "keep") === "sanitize";
|
|
@@ -4698,7 +4971,20 @@ async function openDevSession(input, o = {}) {
|
|
|
4698
4971
|
(p) => stale.has(p)
|
|
4699
4972
|
);
|
|
4700
4973
|
}
|
|
4701
|
-
return { css: false };
|
|
4974
|
+
return { css: false, handled };
|
|
4975
|
+
}
|
|
4976
|
+
async function attributesOnly() {
|
|
4977
|
+
const file = input.files.get("dogsbay.config.yml") ?? input.files.get("dogsbay.config.yaml");
|
|
4978
|
+
const text = file !== void 0 ? await textOf(file) : void 0;
|
|
4979
|
+
if (text === void 0 || !parsedConfig) return void 0;
|
|
4980
|
+
let next;
|
|
4981
|
+
try {
|
|
4982
|
+
next = parseConfig(text);
|
|
4983
|
+
} catch {
|
|
4984
|
+
return void 0;
|
|
4985
|
+
}
|
|
4986
|
+
const rest = (c) => JSON.stringify({ ...c, attributes: void 0 });
|
|
4987
|
+
return rest(next) === rest(parsedConfig) ? next : void 0;
|
|
4702
4988
|
}
|
|
4703
4989
|
async function emitInto(path, content) {
|
|
4704
4990
|
if (START_ONLY.test(path)) return;
|
|
@@ -4818,5 +5104,6 @@ export {
|
|
|
4818
5104
|
parseNavJson,
|
|
4819
5105
|
parseNavYaml,
|
|
4820
5106
|
peleRenderer,
|
|
4821
|
-
prebuiltSiteCss
|
|
5107
|
+
prebuiltSiteCss,
|
|
5108
|
+
projectRoots
|
|
4822
5109
|
};
|
|
@@ -20,6 +20,9 @@ import { type NavCache } from "../theme/regions.js";
|
|
|
20
20
|
import { ThemeTemplates } from "../theme/page.js";
|
|
21
21
|
import type { CssOptions } from "../theme/css-build.js";
|
|
22
22
|
import { type FileRef, type TextRef, type TextStream } from "./detach.js";
|
|
23
|
+
import { type TemplateBudget } from "./preprocess.js";
|
|
24
|
+
import { ParseCache } from "@dogsbay/minja/browser";
|
|
25
|
+
import { ScanCache } from "./scan-cache.js";
|
|
23
26
|
import { type RedirectInput, type RedirectRule } from "./site-files.js";
|
|
24
27
|
import { DiagramStore, type DiagramRenderer, type DiagramRenderers } from "./diagrams.js";
|
|
25
28
|
export type FileContent = string | Uint8Array | FileRef | TextRef;
|
|
@@ -90,6 +93,19 @@ export interface BuildInput {
|
|
|
90
93
|
* 8–16 MB). The CLI passes 64M (up to about 128 MB), the Worker 4M.
|
|
91
94
|
*/
|
|
92
95
|
highlightCacheChars?: number;
|
|
96
|
+
/**
|
|
97
|
+
* Estimated bytes of included templates' parses kept for reuse (minja's `ParseCache`; default
|
|
98
|
+
* 8 MB, which holds every reuse on OpenShift). 0 parses every include again.
|
|
99
|
+
*/
|
|
100
|
+
parseCacheBytes?: number;
|
|
101
|
+
/**
|
|
102
|
+
* Template time: per render, and for the whole build (a dev session: for opening it, and for
|
|
103
|
+
* each change or page request). Defaults: 10 s and 10 minutes; an untrusted build 2 s and 30 s.
|
|
104
|
+
*/
|
|
105
|
+
templateMs?: {
|
|
106
|
+
renderMs?: number;
|
|
107
|
+
buildMs?: number;
|
|
108
|
+
};
|
|
93
109
|
/** Characters of rendered SVG kept for reuse across units (default 8M; a Worker passes less). */
|
|
94
110
|
diagramCacheChars?: number;
|
|
95
111
|
/**
|
|
@@ -189,6 +205,12 @@ export interface SiteState {
|
|
|
189
205
|
written: Set<string>;
|
|
190
206
|
/** The stubs for missing translations last written, so a dev session can replace them. */
|
|
191
207
|
stubs: string[];
|
|
208
|
+
/** A dev session's: what pass 1 read from each page, kept between its rebuilds (src/core/scan-cache.ts). */
|
|
209
|
+
scan?: ScanCache;
|
|
210
|
+
/** Included templates' parses (false: none kept), kept as long as the state: a dev session's unit rebuilds keep it. */
|
|
211
|
+
parseCache: ParseCache | false;
|
|
212
|
+
/** Template time left for the build, or for a dev session's current request. */
|
|
213
|
+
templateBudget: TemplateBudget;
|
|
192
214
|
}
|
|
193
215
|
export interface BuildStats {
|
|
194
216
|
pages: number;
|
|
@@ -203,6 +225,14 @@ export interface BuildStats {
|
|
|
203
225
|
entries: number;
|
|
204
226
|
chars: number;
|
|
205
227
|
};
|
|
228
|
+
/** The parse cache for includes at the end of the build (minja's `ParseCache.stats()`). */
|
|
229
|
+
parseCache?: {
|
|
230
|
+
hits: number;
|
|
231
|
+
misses: number;
|
|
232
|
+
entries: number;
|
|
233
|
+
bytes: number;
|
|
234
|
+
maxBytes: number;
|
|
235
|
+
};
|
|
206
236
|
}
|
|
207
237
|
export interface BuildResult {
|
|
208
238
|
files: Map<string, OutputContent>;
|
|
@@ -8,10 +8,14 @@
|
|
|
8
8
|
* - otherwise a page added, removed or changed, a nav file, or a file of the
|
|
9
9
|
* unit that is not a page (an include): the unit is built again without
|
|
10
10
|
* its pages (`rebuildUnitLazy`), its old output is dropped, and all its
|
|
11
|
-
* pages are stale
|
|
11
|
+
* pages are stale. What pass 1 read from each unchanged page is kept
|
|
12
|
+
* between rebuilds (src/core/scan-cache.ts), so this is cheap;
|
|
13
|
+
* - a topic map, a map it includes or a source's `nav:` file: the units
|
|
14
|
+
* that read it are built again, as above;
|
|
12
15
|
* - an asset: its entry is replaced;
|
|
13
|
-
* -
|
|
14
|
-
*
|
|
16
|
+
* - a config change to `attributes` only: every unit is built again, as above;
|
|
17
|
+
* - any other config change, the theme or extra stylesheets: everything is
|
|
18
|
+
* built again, and swapped in only if that build succeeds.
|
|
15
19
|
*
|
|
16
20
|
* A stale page is rendered when it is asked for, with the current nav and
|
|
17
21
|
* page table, so nothing shown is out of date and no dependency map is
|
|
@@ -32,9 +36,7 @@ export interface DevSession {
|
|
|
32
36
|
* already updated. It does not throw: a change that fails sets `buildError` (and `buildProblem`)
|
|
33
37
|
* and resolves `{ css: false }`, and the last good site stays served.
|
|
34
38
|
*/
|
|
35
|
-
change(paths: string[]): Promise<
|
|
36
|
-
css: boolean;
|
|
37
|
-
}>;
|
|
39
|
+
change(paths: string[]): Promise<ChangeResult>;
|
|
38
40
|
/** Warnings not handed out yet (the start's, then those of each change and page render). */
|
|
39
41
|
takeWarnings(): string[];
|
|
40
42
|
/**
|
|
@@ -62,6 +64,16 @@ export interface DevSession {
|
|
|
62
64
|
/** `buildError` as data: a config that does not parse names the config file, with its line and column. */
|
|
63
65
|
readonly buildProblem: BuildProblem | undefined;
|
|
64
66
|
}
|
|
67
|
+
/** What `change` did: `css` when the stylesheet may have changed, how it handled the change, and how long it took. */
|
|
68
|
+
export interface ChangeResult {
|
|
69
|
+
css: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* The most it rebuilt: `full` (everything, as at the start), `unit` (one or more units without
|
|
72
|
+
* their pages), `page` (pages marked stale), `asset` (files replaced), `none` (nothing it builds).
|
|
73
|
+
*/
|
|
74
|
+
handled: "full" | "unit" | "page" | "asset" | "none";
|
|
75
|
+
ms: number;
|
|
76
|
+
}
|
|
65
77
|
/**
|
|
66
78
|
* By default every page is rendered at the start, as `build` does: search has its index and
|
|
67
79
|
* every warning is reported up front. `lazy`: only pass 1 runs at the start and each page is
|
|
@@ -15,7 +15,8 @@ export interface NavNode {
|
|
|
15
15
|
/** "topics/x.md" → "topics/x"; "index.md" → ""; "a/index.md" → "a". */
|
|
16
16
|
export declare function slugFromPath(p: string): string;
|
|
17
17
|
type LabelFor = (slug: string) => string | undefined;
|
|
18
|
-
|
|
18
|
+
/** `load`: the YAML loader, which a dev session's scan cache wraps (it reads the result, never changes it). */
|
|
19
|
+
export declare function parseNavYaml(text: string, labelFor: LabelFor, baseDir?: string, load?: (text: string) => unknown): NavNode[];
|
|
19
20
|
export declare function parseNavJson(text: string, labelFor: LabelFor): NavNode[];
|
|
20
21
|
/** Derive a nav tree from page slugs: one section per directory, index pages as landing pages. */
|
|
21
22
|
export declare function navFromPages(pages: {
|
|
@@ -1,6 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minja templating pass: `{{ var }}`, `{% if %}`, `{% include %}`.
|
|
3
|
+
* Runs on the raw page text before the markdown parser, the same way
|
|
4
|
+
* the Dogsbay CLI's site build does, but over an in-memory file map.
|
|
5
|
+
*
|
|
6
|
+
* Template syntax inside code (fences and inline spans) is masked so
|
|
7
|
+
* examples such as Helm's `{{ .Values }}` are never evaluated. `{#`
|
|
8
|
+
* (heading anchors like `{#intro}`) is masked globally because minja
|
|
9
|
+
* reads it as a comment opener.
|
|
10
|
+
*/
|
|
11
|
+
import { type ParseCache } from "@dogsbay/minja/browser";
|
|
1
12
|
export interface PreprocessResult {
|
|
2
13
|
text: string;
|
|
3
14
|
error?: string;
|
|
15
|
+
/** Not rendered: the build's template time budget was spent (counted in `TemplateBudget.skipped`). */
|
|
16
|
+
skipped?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Template time for a whole build (plans/worker-scale.md stage 3): each render gets the shorter of
|
|
20
|
+
* its own limit and what is left, and once it is spent the rest are not rendered (counted, for one
|
|
21
|
+
* problem). Time is counted while at least one render is running, so renders the build prepares
|
|
22
|
+
* ahead in parallel are not counted twice. A dev session resets it for each request.
|
|
23
|
+
*/
|
|
24
|
+
export declare class TemplateBudget {
|
|
25
|
+
readonly renderMs: number;
|
|
26
|
+
readonly buildMs: number;
|
|
27
|
+
private readonly now;
|
|
28
|
+
private spentMs;
|
|
29
|
+
private active;
|
|
30
|
+
private since;
|
|
31
|
+
/** Renders not run because the budget was spent, by what they were for. */
|
|
32
|
+
skipped: {
|
|
33
|
+
pages: number;
|
|
34
|
+
titles: number;
|
|
35
|
+
};
|
|
36
|
+
constructor(renderMs: number, buildMs: number, now?: () => number);
|
|
37
|
+
get spent(): number;
|
|
38
|
+
/** The time the next render may take; 0 when the budget is spent. */
|
|
39
|
+
next(): number;
|
|
40
|
+
start(): void;
|
|
41
|
+
end(): void;
|
|
42
|
+
reset(): void;
|
|
43
|
+
/** The problem to report when renders were skipped since the last reset, else undefined. */
|
|
44
|
+
problem(): string | undefined;
|
|
45
|
+
}
|
|
46
|
+
/** Per render: render limits for a build (untrusted: 2 s; else 10 s), and for the whole build (untrusted: 30 s; else 10 minutes). */
|
|
47
|
+
export declare function templateBudget(untrusted: boolean, given?: {
|
|
48
|
+
renderMs?: number;
|
|
49
|
+
buildMs?: number;
|
|
50
|
+
}): TemplateBudget;
|
|
51
|
+
/** What a build's renders share: the parse cache for includes, the time budget, and what the render is for. */
|
|
52
|
+
export interface TemplateRun {
|
|
53
|
+
parseCache?: ParseCache | false;
|
|
54
|
+
budget?: TemplateBudget;
|
|
55
|
+
/** What the render is for: a page's body, a title, or a copy of a body already counted (llms-full.txt), not counted again. */
|
|
56
|
+
kind?: "page" | "title" | "copy";
|
|
4
57
|
}
|
|
5
58
|
/** True when a page contains template syntax worth running minja over. */
|
|
6
59
|
export declare function needsTemplating(text: string): boolean;
|
|
@@ -9,6 +62,6 @@ export declare function needsTemplating(text: string): boolean;
|
|
|
9
62
|
* to the content root; `files` looks up other files by the same kind
|
|
10
63
|
* of path. A template error leaves the page unchanged and is reported.
|
|
11
64
|
*/
|
|
12
|
-
export declare function preprocess(text: string, path: string, attributes: Record<string, unknown>, files: (path: string) => string | undefined | Promise<string | undefined>, undefinedRefs?: "preserve" | "asciidoc-literal"): Promise<PreprocessResult>;
|
|
65
|
+
export declare function preprocess(text: string, path: string, attributes: Record<string, unknown>, files: (path: string) => string | undefined | Promise<string | undefined>, undefinedRefs?: "preserve" | "asciidoc-literal", run?: TemplateRun): Promise<PreprocessResult>;
|
|
13
66
|
/** `product-title` is also reachable as `product_title`, because minja normalises hyphens on lookup. */
|
|
14
67
|
export declare function withUnderscoreAliases(attrs: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What pass 1 of a unit's build reads from each page, kept between a dev session's rebuilds
|
|
3
|
+
* (plans/worker-scale.md, stage 4). Rebuilding a unit after a menu, title, include or new-page
|
|
4
|
+
* edit re-reads every page; on a large site most of that is resolving templated titles, which
|
|
5
|
+
* renders each page's preamble and its includes. A page's entry is used again while its file is
|
|
6
|
+
* the same content (the dev server and the playground replace a changed file's value in the file
|
|
7
|
+
* map), its title was resolved with the same attributes, and no file its title read has changed.
|
|
8
|
+
*
|
|
9
|
+
* Only a dev session builds with one (`BuildHooks.keep` or `lazy`): a build reads each page once.
|
|
10
|
+
*/
|
|
11
|
+
import type { FileContent } from "./build.js";
|
|
12
|
+
import type { TopicMapNav } from "./topicmap.js";
|
|
13
|
+
export interface ScanEntry {
|
|
14
|
+
/** The file map's value the entry was made from: a different value is a different file. */
|
|
15
|
+
content: FileContent;
|
|
16
|
+
fm?: Record<string, unknown>;
|
|
17
|
+
/** The first H1 and the front matter block (`fmKey`), for telling a body edit from a page-table change. */
|
|
18
|
+
fmKey?: string;
|
|
19
|
+
/** Mermaid sources the page fences. */
|
|
20
|
+
diagrams?: string[];
|
|
21
|
+
/** The resolved title and description, and what they were resolved with. */
|
|
22
|
+
title?: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
resolvedWith?: string;
|
|
25
|
+
/** Project paths the title and description read (includes found or looked for). */
|
|
26
|
+
deps?: Set<string>;
|
|
27
|
+
}
|
|
28
|
+
export declare class ScanCache {
|
|
29
|
+
private entries;
|
|
30
|
+
/** Project path of a file read while resolving titles → the pages whose entries read it. */
|
|
31
|
+
private readers;
|
|
32
|
+
/** The last nav YAML loaded, by its text: an unchanged nav.yml is not parsed again. */
|
|
33
|
+
private navText?;
|
|
34
|
+
private navData?;
|
|
35
|
+
/** Resolved topic maps, with what they were resolved with and the file map's value of every file read. */
|
|
36
|
+
private maps;
|
|
37
|
+
/** The page's entry when it was made from this content, else a new empty one for it. */
|
|
38
|
+
entry(path: string, content: FileContent): ScanEntry;
|
|
39
|
+
/** Records that a page's title or description read a file, so a change to that file drops them. */
|
|
40
|
+
read(page: string, file: string): void;
|
|
41
|
+
/** A file changed, was added or was removed: its own entry goes, and the titles that read it. */
|
|
42
|
+
changed(path: string): void;
|
|
43
|
+
/** `load(text)`, or the value it gave for the same text last time (the caller must not change it). */
|
|
44
|
+
yaml(text: string, load: (text: string) => unknown): unknown;
|
|
45
|
+
/** A topic map resolved with `key` (its variables), if no file it read has changed since. */
|
|
46
|
+
topicMap(path: string, key: string, files: Map<string, FileContent>): TopicMapNav | undefined;
|
|
47
|
+
/** Keeps a resolved topic map (not one with errors: the build stops on those) and the files it read. */
|
|
48
|
+
keepTopicMap(path: string, key: string, reads: Map<string, FileContent | undefined>, nav: TopicMapNav): void;
|
|
49
|
+
get size(): number;
|
|
50
|
+
private dropDeps;
|
|
51
|
+
}
|
|
@@ -20,8 +20,8 @@ export declare function openDevSession(input: BuildInput & {
|
|
|
20
20
|
}, o?: DevOptions): Promise<DevSession>;
|
|
21
21
|
export { prebuiltSiteCss };
|
|
22
22
|
export type { BuildInput, BuildResult, FileContent, OutputContent, SinkContent, SiteCssBuilder, BuiltPage, HighlightPool, BuildProblem, PageDiagnostic } from "../core/build.js";
|
|
23
|
-
export type { DevOptions, DevSession } from "../core/dev.js";
|
|
24
|
-
export { parseConfig, ConfigError, type SiteConfig, type DiagramEngine } from "../core/config.js";
|
|
23
|
+
export type { ChangeResult, DevOptions, DevSession } from "../core/dev.js";
|
|
24
|
+
export { parseConfig, projectRoots, ConfigError, type SiteConfig, type DiagramEngine } from "../core/config.js";
|
|
25
25
|
export type { DiagramRenderer, DiagramRenderers, DiagramRequest, DiagramResult } from "../core/diagrams.js";
|
|
26
26
|
export { peleRenderer } from "../core/pele.js";
|
|
27
27
|
export { parseNavYaml, parseNavJson, navFromPages, indexNav, type NavNode, type NavIndex } from "../core/nav.js";
|
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.134",
|
|
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",
|
|
@@ -47,38 +47,38 @@
|
|
|
47
47
|
"tailwindcss": "^4.3.2"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@dogsbay/elements": "0.2.0-beta.
|
|
51
|
-
"@dogsbay/format-dogsbay-md": "0.2.0-beta.
|
|
52
|
-
"@dogsbay/format-openapi": "0.2.0-beta.
|
|
53
|
-
"@dogsbay/format-topicmap": "0.2.0-beta.
|
|
54
|
-
"@dogsbay/highlight": "0.2.0-beta.
|
|
55
|
-
"@dogsbay/minja": "0.2.0-beta.
|
|
56
|
-
"@dogsbay/primitives": "0.2.0-beta.
|
|
57
|
-
"@dogsbay/render-html": "0.2.0-beta.
|
|
58
|
-
"@dogsbay/search": "0.2.0-beta.
|
|
59
|
-
"@dogsbay/serialize-core": "0.2.0-beta.
|
|
60
|
-
"@dogsbay/site-check": "0.2.0-beta.
|
|
61
|
-
"@dogsbay/site-files": "0.2.0-beta.
|
|
62
|
-
"@dogsbay/types": "0.2.0-beta.
|
|
50
|
+
"@dogsbay/elements": "0.2.0-beta.134",
|
|
51
|
+
"@dogsbay/format-dogsbay-md": "0.2.0-beta.134",
|
|
52
|
+
"@dogsbay/format-openapi": "0.2.0-beta.134",
|
|
53
|
+
"@dogsbay/format-topicmap": "0.2.0-beta.134",
|
|
54
|
+
"@dogsbay/highlight": "0.2.0-beta.134",
|
|
55
|
+
"@dogsbay/minja": "0.2.0-beta.134",
|
|
56
|
+
"@dogsbay/primitives": "0.2.0-beta.134",
|
|
57
|
+
"@dogsbay/render-html": "0.2.0-beta.134",
|
|
58
|
+
"@dogsbay/search": "0.2.0-beta.134",
|
|
59
|
+
"@dogsbay/serialize-core": "0.2.0-beta.134",
|
|
60
|
+
"@dogsbay/site-check": "0.2.0-beta.134",
|
|
61
|
+
"@dogsbay/site-files": "0.2.0-beta.134",
|
|
62
|
+
"@dogsbay/types": "0.2.0-beta.134"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@axe-core/playwright": "^4.12.1",
|
|
66
66
|
"@cloudflare/workers-types": "^5.20260921.1",
|
|
67
|
-
"@dogsbay/elements": "0.2.0-beta.
|
|
68
|
-
"@dogsbay/format-dogsbay-md": "0.2.0-beta.
|
|
69
|
-
"@dogsbay/format-openapi": "0.2.0-beta.
|
|
70
|
-
"@dogsbay/format-topicmap": "0.2.0-beta.
|
|
71
|
-
"@dogsbay/highlight": "0.2.0-beta.
|
|
72
|
-
"@dogsbay/icons": "0.2.0-beta.
|
|
73
|
-
"@dogsbay/minja": "0.2.0-beta.
|
|
74
|
-
"@dogsbay/primitives": "0.2.0-beta.
|
|
75
|
-
"@dogsbay/render-html": "0.2.0-beta.
|
|
76
|
-
"@dogsbay/search": "0.2.0-beta.
|
|
77
|
-
"@dogsbay/serialize-core": "0.2.0-beta.
|
|
78
|
-
"@dogsbay/site-check": "0.2.0-beta.
|
|
79
|
-
"@dogsbay/site-files": "0.2.0-beta.
|
|
80
|
-
"@dogsbay/types": "0.2.0-beta.
|
|
81
|
-
"@dogsbay/ui": "0.2.0-beta.
|
|
67
|
+
"@dogsbay/elements": "0.2.0-beta.134",
|
|
68
|
+
"@dogsbay/format-dogsbay-md": "0.2.0-beta.134",
|
|
69
|
+
"@dogsbay/format-openapi": "0.2.0-beta.134",
|
|
70
|
+
"@dogsbay/format-topicmap": "0.2.0-beta.134",
|
|
71
|
+
"@dogsbay/highlight": "0.2.0-beta.134",
|
|
72
|
+
"@dogsbay/icons": "0.2.0-beta.134",
|
|
73
|
+
"@dogsbay/minja": "0.2.0-beta.134",
|
|
74
|
+
"@dogsbay/primitives": "0.2.0-beta.134",
|
|
75
|
+
"@dogsbay/render-html": "0.2.0-beta.134",
|
|
76
|
+
"@dogsbay/search": "0.2.0-beta.134",
|
|
77
|
+
"@dogsbay/serialize-core": "0.2.0-beta.134",
|
|
78
|
+
"@dogsbay/site-check": "0.2.0-beta.134",
|
|
79
|
+
"@dogsbay/site-files": "0.2.0-beta.134",
|
|
80
|
+
"@dogsbay/types": "0.2.0-beta.134",
|
|
81
|
+
"@dogsbay/ui": "0.2.0-beta.134",
|
|
82
82
|
"@mermanjs/web": "0.7.0",
|
|
83
83
|
"@playwright/test": "1.61.1",
|
|
84
84
|
"@types/node": "^22.10.0",
|