@pagenary/publisher 2026.6.14 → 2026.6.15
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/examples/page-effects/config.json +2 -1
- package/examples/page-effects/content/disclosure.md +40 -0
- package/examples/page-effects/content/index.md +28 -0
- package/examples/page-effects/content/parallax-and-sticky.md +13 -0
- package/examples/page-effects/content/scroll-snap.md +29 -0
- package/examples/page-effects/content/scrollytelling.md +35 -0
- package/examples/page-effects/manifest.json +16 -4
- package/package.json +1 -1
- package/scripts/build-tenants.js +138 -15
- package/site/{app.2a8fb673db91.js → app.54e1ad90b733.js} +1 -1
- package/site/app.js +1 -1
- package/site/assets/images/pipeline.e57f0dbfd05a.svg +33 -0
- package/site/assets/images/pipeline.svg +33 -0
- package/site/index.html +4 -4
- package/site/lib/page-effects.2131b53bea6b.js +1 -0
- package/site/lib/page-effects.js +1 -1
- package/site/llms.txt +11 -6
- package/site/{manifest.a870df3a026b.js → manifest.95224f06782d.js} +49 -44
- package/site/manifest.js +49 -44
- package/site/pages/accessible-authoring.html +3 -3
- package/site/pages/api.html +1 -1
- package/site/pages/architecture.html +1 -1
- package/site/pages/blog-layout.html +1 -1
- package/site/pages/deployment.html +1 -1
- package/site/pages/developer-guide.html +1 -1
- package/site/pages/extending.html +1 -1
- package/site/pages/overview.html +189 -0
- package/site/pages/page-effects.html +265 -0
- package/site/pages/publishing.html +258 -0
- package/site/pages/quickstart.html +1 -1
- package/site/pages/search-and-data.html +1 -1
- package/site/pages/seo-strategy.html +1 -1
- package/site/pages/showcase-gallery.html +184 -0
- package/site/pages/showcase-story.html +130 -0
- package/site/pages/tenant-config.html +7 -9
- package/site/pages/theming-recipes.html +1 -1
- package/site/pages/welcome.html +1 -1
- package/site/robots.txt +1 -1
- package/site/search-index/manifest.json +36 -38
- package/site/search-index/metadata.json +706 -355
- package/site/search-index/{part-0000.c67bff0d76c7.json → part-0000.64586040c481.json} +707 -354
- package/site/search-index/part-0000.json +707 -354
- package/site/sections/overview.5a483987fb9d.js +3 -0
- package/site/sections/overview.js +3 -0
- package/site/sections/page-effects.a38e5a7715d4.js +3 -0
- package/site/sections/page-effects.js +3 -0
- package/site/sections/publishing.32bf1d55b285.js +3 -0
- package/site/sections/publishing.js +3 -0
- package/site/sections/showcase-gallery.cd729f94752d.js +3 -0
- package/site/sections/showcase-gallery.js +3 -0
- package/site/sections/showcase-story.79311d1302c8.js +3 -0
- package/site/sections/showcase-story.js +3 -0
- package/site/sections/tenant-config.552c0d8c6d2b.js +3 -0
- package/site/sections/tenant-config.js +1 -1
- package/site/sitemap.xml +21 -9
- package/site/{styles.d957d4c1c1af.css → styles.bdb30ba34de5.css} +326 -8
- package/site/styles.css +326 -8
- package/src/app.js +35 -28
- package/src/lib/page-effects.js +410 -23
- package/src/styles.css +324 -6
- package/examples/page-effects/content/effects-spike.md +0 -212
- package/site/lib/page-effects.2e4e21674b13.js +0 -1
- package/site/pages/managed-hosting.html +0 -298
- package/site/pages/page-effects-spike.html +0 -152
- package/site/pages/theme-token-audit.html +0 -158
- package/site/sections/managed-hosting.e707893d4520.js +0 -3
- package/site/sections/managed-hosting.js +0 -3
- package/site/sections/page-effects-spike.d18d9601f432.js +0 -3
- package/site/sections/page-effects-spike.js +0 -3
- package/site/sections/tenant-config.e99335c66502.js +0 -3
- package/site/sections/theme-token-audit.182808e9139e.js +0 -3
- package/site/sections/theme-token-audit.js +0 -3
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Disclosure (accordion)
|
|
3
|
+
summary: Production accordion built on native <details> — works with zero JS, keyboard-operable, single-open optional.
|
|
4
|
+
hero:
|
|
5
|
+
eyebrow: Primitive
|
|
6
|
+
title: Disclosure
|
|
7
|
+
subtitle: An accordion that's just native <details> — accessible and complete with JavaScript off.
|
|
8
|
+
align: start
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Disclosure (accordion)
|
|
12
|
+
|
|
13
|
+
`.pe-accordion` styles native `<details>/<summary>`, so each panel opens, closes,
|
|
14
|
+
and takes keyboard focus with **zero JavaScript**. Add `data-pe-single` to make it
|
|
15
|
+
single-open — opening one panel closes its siblings — which is a pure enhancement:
|
|
16
|
+
with JS off, every panel still works independently and no content is ever hidden
|
|
17
|
+
behind the script.
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<div class="pe-accordion" data-pe-single>
|
|
21
|
+
<details open>
|
|
22
|
+
<summary>What is a page effect?</summary>
|
|
23
|
+
<p>An opt-in, accessible enhancement — heroes, reveal-on-scroll, living scroll,
|
|
24
|
+
disclosure — that degrades to plain content when JavaScript or motion is off.</p>
|
|
25
|
+
</details>
|
|
26
|
+
<details>
|
|
27
|
+
<summary>Does it work without JavaScript?</summary>
|
|
28
|
+
<p>Yes. The accordion is native <code><details></code>. The only thing JS
|
|
29
|
+
adds is the single-open grouping, and that's optional.</p>
|
|
30
|
+
</details>
|
|
31
|
+
<details>
|
|
32
|
+
<summary>Is it keyboard accessible?</summary>
|
|
33
|
+
<p>Native disclosure is operable with Enter/Space and shows a visible focus
|
|
34
|
+
ring. The open/closed state uses a +/− marker, not color alone.</p>
|
|
35
|
+
</details>
|
|
36
|
+
</div>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Drop `data-pe-single` to let multiple panels stay open at once. Style is theme-token
|
|
40
|
+
aware, so it inherits each tenant's palette automatically.
|
|
@@ -81,6 +81,34 @@ the viewport, and appear instantly under reduced-motion.
|
|
|
81
81
|
</div>
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
+
## Staggered reveal
|
|
85
|
+
|
|
86
|
+
The cards below arrive in a wave — `data-reveal-stagger` on the grid sequences
|
|
87
|
+
each child's entrance as it scrolls into view (JS-off and reduced-motion show all
|
|
88
|
+
at once).
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<div class="pe-card-grid" data-reveal-stagger="90">
|
|
92
|
+
<section class="pe-demo-card"><h3>One</h3><p>Arrives first.</p></section>
|
|
93
|
+
<section class="pe-demo-card"><h3>Two</h3><p>A beat later.</p></section>
|
|
94
|
+
<section class="pe-demo-card"><h3>Three</h3><p>Then this one.</p></section>
|
|
95
|
+
<section class="pe-demo-card"><h3>Four</h3><p>And finally this.</p></section>
|
|
96
|
+
</div>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Figure zoom
|
|
100
|
+
|
|
101
|
+
The figure below shows its image normally; click it (or press Enter when focused)
|
|
102
|
+
to enlarge it in a modal. With JavaScript off, the image is just visible at its
|
|
103
|
+
normal size.
|
|
104
|
+
|
|
105
|
+
```html
|
|
106
|
+
<figure class="pe-figure" data-pe-zoom>
|
|
107
|
+
<img src="images/ridge.svg" alt="Layered ridge illustration" />
|
|
108
|
+
<figcaption>Click to enlarge — opens a native dialog with focus trap and Esc-to-close.</figcaption>
|
|
109
|
+
</figure>
|
|
110
|
+
```
|
|
111
|
+
|
|
84
112
|
## Authoring paths
|
|
85
113
|
|
|
86
114
|
You have four ways to add a hero, from least to most control:
|
|
@@ -61,3 +61,16 @@ The CTA band primitive is just as portable:
|
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
Keep scrolling to confirm the sticky hero releases at the end of the page.
|
|
64
|
+
|
|
65
|
+
## Parallax on any element
|
|
66
|
+
|
|
67
|
+
The card below isn't a hero — it drifts on its own with `data-pe-parallax="0.35"`.
|
|
68
|
+
Any element can; the speed is clamped so it never wanders far, and it's skipped
|
|
69
|
+
entirely under reduced motion.
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<div class="pe-demo-card" data-pe-parallax="0.35" style="max-width: 20rem;">
|
|
73
|
+
<h3>Parallax aside</h3>
|
|
74
|
+
<p>Drifts gently against the scroll — a non-hero element with its own speed.</p>
|
|
75
|
+
</div>
|
|
76
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Scroll-snap sections
|
|
3
|
+
summary: A CSS-only .pe-snap region whose panels snap as you scroll — opt-in, no runtime, never traps the keyboard.
|
|
4
|
+
hero:
|
|
5
|
+
eyebrow: Primitive
|
|
6
|
+
title: Scroll-snap sections
|
|
7
|
+
subtitle: Bounded snap panels for landing pages — pure CSS, and the keyboard is never trapped.
|
|
8
|
+
align: start
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Scroll-snap sections
|
|
12
|
+
|
|
13
|
+
`.pe-snap` is a **self-contained, opt-in** scroll region whose `.pe-snap__panel`
|
|
14
|
+
children snap into place as you scroll it. It's pure CSS — no runtime — and uses
|
|
15
|
+
`scroll-snap-type: y proximity` (not `mandatory`) inside a bounded height, so it
|
|
16
|
+
never takes over the page scroll and never traps keyboard users.
|
|
17
|
+
|
|
18
|
+
```html
|
|
19
|
+
<div class="pe-snap">
|
|
20
|
+
<section class="pe-snap__panel"><h2>Capture</h2><p>Scroll inside this region — each panel snaps to the top.</p></section>
|
|
21
|
+
<section class="pe-snap__panel"><h2>Compose</h2><p>Proximity snapping, so you can still stop between panels.</p></section>
|
|
22
|
+
<section class="pe-snap__panel"><h2>Publish</h2><p>Tab through; the keyboard is never trapped.</p></section>
|
|
23
|
+
</div>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Smooth glide to the snap points is gated under `prefers-reduced-motion:
|
|
27
|
+
no-preference`; reduced-motion readers get instant positioning. The panels are
|
|
28
|
+
ordinary sections, so the content is complete and reachable with or without
|
|
29
|
+
snapping.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Scrollytelling
|
|
3
|
+
summary: A sticky stage beside content steps — the stage updates as each step scrolls into view. JS-off shows the steps as plain content.
|
|
4
|
+
hero:
|
|
5
|
+
eyebrow: Primitive
|
|
6
|
+
title: Scrollytelling
|
|
7
|
+
subtitle: A sticky stage that reacts as you read past each step — built from sticky layout + scroll position, no animation engine.
|
|
8
|
+
align: start
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Scrollytelling
|
|
12
|
+
|
|
13
|
+
A `.pe-scrolly` block pairs a **sticky stage** with a column of `[data-pe-step]`
|
|
14
|
+
content steps. As each step scrolls into view, the stage's matching layer
|
|
15
|
+
crossfades in. With JavaScript off, the steps are ordinary readable content and
|
|
16
|
+
the stage shows its layers statically — the swap is a pure enhancement.
|
|
17
|
+
|
|
18
|
+
```html
|
|
19
|
+
<div class="pe-scrolly">
|
|
20
|
+
<div class="pe-scrolly__stage">
|
|
21
|
+
<div data-pe-step="capture"><h2>Capture</h2></div>
|
|
22
|
+
<div data-pe-step="compose"><h2>Compose</h2></div>
|
|
23
|
+
<div data-pe-step="publish"><h2>Publish</h2></div>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="pe-scrolly__steps">
|
|
26
|
+
<section data-pe-step="capture"><p>Write your content as Markdown, HTML, or a JS module.</p></section>
|
|
27
|
+
<section data-pe-step="compose"><p>Shared templates turn it into a branded, tenant-specific site.</p></section>
|
|
28
|
+
<section data-pe-step="publish"><p>Build emits static files — host them anywhere.</p></section>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The active step is the last one to scroll past the upper-middle of the viewport —
|
|
34
|
+
the same rect-based detection scroll-spy uses, so no bespoke animation engine is
|
|
35
|
+
needed. The crossfade is gated under `prefers-reduced-motion: no-preference`.
|
|
@@ -14,10 +14,22 @@
|
|
|
14
14
|
"file": "parallax-and-sticky.md"
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
|
-
"id": "
|
|
18
|
-
"title": "
|
|
19
|
-
"summary": "
|
|
20
|
-
"file": "
|
|
17
|
+
"id": "disclosure",
|
|
18
|
+
"title": "Disclosure",
|
|
19
|
+
"summary": "Production accordion on native <details> — zero-JS, keyboard-operable, single-open optional.",
|
|
20
|
+
"file": "disclosure.md"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "scroll-snap",
|
|
24
|
+
"title": "Scroll-snap",
|
|
25
|
+
"summary": "CSS-only .pe-snap region — bounded, opt-in snap panels that never trap the keyboard.",
|
|
26
|
+
"file": "scroll-snap.md"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "scrollytelling",
|
|
30
|
+
"title": "Scrollytelling",
|
|
31
|
+
"summary": "A sticky stage that reacts as you read past each step — sticky layout + scroll position, no animation engine.",
|
|
32
|
+
"file": "scrollytelling.md"
|
|
21
33
|
}
|
|
22
34
|
]
|
|
23
35
|
}
|
package/package.json
CHANGED
package/scripts/build-tenants.js
CHANGED
|
@@ -277,6 +277,11 @@ function isGitAvailable() {
|
|
|
277
277
|
* Execute a command with timeout and retry
|
|
278
278
|
*/
|
|
279
279
|
async function execWithRetry(command, options = {}) {
|
|
280
|
+
const commandSegments = Array.isArray(command) ? command : [];
|
|
281
|
+
if (commandSegments.length === 0) {
|
|
282
|
+
throw new Error('execWithRetry expected an argument array');
|
|
283
|
+
}
|
|
284
|
+
|
|
280
285
|
const {
|
|
281
286
|
cwd = root,
|
|
282
287
|
timeout = DEFAULT_GIT_TIMEOUT,
|
|
@@ -288,10 +293,13 @@ async function execWithRetry(command, options = {}) {
|
|
|
288
293
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
289
294
|
try {
|
|
290
295
|
return await new Promise((resolve, reject) => {
|
|
291
|
-
const proc = spawn(
|
|
296
|
+
const proc = spawn(commandSegments[0], commandSegments.slice(1), {
|
|
292
297
|
cwd,
|
|
293
298
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
294
|
-
env: {
|
|
299
|
+
env: {
|
|
300
|
+
...env,
|
|
301
|
+
GIT_TERMINAL_PROMPT: '0'
|
|
302
|
+
},
|
|
295
303
|
timeout
|
|
296
304
|
});
|
|
297
305
|
|
|
@@ -305,7 +313,10 @@ async function execWithRetry(command, options = {}) {
|
|
|
305
313
|
if (code === 0) {
|
|
306
314
|
resolve({ stdout, stderr });
|
|
307
315
|
} else {
|
|
308
|
-
|
|
316
|
+
const prettyCommand = commandSegments
|
|
317
|
+
.map((segment) => maskAuthSegment(String(segment)))
|
|
318
|
+
.join(' ');
|
|
319
|
+
reject(new Error(`Command failed (exit ${code}): ${stderr || stdout} (command: ${prettyCommand})`));
|
|
309
320
|
}
|
|
310
321
|
});
|
|
311
322
|
|
|
@@ -334,6 +345,34 @@ async function execWithRetry(command, options = {}) {
|
|
|
334
345
|
throw lastError;
|
|
335
346
|
}
|
|
336
347
|
|
|
348
|
+
function maskAuthSegment(value) {
|
|
349
|
+
return value.replace(/\/\/[^@]+@/, '//***@');
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Build an authenticated git URL when GIT_CREDENTIALS is available.
|
|
354
|
+
*/
|
|
355
|
+
function withGitCredentials(rawUrl) {
|
|
356
|
+
const credentials = process.env.GIT_CREDENTIALS || '';
|
|
357
|
+
const [username, password] = credentials.split(':', 2);
|
|
358
|
+
if (!credentials || !username || password === undefined || !rawUrl) return rawUrl;
|
|
359
|
+
|
|
360
|
+
try {
|
|
361
|
+
const source = new URL(rawUrl);
|
|
362
|
+
if (!['https:', 'http:'].includes(source.protocol)) {
|
|
363
|
+
return rawUrl;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (source.username) {
|
|
367
|
+
return rawUrl;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return `${source.protocol}//${encodeURIComponent(username)}:${encodeURIComponent(password)}@${source.host}${source.pathname}${source.search}${source.hash}`;
|
|
371
|
+
} catch {
|
|
372
|
+
return rawUrl;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
337
376
|
/**
|
|
338
377
|
* Generate cache key for git source
|
|
339
378
|
*/
|
|
@@ -364,7 +403,10 @@ function isImmutableRef(ref) {
|
|
|
364
403
|
*/
|
|
365
404
|
async function getHeadCommit(repoDir) {
|
|
366
405
|
try {
|
|
367
|
-
const { stdout } = await execWithRetry(
|
|
406
|
+
const { stdout } = await execWithRetry(['git', '-C', repoDir, 'rev-parse', 'HEAD'], {
|
|
407
|
+
cwd: root,
|
|
408
|
+
retries: 1
|
|
409
|
+
});
|
|
368
410
|
return stdout.trim();
|
|
369
411
|
} catch {
|
|
370
412
|
return null;
|
|
@@ -385,7 +427,7 @@ async function getChangedFiles(repoDir, oldCommit, newCommit, subPath = '.') {
|
|
|
385
427
|
try {
|
|
386
428
|
// Use --name-status to get file status (A=added, M=modified, D=deleted)
|
|
387
429
|
const { stdout } = await execWithRetry(
|
|
388
|
-
|
|
430
|
+
['git', '-C', repoDir, 'diff', '--name-status', oldCommit, newCommit],
|
|
389
431
|
{ cwd: root, retries: 1 }
|
|
390
432
|
);
|
|
391
433
|
|
|
@@ -461,6 +503,7 @@ async function cloneGitSource(source, cacheDir, options = {}) {
|
|
|
461
503
|
|
|
462
504
|
// Sanitize URL for logging (hide credentials)
|
|
463
505
|
const safeUrl = url.replace(/\/\/[^@]+@/, '//***@');
|
|
506
|
+
const authUrl = withGitCredentials(url);
|
|
464
507
|
|
|
465
508
|
console.log(` ↳ git source: ${safeUrl}`);
|
|
466
509
|
console.log(` ↳ ref: ${ref}, path: ${subPath || '(root)'}`);
|
|
@@ -494,8 +537,8 @@ async function cloneGitSource(source, cacheDir, options = {}) {
|
|
|
494
537
|
console.log(` ↳ current HEAD: ${oldCommit ? oldCommit.slice(0, 7) : 'unknown'}`);
|
|
495
538
|
|
|
496
539
|
try {
|
|
497
|
-
await execWithRetry(
|
|
498
|
-
await execWithRetry(
|
|
540
|
+
await execWithRetry(['git', '-C', cloneDir, 'fetch', 'origin', ref, '--depth', String(effectiveDepth)], { cwd: root });
|
|
541
|
+
await execWithRetry(['git', '-C', cloneDir, 'checkout', 'FETCH_HEAD'], { cwd: root });
|
|
499
542
|
newCommit = await getHeadCommit(cloneDir);
|
|
500
543
|
console.log(` ↳ updated HEAD: ${newCommit ? newCommit.slice(0, 7) : 'unknown'}`);
|
|
501
544
|
} catch (err) {
|
|
@@ -513,33 +556,33 @@ async function cloneGitSource(source, cacheDir, options = {}) {
|
|
|
513
556
|
wasCloned = true;
|
|
514
557
|
|
|
515
558
|
// Build clone command
|
|
516
|
-
|
|
559
|
+
const cloneArgs = ['git', 'clone', '--depth', String(effectiveDepth)];
|
|
517
560
|
|
|
518
561
|
// Add branch/ref
|
|
519
562
|
// For commits, we can't use --branch, need to fetch after
|
|
520
563
|
if (!isImmutableRef(ref) || /^v?\d+\.\d+/.test(ref)) {
|
|
521
|
-
|
|
564
|
+
cloneArgs.push('--branch', ref);
|
|
522
565
|
}
|
|
523
566
|
|
|
524
567
|
// Sparse checkout preparation
|
|
525
568
|
if (effectiveSparse) {
|
|
526
|
-
|
|
569
|
+
cloneArgs.push('--filter=blob:none', '--sparse');
|
|
527
570
|
}
|
|
528
571
|
|
|
529
|
-
|
|
572
|
+
cloneArgs.push(authUrl, cloneDir);
|
|
530
573
|
|
|
531
574
|
try {
|
|
532
|
-
await execWithRetry(
|
|
575
|
+
await execWithRetry(cloneArgs, { cwd: root });
|
|
533
576
|
|
|
534
577
|
// If ref is a commit SHA, checkout after clone
|
|
535
578
|
if (/^[0-9a-f]{7,40}$/i.test(ref) && !/^v?\d+\.\d+/.test(ref)) {
|
|
536
|
-
await execWithRetry(
|
|
537
|
-
await execWithRetry(
|
|
579
|
+
await execWithRetry(['git', '-C', cloneDir, 'fetch', '--depth', String(effectiveDepth), 'origin', ref], { cwd: root });
|
|
580
|
+
await execWithRetry(['git', '-C', cloneDir, 'checkout', ref], { cwd: root });
|
|
538
581
|
}
|
|
539
582
|
|
|
540
583
|
// Set up sparse checkout if needed
|
|
541
584
|
if (effectiveSparse) {
|
|
542
|
-
await execWithRetry(
|
|
585
|
+
await execWithRetry(['git', '-C', cloneDir, 'sparse-checkout', 'set', subPath], { cwd: root });
|
|
543
586
|
}
|
|
544
587
|
|
|
545
588
|
newCommit = await getHeadCommit(cloneDir);
|
|
@@ -1670,6 +1713,83 @@ async function applyReadingProgressConfig(distDir, config, tenantId) {
|
|
|
1670
1713
|
console.log(` ↳ enabled reading progress for ${tenantId}`);
|
|
1671
1714
|
}
|
|
1672
1715
|
|
|
1716
|
+
/**
|
|
1717
|
+
* Living scroll on any layout (docs included). Blog tenants opt in via
|
|
1718
|
+
* `blog.livingScroll` (handled in applyBlogLayout); this is the general path,
|
|
1719
|
+
* driven by a top-level `livingScroll: true` (or `reader.livingScroll`). It sets
|
|
1720
|
+
* the layout-agnostic body flag plus a reading-progress bar. The hidden base
|
|
1721
|
+
* state, reduced-motion fallback, and JS-off completeness all live in
|
|
1722
|
+
* page-effects.js + styles.css — the build only sets the hooks.
|
|
1723
|
+
*/
|
|
1724
|
+
async function applyLivingScrollConfig(distDir, config, tenantId) {
|
|
1725
|
+
const reader = (config.reader && typeof config.reader === 'object') ? config.reader : {};
|
|
1726
|
+
if (config.livingScroll !== true && reader.livingScroll !== true) return;
|
|
1727
|
+
|
|
1728
|
+
const indexPath = path.join(distDir, 'index.html');
|
|
1729
|
+
if (!(await pathExists(indexPath))) return;
|
|
1730
|
+
|
|
1731
|
+
let html = await fsp.readFile(indexPath, 'utf8');
|
|
1732
|
+
// Idempotent, and don't fight applyBlogLayout if it already set the blog alias.
|
|
1733
|
+
if (/<body[^>]*data-(?:blog-)?living-scroll(?:[\s=>])/.test(html)) return;
|
|
1734
|
+
const attrs = ['data-living-scroll'];
|
|
1735
|
+
// Living scroll pairs with a progress bar; only add it if not already set
|
|
1736
|
+
// (applyReadingProgressConfig runs first and may have added it).
|
|
1737
|
+
if (!/<body[^>]*data-reading-progress(?:[\s=>])/.test(html)) {
|
|
1738
|
+
attrs.push('data-reading-progress');
|
|
1739
|
+
}
|
|
1740
|
+
html = html.replace(/<body(?=[\s>])/, `<body ${attrs.join(' ')}`);
|
|
1741
|
+
await fsp.writeFile(indexPath, html, 'utf8');
|
|
1742
|
+
console.log(` ↳ enabled living scroll for ${tenantId}`);
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
/**
|
|
1746
|
+
* On-this-page TOC + scroll-spy (#73). Opt-in via a top-level `pageToc`:
|
|
1747
|
+
* pageToc: true → rail placement, default min
|
|
1748
|
+
* pageToc: { placement: "rail"|"top"|"off", minHeadings: N }
|
|
1749
|
+
* Sets the body hooks the pageToc page-effect reads; the effect generates the nav
|
|
1750
|
+
* client-side from the page's headings.
|
|
1751
|
+
*/
|
|
1752
|
+
async function applyPageTocConfig(distDir, config, tenantId) {
|
|
1753
|
+
const toc = config.pageToc;
|
|
1754
|
+
if (toc !== true && (!toc || typeof toc !== 'object')) return;
|
|
1755
|
+
const placementRaw = toc && typeof toc === 'object' ? toc.placement : undefined;
|
|
1756
|
+
if (placementRaw === 'off' || (toc && typeof toc === 'object' && toc.enabled === false)) return;
|
|
1757
|
+
const placement = placementRaw === 'top' ? 'top' : 'rail';
|
|
1758
|
+
const min = toc && typeof toc === 'object' && Number.isInteger(toc.minHeadings) && toc.minHeadings > 0
|
|
1759
|
+
? toc.minHeadings : null;
|
|
1760
|
+
|
|
1761
|
+
const indexPath = path.join(distDir, 'index.html');
|
|
1762
|
+
if (!(await pathExists(indexPath))) return;
|
|
1763
|
+
|
|
1764
|
+
let html = await fsp.readFile(indexPath, 'utf8');
|
|
1765
|
+
if (/<body[^>]*data-page-toc(?:[\s=>])/.test(html)) return;
|
|
1766
|
+
const attrs = [`data-page-toc="${placement}"`];
|
|
1767
|
+
if (min) attrs.push(`data-page-toc-min="${min}"`);
|
|
1768
|
+
html = html.replace(/<body(?=[\s>])/, `<body ${attrs.join(' ')}`);
|
|
1769
|
+
await fsp.writeFile(indexPath, html, 'utf8');
|
|
1770
|
+
console.log(` ↳ enabled on-this-page TOC (${placement}) for ${tenantId}`);
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
/**
|
|
1774
|
+
* Sidebar nav collapse behavior. Configurable via `navCollapse`:
|
|
1775
|
+
* "overlay" (default) — drawer hidden by default; hamburger slides it over the content
|
|
1776
|
+
* "push" — nav visible; collapse slides it out and reflows the content
|
|
1777
|
+
* "instant" — nav visible; collapse instantly hides the column
|
|
1778
|
+
* Writes data-nav-collapse so styles.css can switch modes (drawer modes apply only
|
|
1779
|
+
* to the default left-sidebar layout; positioned-nav demos are unaffected).
|
|
1780
|
+
*/
|
|
1781
|
+
async function applyNavCollapseConfig(distDir, config, tenantId) {
|
|
1782
|
+
const raw = typeof config.navCollapse === 'string' ? config.navCollapse.toLowerCase() : '';
|
|
1783
|
+
const mode = raw === 'push' || raw === 'instant' ? raw : 'overlay';
|
|
1784
|
+
const indexPath = path.join(distDir, 'index.html');
|
|
1785
|
+
if (!(await pathExists(indexPath))) return;
|
|
1786
|
+
let html = await fsp.readFile(indexPath, 'utf8');
|
|
1787
|
+
if (/<body[^>]*data-nav-collapse(?:[\s=>])/.test(html)) return;
|
|
1788
|
+
html = html.replace(/<body(?=[\s>])/, `<body data-nav-collapse="${mode}"`);
|
|
1789
|
+
await fsp.writeFile(indexPath, html, 'utf8');
|
|
1790
|
+
console.log(` ↳ nav collapse mode: ${mode} for ${tenantId}`);
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1673
1793
|
/**
|
|
1674
1794
|
* Write the synthetic blog-index section module and register it in manifest.js.
|
|
1675
1795
|
* Mirrors applyDocsMap's injection (append + idempotent).
|
|
@@ -4776,6 +4896,9 @@ async function buildTenant(tenant, targetOverride, cacheDir, buildOptions) {
|
|
|
4776
4896
|
await applyNavAlignment(distDir, config, tenantId);
|
|
4777
4897
|
await applyBlogLayout(distDir, config, tenantId);
|
|
4778
4898
|
await applyReadingProgressConfig(distDir, config, tenantId);
|
|
4899
|
+
await applyLivingScrollConfig(distDir, config, tenantId);
|
|
4900
|
+
await applyPageTocConfig(distDir, config, tenantId);
|
|
4901
|
+
await applyNavCollapseConfig(distDir, config, tenantId);
|
|
4779
4902
|
await applyDocsMap(distDir, config, tenantId);
|
|
4780
4903
|
await applyWelcome(distDir, config, tenantId);
|
|
4781
4904
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{MANIFEST as e,DEFAULT_SECTION as t,findSection as n,getAdjacentSections as a,SITE_CONFIG as o,EXPORT_CONFIG as s}from"./manifest.a870df3a026b.js";import{updateMetaTags as i}from"./seo.90687a1d3d78.js";import{escapeRegExp as r,searchContentPage as c,flattenManifest as l,findPreferredIndex as d,resolveSectionMetadata as m}from"./lib/search.c52bcae8afda.js";import{resolveTarget as p,resolveEntry as u}from"./lib/router.f9d1cfba022d.js";import{composeExportDocument as v,collectExportableSections as f}from"./lib/export.2db2c0bd974c.js";import{renderMermaidBlocks as h}from"./mermaid-init.f25ee3b6ec1e.js";import{initMediaEmbeds as g}from"./media-init.16fde41d8850.js";import{highlightCodeBlocks as y}from"./syntax-highlight.9d51f36b24da.js";import{initPageEffects as b}from"./lib/page-effects.2e4e21674b13.js";const E=document.getElementById("app"),x=document.getElementById("nav"),L=document.getElementById("year"),C=document.getElementById("exportBtn"),T=document.getElementById("commandToggle"),N=document.getElementById("commandPalette"),k=document.getElementById("commandInput"),$=document.getElementById("commandList"),w=document.getElementById("mobileMenuToggle"),A=document.querySelector(".sidebar"),S=document.body.hasAttribute("data-reading-progress"),I=document.body.dataset.readingProgressMode||"bar",M="docs-toolkit-command-query",H=new Map,P=new Map,_=new Map,B=new Set;let q=[],R=0,F=!1,j=(localStorage.getItem(M)||"").trim(),D=!1;function O(e,t){const n=document.createElement("a");return n.href=e.url,n.target="_blank",n.rel="noopener noreferrer",n.className=`${t} nav-external`,n.title=e.summary||e.title,n.innerHTML=`\n <span class="nav-title">${e.title}<span class="nav-external-icon" aria-label="(opens in new tab)">↗</span></span>\n ${e.summary?`<span class="nav-summary">${e.summary}</span>`:""}\n `,n}function W(e,t={}){const{scrollToHighlight:a=!1}=t,{targetId:o,parentId:s}=function(e){return p(e,n)}(e);F&&ee(),s&&z(s,!0),D=a||Boolean(j),location.hash.replace("#","")===o?V():location.hash=`#${o}`}function U(){return location.hash.replace("#","")||t}async function V(){const s=U(),r=u(s,n);if(!r)return;const{entry:c,targetId:l,parentId:d}=r;l===s?(d&&z(d,!0),function(e,t=null){P.forEach(e=>{e.setAttribute("aria-current","false")});const n=P.get(e);if(n&&n.setAttribute("aria-current","page"),t){const e=P.get(t);e&&e.setAttribute("aria-current","page")}}(c.id,d),await async function(s){if(!s)return;const r=await import(s.module),c=r.load||r.default;if("function"!=typeof c)return void(E.innerHTML='<article class="section"><p>Section failed to load.</p></article>');const l=await c();E.innerHTML=l.html||"",function(t){if(function(e){const t=function(e){if(S)return!0;const t=e?.progress;return!0===e?.reading_progress||!0===e?.readingProgress||(!0===t||!(!t||"object"!=typeof t||!0!==t.enabled&&!0!==t.bar&&"bar"!==t.mode))}(e);if(document.body.toggleAttribute("data-reading-progress",t),t){const t=e?.progress&&"object"==typeof e.progress?e.progress.mode||(e.progress.label?"label":"bar"):I;document.body.dataset.readingProgressMode=t}else delete document.body.dataset.readingProgressMode}(t),!t)return;const n=(E.querySelector(".doc-content")||E.querySelector("article, section")||E).querySelector("h1");if(!n)return;if(t.hero){const e=document.createElement("figure");e.className="post-hero";const a=document.createElement("img");a.src=t.hero,a.alt="",a.loading="eager",e.appendChild(a),n.before(e)}const a=[];t.showDate&&t.date&&a.push(function(e){const t=String(e||"").trim();if(!t)return"";const n=/^\d{4}-\d{2}-\d{2}$/.test(t)?`${t}T00:00:00Z`:t,a=new Date(n);return Number.isNaN(a.getTime())?t:new Intl.DateTimeFormat(void 0,{year:"numeric",month:"long",day:"numeric",timeZone:"UTC"}).format(a)}(t.date)),t.author&&a.push(`By ${t.author}`),t.showReadingTime&&t.reading_time&&a.push(t.reading_label||`${t.reading_time} min read`);let o=n,s=null;if(a.length>0){const e=document.createElement("p");e.className="doc-meta";const t=document.createElement("span");t.className="doc-meta-text",t.textContent=a.join(" · "),e.appendChild(t),n.after(e),o=e,s=e}if(t.showSummary&&t.summary){const e=document.createElement("p");e.className="doc-summary",e.textContent=t.summary,o.after(e),o=e}if(Array.isArray(t.tags)&&t.tags.length){const e=document.createElement("ul");e.className="post-tags";for(const n of t.tags){const t=document.createElement("li");t.textContent=n,e.appendChild(t)}o.after(e),o=e}!async function(t,n,a=null){const o=t.id,s=n.closest(".doc-content")||n.parentElement;let i=null;try{i=await m(e,o)}catch{return}if(U()!==o||!function(e){return!!e&&Boolean(e.concepts&&e.concepts.length||e.skos_concepts&&e.skos_concepts.length||e.relationships&&e.relationships.length||e.provenance&&e.provenance.length||e.provenance_events&&e.provenance_events.length||e.source||e.privacy)}(i))return;const r=document.createElement("div");r.className="doc-fortemi-tools";const c=`docFortemiPanel-${o}`,l=document.createElement("div");l.id=c,l.className="doc-fortemi-panel",l.hidden=!0,l.setAttribute("role","region"),l.setAttribute("aria-label","Page metadata"),function(e,t){e.textContent="",K(e,"Concepts",e=>{const n=t.skos_concepts&&t.skos_concepts.length?t.skos_concepts:t.concepts||[];n.length?function(e,t){const n=document.createElement("div");n.className="doc-fortemi-chips",t.forEach(e=>{const t=document.createElement("span");t.className="doc-fortemi-chip",t.textContent=X(e),"object"==typeof e&&e&&e.definition&&(t.title=e.definition),n.appendChild(t)}),e.appendChild(n)}(e,n):G(e,"concepts","none"),(t.skos_relations||[]).forEach(t=>{const n=X({id:t.source_id||t.source}),a=X({id:t.target_id||t.target});G(e,t.type||"related",`${J(n)} -> ${J(a)}`)})}),K(e,"Source and Provenance",e=>{G(e,"source",t.source?.repo_relative_path||t.source?.path),G(e,"locator",t.source?.locator),G(e,"updated",t.updated_at),G(e,"privacy",t.privacy?.classification),(t.provenance||[]).forEach(t=>{G(e,t.field||"field",`${t.source||"source"} (${t.confidence||"unknown"})`)}),(t.provenance_events||[]).forEach(t=>{const n=[t.agent||"unknown agent",t.source,t.started_at||t.ended_at].filter(Boolean).join(" · ");G(e,t.activity||"activity",n)})}),K(e,"Related Pages",e=>{const n=t.relationships||[];if(!n.length)return void G(e,"related","none");const a=document.createElement("ul");a.className="doc-fortemi-links",n.forEach(e=>{const t=document.createElement("li"),n=document.createElement("button");n.type="button",n.className="doc-fortemi-link";const o=function(e){return String(e?.target_id||e?.target||"").replace(/^docs:page:/,"")}(e),s=function(e){const t=Number(e);return Number.isFinite(t)?`${Math.round(100*Math.max(0,Math.min(1,t)))}%`:null}(e.confidence),i=e.label||e.type||"related",r=Array.isArray(e.metadata?.shared_concepts)?e.metadata.shared_concepts.map(J).join(", "):null;n.textContent=`${i}: ${J(o)}${s?` (${s})`:""}`,r&&(n.title=`Shared concepts: ${r}`),n.addEventListener("click",()=>{o&&W(o)}),t.appendChild(n),a.appendChild(t)}),e.appendChild(a)})}(l,i);const d=document.createElement("button");d.type="button",d.className="doc-fortemi-button",d.setAttribute("aria-expanded","false"),d.setAttribute("aria-controls",c),d.title="Show page metadata",d.innerHTML='<span aria-hidden="true">i</span><span class="sr-only">Show page metadata</span>',d.addEventListener("click",()=>{const e=l.hidden;l.hidden=!e,d.setAttribute("aria-expanded",String(e))}),a?(d.classList.add("doc-fortemi-button-inline"),a.appendChild(d),s.appendChild(l)):(r.appendChild(d),s.append(r,l))}(t,o,s)}(s),await h(E),g(E),await y(E),function(e){const s=E.querySelector(".bottom-nav");s&&s.remove();const i="function"==typeof n?n(e):null;if(i&&i.collection)return void function(e){const n=function(){const e=o.postNav;if(!1===e)return null;const t=e&&"object"==typeof e?e:{};return{prev:!1!==t.prev,next:!1!==t.next,index:!1!==t.index,label:"string"==typeof t.label?t.label:null}}();if(!n)return;const{prev:s,next:i}=a(e),r=o.blogIndex||("string"==typeof t?t:null),c=n.index&&r&&r!==e,l=n.prev&&Boolean(s),d=n.next&&Boolean(i);if(!l&&!d&&!c)return;const m=document.createElement("nav");if(m.className="bottom-nav bottom-nav--posts",m.setAttribute("aria-label","Post navigation"),m.appendChild(l?Y(s,"prev"):Z()),c){const e=n.label||(o.blogIndexTitle?`All ${o.blogIndexTitle}`:"Back to index"),t=document.createElement("a");t.href=`#${r}`,t.className="bottom-nav-index",t.textContent=e,t.setAttribute("aria-label",e),t.addEventListener("click",e=>{e.preventDefault(),W(r)}),m.appendChild(t)}else m.appendChild(Z());m.appendChild(d?Y(i,"next"):Z());(E.querySelector("section")||E).appendChild(m)}(e);if("never"===o.bottomNav)return;const r=(o.bottomNavSections||[]).some(t=>e.startsWith(t)),c="mobile"===o.bottomNav&&!r,{prev:l,next:d}=a(e);if(!l&&!d)return;const m=document.createElement("nav");m.className="bottom-nav",c&&m.classList.add("mobile-only"),m.appendChild(l?Y(l,"prev"):Z()),d&&m.appendChild(Y(d,"next")),(E.querySelector("section")||E).appendChild(m)}(s.id),E.scrollTop=0,window.scrollTo(0,0),"function"==typeof l.afterRender&&l.afterRender(E),b(E),i({title:s.title,description:s.summary,siteTitle:o.siteTitle,siteUrl:o.siteUrl,sectionId:s.id,ogImage:s.ogImage||o.ogImage}),H.set(s.id,Date.now());const d=D;D=!1,ue(d),requestAnimationFrame(()=>E.focus())}(c)):location.replace(`#${l}`)}function z(e,t){if(!e)return;const n=_.get(e);t?(B.add(e),n&&n.group.classList.add("expanded")):(B.delete(e),n&&n.group.classList.remove("expanded"))}function J(e){return String(e||"").replace(/[-_]+/g," ").replace(/\s+/g," ").trim()}function X(e){return"string"==typeof e?J(e):e.prefLabel||e.pref_label||e.label||e.id||"concept"}function G(e,t,n){if(null==n||""===n)return;const a=document.createElement("div");a.className="doc-fortemi-row";const o=document.createElement("span");o.className="doc-fortemi-key",o.textContent=t;const s=document.createElement("span");s.textContent=String(n),a.append(o,s),e.appendChild(a)}function K(e,t,n){const a=document.createElement("section");a.className="doc-fortemi-section";const o=document.createElement("h2");o.textContent=t,a.appendChild(o),n(a),e.appendChild(a)}function Y(e,t){const n=document.createElement("div");n.className=`bottom-nav-item bottom-nav-${t}`;const a=`<span class="bottom-nav-chevron">${"prev"===t?"‹":"›"}</span>`,o=document.createElement("a");o.href=`#${e.id}`,o.className="bottom-nav-link";const s="prev"===t?"Previous":"Next";return o.title=`${s}: ${e.title}`,o.setAttribute("aria-label",`${s}: ${e.title}`),o.textContent=e.title,o.addEventListener("click",t=>{t.preventDefault(),W(e.id)}),"prev"===t?(n.innerHTML=a,n.appendChild(o)):(n.appendChild(o),n.insertAdjacentHTML("beforeend",a)),n}function Z(){const e=document.createElement("div");return e.className="bottom-nav-spacer",e}function Q(){if(!N||!k)return;F=!0,N.hidden=!1;const e=j;k.value=e,se(e),requestAnimationFrame(()=>{k.focus(),e&&k.select()})}function ee(){N&&k&&(F=!1,N.hidden=!0,k.blur())}!function(){x.innerHTML="",P.clear(),_.clear();let t=B.size>0;e.forEach((e,n)=>{if(e.url){const t=O(e,"nav-leaf");return void x.appendChild(t)}if(e.subsections&&e.subsections.length){const n=document.createElement("div");n.className="nav-group";const a=Boolean(e.module),o=document.createElement("button");o.type="button",o.className="nav-parent"+(a?" nav-parent-with-content":""),o.dataset.section=e.id,o.title=e.summary,a?(o.innerHTML=`\n <span class="nav-title-link">${e.title}</span>\n <span class="nav-expand-toggle" aria-label="Expand"></span>\n ${e.summary?`<span class="nav-summary">${e.summary}</span>`:""}\n `,o.querySelector(".nav-title-link").addEventListener("click",t=>{t.stopPropagation(),W(e.id,{scrollToHighlight:Boolean(j)})}),o.querySelector(".nav-expand-toggle").addEventListener("click",t=>{t.stopPropagation();const n=!B.has(e.id);z(e.id,n)}),o.addEventListener("click",t=>{if(t.target===o){const t=!B.has(e.id);z(e.id,t)}})):(o.innerHTML=`\n <span class="nav-title">${e.title}</span>\n ${e.summary?`<span class="nav-summary">${e.summary}</span>`:""}\n `,o.addEventListener("click",()=>{const t=!B.has(e.id);z(e.id,t)}));const s=document.createElement("div");s.className="nav-sublist",e.subsections.forEach(e=>{if(e.url){const t=O(e,"nav-item");return void s.appendChild(t)}if(e.subsections&&e.subsections.length){const t=document.createElement("div");t.className="nav-group nav-group-nested";const n=document.createElement("button");n.type="button",n.className="nav-parent nav-parent-nested",n.dataset.section=e.id,n.title=e.summary||e.title,n.innerHTML=`<span class="nav-title">${e.title}</span>`,n.addEventListener("click",()=>{const t=!B.has(e.id);z(e.id,t)});const a=document.createElement("div");a.className="nav-sublist nav-sublist-nested",e.subsections.forEach(e=>{if(e.url){const t=O(e,"nav-item");return void a.appendChild(t)}if(e.subsections&&e.subsections.length){const t=document.createElement("div");t.className="nav-group nav-group-deep";const n=document.createElement("button");n.type="button",n.className="nav-parent nav-parent-deep",n.dataset.section=e.id,n.title=e.summary||e.title,n.innerHTML=`<span class="nav-title">${e.title}</span>`,n.addEventListener("click",()=>{const t=!B.has(e.id);z(e.id,t)});const o=document.createElement("div");o.className="nav-sublist nav-sublist-deep",e.subsections.forEach(e=>{if(e.url){const t=O(e,"nav-item");return void o.appendChild(t)}if(e.subsections&&e.subsections.length){const t=document.createElement("div");t.className="nav-group nav-group-ultra";const n=document.createElement("button");n.type="button",n.className="nav-parent nav-parent-ultra",n.dataset.section=e.id,n.title=e.summary||e.title,n.innerHTML=`<span class="nav-title">${e.title}</span>`,n.addEventListener("click",()=>{const t=!B.has(e.id);z(e.id,t)});const a=document.createElement("div");a.className="nav-sublist nav-sublist-ultra",e.subsections.forEach(e=>{if(e.url){const t=O(e,"nav-item");return void a.appendChild(t)}const t=document.createElement("button");t.type="button",t.className="nav-item nav-item-ultra"+(e.type?` nav-type-${e.type}`:""),t.dataset.section=e.id,t.title=e.summary||e.title,t.innerHTML=`\n <span class="nav-title">${e.title}</span>\n <span class="nav-summary">${e.summary||""}</span>\n `,t.addEventListener("click",()=>W(e.id,{scrollToHighlight:Boolean(j)})),a.appendChild(t),P.set(e.id,t)}),t.append(n,a),o.appendChild(t),P.set(e.id,n),_.set(e.id,{group:t,button:n,list:a});const s=B.has(e.id)&&!e.collapsed;return void z(e.id,s)}const t=document.createElement("button");t.type="button",t.className="nav-item nav-item-deep"+(e.type?` nav-type-${e.type}`:""),t.dataset.section=e.id,t.title=e.summary||e.title,t.innerHTML=`\n <span class="nav-title">${e.title}${"press-release"===e.type?'<span class="nav-type-icon" aria-label="Press Release"></span>':""}</span>\n <span class="nav-summary">${e.summary||""}</span>\n `,t.addEventListener("click",()=>W(e.id,{scrollToHighlight:Boolean(j)})),o.appendChild(t),P.set(e.id,t)}),t.append(n,o),a.appendChild(t),P.set(e.id,n),_.set(e.id,{group:t,button:n,list:o});const s=B.has(e.id)&&!e.collapsed;return void z(e.id,s)}const t=document.createElement("button");t.type="button",t.className="nav-item nav-item-nested"+(e.type?` nav-type-${e.type}`:""),t.dataset.section=e.id,t.title=e.summary||e.title,t.innerHTML=`\n <span class="nav-title">${e.title}${"press-release"===e.type?'<span class="nav-type-icon" aria-label="Press Release"></span>':""}</span>\n <span class="nav-summary">${e.summary||""}</span>\n `,t.addEventListener("click",()=>W(e.id,{scrollToHighlight:Boolean(j)})),a.appendChild(t),P.set(e.id,t)}),t.append(n,a),s.appendChild(t),P.set(e.id,n),_.set(e.id,{group:t,button:n,list:a});const o=B.has(e.id)&&!e.collapsed;return void z(e.id,o)}const t=document.createElement("button");t.type="button",t.className="nav-item"+(e.type?` nav-type-${e.type}`:""),t.dataset.section=e.id,t.title=e.summary,t.innerHTML=`\n <span class="nav-title">${e.title}${"press-release"===e.type?'<span class="nav-type-icon" aria-label="Press Release"></span>':""}</span>\n <span class="nav-summary">${e.summary}</span>\n `,t.addEventListener("click",()=>W(e.id,{scrollToHighlight:Boolean(j)})),s.appendChild(t),P.set(e.id,t)}),n.append(o,s),x.appendChild(n),P.set(e.id,o),_.set(e.id,{group:n,button:o,list:s});const i=!e.collapsed&&(B.has(e.id)||!t&&!B.size);z(e.id,i),i&&(t=!0)}else{const t=document.createElement("button");t.type="button",t.className="nav-leaf"+(e.type?` nav-type-${e.type}`:""),t.dataset.section=e.id,t.title=e.summary,t.innerHTML=`\n <span class="nav-title">${e.title}${"press-release"===e.type?'<span class="nav-type-icon" aria-label="Press Release"></span>':""}</span>\n <span class="nav-summary">${e.summary}</span>\n `,t.addEventListener("click",()=>W(e.id,{scrollToHighlight:Boolean(j)})),x.appendChild(t),P.set(e.id,t)}})}(),function(){const e=document.getElementById("themePicker"),t=document.getElementById("themeStylesheet");if(!e||!t)return;let n;try{n=JSON.parse(e.dataset.themes||"[]")}catch{return}if(!Array.isArray(n)||0===n.length)return;const a="pagenary:theme",o=e=>{const t=n.find(t=>t.name===e);return t?t.file:null};function s(n){const a=o(n);a&&(t.setAttribute("href",a),e.value=n)}let i=null;try{i=localStorage.getItem(a)}catch{i=null}const r=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches;s(i&&o(i)?i:r&&o("dark")?"dark":e.dataset.default&&o(e.dataset.default)?e.dataset.default:n[0].name),e.addEventListener("change",()=>{s(e.value);try{localStorage.setItem(a,e.value)}catch{}})}(),j&&(D=!0),window.addEventListener("hashchange",()=>{j&&(D=!0),V()}),L.textContent=(new Date).getFullYear(),V(),T&&N&&k&&$&&(T.addEventListener("click",()=>{F?ee():Q()}),k.addEventListener("input",()=>{const e=k.value;pe(e,!0),se(e)}),k.addEventListener("keydown",e=>{const t=q.length-1;if("ArrowDown"===e.key)e.preventDefault(),R=Math.min(t,R+1),re();else if("ArrowUp"===e.key)e.preventDefault(),R=Math.max(0,R-1),re();else if("Enter"===e.key){e.preventDefault();const t=q[R];t&&(pe(k.value,!0),W(t.id,{scrollToHighlight:!0}),ee())}else"Escape"===e.key&&(e.preventDefault(),ee())}),$.addEventListener("click",e=>{const t=e.target.closest("[data-section]");if(!t)return;const n=t.dataset.section;n&&(pe(k.value,!0),W(n,{scrollToHighlight:!0}),ee())}),N.addEventListener("click",e=>{e.target===N&&ee()}),$.addEventListener("scroll",()=>{oe.loading||oe.complete||$.scrollTop+$.clientHeight>=$.scrollHeight-48&&ie(!1)}),window.addEventListener("keydown",e=>{const t=e.target,n=t&&("INPUT"===t.tagName||"TEXTAREA"===t.tagName||t.isContentEditable),a=e.metaKey||e.ctrlKey;"k"===e.key.toLowerCase()&&a||"/"===e.key&&!n?(e.preventDefault(),F?ee():Q()):"Escape"===e.key&&F&&(e.preventDefault(),ee())}));let te=null,ne=!1;const ae=25;let oe={query:"",offset:0,total:0,complete:!0,loading:!1};async function se(e){$&&(oe={query:e,offset:0,total:0,complete:!1,loading:!1},q=[],!ne&&e.trim()&&(ne=!0,$.innerHTML='<li class="cmd-item cmd-loading">Indexing content...</li>'),clearTimeout(te),te=setTimeout(async()=>{await ie(!0);const e=U();R=d(q,e),re(),ne=!1},e.trim()?150:0))}async function ie(t=!1){if(oe.loading)return;if(!t&&oe.complete)return;const n=oe.query;let a;oe.loading=!0;try{a=await c(e,n,{offset:oe.offset,limit:ae})}catch{return void(oe.loading=!1)}n===oe.query?(q=t?a.items:q.concat(a.items),oe.offset=q.length,oe.total=a.total,oe.complete=a.complete||0===a.items.length,oe.loading=!1,function(){if($){if($.innerHTML="",!q.length){const e=document.createElement("li");return e.className="cmd-item",e.setAttribute("aria-selected","false"),e.textContent="No matches.",void $.appendChild(e)}if(q.forEach(e=>{const t=document.createElement("li");t.className="cmd-item",t.dataset.section=e.id,t.setAttribute("role","option");const n=document.createElement("span");if(n.className="cmd-item-title",n.textContent=e.title,e.group){const t=document.createElement("span");t.className="cmd-item-group",t.textContent=e.group,n.prepend(t)}const a=document.createElement("span");if(a.className="cmd-item-summary",a.textContent=e.summary||"",t.append(n,a),e.searchSnippet&&e.searchSnippet!==e.summary){const n=document.createElement("span");n.className="cmd-item-snippet",n.textContent=e.searchSnippet,t.appendChild(n)}if("number"==typeof e.searchRank&&e.searchRank>0){const n=document.createElement("span");n.className="cmd-item-score",n.textContent=`Rank ${e.searchRank}`,t.appendChild(n)}$.appendChild(t)}),!oe.complete&&oe.total>q.length){const e=document.createElement("li");e.className="cmd-item cmd-more",e.setAttribute("aria-selected","false"),e.setAttribute("role","presentation"),e.textContent=`Showing ${q.length} of ${oe.total} — scroll for more`,$.appendChild(e)}}}()):oe.loading=!1}function re(){$&&Array.from($.children).forEach((e,t)=>{const n=t===R&&q.length;e.setAttribute("aria-selected",n?"true":"false"),n&&e.scrollIntoView({block:"nearest"})})}const ce=!s||!1!==s.enabled,le=s&&Array.isArray(s.scopes)&&s.scopes.length?s.scopes:["page","site"];C&&(ce?C.addEventListener("click",function(){const t=document.createElement("div");t.className="export-options-overlay";const n=le.map(e=>{const t=de[e];return t?`<button type="button" class="export-option-btn" data-scope="${e}">\n <span class="export-option-title">${t.title}</span>\n <span class="export-option-desc">${t.desc}</span>\n </button>`:""}).join("");t.innerHTML=`\n <div class="export-options-modal">\n <div class="export-options-header">EXPORT OPTIONS</div>\n <div class="export-options-buttons">\n ${n}\n </div>\n <button type="button" class="export-cancel-btn">Cancel</button>\n </div>\n `,document.body.appendChild(t),setTimeout(()=>t.classList.add("active"),10);const a=()=>{t.classList.remove("active"),setTimeout(()=>t.remove(),200)};t.querySelector(".export-cancel-btn").addEventListener("click",a),t.addEventListener("click",e=>{e.target===t&&a()}),t.querySelectorAll(".export-option-btn").forEach(t=>{t.addEventListener("click",()=>{const n=t.dataset.scope;a(),async function(t="site"){if(!C)return;const n=C.innerHTML;C.disabled=!0;const a=document.createElement("div");a.className="export-loading-overlay",a.innerHTML='\n <div class="export-loading-modal">\n <div class="export-loading-header">\n <div class="export-loading-title">COMPILING DOCUMENTATION</div>\n <div class="export-loading-subtitle">Assembling all sections into unified document</div>\n </div>\n <div class="export-loading-progress">\n <div class="export-loading-bar">\n <div class="export-loading-fill"></div>\n </div>\n <div class="export-loading-status-container">\n <div class="export-loading-status">Initializing...</div>\n </div>\n </div>\n <div class="export-loading-scanner">\n <div class="scanner-line"></div>\n </div>\n </div>\n ',document.body.appendChild(a),setTimeout(()=>a.classList.add("active"),10);const o=a.querySelector(".export-loading-fill"),i=a.querySelector(".export-loading-status");try{let n;if("page"===t){const t=U(),a=f(e).find(e=>e.id===t);n=a?[a]:[]}else n=f(e);if(0===n.length)return alert("No content available to export."),a.remove(),void(C.disabled=!1);const r=[],c=n.length;let l=0;for(const e of n){l++;const n=l/c*100;o.style.width=`${n}%`,i.textContent="page"===t?`Exporting: ${e.title}`:`Processing section ${l} of ${c}: ${e.title}`,await new Promise(e=>setTimeout(e,50));try{const t=await import(e.module),n=t.load||t.default;if("function"!=typeof n)continue;const a=me((await n()).html||"");r.push({section:e,html:a})}catch(t){console.error("Failed to include section in export",e.id,t)}}i.textContent="Generating document...",await new Promise(e=>setTimeout(e,200));const d=v(r,s);i.textContent="Opening print dialog...",await new Promise(e=>setTimeout(e,100)),function(e){document.getElementById("exportPrintFrame")?.remove();const t=document.createElement("iframe");t.id="exportPrintFrame",t.setAttribute("aria-hidden","true"),t.setAttribute("tabindex","-1"),t.style.cssText="position:fixed;width:0;height:0;border:0;left:-9999px;top:0;visibility:hidden;",document.body.appendChild(t);let n=!1;const a=()=>{n||(n=!0,setTimeout(()=>t.remove(),500))},o=t.contentWindow.document;o.open(),o.write(e),o.close();const s=()=>{const e=t.contentWindow;try{e.addEventListener("afterprint",a,{once:!0}),e.focus(),e.print(),setTimeout(a,6e4)}catch(e){console.error("Export print failed",e),t.remove()}};"complete"===t.contentWindow.document.readyState?setTimeout(s,60):t.addEventListener("load",()=>setTimeout(s,60),{once:!0})}(d),a.classList.remove("active"),setTimeout(()=>a.remove(),300)}catch(e){console.error("Export failed",e),alert("Export failed. Check console for details."),a.remove()}finally{C.disabled=!1,C.innerHTML=n}}(n)})})}):C.remove());const de={page:{title:"Current Page",desc:"Export only this section"},site:{title:"Entire Site",desc:"Export all documentation"}};function me(e){const t=document.createElement("div");t.innerHTML=e,t.querySelectorAll("script").forEach(e=>e.remove()),t.querySelectorAll("button").forEach(e=>e.removeAttribute("onclick")),t.querySelectorAll("mark.hl").forEach(e=>{const t=document.createTextNode(e.textContent||"");e.replaceWith(t)});const n=t.querySelector("section");return n?n.innerHTML:t.innerHTML}function pe(e,t=!1){j=e.trim(),t&&(j?localStorage.setItem(M,j):localStorage.removeItem(M)),ue()}function ue(e=!1){E&&function(e,t,{scrollToFirst:n=!1}={}){if(!e)return;if(function(e){e&&e.querySelectorAll("mark.hl").forEach(e=>{const t=document.createTextNode(e.textContent||"");e.replaceWith(t)})}(e),!t)return;const a=t.split(/\s+/).map(e=>e.trim()).filter(Boolean);if(!a.length)return;const o=a.map(e=>e.toLowerCase()),s=new Set(["SCRIPT","STYLE","CODE","PRE"]),i=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,{acceptNode(e){if(!e.nodeValue||!e.nodeValue.trim())return NodeFilter.FILTER_REJECT;const t=e.parentNode;return t&&s.has(t.tagName)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}}),c=[];let l;for(;l=i.nextNode();){const e=l.nodeValue.toLowerCase();o.some(t=>e.includes(t))&&c.push(l)}const d=new RegExp(`(${a.map(r).join("|")})`,"gi");c.forEach(e=>{const t=e.nodeValue,n=[];let a=0;t.replace(d,(e,o,s)=>{s>a&&n.push(document.createTextNode(t.slice(a,s)));const i=document.createElement("mark");return i.className="hl",i.textContent=e,n.push(i),a=s+e.length,e}),a<t.length&&n.push(document.createTextNode(t.slice(a)));const o=document.createDocumentFragment();n.forEach(e=>o.appendChild(e)),e.parentNode.replaceChild(o,e)}),n&&requestAnimationFrame(()=>{const t=e.querySelector("mark.hl");t&&t.scrollIntoView({behavior:"smooth",block:"center"})})}(E,j,{scrollToFirst:e})}w&&A&&(w.addEventListener("click",()=>{A.classList.contains("mobile-open")?(A.classList.remove("mobile-open"),document.body.classList.remove("menu-open"),w.setAttribute("aria-expanded","false")):(A.classList.add("mobile-open"),document.body.classList.add("menu-open"),w.setAttribute("aria-expanded","true"))}),x.addEventListener("click",e=>{if(window.innerWidth<=960){const t=e.target.closest(".nav-item, .nav-leaf, .nav-parent");t&&(t.classList.contains("nav-item")||t.classList.contains("nav-leaf"))&&(A.classList.remove("mobile-open"),document.body.classList.remove("menu-open"),w.setAttribute("aria-expanded","false"))}}),document.addEventListener("click",e=>{window.innerWidth<=960&&A.classList.contains("mobile-open")&&!A.contains(e.target)&&!w.contains(e.target)&&(A.classList.remove("mobile-open"),document.body.classList.remove("menu-open"),w.setAttribute("aria-expanded","false"))}));const ve=document.getElementById("brandHome");ve&&ve.addEventListener("click",e=>{e.preventDefault(),W(t)});
|
|
1
|
+
import{MANIFEST as e,DEFAULT_SECTION as t,findSection as n,getAdjacentSections as a,SITE_CONFIG as o,EXPORT_CONFIG as s}from"./manifest.95224f06782d.js";import{updateMetaTags as i}from"./seo.90687a1d3d78.js";import{escapeRegExp as r,searchContentPage as c,flattenManifest as l,findPreferredIndex as d,resolveSectionMetadata as m}from"./lib/search.c52bcae8afda.js";import{resolveTarget as p,resolveEntry as u}from"./lib/router.f9d1cfba022d.js";import{composeExportDocument as v,collectExportableSections as f}from"./lib/export.2db2c0bd974c.js";import{renderMermaidBlocks as h}from"./mermaid-init.f25ee3b6ec1e.js";import{initMediaEmbeds as g}from"./media-init.16fde41d8850.js";import{highlightCodeBlocks as y}from"./syntax-highlight.9d51f36b24da.js";import{initPageEffects as b}from"./lib/page-effects.2131b53bea6b.js";const E=document.getElementById("app"),x=document.getElementById("nav"),C=document.getElementById("year"),T=document.getElementById("exportBtn"),L=document.getElementById("commandToggle"),N=document.getElementById("commandPalette"),k=document.getElementById("commandInput"),$=document.getElementById("commandList"),w=document.getElementById("mobileMenuToggle"),A=document.querySelector(".sidebar"),S=document.body.hasAttribute("data-reading-progress"),I=document.body.dataset.readingProgressMode||"bar",M="docs-toolkit-command-query",H=new Map,P=new Map,_=new Map,B=new Set;let q=[],R=0,F=!1,j=(localStorage.getItem(M)||"").trim(),D=!1;function W(e,t){const n=document.createElement("a");return n.href=e.url,n.target="_blank",n.rel="noopener noreferrer",n.className=`${t} nav-external`,n.title=e.summary||e.title,n.innerHTML=`\n <span class="nav-title">${e.title}<span class="nav-external-icon" aria-label="(opens in new tab)">↗</span></span>\n ${e.summary?`<span class="nav-summary">${e.summary}</span>`:""}\n `,n}function O(e,t={}){const{scrollToHighlight:a=!1}=t,{targetId:o,parentId:s}=function(e){return p(e,n)}(e);F&&ee(),s&&z(s,!0),D=a||Boolean(j),location.hash.replace("#","")===o?V():location.hash=`#${o}`}function U(){return location.hash.replace("#","")||t}async function V(){const s=U(),r=u(s,n);if(!r)return;const{entry:c,targetId:l,parentId:d}=r;l===s?(d&&z(d,!0),function(e,t=null){P.forEach(e=>{e.setAttribute("aria-current","false")});const n=P.get(e);if(n&&n.setAttribute("aria-current","page"),t){const e=P.get(t);e&&e.setAttribute("aria-current","page")}}(c.id,d),await async function(s){if(!s)return;const r=await import(s.module),c=r.load||r.default;if("function"!=typeof c)return void(E.innerHTML='<article class="section"><p>Section failed to load.</p></article>');const l=await c();E.innerHTML=l.html||"",function(t){if(function(e){const t=function(e){if(S)return!0;const t=e?.progress;return!0===e?.reading_progress||!0===e?.readingProgress||(!0===t||!(!t||"object"!=typeof t||!0!==t.enabled&&!0!==t.bar&&"bar"!==t.mode))}(e);if(document.body.toggleAttribute("data-reading-progress",t),t){const t=e?.progress&&"object"==typeof e.progress?e.progress.mode||(e.progress.label?"label":"bar"):I;document.body.dataset.readingProgressMode=t}else delete document.body.dataset.readingProgressMode}(t),!t)return;const n=(E.querySelector(".doc-content")||E.querySelector("article, section")||E).querySelector("h1");if(!n)return;if(t.hero){const e=document.createElement("figure");e.className="post-hero";const a=document.createElement("img");a.src=t.hero,a.alt="",a.loading="eager",e.appendChild(a),n.before(e)}const a=[];t.showDate&&t.date&&a.push(function(e){const t=String(e||"").trim();if(!t)return"";const n=/^\d{4}-\d{2}-\d{2}$/.test(t)?`${t}T00:00:00Z`:t,a=new Date(n);return Number.isNaN(a.getTime())?t:new Intl.DateTimeFormat(void 0,{year:"numeric",month:"long",day:"numeric",timeZone:"UTC"}).format(a)}(t.date)),t.author&&a.push(`By ${t.author}`),t.showReadingTime&&t.reading_time&&a.push(t.reading_label||`${t.reading_time} min read`);let o=n,s=null;if(a.length>0){const e=document.createElement("p");e.className="doc-meta";const t=document.createElement("span");t.className="doc-meta-text",t.textContent=a.join(" · "),e.appendChild(t),n.after(e),o=e,s=e}if(t.showSummary&&t.summary){const e=document.createElement("p");e.className="doc-summary",e.textContent=t.summary,o.after(e),o=e}if(Array.isArray(t.tags)&&t.tags.length){const e=document.createElement("ul");e.className="post-tags";for(const n of t.tags){const t=document.createElement("li");t.textContent=n,e.appendChild(t)}o.after(e),o=e}!async function(t,n,a=null){const o=t.id,s=n.closest(".doc-content")||n.parentElement;let i=null;try{i=await m(e,o)}catch{return}if(U()!==o||!function(e){return!!e&&Boolean(e.concepts&&e.concepts.length||e.skos_concepts&&e.skos_concepts.length||e.relationships&&e.relationships.length||e.provenance&&e.provenance.length||e.provenance_events&&e.provenance_events.length||e.source||e.privacy)}(i))return;const r=document.createElement("div");r.className="doc-fortemi-tools";const c=`docFortemiPanel-${o}`,l=document.createElement("div");l.id=c,l.className="doc-fortemi-panel",l.hidden=!0,l.setAttribute("role","region"),l.setAttribute("aria-label","Page metadata"),function(e,t){e.textContent="",K(e,"Concepts",e=>{const n=t.skos_concepts&&t.skos_concepts.length?t.skos_concepts:t.concepts||[];n.length?function(e,t){const n=document.createElement("div");n.className="doc-fortemi-chips",t.forEach(e=>{const t=document.createElement("span");t.className="doc-fortemi-chip",t.textContent=X(e),"object"==typeof e&&e&&e.definition&&(t.title=e.definition),n.appendChild(t)}),e.appendChild(n)}(e,n):G(e,"concepts","none"),(t.skos_relations||[]).forEach(t=>{const n=X({id:t.source_id||t.source}),a=X({id:t.target_id||t.target});G(e,t.type||"related",`${J(n)} -> ${J(a)}`)})}),K(e,"Source and Provenance",e=>{G(e,"source",t.source?.repo_relative_path||t.source?.path),G(e,"locator",t.source?.locator),G(e,"updated",t.updated_at),G(e,"privacy",t.privacy?.classification),(t.provenance||[]).forEach(t=>{G(e,t.field||"field",`${t.source||"source"} (${t.confidence||"unknown"})`)}),(t.provenance_events||[]).forEach(t=>{const n=[t.agent||"unknown agent",t.source,t.started_at||t.ended_at].filter(Boolean).join(" · ");G(e,t.activity||"activity",n)})}),K(e,"Related Pages",e=>{const n=t.relationships||[];if(!n.length)return void G(e,"related","none");const a=document.createElement("ul");a.className="doc-fortemi-links",n.forEach(e=>{const t=document.createElement("li"),n=document.createElement("button");n.type="button",n.className="doc-fortemi-link";const o=function(e){return String(e?.target_id||e?.target||"").replace(/^docs:page:/,"")}(e),s=function(e){const t=Number(e);return Number.isFinite(t)?`${Math.round(100*Math.max(0,Math.min(1,t)))}%`:null}(e.confidence),i=e.label||e.type||"related",r=Array.isArray(e.metadata?.shared_concepts)?e.metadata.shared_concepts.map(J).join(", "):null;n.textContent=`${i}: ${J(o)}${s?` (${s})`:""}`,r&&(n.title=`Shared concepts: ${r}`),n.addEventListener("click",()=>{o&&O(o)}),t.appendChild(n),a.appendChild(t)}),e.appendChild(a)})}(l,i);const d=document.createElement("button");d.type="button",d.className="doc-fortemi-button",d.setAttribute("aria-expanded","false"),d.setAttribute("aria-controls",c),d.title="Show page metadata",d.innerHTML='<span aria-hidden="true">i</span><span class="sr-only">Show page metadata</span>',d.addEventListener("click",()=>{const e=l.hidden;l.hidden=!e,d.setAttribute("aria-expanded",String(e))}),a?(d.classList.add("doc-fortemi-button-inline"),a.appendChild(d),s.appendChild(l)):(r.appendChild(d),s.append(r,l))}(t,o,s)}(s),await h(E),g(E),await y(E),function(e){const s=E.querySelector(".bottom-nav");s&&s.remove();const i="function"==typeof n?n(e):null;if(i&&i.collection)return void function(e){const n=function(){const e=o.postNav;if(!1===e)return null;const t=e&&"object"==typeof e?e:{};return{prev:!1!==t.prev,next:!1!==t.next,index:!1!==t.index,label:"string"==typeof t.label?t.label:null}}();if(!n)return;const{prev:s,next:i}=a(e),r=o.blogIndex||("string"==typeof t?t:null),c=n.index&&r&&r!==e,l=n.prev&&Boolean(s),d=n.next&&Boolean(i);if(!l&&!d&&!c)return;const m=document.createElement("nav");if(m.className="bottom-nav bottom-nav--posts",m.setAttribute("aria-label","Post navigation"),m.appendChild(l?Y(s,"prev"):Z()),c){const e=n.label||(o.blogIndexTitle?`All ${o.blogIndexTitle}`:"Back to index"),t=document.createElement("a");t.href=`#${r}`,t.className="bottom-nav-index",t.textContent=e,t.setAttribute("aria-label",e),t.addEventListener("click",e=>{e.preventDefault(),O(r)}),m.appendChild(t)}else m.appendChild(Z());m.appendChild(d?Y(i,"next"):Z());(E.querySelector("section")||E).appendChild(m)}(e);if("never"===o.bottomNav)return;const r=(o.bottomNavSections||[]).some(t=>e.startsWith(t)),c="mobile"===o.bottomNav&&!r,{prev:l,next:d}=a(e);if(!l&&!d)return;const m=document.createElement("nav");m.className="bottom-nav",c&&m.classList.add("mobile-only"),m.appendChild(l?Y(l,"prev"):Z()),d&&m.appendChild(Y(d,"next")),(E.querySelector("section")||E).appendChild(m)}(s.id),E.scrollTop=0,window.scrollTo(0,0),"function"==typeof l.afterRender&&l.afterRender(E),b(E),i({title:s.title,description:s.summary,siteTitle:o.siteTitle,siteUrl:o.siteUrl,sectionId:s.id,ogImage:s.ogImage||o.ogImage}),H.set(s.id,Date.now());const d=D;D=!1,ue(d),requestAnimationFrame(()=>E.focus())}(c)):location.replace(`#${l}`)}function z(e,t){if(!e)return;const n=_.get(e);t?(B.add(e),n&&n.group.classList.add("expanded")):(B.delete(e),n&&n.group.classList.remove("expanded"))}function J(e){return String(e||"").replace(/[-_]+/g," ").replace(/\s+/g," ").trim()}function X(e){return"string"==typeof e?J(e):e.prefLabel||e.pref_label||e.label||e.id||"concept"}function G(e,t,n){if(null==n||""===n)return;const a=document.createElement("div");a.className="doc-fortemi-row";const o=document.createElement("span");o.className="doc-fortemi-key",o.textContent=t;const s=document.createElement("span");s.textContent=String(n),a.append(o,s),e.appendChild(a)}function K(e,t,n){const a=document.createElement("section");a.className="doc-fortemi-section";const o=document.createElement("h2");o.textContent=t,a.appendChild(o),n(a),e.appendChild(a)}function Y(e,t){const n=document.createElement("div");n.className=`bottom-nav-item bottom-nav-${t}`;const a=`<span class="bottom-nav-chevron">${"prev"===t?"‹":"›"}</span>`,o=document.createElement("a");o.href=`#${e.id}`,o.className="bottom-nav-link";const s="prev"===t?"Previous":"Next";return o.title=`${s}: ${e.title}`,o.setAttribute("aria-label",`${s}: ${e.title}`),o.textContent=e.title,o.addEventListener("click",t=>{t.preventDefault(),O(e.id)}),"prev"===t?(n.innerHTML=a,n.appendChild(o)):(n.appendChild(o),n.insertAdjacentHTML("beforeend",a)),n}function Z(){const e=document.createElement("div");return e.className="bottom-nav-spacer",e}function Q(){if(!N||!k)return;F=!0,N.hidden=!1;const e=j;k.value=e,se(e),requestAnimationFrame(()=>{k.focus(),e&&k.select()})}function ee(){N&&k&&(F=!1,N.hidden=!0,k.blur())}!function(){x.innerHTML="",P.clear(),_.clear();let t=B.size>0;e.forEach((e,n)=>{if(e.url){const t=W(e,"nav-leaf");return void x.appendChild(t)}if(e.subsections&&e.subsections.length){const n=document.createElement("div");n.className="nav-group";const a=Boolean(e.module),o=document.createElement("button");o.type="button",o.className="nav-parent"+(a?" nav-parent-with-content":""),o.dataset.section=e.id,o.title=e.summary,a?(o.innerHTML=`\n <span class="nav-title-link">${e.title}</span>\n <span class="nav-expand-toggle" aria-label="Expand"></span>\n ${e.summary?`<span class="nav-summary">${e.summary}</span>`:""}\n `,o.querySelector(".nav-title-link").addEventListener("click",t=>{t.stopPropagation(),O(e.id,{scrollToHighlight:Boolean(j)})}),o.querySelector(".nav-expand-toggle").addEventListener("click",t=>{t.stopPropagation();const n=!B.has(e.id);z(e.id,n)}),o.addEventListener("click",t=>{if(t.target===o){const t=!B.has(e.id);z(e.id,t)}})):(o.innerHTML=`\n <span class="nav-title">${e.title}</span>\n ${e.summary?`<span class="nav-summary">${e.summary}</span>`:""}\n `,o.addEventListener("click",()=>{const t=!B.has(e.id);z(e.id,t)}));const s=document.createElement("div");s.className="nav-sublist",e.subsections.forEach(e=>{if(e.url){const t=W(e,"nav-item");return void s.appendChild(t)}if(e.subsections&&e.subsections.length){const t=document.createElement("div");t.className="nav-group nav-group-nested";const n=document.createElement("button");n.type="button",n.className="nav-parent nav-parent-nested",n.dataset.section=e.id,n.title=e.summary||e.title,n.innerHTML=`<span class="nav-title">${e.title}</span>`,n.addEventListener("click",()=>{const t=!B.has(e.id);z(e.id,t)});const a=document.createElement("div");a.className="nav-sublist nav-sublist-nested",e.subsections.forEach(e=>{if(e.url){const t=W(e,"nav-item");return void a.appendChild(t)}if(e.subsections&&e.subsections.length){const t=document.createElement("div");t.className="nav-group nav-group-deep";const n=document.createElement("button");n.type="button",n.className="nav-parent nav-parent-deep",n.dataset.section=e.id,n.title=e.summary||e.title,n.innerHTML=`<span class="nav-title">${e.title}</span>`,n.addEventListener("click",()=>{const t=!B.has(e.id);z(e.id,t)});const o=document.createElement("div");o.className="nav-sublist nav-sublist-deep",e.subsections.forEach(e=>{if(e.url){const t=W(e,"nav-item");return void o.appendChild(t)}if(e.subsections&&e.subsections.length){const t=document.createElement("div");t.className="nav-group nav-group-ultra";const n=document.createElement("button");n.type="button",n.className="nav-parent nav-parent-ultra",n.dataset.section=e.id,n.title=e.summary||e.title,n.innerHTML=`<span class="nav-title">${e.title}</span>`,n.addEventListener("click",()=>{const t=!B.has(e.id);z(e.id,t)});const a=document.createElement("div");a.className="nav-sublist nav-sublist-ultra",e.subsections.forEach(e=>{if(e.url){const t=W(e,"nav-item");return void a.appendChild(t)}const t=document.createElement("button");t.type="button",t.className="nav-item nav-item-ultra"+(e.type?` nav-type-${e.type}`:""),t.dataset.section=e.id,t.title=e.summary||e.title,t.innerHTML=`\n <span class="nav-title">${e.title}</span>\n <span class="nav-summary">${e.summary||""}</span>\n `,t.addEventListener("click",()=>O(e.id,{scrollToHighlight:Boolean(j)})),a.appendChild(t),P.set(e.id,t)}),t.append(n,a),o.appendChild(t),P.set(e.id,n),_.set(e.id,{group:t,button:n,list:a});const s=B.has(e.id)&&!e.collapsed;return void z(e.id,s)}const t=document.createElement("button");t.type="button",t.className="nav-item nav-item-deep"+(e.type?` nav-type-${e.type}`:""),t.dataset.section=e.id,t.title=e.summary||e.title,t.innerHTML=`\n <span class="nav-title">${e.title}${"press-release"===e.type?'<span class="nav-type-icon" aria-label="Press Release"></span>':""}</span>\n <span class="nav-summary">${e.summary||""}</span>\n `,t.addEventListener("click",()=>O(e.id,{scrollToHighlight:Boolean(j)})),o.appendChild(t),P.set(e.id,t)}),t.append(n,o),a.appendChild(t),P.set(e.id,n),_.set(e.id,{group:t,button:n,list:o});const s=B.has(e.id)&&!e.collapsed;return void z(e.id,s)}const t=document.createElement("button");t.type="button",t.className="nav-item nav-item-nested"+(e.type?` nav-type-${e.type}`:""),t.dataset.section=e.id,t.title=e.summary||e.title,t.innerHTML=`\n <span class="nav-title">${e.title}${"press-release"===e.type?'<span class="nav-type-icon" aria-label="Press Release"></span>':""}</span>\n <span class="nav-summary">${e.summary||""}</span>\n `,t.addEventListener("click",()=>O(e.id,{scrollToHighlight:Boolean(j)})),a.appendChild(t),P.set(e.id,t)}),t.append(n,a),s.appendChild(t),P.set(e.id,n),_.set(e.id,{group:t,button:n,list:a});const o=B.has(e.id)&&!e.collapsed;return void z(e.id,o)}const t=document.createElement("button");t.type="button",t.className="nav-item"+(e.type?` nav-type-${e.type}`:""),t.dataset.section=e.id,t.title=e.summary,t.innerHTML=`\n <span class="nav-title">${e.title}${"press-release"===e.type?'<span class="nav-type-icon" aria-label="Press Release"></span>':""}</span>\n <span class="nav-summary">${e.summary}</span>\n `,t.addEventListener("click",()=>O(e.id,{scrollToHighlight:Boolean(j)})),s.appendChild(t),P.set(e.id,t)}),n.append(o,s),x.appendChild(n),P.set(e.id,o),_.set(e.id,{group:n,button:o,list:s});const i=!e.collapsed&&(B.has(e.id)||!t&&!B.size);z(e.id,i),i&&(t=!0)}else{const t=document.createElement("button");t.type="button",t.className="nav-leaf"+(e.type?` nav-type-${e.type}`:""),t.dataset.section=e.id,t.title=e.summary,t.innerHTML=`\n <span class="nav-title">${e.title}${"press-release"===e.type?'<span class="nav-type-icon" aria-label="Press Release"></span>':""}</span>\n <span class="nav-summary">${e.summary}</span>\n `,t.addEventListener("click",()=>O(e.id,{scrollToHighlight:Boolean(j)})),x.appendChild(t),P.set(e.id,t)}})}(),function(){const e=document.getElementById("themePicker"),t=document.getElementById("themeStylesheet");if(!e||!t)return;let n;try{n=JSON.parse(e.dataset.themes||"[]")}catch{return}if(!Array.isArray(n)||0===n.length)return;const a="pagenary:theme",o=e=>{const t=n.find(t=>t.name===e);return t?t.file:null};function s(n){const a=o(n);a&&(t.setAttribute("href",a),e.value=n)}let i=null;try{i=localStorage.getItem(a)}catch{i=null}const r=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches;s(i&&o(i)?i:r&&o("dark")?"dark":e.dataset.default&&o(e.dataset.default)?e.dataset.default:n[0].name),e.addEventListener("change",()=>{s(e.value);try{localStorage.setItem(a,e.value)}catch{}})}(),j&&(D=!0),window.addEventListener("hashchange",()=>{j&&(D=!0),V()}),C.textContent=(new Date).getFullYear(),V(),L&&N&&k&&$&&(L.addEventListener("click",()=>{F?ee():Q()}),k.addEventListener("input",()=>{const e=k.value;pe(e,!0),se(e)}),k.addEventListener("keydown",e=>{const t=q.length-1;if("ArrowDown"===e.key)e.preventDefault(),R=Math.min(t,R+1),re();else if("ArrowUp"===e.key)e.preventDefault(),R=Math.max(0,R-1),re();else if("Enter"===e.key){e.preventDefault();const t=q[R];t&&(pe(k.value,!0),O(t.id,{scrollToHighlight:!0}),ee())}else"Escape"===e.key&&(e.preventDefault(),ee())}),$.addEventListener("click",e=>{const t=e.target.closest("[data-section]");if(!t)return;const n=t.dataset.section;n&&(pe(k.value,!0),O(n,{scrollToHighlight:!0}),ee())}),N.addEventListener("click",e=>{e.target===N&&ee()}),$.addEventListener("scroll",()=>{oe.loading||oe.complete||$.scrollTop+$.clientHeight>=$.scrollHeight-48&&ie(!1)}),window.addEventListener("keydown",e=>{const t=e.target,n=t&&("INPUT"===t.tagName||"TEXTAREA"===t.tagName||t.isContentEditable),a=e.metaKey||e.ctrlKey;"k"===e.key.toLowerCase()&&a||"/"===e.key&&!n?(e.preventDefault(),F?ee():Q()):"Escape"===e.key&&F&&(e.preventDefault(),ee())}));let te=null,ne=!1;const ae=25;let oe={query:"",offset:0,total:0,complete:!0,loading:!1};async function se(e){$&&(oe={query:e,offset:0,total:0,complete:!1,loading:!1},q=[],!ne&&e.trim()&&(ne=!0,$.innerHTML='<li class="cmd-item cmd-loading">Indexing content...</li>'),clearTimeout(te),te=setTimeout(async()=>{await ie(!0);const e=U();R=d(q,e),re(),ne=!1},e.trim()?150:0))}async function ie(t=!1){if(oe.loading)return;if(!t&&oe.complete)return;const n=oe.query;let a;oe.loading=!0;try{a=await c(e,n,{offset:oe.offset,limit:ae})}catch{return void(oe.loading=!1)}n===oe.query?(q=t?a.items:q.concat(a.items),oe.offset=q.length,oe.total=a.total,oe.complete=a.complete||0===a.items.length,oe.loading=!1,function(){if($){if($.innerHTML="",!q.length){const e=document.createElement("li");return e.className="cmd-item",e.setAttribute("aria-selected","false"),e.textContent="No matches.",void $.appendChild(e)}if(q.forEach(e=>{const t=document.createElement("li");t.className="cmd-item",t.dataset.section=e.id,t.setAttribute("role","option");const n=document.createElement("span");if(n.className="cmd-item-title",n.textContent=e.title,e.group){const t=document.createElement("span");t.className="cmd-item-group",t.textContent=e.group,n.prepend(t)}const a=document.createElement("span");if(a.className="cmd-item-summary",a.textContent=e.summary||"",t.append(n,a),e.searchSnippet&&e.searchSnippet!==e.summary){const n=document.createElement("span");n.className="cmd-item-snippet",n.textContent=e.searchSnippet,t.appendChild(n)}if("number"==typeof e.searchRank&&e.searchRank>0){const n=document.createElement("span");n.className="cmd-item-score",n.textContent=`Rank ${e.searchRank}`,t.appendChild(n)}$.appendChild(t)}),!oe.complete&&oe.total>q.length){const e=document.createElement("li");e.className="cmd-item cmd-more",e.setAttribute("aria-selected","false"),e.setAttribute("role","presentation"),e.textContent=`Showing ${q.length} of ${oe.total} — scroll for more`,$.appendChild(e)}}}()):oe.loading=!1}function re(){$&&Array.from($.children).forEach((e,t)=>{const n=t===R&&q.length;e.setAttribute("aria-selected",n?"true":"false"),n&&e.scrollIntoView({block:"nearest"})})}const ce=!s||!1!==s.enabled,le=s&&Array.isArray(s.scopes)&&s.scopes.length?s.scopes:["page","site"];T&&(ce?T.addEventListener("click",function(){const t=document.createElement("div");t.className="export-options-overlay";const n=le.map(e=>{const t=de[e];return t?`<button type="button" class="export-option-btn" data-scope="${e}">\n <span class="export-option-title">${t.title}</span>\n <span class="export-option-desc">${t.desc}</span>\n </button>`:""}).join("");t.innerHTML=`\n <div class="export-options-modal">\n <div class="export-options-header">EXPORT OPTIONS</div>\n <div class="export-options-buttons">\n ${n}\n </div>\n <button type="button" class="export-cancel-btn">Cancel</button>\n </div>\n `,document.body.appendChild(t),setTimeout(()=>t.classList.add("active"),10);const a=()=>{t.classList.remove("active"),setTimeout(()=>t.remove(),200)};t.querySelector(".export-cancel-btn").addEventListener("click",a),t.addEventListener("click",e=>{e.target===t&&a()}),t.querySelectorAll(".export-option-btn").forEach(t=>{t.addEventListener("click",()=>{const n=t.dataset.scope;a(),async function(t="site"){if(!T)return;const n=T.innerHTML;T.disabled=!0;const a=document.createElement("div");a.className="export-loading-overlay",a.innerHTML='\n <div class="export-loading-modal">\n <div class="export-loading-header">\n <div class="export-loading-title">COMPILING DOCUMENTATION</div>\n <div class="export-loading-subtitle">Assembling all sections into unified document</div>\n </div>\n <div class="export-loading-progress">\n <div class="export-loading-bar">\n <div class="export-loading-fill"></div>\n </div>\n <div class="export-loading-status-container">\n <div class="export-loading-status">Initializing...</div>\n </div>\n </div>\n <div class="export-loading-scanner">\n <div class="scanner-line"></div>\n </div>\n </div>\n ',document.body.appendChild(a),setTimeout(()=>a.classList.add("active"),10);const o=a.querySelector(".export-loading-fill"),i=a.querySelector(".export-loading-status");try{let n;if("page"===t){const t=U(),a=f(e).find(e=>e.id===t);n=a?[a]:[]}else n=f(e);if(0===n.length)return alert("No content available to export."),a.remove(),void(T.disabled=!1);const r=[],c=n.length;let l=0;for(const e of n){l++;const n=l/c*100;o.style.width=`${n}%`,i.textContent="page"===t?`Exporting: ${e.title}`:`Processing section ${l} of ${c}: ${e.title}`,await new Promise(e=>setTimeout(e,50));try{const t=await import(e.module),n=t.load||t.default;if("function"!=typeof n)continue;const a=me((await n()).html||"");r.push({section:e,html:a})}catch(t){console.error("Failed to include section in export",e.id,t)}}i.textContent="Generating document...",await new Promise(e=>setTimeout(e,200));const d=v(r,s);i.textContent="Opening print dialog...",await new Promise(e=>setTimeout(e,100)),function(e){document.getElementById("exportPrintFrame")?.remove();const t=document.createElement("iframe");t.id="exportPrintFrame",t.setAttribute("aria-hidden","true"),t.setAttribute("tabindex","-1"),t.style.cssText="position:fixed;width:0;height:0;border:0;left:-9999px;top:0;visibility:hidden;",document.body.appendChild(t);let n=!1;const a=()=>{n||(n=!0,setTimeout(()=>t.remove(),500))},o=t.contentWindow.document;o.open(),o.write(e),o.close();const s=()=>{const e=t.contentWindow;try{e.addEventListener("afterprint",a,{once:!0}),e.focus(),e.print(),setTimeout(a,6e4)}catch(e){console.error("Export print failed",e),t.remove()}};"complete"===t.contentWindow.document.readyState?setTimeout(s,60):t.addEventListener("load",()=>setTimeout(s,60),{once:!0})}(d),a.classList.remove("active"),setTimeout(()=>a.remove(),300)}catch(e){console.error("Export failed",e),alert("Export failed. Check console for details."),a.remove()}finally{T.disabled=!1,T.innerHTML=n}}(n)})})}):T.remove());const de={page:{title:"Current Page",desc:"Export only this section"},site:{title:"Entire Site",desc:"Export all documentation"}};function me(e){const t=document.createElement("div");t.innerHTML=e,t.querySelectorAll("script").forEach(e=>e.remove()),t.querySelectorAll("button").forEach(e=>e.removeAttribute("onclick")),t.querySelectorAll("mark.hl").forEach(e=>{const t=document.createTextNode(e.textContent||"");e.replaceWith(t)});const n=t.querySelector("section");return n?n.innerHTML:t.innerHTML}function pe(e,t=!1){j=e.trim(),t&&(j?localStorage.setItem(M,j):localStorage.removeItem(M)),ue()}function ue(e=!1){E&&function(e,t,{scrollToFirst:n=!1}={}){if(!e)return;if(function(e){e&&e.querySelectorAll("mark.hl").forEach(e=>{const t=document.createTextNode(e.textContent||"");e.replaceWith(t)})}(e),!t)return;const a=t.split(/\s+/).map(e=>e.trim()).filter(Boolean);if(!a.length)return;const o=a.map(e=>e.toLowerCase()),s=new Set(["SCRIPT","STYLE","CODE","PRE"]),i=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,{acceptNode(e){if(!e.nodeValue||!e.nodeValue.trim())return NodeFilter.FILTER_REJECT;const t=e.parentNode;return t&&s.has(t.tagName)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}}),c=[];let l;for(;l=i.nextNode();){const e=l.nodeValue.toLowerCase();o.some(t=>e.includes(t))&&c.push(l)}const d=new RegExp(`(${a.map(r).join("|")})`,"gi");c.forEach(e=>{const t=e.nodeValue,n=[];let a=0;t.replace(d,(e,o,s)=>{s>a&&n.push(document.createTextNode(t.slice(a,s)));const i=document.createElement("mark");return i.className="hl",i.textContent=e,n.push(i),a=s+e.length,e}),a<t.length&&n.push(document.createTextNode(t.slice(a)));const o=document.createDocumentFragment();n.forEach(e=>o.appendChild(e)),e.parentNode.replaceChild(o,e)}),n&&requestAnimationFrame(()=>{const t=e.querySelector("mark.hl");t&&t.scrollIntoView({behavior:"smooth",block:"center"})})}(E,j,{scrollToFirst:e})}if(w&&A){const e=()=>document.body.dataset.navCollapse||"overlay",t=()=>window.innerWidth<=960||"overlay"===e(),n=()=>{A.classList.remove("mobile-open"),document.body.classList.remove("menu-open"),w.setAttribute("aria-expanded","false")};window.innerWidth>960&&"overlay"!==e()&&w.setAttribute("aria-expanded","true"),w.addEventListener("click",()=>{if(window.innerWidth>960&&"overlay"!==e()){const e=document.body.classList.toggle("nav-collapsed");return void w.setAttribute("aria-expanded",String(!e))}const t=A.classList.toggle("mobile-open");document.body.classList.toggle("menu-open",t),w.setAttribute("aria-expanded",String(t))}),x.addEventListener("click",e=>{if(!t())return;const a=e.target.closest(".nav-item, .nav-leaf, .nav-parent");a&&(a.classList.contains("nav-item")||a.classList.contains("nav-leaf"))&&n()}),document.addEventListener("click",e=>{t()&&A.classList.contains("mobile-open")&&!A.contains(e.target)&&!w.contains(e.target)&&n()})}const ve=document.getElementById("brandHome");ve&&ve.addEventListener("click",e=>{e.preventDefault(),O(t)});
|