@takazudo/zudo-doc 5.16.1 → 5.17.0

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/CHANGELOG.md CHANGED
@@ -4,6 +4,32 @@ All notable changes to `@takazudo/zudo-doc` are documented in this file.
4
4
 
5
5
  The format is based on Keep a Changelog, and release notes are generated from the changelog MDX pages.
6
6
 
7
+ ## [5.17.0] - 2026-09-04
8
+
9
+ ### Features
10
+
11
+ - The asset page's details side rail can now be collapsed and expanded with a toggle tab (`0eee44478`).
12
+
13
+ ### Bug Fixes
14
+
15
+ - Route code assets through the shared details side rail instead of their own layout (`bcfd3c0dc`).
16
+ - Keep the details card at a fixed width while the rail collapses, so its contents no longer reflow mid-animation (`a052aac2e`).
17
+ - Collapse the details rail's grid row rather than only its paint, so the space is actually reclaimed (`856ad6dd6`).
18
+ - Stop the prose `dt`/`dd` rules from breaking the Details grid rows (`9422069e2`, `5beb96506`).
19
+ - Only inject `/sitemap.xml` when `settings.sitemap` is enabled (`40c89e59a`).
20
+ - Give the language disclosure list an accessible name (`597c74828`).
21
+
22
+ ### Other Changes
23
+
24
+ - Update the zfb peer and development dependency family to 2.15.0 (`d9f5b2f64`). `ts` and `typescript` code fences now resolve to the TypeScript grammar and `tsx` to TypeScriptReact, where both previously fell back to JavaScript highlighting. Token classes stay on zfb's existing semantic-role vocabulary, so themes need no new rules. zfb's content-pipeline fingerprint moves to v3, so the first build after upgrading re-renders cached content.
25
+
26
+ ## [5.16.2] - 2026-09-03
27
+
28
+ ### Bug Fixes
29
+
30
+ - Asset pages that fall back to the download panel (non-previewable or failed sniff) now render it through the shared media rail layout, so their details and linked-page sections line up with previewable assets instead of stacking. (`19e2166c9`)
31
+ - Manifest-backed block images now receive the `p-hsp-lg` inset on their figure, matching the surrounding content rhythm; `zd-enlargeable` and its enlarge button stay gated by the existing eligibility rule. (`b40ffb4c1`)
32
+
7
33
  ## [5.16.1] - 2026-09-02
8
34
 
9
35
  ### Other Changes
@@ -4,7 +4,7 @@ import type { ComponentChildren, JSX, VNode } from "preact";
4
4
  import type { ChromeContext } from "../factory-context/index.js";
5
5
  import type { AssetRecord } from "../plugins/internal/asset-viewer/types.js";
6
6
  import type { Settings } from "../settings.js";
7
- export { ASSET_PAGE_SCRIPT } from "./script.js";
7
+ export { ASSET_DETAILS_HIDDEN_ATTR, ASSET_DETAILS_PREPAINT_SCRIPT, ASSET_DETAILS_STORAGE_KEY, ASSET_PAGE_SCRIPT, } from "./script.js";
8
8
  export type { AssetRecord } from "../plugins/internal/asset-viewer/types.js";
9
9
  export interface AssetPageViewProps {
10
10
  entry: AssetRecord;
@@ -81,5 +81,9 @@ export declare function AssetDetails({ asset, labels }: {
81
81
  asset: AssetRecord;
82
82
  labels: AssetDetailsLabels;
83
83
  }): VNode;
84
+ export interface AssetDetailsToggleLabels {
85
+ collapse: string;
86
+ expand: string;
87
+ }
84
88
  /** Build the package-owned wide asset viewer page from a chrome context. */
85
89
  export declare function createAssetPageView<S extends Settings = Settings>(ctx: ChromeContext<S>): (props: AssetPageViewProps) => JSX.Element;
@@ -9,10 +9,16 @@ import { formatDate } from "../format-date/index.js";
9
9
  import { buildGitHubSourceUrl } from "../github-helpers/index.js";
10
10
  import { createHeadWithDefaults } from "../head-with-defaults/index.js";
11
11
  import { assetRawHref, assetViewerHref } from "../asset-path/index.js";
12
+ import { ChevronLeft, ChevronRight } from "../icons/index.js";
12
13
  import { formatAssetBytes } from "../asset-components/index.js";
13
14
  import { resolveThemePackSsrSlug } from "../theme/theme-pack-provider.js";
14
- import { ASSET_PAGE_SCRIPT } from "./script.js";
15
- import { ASSET_PAGE_SCRIPT as ASSET_PAGE_SCRIPT2 } from "./script.js";
15
+ import { ASSET_DETAILS_PREPAINT_SCRIPT, ASSET_PAGE_SCRIPT } from "./script.js";
16
+ import {
17
+ ASSET_DETAILS_HIDDEN_ATTR,
18
+ ASSET_DETAILS_PREPAINT_SCRIPT as ASSET_DETAILS_PREPAINT_SCRIPT2,
19
+ ASSET_DETAILS_STORAGE_KEY,
20
+ ASSET_PAGE_SCRIPT as ASSET_PAGE_SCRIPT2
21
+ } from "./script.js";
16
22
  function formatDuration(seconds) {
17
23
  const rounded = Math.round(seconds);
18
24
  const minutes = Math.floor(rounded / 60);
@@ -153,18 +159,42 @@ function AssetDetails({ asset, labels }) {
153
159
  if (asset.updatedDate) rows.push([labels.updated, asset.updatedDate]);
154
160
  return /* @__PURE__ */ jsxs("section", { children: [
155
161
  /* @__PURE__ */ jsx("h2", { class: "mb-vsp-xs text-title font-bold", children: labels.heading }),
156
- /* @__PURE__ */ jsx("dl", { class: "grid grid-cols-[auto_1fr] gap-x-hsp-md gap-y-vsp-2xs text-caption", children: rows.map(([term, value]) => /* @__PURE__ */ jsxs(Fragment, { children: [
162
+ /* @__PURE__ */ jsx("dl", { "data-zd-asset-details-list": true, class: "grid grid-cols-[auto_1fr] gap-x-hsp-md gap-y-vsp-2xs text-caption", children: rows.map(([term, value]) => /* @__PURE__ */ jsxs(Fragment, { children: [
157
163
  /* @__PURE__ */ jsx("dt", { class: "font-medium text-muted", children: term }),
158
164
  /* @__PURE__ */ jsx("dd", { class: "min-w-0 break-words text-fg", children: value })
159
165
  ] })) })
160
166
  ] });
161
167
  }
162
- function MediaLayout({ stage, details, linked }) {
163
- return /* @__PURE__ */ jsxs("div", { class: "zd-asset-media-grid", children: [
164
- /* @__PURE__ */ jsx("div", { class: "min-w-0", children: stage }),
165
- /* @__PURE__ */ jsxs("div", { class: "zd-asset-media-rail", children: [
166
- /* @__PURE__ */ jsx("div", { class: "rounded border border-muted p-hsp-lg", children: details }),
167
- linked
168
+ const ASSET_DETAILS_RAIL_ID = "zd-asset-details-rail";
169
+ function AssetDetailsToggle({ labels }) {
170
+ return /* @__PURE__ */ jsxs(
171
+ "button",
172
+ {
173
+ type: "button",
174
+ disabled: true,
175
+ "data-zd-asset-details-toggle": true,
176
+ "data-zd-label-collapse": labels.collapse,
177
+ "data-zd-label-expand": labels.expand,
178
+ "aria-controls": ASSET_DETAILS_RAIL_ID,
179
+ "aria-expanded": "true",
180
+ "aria-label": labels.collapse,
181
+ class: "zd-asset-details-toggle hidden lg:flex fixed bottom-vsp-xl z-sidebar items-center justify-center w-[1.5rem] h-[3rem] bg-surface border border-muted border-r-0 rounded-l-DEFAULT text-muted cursor-pointer transition-colors duration-200 ease-in-out hover:text-fg disabled:cursor-default disabled:opacity-50",
182
+ children: [
183
+ /* @__PURE__ */ jsx("span", { "data-zd-asset-details-chevron": "collapse", children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-icon-sm w-icon-sm" }) }),
184
+ /* @__PURE__ */ jsx("span", { "data-zd-asset-details-chevron": "expand", children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-icon-sm w-icon-sm" }) })
185
+ ]
186
+ }
187
+ );
188
+ }
189
+ function AssetBodyLayout({ stage, details, linked, toggleLabels }) {
190
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
191
+ /* @__PURE__ */ jsx(AssetDetailsToggle, { labels: toggleLabels }),
192
+ /* @__PURE__ */ jsxs("div", { class: "zd-asset-media-grid", children: [
193
+ /* @__PURE__ */ jsx("div", { class: "min-w-0", children: stage }),
194
+ /* @__PURE__ */ jsxs("div", { id: ASSET_DETAILS_RAIL_ID, "data-zd-asset-details": true, class: "zd-asset-media-rail", children: [
195
+ /* @__PURE__ */ jsx("div", { class: "rounded border border-muted p-hsp-lg", children: details }),
196
+ linked
197
+ ] })
168
198
  ] })
169
199
  ] });
170
200
  }
@@ -215,23 +245,24 @@ function createAssetPageView(ctx) {
215
245
  };
216
246
  const details = /* @__PURE__ */ jsx(AssetDetails, { asset, labels: detailsLabels });
217
247
  const downloadPanel = /* @__PURE__ */ jsx(AssetDownloadPanel, { asset, rawUrl, noPreview: t("asset.noPreview", locale), downloadLabel: t("asset.download", locale), copyLabel: t("asset.copy", locale) });
218
- let body;
248
+ let stage;
219
249
  const isMedia = asset.previewable && asset.sniffOk && ["image", "video", "pdf"].includes(asset.kind);
220
- if (!asset.previewable || !asset.sniffOk) body = /* @__PURE__ */ jsxs(Fragment, { children: [
221
- downloadPanel,
222
- /* @__PURE__ */ jsx(AssetDetails, { asset, labels: detailsLabels }),
223
- linked
224
- ] });
225
- else if (asset.kind === "image") body = /* @__PURE__ */ jsx(MediaLayout, { stage: /* @__PURE__ */ jsx(AssetImageStage, { asset, rawUrl, labels: imageStageLabels }), details, linked });
226
- else if (asset.kind === "video") body = /* @__PURE__ */ jsx(MediaLayout, { stage: /* @__PURE__ */ jsx(AssetVideoStage, { asset, rawUrl }), details, linked });
227
- else if (asset.kind === "pdf") body = /* @__PURE__ */ jsx(MediaLayout, { stage: /* @__PURE__ */ jsx(AssetPdfStage, { asset, rawUrl, children: downloadPanel }), details, linked });
228
- else body = /* @__PURE__ */ jsxs(Fragment, { children: [
229
- /* @__PURE__ */ jsx(AssetCodeBody, { asset, copyLabel: t("asset.copy", locale), wrapLabel: t("asset.wrap", locale), truncatedLabel: t("asset.truncated", locale), linesLabel }),
230
- /* @__PURE__ */ jsx(AssetDetails, { asset, labels: detailsLabels }),
231
- linked
232
- ] });
250
+ if (!asset.previewable || !asset.sniffOk) stage = downloadPanel;
251
+ else if (asset.kind === "image") stage = /* @__PURE__ */ jsx(AssetImageStage, { asset, rawUrl, labels: imageStageLabels });
252
+ else if (asset.kind === "video") stage = /* @__PURE__ */ jsx(AssetVideoStage, { asset, rawUrl });
253
+ else if (asset.kind === "pdf") stage = /* @__PURE__ */ jsx(AssetPdfStage, { asset, rawUrl, children: downloadPanel });
254
+ else stage = /* @__PURE__ */ jsx(AssetCodeBody, { asset, copyLabel: t("asset.copy", locale), wrapLabel: t("asset.wrap", locale), truncatedLabel: t("asset.truncated", locale), linesLabel });
255
+ const detailsToggleLabels = {
256
+ collapse: t("asset.detailsCollapse", locale),
257
+ expand: t("asset.detailsExpand", locale)
258
+ };
259
+ const body = /* @__PURE__ */ jsx(AssetBodyLayout, { stage, details, linked, toggleLabels: detailsToggleLabels });
233
260
  const showSource = settings.bodyFootUtilArea !== false && settings.bodyFootUtilArea.viewSourceLink !== false;
234
- return /* @__PURE__ */ jsx(DocLayoutWithDefaults, { title: composeMetaTitle(asset.name), head: /* @__PURE__ */ jsx(HeadWithDefaults, { title: asset.name, description: asset.description, canonical: ctx.absoluteUrl(viewerUrl) }), lang: locale, dataThemePack, noindex: settings.noindex, hideSidebar: true, hideToc: true, sidebarOverride: false, contentWide: true, breadcrumbOverride: /* @__PURE__ */ jsx(BreadcrumbWithDefaults, { items: breadcrumbItems }), headerOverride: /* @__PURE__ */ jsx(HeaderWithDefaults, { lang: locale, currentPath: viewerUrl, hideSidebarToggle: true }), footerOverride: /* @__PURE__ */ jsx(FooterWithDefaults, { lang: locale }), bodyEndComponents: /* @__PURE__ */ jsx(BodyEndIslands, { basePath: settings.base ?? "/", forceImageEnlarge: asset.kind === "image" && asset.previewable && asset.sniffOk }), enableClientRouter: settings.dynamicPageTransition, children: /* @__PURE__ */ jsxs("div", { class: "zd-asset-page", "data-zd-asset-page": true, children: [
261
+ const railPrepaint = /* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: ASSET_DETAILS_PREPAINT_SCRIPT } });
262
+ return /* @__PURE__ */ jsx(DocLayoutWithDefaults, { title: composeMetaTitle(asset.name), head: /* @__PURE__ */ jsxs(Fragment, { children: [
263
+ railPrepaint,
264
+ /* @__PURE__ */ jsx(HeadWithDefaults, { title: asset.name, description: asset.description, canonical: ctx.absoluteUrl(viewerUrl) })
265
+ ] }), lang: locale, dataThemePack, noindex: settings.noindex, hideSidebar: true, hideToc: true, sidebarOverride: false, contentWide: true, breadcrumbOverride: /* @__PURE__ */ jsx(BreadcrumbWithDefaults, { items: breadcrumbItems }), headerOverride: /* @__PURE__ */ jsx(HeaderWithDefaults, { lang: locale, currentPath: viewerUrl, hideSidebarToggle: true }), footerOverride: /* @__PURE__ */ jsx(FooterWithDefaults, { lang: locale }), bodyEndComponents: /* @__PURE__ */ jsx(BodyEndIslands, { basePath: settings.base ?? "/", forceImageEnlarge: asset.kind === "image" && asset.previewable && asset.sniffOk }), enableClientRouter: settings.dynamicPageTransition, children: /* @__PURE__ */ jsxs("div", { class: "zd-asset-page", "data-zd-asset-page": true, children: [
235
266
  backLink && /* @__PURE__ */ jsx("p", { class: "mb-vsp-xs text-caption", children: /* @__PURE__ */ jsxs("a", { href: backLink.href, class: "text-muted hover:text-accent focus-visible:text-accent hover:underline focus-visible:underline", children: [
236
267
  "\u2190 ",
237
268
  t("asset.backTo", locale),
@@ -248,6 +279,9 @@ function createAssetPageView(ctx) {
248
279
  };
249
280
  }
250
281
  export {
282
+ ASSET_DETAILS_HIDDEN_ATTR,
283
+ ASSET_DETAILS_PREPAINT_SCRIPT2 as ASSET_DETAILS_PREPAINT_SCRIPT,
284
+ ASSET_DETAILS_STORAGE_KEY,
251
285
  ASSET_PAGE_SCRIPT2 as ASSET_PAGE_SCRIPT,
252
286
  AssetActions,
253
287
  AssetCodeBody,
@@ -1,2 +1,31 @@
1
+ /**
2
+ * `localStorage` key holding the details-rail visibility preference.
3
+ *
4
+ * Exported so the controller below AND the pre-paint script interpolate the
5
+ * SAME constant — two string literals could silently drift and leave the
6
+ * pre-paint restore reading a key nothing ever writes (the pattern
7
+ * `TOC_VISIBILITY_PREPAINT_SCRIPT` uses with `TOC_STORAGE_KEY`).
8
+ * Only the exact value `"false"` means collapsed; anything else (including a
9
+ * missing entry) means visible, so the default needs no stored value.
10
+ */
11
+ export declare const ASSET_DETAILS_STORAGE_KEY = "zudo-doc-asset-details-visible";
12
+ /**
13
+ * `<html>` attribute marking the details rail as collapsed.
14
+ *
15
+ * Lives on `<html>` — not on the page wrapper — because the pre-paint script
16
+ * runs before `<body>` is parsed, so `<html>` is the only element that can
17
+ * carry pre-paint state (#3941 D3). Listed in doc-layout's `preserveHtmlAttrs`
18
+ * so it survives an SPA swap before paint.
19
+ */
20
+ export declare const ASSET_DETAILS_HIDDEN_ATTR = "data-asset-details-hidden";
21
+ /**
22
+ * Pre-paint inline script body: restore the persisted collapsed preference to
23
+ * `<html data-asset-details-hidden>` before first paint, so a hard reload of a
24
+ * collapsed asset page never flashes the expanded rail.
25
+ *
26
+ * A tiny synchronous IIFE intended for the page `<head>`. Silently no-ops when
27
+ * storage is disabled or throws (private mode, blocked cookies).
28
+ */
29
+ export declare const ASSET_DETAILS_PREPAINT_SCRIPT: string;
1
30
  /** Inline bootstrap for asset-page controls. Kept dependency-free for SSR. */
2
31
  export declare const ASSET_PAGE_SCRIPT: string;
@@ -1,4 +1,18 @@
1
- const ASSET_PAGE_SCRIPT = String.raw`(()=>{const init=()=>{document.querySelectorAll('[data-zd-asset-page]').forEach(page=>{if(page.hasAttribute('data-zd-asset-ready'))return;page.setAttribute('data-zd-asset-ready','true');const pre=page.querySelector('.zd-asset-code');page.addEventListener('click',event=>{const target=event.target;if(!(target instanceof Element))return;const button=target.closest('button');const action=target.closest('[data-zd-asset-action]')?.getAttribute('data-zd-asset-action');if(action==='copy'||action==='wrap'){const proxy=pre?.closest('.code-block-wrapper')?.querySelector('.code-btn-'+action);if(proxy instanceof HTMLElement)proxy.click();return}if(action==='copy-url'&&button){navigator.clipboard.writeText(button.dataset.zdCopyUrl||location.href);return}const section=target.closest('section');const stage=section?.querySelector('.zd-asset-stage');if(action==='fit'||action==='1to1'){stage?.classList.toggle('is-1to1',action==='1to1');section?.querySelectorAll('[data-zd-asset-action="fit"],[data-zd-asset-action="1to1"]').forEach(item=>item.setAttribute('aria-pressed',String(item===button)));return}if((action==='checker'||action==='dark')&&button){stage?.classList.toggle('is-checker',action==='checker');stage?.classList.toggle('is-dark',action==='dark');section?.querySelectorAll('[data-zd-asset-action="checker"],[data-zd-asset-action="dark"]').forEach(item=>item.setAttribute('aria-pressed',String(item===button)));return}const line=target.closest('.zd-asset-code .line');const lineOffset=line?event.clientX-line.getBoundingClientRect().left:Infinity;const gutterWidth=line?parseFloat(getComputedStyle(line,'::before').width):0;if(line&&lineOffset<gutterWidth){location.hash=line.id}});if(pre){const wait=()=>{const wrapper=pre.closest('.code-block-wrapper');if(!wrapper){requestAnimationFrame(wait);return}page.querySelectorAll('[data-zd-asset-action="copy"],[data-zd-asset-action="wrap"]').forEach(button=>button.removeAttribute('disabled'))};requestAnimationFrame(wait)}})};if(!document.__zdAssetPageInit){document.__zdAssetPageInit=init;document.addEventListener('zfb:after-swap',init)}document.__zdAssetPageInit()})();`;
1
+ const ASSET_DETAILS_STORAGE_KEY = "zudo-doc-asset-details-visible";
2
+ const ASSET_DETAILS_HIDDEN_ATTR = "data-asset-details-hidden";
3
+ const ASSET_DETAILS_PREPAINT_SCRIPT = `(function(){try{if(localStorage.getItem(${JSON.stringify(
4
+ ASSET_DETAILS_STORAGE_KEY
5
+ )})==='false'){document.documentElement.setAttribute(${JSON.stringify(
6
+ ASSET_DETAILS_HIDDEN_ATTR
7
+ )},'');}}catch(e){}})();`;
8
+ const ASSET_PAGE_SCRIPT = String.raw`(()=>{const DKEY=${JSON.stringify(
9
+ ASSET_DETAILS_STORAGE_KEY
10
+ )};const DATTR=${JSON.stringify(
11
+ ASSET_DETAILS_HIDDEN_ATTR
12
+ )};const readDetails=()=>{try{return localStorage.getItem(DKEY)!=='false'}catch(e){return true}};const writeDetails=visible=>{try{localStorage.setItem(DKEY,String(visible))}catch(e){}};const applyDetails=(toggle,visible)=>{const root=document.documentElement;if(root){if(visible){root.removeAttribute(DATTR)}else{root.setAttribute(DATTR,'')}}if(toggle){toggle.setAttribute('aria-expanded',String(visible));const label=toggle.getAttribute(visible?'data-zd-label-collapse':'data-zd-label-expand');if(label)toggle.setAttribute('aria-label',label)}};const init=()=>{document.querySelectorAll('[data-zd-asset-page]').forEach(page=>{if(page.hasAttribute('data-zd-asset-ready'))return;page.setAttribute('data-zd-asset-ready','true');const detailsToggle=page.querySelector('[data-zd-asset-details-toggle]');if(detailsToggle)detailsToggle.removeAttribute('disabled');let detailsVisible=readDetails();applyDetails(detailsToggle,detailsVisible);const pre=page.querySelector('.zd-asset-code');page.addEventListener('click',event=>{const target=event.target;if(!(target instanceof Element))return;const button=target.closest('button');if(target.closest('[data-zd-asset-details-toggle]')){detailsVisible=!detailsVisible;applyDetails(detailsToggle,detailsVisible);writeDetails(detailsVisible);return}const action=target.closest('[data-zd-asset-action]')?.getAttribute('data-zd-asset-action');if(action==='copy'||action==='wrap'){const proxy=pre?.closest('.code-block-wrapper')?.querySelector('.code-btn-'+action);if(proxy instanceof HTMLElement)proxy.click();return}if(action==='copy-url'&&button){navigator.clipboard.writeText(button.dataset.zdCopyUrl||location.href);return}const section=target.closest('section');const stage=section?.querySelector('.zd-asset-stage');if(action==='fit'||action==='1to1'){stage?.classList.toggle('is-1to1',action==='1to1');section?.querySelectorAll('[data-zd-asset-action="fit"],[data-zd-asset-action="1to1"]').forEach(item=>item.setAttribute('aria-pressed',String(item===button)));return}if((action==='checker'||action==='dark')&&button){stage?.classList.toggle('is-checker',action==='checker');stage?.classList.toggle('is-dark',action==='dark');section?.querySelectorAll('[data-zd-asset-action="checker"],[data-zd-asset-action="dark"]').forEach(item=>item.setAttribute('aria-pressed',String(item===button)));return}const line=target.closest('.zd-asset-code .line');const lineOffset=line?event.clientX-line.getBoundingClientRect().left:Infinity;const gutterWidth=line?parseFloat(getComputedStyle(line,'::before').width):0;if(line&&lineOffset<gutterWidth){location.hash=line.id}});if(pre){const wait=()=>{const wrapper=pre.closest('.code-block-wrapper');if(!wrapper){requestAnimationFrame(wait);return}page.querySelectorAll('[data-zd-asset-action="copy"],[data-zd-asset-action="wrap"]').forEach(button=>button.removeAttribute('disabled'))};requestAnimationFrame(wait)}})};if(!document.__zdAssetPageInit){document.__zdAssetPageInit=init;document.addEventListener('zfb:after-swap',init)}document.__zdAssetPageInit()})();`;
2
13
  export {
14
+ ASSET_DETAILS_HIDDEN_ATTR,
15
+ ASSET_DETAILS_PREPAINT_SCRIPT,
16
+ ASSET_DETAILS_STORAGE_KEY,
3
17
  ASSET_PAGE_SCRIPT
4
18
  };
package/dist/compiled.css CHANGED
@@ -1979,6 +1979,11 @@
1979
1979
  pointer-events: none;
1980
1980
  }
1981
1981
  }
1982
+ .disabled\:cursor-default {
1983
+ &:disabled {
1984
+ cursor: default;
1985
+ }
1986
+ }
1982
1987
  .disabled\:opacity-50 {
1983
1988
  &:disabled {
1984
1989
  opacity: 50%;
@@ -3411,6 +3416,11 @@ button[data-zd-pending] {
3411
3416
  opacity: 0.7;
3412
3417
  pointer-events: none;
3413
3418
  }
3419
+ .zd-asset-page [data-zd-asset-details-list] :is(dt, dd) {
3420
+ margin-top: 0;
3421
+ margin-bottom: 0;
3422
+ padding-left: 0;
3423
+ }
3414
3424
  .zd-asset-page .zd-asset-code {
3415
3425
  counter-reset: line;
3416
3426
  }
@@ -3474,8 +3484,43 @@ button[data-zd-pending] {
3474
3484
  }
3475
3485
  @media (min-width: 1024px) {
3476
3486
  .zd-asset-page .zd-asset-media-grid {
3477
- grid-template-columns: minmax(0, 1fr) 20rem;
3487
+ --zd-asset-rail-w: 20rem;
3488
+ grid-template-columns: minmax(0, 1fr) var(--zd-asset-rail-w);
3478
3489
  align-items: start;
3490
+ transition: grid-template-columns var(--zd-transition-slow) ease-in-out, gap var(--zd-transition-slow) ease-in-out;
3491
+ }
3492
+ }
3493
+ .zd-asset-details-toggle [data-zd-asset-details-chevron] {
3494
+ display: contents;
3495
+ }
3496
+ .zd-asset-details-toggle [data-zd-asset-details-chevron="expand"] {
3497
+ display: none;
3498
+ }
3499
+ html[data-asset-details-hidden] .zd-asset-details-toggle [data-zd-asset-details-chevron="collapse"] {
3500
+ display: none;
3501
+ }
3502
+ html[data-asset-details-hidden] .zd-asset-details-toggle [data-zd-asset-details-chevron="expand"] {
3503
+ display: contents;
3504
+ }
3505
+ @media (min-width: 1024px) {
3506
+ html[data-asset-details-hidden] .zd-asset-page .zd-asset-media-grid {
3507
+ grid-template-columns: minmax(0, 1fr) 0rem;
3508
+ gap: 0;
3509
+ }
3510
+ .zd-asset-page .zd-asset-media-rail {
3511
+ overflow: clip;
3512
+ transition: opacity var(--zd-transition-slow) ease-in-out, visibility var(--zd-transition-slow);
3513
+ }
3514
+ .zd-asset-page .zd-asset-media-rail > * {
3515
+ width: var(--zd-asset-rail-w);
3516
+ }
3517
+ html[data-asset-details-hidden] .zd-asset-page .zd-asset-media-rail {
3518
+ opacity: 0;
3519
+ visibility: hidden;
3520
+ max-height: 0;
3521
+ }
3522
+ .zd-asset-details-toggle {
3523
+ right: 0;
3479
3524
  }
3480
3525
  }
3481
3526
  [data-zd-asset-tree]:where(ul), [data-zd-asset-tree] :where(ul) {
@@ -56,7 +56,8 @@ function DocLayout(props) {
56
56
  "data-theme",
57
57
  "data-theme-pack",
58
58
  "style",
59
- "data-toc-hidden"
59
+ "data-toc-hidden",
60
+ "data-asset-details-hidden"
60
61
  ]
61
62
  }) : null,
62
63
  head
package/dist/features.css CHANGED
@@ -1052,6 +1052,25 @@ button[data-zd-pending] {
1052
1052
 
1053
1053
  /* ======== Asset viewer ======== */
1054
1054
 
1055
+ /* The Details card is a LAYOUT grid, but it renders inside `.zd-content`, whose
1056
+ * prose rules style authored definition lists (content.css: `:where(dt)` gets a
1057
+ * top margin, `:where(dd)` a left padding). Applied to grid items those printed
1058
+ * every label a row-gap BELOW its own value — "Type" under "image/png" (#3944).
1059
+ *
1060
+ * This reset must live HERE, not as utility classes on the elements. `:where()`
1061
+ * zeroes only its own contents, so `.zd-content :where(dt)` still scores (0,1,0)
1062
+ * from `.zd-content` — a TIE with `.mt-0`, broken by source order, and
1063
+ * content.css is imported before the utilities (measured: the prose rule landed
1064
+ * ~110KB later in the bundle and won). features.css is imported AFTER
1065
+ * content.css by the documented consumer contract, and this selector is (0,2,0),
1066
+ * so it wins on both counts. Scoped to the hook so authored definition lists in
1067
+ * real prose keep their prose styling. */
1068
+ .zd-asset-page [data-zd-asset-details-list] :is(dt, dd) {
1069
+ margin-top: 0;
1070
+ margin-bottom: 0;
1071
+ padding-left: 0;
1072
+ }
1073
+
1055
1074
  .zd-asset-page .zd-asset-code {
1056
1075
  counter-reset: line;
1057
1076
  }
@@ -1127,12 +1146,107 @@ button[data-zd-pending] {
1127
1146
 
1128
1147
  @media (min-width: 1024px) {
1129
1148
  .zd-asset-page .zd-asset-media-grid {
1130
- grid-template-columns: minmax(0, 1fr) 20rem;
1149
+ --zd-asset-rail-w: 20rem;
1150
+ grid-template-columns: minmax(0, 1fr) var(--zd-asset-rail-w);
1131
1151
  align-items: start;
1152
+ /* Collapsing must RECLAIM width, so the animated properties are the track
1153
+ * sizes and the gap — not opacity alone. Both interpolate because the
1154
+ * collapsed state below keeps the same two-track shape. */
1155
+ transition:
1156
+ grid-template-columns var(--zd-transition-slow) ease-in-out,
1157
+ gap var(--zd-transition-slow) ease-in-out;
1132
1158
  }
1133
1159
 
1134
1160
  }
1135
1161
 
1162
+ /* ========================================
1163
+ * Asset details rail collapse toggle (#3941) — mirrors "Desktop TOC toggle"
1164
+ * above, with two deliberate differences:
1165
+ *
1166
+ * - Breakpoint is lg/1024px, matching the asset grid's OWN side-by-side
1167
+ * switch (the block right above), NOT the TOC toggle's xl/1280px. Below
1168
+ * it the rail stacks normally and the toggle is not rendered.
1169
+ * - Disclosure semantics: the button carries aria-expanded/aria-controls.
1170
+ *
1171
+ * `data-asset-details-hidden` persists across SPA navigation (doc-layout.tsx
1172
+ * preserveHtmlAttrs), so EVERY hidden-state rule below is scoped to the asset
1173
+ * page (`.zd-asset-page` descendants / `.zd-asset-details-toggle`, which only
1174
+ * exists there) — an unscoped rule would leak onto whatever page is reached
1175
+ * after collapsing the rail.
1176
+ * ======================================== */
1177
+
1178
+ /* The controller is vanilla DOM and cannot re-render a Preact icon, so both
1179
+ * chevrons are server-rendered and CSS picks the one matching the state. */
1180
+ .zd-asset-details-toggle [data-zd-asset-details-chevron] {
1181
+ display: contents;
1182
+ }
1183
+
1184
+ .zd-asset-details-toggle [data-zd-asset-details-chevron="expand"] {
1185
+ display: none;
1186
+ }
1187
+
1188
+ html[data-asset-details-hidden]
1189
+ .zd-asset-details-toggle
1190
+ [data-zd-asset-details-chevron="collapse"] {
1191
+ display: none;
1192
+ }
1193
+
1194
+ html[data-asset-details-hidden]
1195
+ .zd-asset-details-toggle
1196
+ [data-zd-asset-details-chevron="expand"] {
1197
+ display: contents;
1198
+ }
1199
+
1200
+ @media (min-width: 1024px) {
1201
+ html[data-asset-details-hidden] .zd-asset-page .zd-asset-media-grid {
1202
+ grid-template-columns: minmax(0, 1fr) 0rem;
1203
+ gap: 0;
1204
+ }
1205
+
1206
+ .zd-asset-page .zd-asset-media-rail {
1207
+ overflow: clip; /* NOT hidden: hidden would create a scroll container */
1208
+ transition:
1209
+ opacity var(--zd-transition-slow) ease-in-out,
1210
+ visibility var(--zd-transition-slow);
1211
+ }
1212
+
1213
+ /* Pin the card to the EXPANDED track width instead of the base `width: 100%`
1214
+ * (identical while expanded, since the track is exactly that wide). Letting
1215
+ * it follow the shrinking track would re-wrap the <dl> values and the linked
1216
+ * -from prose one character per line, ballooning the rail's height for the
1217
+ * length of the animation and visibly jolting the page. At a fixed width the
1218
+ * card keeps its layout and the rail simply clips it away. */
1219
+ .zd-asset-page .zd-asset-media-rail > * {
1220
+ width: var(--zd-asset-rail-w);
1221
+ }
1222
+
1223
+ html[data-asset-details-hidden] .zd-asset-page .zd-asset-media-rail {
1224
+ opacity: 0;
1225
+ visibility: hidden; /* a11y: clipped rail content must not be focusable */
1226
+
1227
+ /* Stop the zero-width rail from sizing the grid row. `visibility` and
1228
+ * `overflow` suppress paint, NOT layout, so without this the row stays as
1229
+ * tall as the rail and a blank band opens under a shorter stage — measured
1230
+ * 176px on /files/bundle.zip/ and 272px on /files/demo.js/. This is where
1231
+ * the grid differs from the `.zd-toc-col` toggle it otherwise mirrors: the
1232
+ * TOC is a flex row, where a zero-width column contributes no height.
1233
+ *
1234
+ * This applies on the click frame, NOT over the transition: `max-height`
1235
+ * goes `none` -> `0`, and `none` is not interpolable with a length, so a
1236
+ * transition on it is skipped entirely (verified — `getAnimations()` during
1237
+ * a collapse lists only opacity and visibility). Do not add one back
1238
+ * expecting a delay; making it animate would need a concrete expanded
1239
+ * `max-height`, and a *delayed* close reads worse than an immediate one —
1240
+ * content below would sit still for 200ms and then jump. As written, the
1241
+ * row closes at once while the track animates out, which reads cleanly. */
1242
+ max-height: 0;
1243
+ }
1244
+
1245
+ .zd-asset-details-toggle {
1246
+ right: 0; /* constant — pins to the viewport edge; no tracking var needed */
1247
+ }
1248
+ }
1249
+
1136
1250
  [data-zd-asset-tree]:where(ul),
1137
1251
  [data-zd-asset-tree] :where(ul) {
1138
1252
  margin: 0;
@@ -89,6 +89,8 @@ const defaultTranslations = {
89
89
  "asset.showingLines": "Showing {shown} of {total} lines",
90
90
  "asset.truncated": "Preview truncated \u2014 download the file for the rest.",
91
91
  "asset.details": "Details",
92
+ "asset.detailsCollapse": "Hide details",
93
+ "asset.detailsExpand": "Show details",
92
94
  "asset.type": "Type",
93
95
  "asset.size": "Size",
94
96
  "asset.path": "Path",
@@ -215,6 +217,8 @@ const defaultTranslations = {
215
217
  "asset.showingLines": "{total} \u884C\u4E2D {shown} \u884C\u3092\u8868\u793A",
216
218
  "asset.truncated": "\u30D7\u30EC\u30D3\u30E5\u30FC\u306F\u7701\u7565\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u5168\u4F53\u306F\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
217
219
  "asset.details": "\u8A73\u7D30",
220
+ "asset.detailsCollapse": "\u8A73\u7D30\u3092\u96A0\u3059",
221
+ "asset.detailsExpand": "\u8A73\u7D30\u3092\u8868\u793A",
218
222
  "asset.type": "\u7A2E\u985E",
219
223
  "asset.size": "\u30B5\u30A4\u30BA",
220
224
  "asset.path": "\u30D1\u30B9",
@@ -110,6 +110,7 @@ function LanguageSwitcher({
110
110
  }) {
111
111
  if (links.length <= 1) return null;
112
112
  const menuId = `language-menu${idSuffix ? `-${idSuffix}` : ""}`;
113
+ const toggleId = `language-toggle${idSuffix ? `-${idSuffix}` : ""}`;
113
114
  const activeLink = links.find((link) => link.active) ?? links[0];
114
115
  const rewireAttrs = config ? {
115
116
  "data-base": config.base,
@@ -128,6 +129,7 @@ function LanguageSwitcher({
128
129
  "button",
129
130
  {
130
131
  type: "button",
132
+ id: toggleId,
131
133
  class: "flex max-w-[16rem] cursor-pointer items-center gap-hsp-2xs whitespace-nowrap rounded border border-muted px-hsp-sm py-vsp-3xs text-small text-muted transition-colors hover:border-accent hover:text-accent focus-visible:border-accent focus-visible:text-accent",
132
134
  "aria-label": accessibleLabel,
133
135
  "aria-controls": menuId,
@@ -143,6 +145,7 @@ function LanguageSwitcher({
143
145
  "ul",
144
146
  {
145
147
  id: menuId,
148
+ "aria-labelledby": toggleId,
146
149
  class: "absolute right-0 top-full z-dropdown mt-vsp-3xs hidden min-w-[8rem] max-w-[calc(100vw-var(--spacing-hsp-xl))] overflow-x-auto whitespace-nowrap rounded border border-muted bg-surface py-vsp-3xs shadow-lg group-hover:block group-focus-within:block",
147
150
  "data-language-menu": true,
148
151
  children: links.map((link) => /* @__PURE__ */ jsx("li", { children: link.active ? /* @__PURE__ */ jsx(
@@ -146,7 +146,10 @@ function makeEnlargeableParagraph(imageEnlarge, ContentImg, assetOptions) {
146
146
  return {
147
147
  type: "figure",
148
148
  props: {
149
- ...canEnlarge ? { class: "zd-enlargeable" } : {},
149
+ class: [
150
+ canEnlarge ? "zd-enlargeable" : null,
151
+ imageEntry ? "p-hsp-lg" : null
152
+ ].filter((className) => className !== null).join(" "),
150
153
  children: [vnode, canEnlarge ? enlargeBtn : null, figcaption]
151
154
  },
152
155
  key: null,
@@ -205,8 +208,9 @@ function createMdxComponents(options) {
205
208
  a: ManifestAwareContentLink,
206
209
  // img override: rewrites root-relative src to include settings.base.
207
210
  img: ContentImg,
208
- // p override: wraps block-level images in <figure class="zd-enlargeable">.
209
- // Must come AFTER ...defaultComponents to override ContentParagraph.
211
+ // p override: wraps eligible block-level images in a figure; manifest-backed
212
+ // figures also receive the p-hsp-lg inset. Must come AFTER ...defaultComponents
213
+ // to override ContentParagraph.
210
214
  p: EnlargeableParagraph,
211
215
  // Admonitions — real typed Preact components emitting the
212
216
  // `.admonition` / `data-admonition` structure the design-system CSS
@@ -22,9 +22,10 @@ interface RouteSpec {
22
22
  * locale home, the tag pages and the version pages.
23
23
  *
24
24
  * `false` for the four routes a reader never browses as documentation:
25
- * `/sitemap.xml` and `/robots.txt` cannot render an HTML panel at all (they
26
- * would hold the check at "not fully shadowed" forever), `/api/ai-chat` is a
27
- * JSON endpoint, and `/404` is an error page losing the panel there says
25
+ * `/sitemap.xml` (when injected see the `settings.sitemap` gate below,
26
+ * #3931/#3933) and `/robots.txt` cannot render an HTML panel at all (either
27
+ * would hold the check at "not fully shadowed" forever if counted),
28
+ * `/api/ai-chat` is a JSON endpoint, and `/404` is an error page — losing the panel there says
28
29
  * nothing about whether the site's docs still have one. The never-injected
29
30
  * `/` (see the note in `deriveRoutes`) is absent from the catalog entirely
30
31
  * and so cannot be counted either.
@@ -44,7 +44,9 @@ function deriveRoutes(settings, options) {
44
44
  return routes;
45
45
  }
46
46
  routes.push({ pattern: "/404", entrypoint: "@takazudo/zudo-doc/routes/404", includedInDtpShadowDiagnostic: false });
47
- routes.push({ pattern: "/sitemap.xml", entrypoint: "@takazudo/zudo-doc/routes/sitemap.xml", includedInDtpShadowDiagnostic: false });
47
+ if (settings.sitemap === true) {
48
+ routes.push({ pattern: "/sitemap.xml", entrypoint: "@takazudo/zudo-doc/routes/sitemap.xml", includedInDtpShadowDiagnostic: false });
49
+ }
48
50
  routes.push({ pattern: "/robots.txt", entrypoint: "@takazudo/zudo-doc/routes/robots.txt", includedInDtpShadowDiagnostic: false });
49
51
  routes.push({ pattern: "/docs/[[...slug]]", entrypoint: "@takazudo/zudo-doc/routes/docs-slug", includedInDtpShadowDiagnostic: true });
50
52
  if (docTags) {
@@ -6,6 +6,9 @@ function escapeXml(str) {
6
6
  }
7
7
  function Sitemap() {
8
8
  if (!settings.sitemap) {
9
+ console.warn(
10
+ "[zudo-doc] routes/sitemap.xml was rendered while settings.sitemap is false/unset; emitting an empty <urlset>. Set settings.sitemap: true to enable it, or remove the manual route that reached this entrypoint."
11
+ );
9
12
  return `<?xml version="1.0" encoding="UTF-8"?>
10
13
  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
11
14
  </urlset>`;
package/dist/safelist.css CHANGED
@@ -1,2 +1,2 @@
1
1
  /* generated by gen-safelist.mjs — do not edit by hand */
2
- @source inline("-domtweaker-enabled -elpath-enabled -left-[calc(var(--spacing-icon-lg)/2)] -link -mb-px -ml-hsp-sm -mt-px -noscript -open -state -translate-x-full 2xl:w-[24px] [&::-webkit-details-marker]:hidden [&_a]:pointer-events-auto [&_a]:text-accent [&_a]:underline [&_li]:mb-0 [&_nav]:mb-0 [asset-viewer] [data-admonition] [data-kbd-shortcut] [data-switcher-launcher] [doc-history-meta] [doc-history] [doc-layout] [llms-txt] [zudo-doc] a a2 abbr about above absent absolute accent accent- accent:accent- access across activated active actual actually added admonition admonition- admonition-body admonition-title admonition/callout after after-breadcrumb after-content after-navigate after-sidebar after-title against agent agents ai-chat ai-chat-md ai-chat-trigger alert align-top all allow allow-same-origin allow-scripts allowed alone already already-executed already-multiline already-picked also always an anchor and and/or animate-pulse animate-spin announce ansehen antialiased any anywhere anzeigen app appear application/json application/octet-stream application/pdf application/sql application/toml application/x-httpd-php application/xml application/yaml applied applies apply applying approach approval are area arg argument aria-atomic aria-busy aria-controls aria-current aria-disabled aria-expanded aria-haspopup aria-hidden aria-label aria-labelledby aria-live aria-orientation aria-pressed aria-selected aria-valuemax aria-valuemin aria-valuenow arm arms around arrows article as asc ascii aside aspect-[1200/630] aspect-square asset asset- asset-components assets assets/client assistant async at at-rule attach attribute attributes auf authored auto auto-logo-mask autogenerated availability available avc1 avif avis avoid await away b back backdrop:bg-bg/30 backdrop:bg-bg/80 backdrop:bg-overlay/60 backdrop:z-modal-backdrop background background-color backtick backticks baked banner bare base base- base64 base:base- based bash batch be bearbeiten because becomes been before below best best-effort between bg bg-[#fff] bg-accent bg-bg bg-chat-assistant-bg bg-chat-user-bg bg-code-bg bg-fg bg-info/10 bg-info/5 bg-muted bg-overlay/30 bg-surface bg-surface/50 bg-transparent bg-warning/10 bg-warning/5 bi bigint bin binaries bind binding blank blanks block blockquote blocks blur bodies body body-end-components body-end-scripts bold boolean bootstrap border border-accent border-b border-b-2 border-b-[5px] border-bg/30 border-collapse border-danger border-dashed border-fg border-image border-info/30 border-l border-l-0 border-l-[3px] border-left-width border-muted border-none border-r border-r-0 border-radius border-solid border-t border-t-[2px] border-t-[3px] border-transparent border-warning/30 border-width border-y both bottom-hsp-lg bottom-vsp-xl boundaries box box-border br brackets brand breadcrumb:end breadcrumb:start break-words brief brown browser browser-tab browsers browses btn budget bug build builder built built-in bundler but button buttons by bypassed byte-identical bytes c cache cached calendar-valid call callable called caller calls can cancellation candidate cannot canonical canvas caption captured captures card card-grid cards carry case-insensitive cases cat-nav- catalog catch categories category caught caution center center/contain ch chains change changed changelog changelogs changes characters check checker child children choose chrome chrome-font ci circle cite cjs class class-less class-mode claude claude-agents claude-commands claude-md claude-resources claude-skills cleaned cleanly clear clearing click client client-router client-side clip clobber clobbering close closed closes closing closure code code-block-sr-announce code-group code-group-panel codex codex-agents codex-agents-md codex-config codex-hooks codex-resources codex-rules codex-skills col col-resize col-span-full col-start-1 colgroup collapse collapses collapsible collision color color-scheme color-scheme-changed color-scheme-provider color-tweak colorization colors column comma command commands commas comment commercial commercial-font-denylist commit compare complete component component:github-link component:language-switcher component:search component:theme-toggle component:version-switcher composes composition compute computed concrete conf config configuration configurations configure configured conflicting conflicts confuse connect const construction consumer consumes contain container containers containing contains content content-admonition content-layer content-link content-type content-wrapper:end content-wrapper:start contents context contract control controller controls converts cookie-blocking copied copy copy-url core corners correct correctly corrupt could count covered covers cpp crashes created cross-component crumb- cs csharp css css-presence csv ctx cur current current-path/index.ts current-route currently cursor cursor-not-allowed cursor-pointer custom cycle d danger dark dash data data-active data-admonition data-auto-logo data-base data-close-search data-current-locale data-default-locale data-doc-date data-doc-description data-doc-metainfo data-doc-pager data-doc-unavailable-versions data-find-active data-find-match data-footer data-group-id data-header data-header-logo data-header-nav data-header-right data-kbd-shortcut data-lang data-language-menu data-language-switcher data-language-toggle data-loading-index data-mermaid-enlarge-ready data-mermaid-rendered data-mermaid-src data-nav-active data-nav-item data-nav-item-dropdown data-nav-more data-nav-more-menu data-nav-more-toggle data-no-results data-note-tray-group data-note-tray-row data-open-search data-pan-active data-processed data-props data-result-count-template data-search-count data-search-count-narrow data-search-dialog data-search-input data-search-placeholder data-search-results data-search-unavailable data-sidebar-hidden data-sidebar-resizer data-site-nav data-switcher-card data-switcher-launcher data-tab-btn data-tab-default data-tab-label data-tab-value data-tabs data-taglist-group data-testid data-theme data-theme-pack data-theme-pack-switcher data-theme/style data-toc-hidden data-trailing-slash data-unavailable-label data-variant data-version-banner data-version-latest data-version-menu data-version-rewire data-version-slug data-version-switcher data-version-toggle data-version-trigger-label data-zd-asset-action data-zd-asset-actions data-zd-asset-index-action data-zd-asset-index-empty data-zd-asset-index-page data-zd-asset-page data-zd-asset-tree data-zd-copy-url data-zd-html-preview-reservation data-zd-mobile-sidebar data-zd-mobile-toc data-zd-nosidebar data-zd-pending data-zd-props-preserve data-zd-sidebar-open-key data-zd-theme-pack-css data-zd-theme-pack-css-loading data-zd-theme-pack-loading data-zd-toc data-zd-wide data-zfb-island data-zfb-island-remount data-zfb-reload data-zfb-transition-persist date dated dd decimal decision declaration declare declared declares decoration decoration-muted deepest deepest-match default default-transition-duration defaults deferral deferred del delegated delete deliberately delimiter dependency depends depth der desc description design design-token design-token-panel design-token-trigger desktop desktop-sidebar desktop-sidebar-toggle desktop-sidebar-toggle-island desktop-toc-toggle destroys destructive detach detached details determine deterministic dev dfn diagram diagrams dialog did die dieser diff diff-line-added diff-line-content diff-line-empty diff-line-num diff-line-removed diff-row differ different dir directly directories directory disabled disabled:opacity-50 disabled:pointer-events-none disc display display:none dist distance distinct div dl do doc doc-card- doc-content-band doc-history doc-history-generate doc-history-panel doc-history-trigger doc-page doc-pager doc-prose doc-title docblock docs docs- docs-v- document document-level documentation documented documents does dog dot double-registration download draft drag drawer drift drifts drop dropdown dropdown-parent dropdowns dt duplicate duration-150 duration-200 during dynamically e e2e each eager earlier early ease-in-out edge editing einer either eject ejectable ejectables ejected el element elements els else em embedded emit emitting empty empty/undefined en enable enabled end enhanced enhancement enlarged entire entirely entities entries entry entrypoint env equal error escape escaped escapes even event eventually every everything-enabled exactly example exceeds excerpt excludes exclusively existing exists exit expand expected explicit export extends extra f factories failed fall fallback fallbacks falling falls false family fast favicon feature fg field fields fieldset figcaption figure file files fill fills finally find find-match find-match-active fire fires first first-paint first:mt-0 fit fix fixed fixed-width fixtures flag flash flat flex flex-1 flex-col flex-wrap flip flipping flips flow flush-left focus focus-visible:bg-accent/10 focus-visible:border-accent focus-visible:decoration-accent focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2 focus-visible:text-accent focus-visible:underline focus-within:border-accent focus-within:z-local-1 focus:border-accent focus:outline-none focus:text-accent focus:underline folder folders follows font font-bold font-face-parity font-family font-file-missing font-medium font-mono font-sans font-scale font-semibold font-size font-weight font-weight-bold font-weight-medium font-weight-normal font-weight-semibold font/woff2 fonts footer footer- for form format former found four-link fox fragment frame free freeze fresh from frontmatter frontmatter-preview frozen frozen-script fs-extra ftyp full fully function further g gains gap-[0.3em] gap-[clamp(1.5rem,3vw,4rem)] gap-hsp-2xs gap-hsp-lg gap-hsp-md gap-hsp-sm gap-hsp-xl gap-hsp-xs gap-vsp-2xs gap-vsp-3xs gap-vsp-lg gap-vsp-md gap-vsp-xs gap-x-hsp-2xs gap-x-hsp-lg gap-x-hsp-md gap-x-hsp-sm gap-x-hsp-xs gap-y-vsp-2xs gap-y-vsp-3xs gap-y-vsp-lg gap-y-vsp-md gap-y-vsp-xs gaps gate geladen2026 generate generated generation genuine geometry get getting-started gif git github github-dark github-link give go got grab gradient granular graph grid grid-cols-1 grid-cols-2 grid-cols-[auto_1fr] grid-rows-[auto_auto] grid-rows-subgrid group group-focus-visible:decoration-accent group-focus-visible:text-accent group-focus-visible:text-accent-hover group-focus-visible:text-fg group-focus-visible:underline group-focus-within:block group-hover:bg-fg group-hover:block group-hover:decoration-accent group-hover:text-accent group-hover:text-accent-hover group-hover:text-bg group-hover:text-fg group-hover:underline group-open:rotate-90 grouped grouping guard gz h h-[0.5rem] h-[0.625rem] h-[0.875rem] h-[1.125rem] h-[1.25rem] h-[1.575rem] h-[10rem] h-[14px] h-[1em] h-[1lh] h-[2.5rem] h-[2rem] h-[3.5rem] h-[3rem] h-[70vh] h-[90vh] h-[calc(100%-3rem)] h-[calc(100vh-3.5rem)] h-dvh h-full h-icon-lg h-icon-md h-icon-sm h-icon-xs h1 h1s h2 h22013h4 h2s h3 h4 h5 h6 half hand-copied hand-editable handle handled handler handlers happens hard-loaded hardcoded has hash-link have head head-links head-scripts header header- header-call:end header-call:start header-right heading heading-h2 heading-h3 heading-h4 heading-rule headings height here hex hi-root hidden hide hierarchical highlight highlighting history home hook hooks hooks-json horizontal host hover:bg-[color-mix(in_srgb,var(--color-surface)_80%,var(--color-fg)_20%)] hover:bg-accent-hover hover:bg-accent/10 hover:bg-danger/10 hover:bg-surface hover:border-accent hover:border-accent-hover hover:border-fg hover:decoration-accent hover:text-accent hover:text-accent-hover hover:text-fg hover:underline hover:z-local-1 hpp hr href hrefs hsp hsp-2xl hsp-2xs hsp-lg hsp-md hsp-sm hsp-xl hsp-xs html i i18n/theme. i2 i3 i4 ico icon icon-lg icon-md icon-sm icon-xs identical idle idx if iframe ignoring image image-enlarge image-overlay-inset image/avif image/gif image/jpeg image/png image/webp image/x-icon img implementation import important important-allowlist imports in inactive includes including incomplete independently index index2026 indirectly info inherit inherited ini initial initialised injected inline inline-block inline-flex inner input input-clear ins inserted-after-color-mode inserted-after-color-scheme inserted-after-site-name inserted-first insertion inset-0 inside inside-only inspect install installation installed instance instanceof instead instructions intended intent intentionally intercept interface internal interpolation into invalid invalidated inverse inversion invocation invoke is is-checker island island-root iso2 iso3 iso4 iso5 iso6 isom ispe issues it italic item item- items items-baseline items-center items-end items-start iteration its itself ja java javascript jpeg jpg js json jsx jumps just justification justify-between justify-center justify-end justify-start katex kbd keep keeping keeps kept key keyboard keyboard-shortcut keydown keys keystroke keyword keywords khroma known-token-names kopieren kotlin kt label landing lands language-menu language-switcher larger last:border-b-0 last:pb-0 later latest launch layout lazy leading leading-none leading-normal leading-relaxed leading-snug leading-tight leaf leaf- leak leaves leaving left left-0 left:calc legend legitimate length lets letter-spacing lg lg:block lg:border lg:border-fg lg:border-solid lg:flex lg:flex-col lg:flex-row lg:gap-hsp-xl lg:grid-cols-3 lg:grid-cols-[repeat(auto-fit,minmax(12rem,1fr))] lg:h-[90vh] lg:hidden lg:justify-start lg:m-auto lg:max-h-[90vh] lg:max-w-[52.5rem] lg:ml-[var(--zd-sidebar-w)] lg:pr-hsp-sm lg:pt-vsp-2xl lg:px-hsp-2xl lg:py-vsp-2xl lg:text-left lg:w-[90vw] lg:w-[clamp(16rem,25%,22rem)] li li2 library license lifecycle light light/dark like likely line line-height line/statement lines linger link link- links list list-disc list-none listener lists literal literally literals live lives llms llms-txt load loaded loader loading local local-1 local-2 local-3 locale locales log logo long longer longest-match look loses lostpointercapture lower luminance m m-0 m-auto m10 m14 m16 m21 m6 machinery main major make malformed malformed-markup malicious managed manifest manually maps mark markdown marks match matches matching math math-display math-inline max max-h-[85vh] max-h-[90vh] max-h-full max-h-none max-w-[16rem] max-w-[64rem] max-w-[85%] max-w-[85vw] max-w-[90vw] max-w-[calc(100vw-2rem)] max-w-[calc(100vw-var(--spacing-hsp-xl))] max-w-[clamp(50rem,75vw,90rem)] max-w-full max-w-none max-w-sm max-width maximum may mb-0 mb-vsp-2xs mb-vsp-lg mb-vsp-md mb-vsp-sm mb-vsp-xl mb-vsp-xs md mdx means measured measurement measures measuring mechanism menu mermaid message messages meta meta-knob meta-schema metadata migration min-h-0 min-h-[20rem] min-h-[44px] min-h-[60vh] min-h-[calc(100vh-3.5rem)] min-h-screen min-w-0 min-w-[10rem] min-w-[3rem] min-w-[44px] min-w-[8rem] minifier minor mirror mirroring mirrors missing mit mjs ml-[calc(var(--spacing-hsp-xl)+1px)] ml-auto ml-hsp-2xl ml-hsp-lg ml-hsp-md ml-hsp-sm ml-hsp-xl mobile mod modal modal-backdrop mode model modify module moment monospace month more most mount mounted mouseenter mouseleave mov move mp4 mp41 mp42 mr-[calc(var(--spacing-hsp-xl)+1px)] mr-hsp-sm ms mt-0 mt-vsp-2xl mt-vsp-2xs mt-vsp-3xs mt-vsp-lg mt-vsp-md mt-vsp-sm mt-vsp-xl mt-vsp-xs multi-changelog multiple must mutates mutation mutations muted mvhd mx-auto my-vsp-lg my-vsp-md n name named names native natural nav nav-active nav-card- nav/doc navigating navigation navigations near needed needs neither nested neutral never new newly-swapped next nicht no no-color-scheme no-data-theme-selector no-enlarge no-op no-repeat no-underline noch node node:buffer node:fs node:fs/promises node:module node:path node:url node:util nodes nofollow noindex non-draggable non-empty non-index non-light-dark non-literal non-null non-persisted none noopener noreferrer normal noscript not notable note note-tray notes now null number numeric object object-contain observe observer occurred of off offered offsets ofl-required og:description og:image og:image:alt og:image:height og:image:width og:title og:type og:url oklch ol old older omit omitting on once one only onto opacity-60 open open/close option or order original other others otherwise out outgoing outline-none over overflow overflow-auto overflow-hidden overflow-x-auto overflow-y-auto overflow-y:auto overlaps override overrides overscroll-contain overwrite own owned p p-0 p-hsp-2xs p-hsp-lg p-hsp-md p-hsp-sm p-hsp-xl pack pack-scoped package package-default package-injected package-owned packages packs padding page page-loading page-loading-overlay page-loading-spinner page-navigate-end page-title page-wide pages pages/. paint paint-and-read palette pan panel panels paren-balance-aware parent parse parsed parser parses part pass passed passes patch path paths pattern payload payload-budget pb-[50vh] pb-vsp-2xs pb-vsp-lg pb-vsp-md pb-vsp-xl pb-vsp-xs pdf peer peer-focus-visible:border-accent peer-focus-visible:text-accent peer-hover:border-accent peer-hover:text-accent pending per per-block per-link per-package per-release permanently persisted persistence php pi pick picked picks picocolors pins pipelines pl-[1.25rem] pl-hsp-lg pl-hsp-md pl-hsp-sm pl-hsp-xl place place-items-center placeholder placeholder:text-muted plain plural plus png png16 png32 pnpm point pointer pointer-events-none pointercancel pointerdown pointermove pointerup policy polite polygon polyline popover populates port position position:fixed pr-hsp-lg pr-hsp-md pr-hsp-sm pr-hsp-xl pr-hsp-xs pre pre-lowercased preact preact/compat preact/hooks preact/jsx-runtime preconnect preference prefix preload pres present preserving preview preview-swatch-color previews2026 previously primary print prior private produce produced produces producing production profiles project project-owned project-root-relative properties property props prose provided proxy pt-[0.15rem] pt-[2px] pt-vsp-3xs pt-vsp-md pt-vsp-sm pt-vsp-xl pt-vsp-xs ptag- public purely puts px px-hsp-2xl px-hsp-2xs px-hsp-lg px-hsp-md px-hsp-sm px-hsp-xl px-hsp-xs py py-0 py-[2px] py-[4px] py-[calc(var(--spacing-vsp-xs)+0.15rem)] py-hsp-2xs py-hsp-3xs py-hsp-sm py-hsp-xs py-vsp-2xs py-vsp-3xs py-vsp-lg py-vsp-md py-vsp-sm py-vsp-xl py-vsp-xs python q qt query question quick r radius radius-full radius-lg rail ramp range rar rather raw rb re-encode/decode re-exports re-initialized re-querying re-render re-renders re-run re-running re-runs re-selects re-syncs reach reached reaches read reader reader-facing reading readings reads/rewrites real real-value received receives recorded recovers rect redefine redistribution ref- reference referenced references refetch refresh refreshes refusing regardless regenerate regenerates regex registry reinit reinits rejected rel relative release released releases reload relying rem remapped remembered remove remove/rename removed removing rename render rendered renderer renderers renders reorder repaint repair repeated repeating replace replaced replacement replaces repopulate report repository requested require required requires reserved resize resize-x resolve resolved resolves responded response restore restores restyle result result-click results results-area retry return returns rev-parse reveal revision revisions rewire rewrite rewrites right right- right-0 right-hsp-lg ring-2 ring-accent risking ro robots role roles root rotate-180 rotate-90 round round-trip rounded rounded-[0.75rem] rounded-bl-[0.25rem] rounded-bl-[1rem] rounded-bl-lg rounded-br-[0.25rem] rounded-br-[1rem] rounded-full rounded-lg rounded-md rounded-t-[1rem] rounds route routed router routes routes-src row row-span-2 row-start-1 row-start-2 rs ruby rule rules run running runs runtime rust s safe safely safer same same-locale samp sans sans-serif scale scanned scanning scheme scoped scoping score scored script script- script-eval script-evaluation script-injection scripts scroll scrollbar scrolled scrollend scrolling scss seam search search-index section section- see seed segment segments sehen select select-none selection-bg selection-fg selector self self-contained self-hosted self-start self-stretch semantic semibold semver sentinel separator serialised serialize server server-rendered session set sets setting settles setup sh shadow shadow-[0_1px_3px_color-mix(in_srgb,var(--color-fg)_8%,transparent)] shadow-lg shadow-md shadowed shape share shared sharing shell ship shipped ships short shortcut should show shown shrink-0 sidebar sidebar- sidebar-toggle-island sidebar-tree-island sidebar-w sidecar signal silently similarity simple since single single-line single-object-literal singular site site-search site-tree-nav-island sitemap- sites size size-icon-lg skill skills skipped skipping skips slash slot slug slug-dir-parity slugs sm:block sm:border sm:border-muted sm:col-start-2 sm:flex sm:flex-row sm:gap-x-hsp-xl sm:grid sm:grid-cols-2 sm:grid-cols-[minmax(0,1fr)_auto] sm:grid-cols-subgrid sm:h-auto sm:hidden sm:items-center sm:justify-between sm:max-h-[80vh] sm:max-w-[52rem] sm:mr-0 sm:mx-auto sm:my-[10vh] sm:rounded-lg sm:row-span-2 sm:row-start-1 small smol-toml smooth snapping snapshot snapshots so soft soft-nav solid some somehow source sources space-y-vsp-2xs space-y-vsp-lg space-y-vsp-sm spacing spacing-0 spacing-px span spans spec specifiers specify spelling splitter spread spurious sql square sr-only src stable stack stale standalone start state state- state:state- statement status stay staying sticky still stock stop stops stored straddles stray strict string strings strip stripe strips stroke-linecap stroke-linejoin stroke-width strong stronger stub-rendered style style-attribute styled styles stylesheet sub subagents subsequent substitute substitution subtracting success successful summary sup supply supported surface surfaces survives svg swap swapped swaps swift switcher switching symlink synchronous synchronously syntactically syntax t tab tab-item tab-panel tabindex table tablist tabpanel tabs tabs-container tabs-content tabs-nav tabular-nums tag tag- tag-item- tagged tags tags:audit take tar tbody td temp-element template temporary temporary-element terminal terms test-results tested text text-accent text-bg text-body text-caption text-center text-chat-assistant-text text-chat-user-text text-code-fg text-danger text-decoration text-display text-fg text-fg/60 text-heading text-info text-left text-micro text-muted text-muted/50 text-right text-scale-2xl text-scale-2xs text-scale-lg text-scale-md text-scale-sm text-scale-xl text-scale-xs text-small text-title text-warning text/css text/csv text/html text/javascript text/jsx text/markdown text/mdx text/plain text/tab-separated-values text/tsx text/typescript text/x-c text/x-csharp text/x-go text/x-java-source text/x-kotlin text/x-python text/x-ruby text/x-rust text/x-scss text/x-shellscript text/x-swift textarea tfoot tgz th than that the thead their them theme theme-color theme-pack theme-pack-changed theme-packs theme-packs/index.json theme-toggle theme/token then there these they this those though three threw through throw throws tighten time timeline tip title tkhd to toast toc toggle toggle- toggle-ai-chat toggle-design-token-panel toggles toggling token tokens tolerates toml too toolbar tooltip top top-0 top-[3.5rem] top-full top-hsp-2xs top-level total touches tr tracked tracking-wide tracking-wider trade-off trailing transferred transition transition-[background,color,border-color] transition-[left,color] transition-[right,color] transition-colors transition-transform translate-x-0 translated translations transparent tray treats tree tree-child- tree-item- tree-top- trigger trigger:ai-chat trigger:design-token-panel triggers true truncate truncated try ts tsv tsx turn twitter:card twitter:creator twitter:description twitter:image twitter:site twitter:title two txt type typeface typeof typescript typography u ul umschalten unable unavailable unbalanced unchanged und undefined under underline underlines understand unit-tested unknown unlike unlisted unmaintained unobserve unreadable unrelated unreleased unresolvable unresolved unset unsupported unterminated until unusable unwrapped up up-to-date update updated uppercase use used useful user uses using usual utf-8 utf8 utilities utility v v2 val value value-reader values var variable variant verbatim version version- version-menu version-switcher versions vertical via video video/mp4 video/quicktime video/webm viewer viewing viewport viewports virtual:zudo-doc-asset-bodies virtual:zudo-doc-chrome-bindings virtual:zudo-doc-design-token-panel-config virtual:zudo-doc-route-context visibility visible vocabulary void von vsp vsp-2xl vsp-2xs vsp-3xs vsp-lg vsp-md vsp-sm vsp-xl vsp-xs w w-1/2 w-[0.5rem] w-[0.625rem] w-[0.875rem] w-[1.125rem] w-[1.575rem] w-[1.5rem] w-[1.75rem] w-[12rem] w-[14px] w-[16px] w-[16rem] w-[18px] w-[1em] w-[2.5rem] w-[280px] w-[2rem] w-[320px] w-[360px] w-[6.5rem] w-[90vw] w-[calc(100vw-2rem)] w-[var(--zd-sidebar-w)] w-dvw w-full w-icon-lg w-icon-md w-icon-sm w-icon-xs walk walks want warn warning was watching way wbr wbr- we webm webp website weight went were what when where whereas whether which while whitespace-nowrap whitespace-pre whole whose wide wide-gamut wider-than-scrollbar width will window wins wird wired with without word wordmark working works worktrees would wrap wrapped wrapper wrappers wrapping wraps writing written wrong wrote wurde x xl:flex xl:hidden xml y-scrollbar yaml year yet yielded yields yml you your z-dropdown z-local-1 z-modal z-modal-backdrop z-popover z-sidebar z-toolbar zd-asset-code zd-asset-filebar zd-asset-media-grid zd-asset-media-rail zd-asset-page zd-asset-pdf zd-asset-stage zd-content zd-desktop-sidebar-toggle zd-desktop-toc-toggle zd-doc-content-band zd-enlarge-btn zd-enlarge-dialog zd-enlarge-dialog-close zd-enlargeable zd-html-preview-code zd-mermaid-dialog zd-mermaid-enlargeable zd-mermaid-tool-btn zd-mermaid-toolbar zd-mermaid-transform zd-mermaid-viewport zd-sidebar-content-wrapper zd-sidebar-open zd-theme-pack-dialog-title zd-toc-col zdtp zfb zfb:after-swap zfb:before-preparation zfb:before-swap zip zod zoom zudo-design-token-panel zudo-design-tokens/v3 zudo-doc zudo-doc-code-wrap zudo-doc-design-token-panel-modal zudo-doc-design-tokens zudo-doc-sidebar-visible zudo-doc-sidebar-width zudo-doc-theme zudo-doc-theme-pack zudo-doc-toc-visible zudo-doc-tweak zum");
2
+ @source inline("-domtweaker-enabled -elpath-enabled -left-[calc(var(--spacing-icon-lg)/2)] -link -mb-px -ml-hsp-sm -mt-px -noscript -open -state -translate-x-full 2xl:w-[24px] [&::-webkit-details-marker]:hidden [&_a]:pointer-events-auto [&_a]:text-accent [&_a]:underline [&_li]:mb-0 [&_nav]:mb-0 [asset-viewer] [data-admonition] [data-kbd-shortcut] [data-switcher-launcher] [doc-history-meta] [doc-history] [doc-layout] [llms-txt] [zudo-doc] a a2 abbr about above absent absolute accent accent- accent:accent- access across activated active actual actually added admonition admonition- admonition-body admonition-title admonition/callout after after-breadcrumb after-content after-navigate after-sidebar after-title against agent agents ai-chat ai-chat-md ai-chat-trigger alert align-top all allow allow-same-origin allow-scripts allowed alone already already-executed already-multiline already-picked also always an anchor and and/or animate-pulse animate-spin announce ansehen antialiased any anywhere anzeigen app appear application/json application/octet-stream application/pdf application/sql application/toml application/x-httpd-php application/xml application/yaml applied applies apply applying approach approval are area arg argument aria-atomic aria-busy aria-controls aria-current aria-disabled aria-expanded aria-haspopup aria-hidden aria-label aria-labelledby aria-live aria-orientation aria-pressed aria-selected aria-valuemax aria-valuemin aria-valuenow arm arms around arrows article as asc ascii aside aspect-[1200/630] aspect-square asset asset- asset-components assets assets/client assistant async at at-rule attach attribute attributes auf authored auto auto-logo-mask autogenerated availability available avc1 avif avis avoid await away b back backdrop:bg-bg/30 backdrop:bg-bg/80 backdrop:bg-overlay/60 backdrop:z-modal-backdrop background background-color backtick backticks baked banner bare base base- base64 base:base- based bash batch be bearbeiten because becomes been before below best best-effort between bg bg-[#fff] bg-accent bg-bg bg-chat-assistant-bg bg-chat-user-bg bg-code-bg bg-fg bg-info/10 bg-info/5 bg-muted bg-overlay/30 bg-surface bg-surface/50 bg-transparent bg-warning/10 bg-warning/5 bi bigint bin binaries bind binding blank blanks block blockquote blocks blur bodies body body-end-components body-end-scripts bold boolean bootstrap border border-accent border-b border-b-2 border-b-[5px] border-bg/30 border-collapse border-danger border-dashed border-fg border-image border-info/30 border-l border-l-0 border-l-[3px] border-left-width border-muted border-none border-r border-r-0 border-radius border-solid border-t border-t-[2px] border-t-[3px] border-transparent border-warning/30 border-width border-y both bottom-hsp-lg bottom-vsp-xl boundaries box box-border br brackets brand breadcrumb:end breadcrumb:start break-words brief brown browser browser-tab browsers browses btn budget bug build builder built built-in bundler but button buttons by bypassed byte-identical bytes c cache cached calendar-valid call callable called caller calls can cancellation candidate cannot canonical canvas caption captured captures card card-grid cards carry case-insensitive cases cat-nav- catalog catch categories category caught caution center center/contain ch chains change changed changelog changelogs changes characters check checker child children choose chrome chrome-font ci circle cite cjs class class-less class-mode claude claude-agents claude-commands claude-md claude-resources claude-skills cleaned cleanly clear clearing click client client-router client-side clip clobber clobbering close closed closes closing closure code code-block-sr-announce code-group code-group-panel codex codex-agents codex-agents-md codex-config codex-hooks codex-resources codex-rules codex-skills col col-resize col-span-full col-start-1 colgroup collapse collapses collapsible collision color color-scheme color-scheme-changed color-scheme-provider color-tweak colorization colors column comma command commands commas comment commercial commercial-font-denylist commit compare complete component component:github-link component:language-switcher component:search component:theme-toggle component:version-switcher composes composition compute computed concrete conf config configuration configurations configure configured conflicting conflicts confuse connect const construction consumer consumes contain container containers containing contains content content-admonition content-layer content-link content-type content-wrapper:end content-wrapper:start contents context contract control controller controls converts cookie-blocking copied copy copy-url core corners correct correctly corrupt could count covered covers cpp crashes created cross-component crumb- cs csharp css css-presence csv ctx cur current current-path/index.ts current-route currently cursor cursor-not-allowed cursor-pointer custom cycle d danger dark dash data data-active data-admonition data-asset-details-hidden data-auto-logo data-base data-close-search data-current-locale data-default-locale data-doc-date data-doc-description data-doc-metainfo data-doc-pager data-doc-unavailable-versions data-find-active data-find-match data-footer data-group-id data-header data-header-logo data-header-nav data-header-right data-kbd-shortcut data-lang data-language-menu data-language-switcher data-language-toggle data-loading-index data-mermaid-enlarge-ready data-mermaid-rendered data-mermaid-src data-nav-active data-nav-item data-nav-item-dropdown data-nav-more data-nav-more-menu data-nav-more-toggle data-no-results data-note-tray-group data-note-tray-row data-open-search data-pan-active data-processed data-props data-result-count-template data-search-count data-search-count-narrow data-search-dialog data-search-input data-search-placeholder data-search-results data-search-unavailable data-sidebar-hidden data-sidebar-resizer data-site-nav data-switcher-card data-switcher-launcher data-tab-btn data-tab-default data-tab-label data-tab-value data-tabs data-taglist-group data-testid data-theme data-theme-pack data-theme-pack-switcher data-theme/style data-toc-hidden data-trailing-slash data-unavailable-label data-variant data-version-banner data-version-latest data-version-menu data-version-rewire data-version-slug data-version-switcher data-version-toggle data-version-trigger-label data-zd-asset-action data-zd-asset-actions data-zd-asset-details data-zd-asset-details-chevron data-zd-asset-details-list data-zd-asset-details-toggle data-zd-asset-index-action data-zd-asset-index-empty data-zd-asset-index-page data-zd-asset-page data-zd-asset-tree data-zd-copy-url data-zd-html-preview-reservation data-zd-label-collapse data-zd-label-expand data-zd-mobile-sidebar data-zd-mobile-toc data-zd-nosidebar data-zd-pending data-zd-props-preserve data-zd-sidebar-open-key data-zd-theme-pack-css data-zd-theme-pack-css-loading data-zd-theme-pack-loading data-zd-toc data-zd-wide data-zfb-island data-zfb-island-remount data-zfb-reload data-zfb-transition-persist date dated dd decimal decision declaration declare declared declares decoration decoration-muted deepest deepest-match default default-transition-duration defaults deferral deferred del delegated delete deliberately delimiter dependency depends depth der desc description design design-token design-token-panel design-token-trigger desktop desktop-sidebar desktop-sidebar-toggle desktop-sidebar-toggle-island desktop-toc-toggle destroys destructive detach detached details determine deterministic dev dfn diagram diagrams dialog did die dieser diff diff-line-added diff-line-content diff-line-empty diff-line-num diff-line-removed diff-row differ different dir directly directories directory disabled disabled:cursor-default disabled:opacity-50 disabled:pointer-events-none disc display display:none dist distance distinct div dl do doc doc-card- doc-content-band doc-history doc-history-generate doc-history-panel doc-history-trigger doc-page doc-pager doc-prose doc-title docblock docs docs- docs-v- document document-level documentation documented documents does dog dot double-registration download draft drag drawer drift drifts drop dropdown dropdown-parent dropdowns dt duplicate duration-150 duration-200 during dynamically e e2e each eager earlier early ease-in-out edge editing einer either eject ejectable ejectables ejected el element elements els else em embedded emit emitting empty empty/undefined en enable enabled end enhanced enhancement enlarged entire entirely entities entries entry entrypoint env equal error escape escaped escapes even event eventually every everything-enabled exactly example exceeds excerpt excludes exclusively existing exists exit expand expected explicit export extends extra f factories failed fall fallback fallbacks falling falls false family fast favicon feature fg field fields fieldset figcaption figure file files fill fills finally find find-match find-match-active fire fires first first-paint first:mt-0 fit fix fixed fixed-width fixtures flag flash flat flex flex-1 flex-col flex-wrap flip flipping flips flow flush-left focus focus-visible:bg-accent/10 focus-visible:border-accent focus-visible:decoration-accent focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2 focus-visible:text-accent focus-visible:underline focus-within:border-accent focus-within:z-local-1 focus:border-accent focus:outline-none focus:text-accent focus:underline folder folders follows font font-bold font-face-parity font-family font-file-missing font-medium font-mono font-sans font-scale font-semibold font-size font-weight font-weight-bold font-weight-medium font-weight-normal font-weight-semibold font/woff2 fonts footer footer- for form format former found four-link fox fragment frame free freeze fresh from frontmatter frontmatter-preview frozen frozen-script fs-extra ftyp full fully function further g gains gap-[0.3em] gap-[clamp(1.5rem,3vw,4rem)] gap-hsp-2xs gap-hsp-lg gap-hsp-md gap-hsp-sm gap-hsp-xl gap-hsp-xs gap-vsp-2xs gap-vsp-3xs gap-vsp-lg gap-vsp-md gap-vsp-xs gap-x-hsp-2xs gap-x-hsp-lg gap-x-hsp-md gap-x-hsp-sm gap-x-hsp-xs gap-y-vsp-2xs gap-y-vsp-3xs gap-y-vsp-lg gap-y-vsp-md gap-y-vsp-xs gaps gate geladen2026 generate generated generation genuine geometry get getting-started gif git github github-dark github-link give go got grab gradient granular graph grid grid-cols-1 grid-cols-2 grid-cols-[auto_1fr] grid-rows-[auto_auto] grid-rows-subgrid group group-focus-visible:decoration-accent group-focus-visible:text-accent group-focus-visible:text-accent-hover group-focus-visible:text-fg group-focus-visible:underline group-focus-within:block group-hover:bg-fg group-hover:block group-hover:decoration-accent group-hover:text-accent group-hover:text-accent-hover group-hover:text-bg group-hover:text-fg group-hover:underline group-open:rotate-90 grouped grouping guard gz h h-[0.5rem] h-[0.625rem] h-[0.875rem] h-[1.125rem] h-[1.25rem] h-[1.575rem] h-[10rem] h-[14px] h-[1em] h-[1lh] h-[2.5rem] h-[2rem] h-[3.5rem] h-[3rem] h-[70vh] h-[90vh] h-[calc(100%-3rem)] h-[calc(100vh-3.5rem)] h-dvh h-full h-icon-lg h-icon-md h-icon-sm h-icon-xs h1 h1s h2 h22013h4 h2s h3 h4 h5 h6 half hand-copied hand-editable handle handled handler handlers happens hard-loaded hardcoded has hash-link have head head-links head-scripts header header- header-call:end header-call:start header-right heading heading-h2 heading-h3 heading-h4 heading-rule headings height here hex hi-root hidden hide hierarchical highlight highlighting history home hook hooks hooks-json horizontal host hover:bg-[color-mix(in_srgb,var(--color-surface)_80%,var(--color-fg)_20%)] hover:bg-accent-hover hover:bg-accent/10 hover:bg-danger/10 hover:bg-surface hover:border-accent hover:border-accent-hover hover:border-fg hover:decoration-accent hover:text-accent hover:text-accent-hover hover:text-fg hover:underline hover:z-local-1 hpp hr href hrefs hsp hsp-2xl hsp-2xs hsp-lg hsp-md hsp-sm hsp-xl hsp-xs html i i18n/theme. i2 i3 i4 ico icon icon-lg icon-md icon-sm icon-xs identical idle idx if iframe ignoring image image-enlarge image-overlay-inset image/avif image/gif image/jpeg image/png image/webp image/x-icon img implementation import important important-allowlist imports in inactive includes including incomplete independently index index2026 indirectly info inherit inherited ini initial initialised injected inline inline-block inline-flex inner input input-clear ins inserted-after-color-mode inserted-after-color-scheme inserted-after-site-name inserted-first insertion inset-0 inside inside-only inspect install installation installed instance instanceof instead instructions intended intent intentionally intercept interface internal interpolation into invalid invalidated inverse inversion invocation invoke is is-checker island island-root iso2 iso3 iso4 iso5 iso6 isom ispe issues it italic item item- items items-baseline items-center items-end items-start iteration its itself ja java javascript jpeg jpg js json jsx jumps just justification justify-between justify-center justify-end justify-start katex kbd keep keeping keeps kept key keyboard keyboard-shortcut keydown keys keystroke keyword keywords khroma known-token-names kopieren kotlin kt label landing lands language-menu language-switcher language-toggle larger last:border-b-0 last:pb-0 later latest launch layout lazy leading leading-none leading-normal leading-relaxed leading-snug leading-tight leaf leaf- leak leaves leaving left left-0 left:calc legend legitimate length lets letter-spacing lg lg:block lg:border lg:border-fg lg:border-solid lg:flex lg:flex-col lg:flex-row lg:gap-hsp-xl lg:grid-cols-3 lg:grid-cols-[repeat(auto-fit,minmax(12rem,1fr))] lg:h-[90vh] lg:hidden lg:justify-start lg:m-auto lg:max-h-[90vh] lg:max-w-[52.5rem] lg:ml-[var(--zd-sidebar-w)] lg:pr-hsp-sm lg:pt-vsp-2xl lg:px-hsp-2xl lg:py-vsp-2xl lg:text-left lg:w-[90vw] lg:w-[clamp(16rem,25%,22rem)] li li2 library license lifecycle light light/dark like likely line line-height line/statement lines linger link link- links list list-disc list-none listener lists literal literally literals live lives llms llms-txt load loaded loader loading local local-1 local-2 local-3 locale locales log logo long longer longest-match look loses lostpointercapture lower luminance m m-0 m-auto m10 m14 m16 m21 m6 machinery main major make malformed malformed-markup malicious managed manifest manual manually maps mark markdown marks match matches matching math math-display math-inline max max-h-[85vh] max-h-[90vh] max-h-full max-h-none max-w-[16rem] max-w-[64rem] max-w-[85%] max-w-[85vw] max-w-[90vw] max-w-[calc(100vw-2rem)] max-w-[calc(100vw-var(--spacing-hsp-xl))] max-w-[clamp(50rem,75vw,90rem)] max-w-full max-w-none max-w-sm max-width maximum may mb-0 mb-vsp-2xs mb-vsp-lg mb-vsp-md mb-vsp-sm mb-vsp-xl mb-vsp-xs md mdx means measured measurement measures measuring mechanism menu mermaid message messages meta meta-knob meta-schema metadata migration min-h-0 min-h-[20rem] min-h-[44px] min-h-[60vh] min-h-[calc(100vh-3.5rem)] min-h-screen min-w-0 min-w-[10rem] min-w-[3rem] min-w-[44px] min-w-[8rem] minifier minor mirror mirroring mirrors missing mit mjs ml-[calc(var(--spacing-hsp-xl)+1px)] ml-auto ml-hsp-2xl ml-hsp-lg ml-hsp-md ml-hsp-sm ml-hsp-xl mobile mod modal modal-backdrop mode model modify module moment monospace month more most mount mounted mouseenter mouseleave mov move mp4 mp41 mp42 mr-[calc(var(--spacing-hsp-xl)+1px)] mr-hsp-sm ms mt-0 mt-vsp-2xl mt-vsp-2xs mt-vsp-3xs mt-vsp-lg mt-vsp-md mt-vsp-sm mt-vsp-xl mt-vsp-xs multi-changelog multiple must mutates mutation mutations muted mvhd mx-auto my-vsp-lg my-vsp-md n name named names native natural nav nav-active nav-card- nav/doc navigating navigation navigations near needed needs neither nested neutral never new newly-swapped next nicht no no-color-scheme no-data-theme-selector no-enlarge no-op no-repeat no-underline noch node node:buffer node:fs node:fs/promises node:module node:path node:url node:util nodes nofollow noindex non-draggable non-empty non-index non-light-dark non-literal non-null non-persisted none noopener noreferrer normal noscript not notable note note-tray notes now null number numeric object object-contain observe observer occurred of off offered offsets ofl-required og:description og:image og:image:alt og:image:height og:image:width og:title og:type og:url oklch ol old older omit omitting on once one only onto opacity-60 open open/close option or order original other others otherwise out outgoing outline-none over overflow overflow-auto overflow-hidden overflow-x-auto overflow-y-auto overflow-y:auto overlaps override overrides overscroll-contain overwrite own owned p p-0 p-hsp-2xs p-hsp-lg p-hsp-md p-hsp-sm p-hsp-xl pack pack-scoped package package-default package-injected package-owned packages packs padding page page-loading page-loading-overlay page-loading-spinner page-navigate-end page-title page-wide pages pages/. paint paint-and-read palette pan panel panels paren-balance-aware parent parse parsed parser parses part pass passed passes patch path paths pattern payload payload-budget pb-[50vh] pb-vsp-2xs pb-vsp-lg pb-vsp-md pb-vsp-xl pb-vsp-xs pdf peer peer-focus-visible:border-accent peer-focus-visible:text-accent peer-hover:border-accent peer-hover:text-accent pending per per-block per-link per-package per-release permanently persisted persistence php pi pick picked picks picocolors pins pipelines pl-[1.25rem] pl-hsp-lg pl-hsp-md pl-hsp-sm pl-hsp-xl place place-items-center placeholder placeholder:text-muted plain plural plus png png16 png32 pnpm point pointer pointer-events-none pointercancel pointerdown pointermove pointerup policy polite polygon polyline popover populates port position position:fixed pr-hsp-lg pr-hsp-md pr-hsp-sm pr-hsp-xl pr-hsp-xs pre pre-lowercased preact preact/compat preact/hooks preact/jsx-runtime preconnect preference prefix preload pres present preserving preview preview-swatch-color previews2026 previously primary print prior private produce produced produces producing production profiles project project-owned project-root-relative properties property props prose provided proxy pt-[0.15rem] pt-[2px] pt-vsp-3xs pt-vsp-md pt-vsp-sm pt-vsp-xl pt-vsp-xs ptag- public purely puts px px-hsp-2xl px-hsp-2xs px-hsp-lg px-hsp-md px-hsp-sm px-hsp-xl px-hsp-xs py py-0 py-[2px] py-[4px] py-[calc(var(--spacing-vsp-xs)+0.15rem)] py-hsp-2xs py-hsp-3xs py-hsp-sm py-hsp-xs py-vsp-2xs py-vsp-3xs py-vsp-lg py-vsp-md py-vsp-sm py-vsp-xl py-vsp-xs python q qt query question quick r radius radius-full radius-lg rail ramp range rar rather raw rb re-encode/decode re-exports re-initialized re-querying re-render re-renders re-run re-running re-runs re-selects re-syncs reach reached reaches read reader reader-facing reading readings reads/rewrites real real-value received receives recorded recovers rect redefine redistribution ref- reference referenced references refetch refresh refreshes refusing regardless regenerate regenerates regex registry reinit reinits rejected rel relative release released releases reload relying rem remapped remembered remove remove/rename removed removing rename render rendered renderer renderers renders reorder repaint repair repeated repeating replace replaced replacement replaces repopulate report repository requested require required requires reserved resize resize-x resolve resolved resolves responded response restore restores restyle result result-click results results-area retry return returns rev-parse reveal revision revisions rewire rewrite rewrites right right- right-0 right-hsp-lg ring-2 ring-accent risking ro robots role roles root rotate-180 rotate-90 round round-trip rounded rounded-[0.75rem] rounded-bl-[0.25rem] rounded-bl-[1rem] rounded-bl-lg rounded-br-[0.25rem] rounded-br-[1rem] rounded-full rounded-lg rounded-md rounded-t-[1rem] rounds route routed router routes routes-src routes/sitemap.xml row row-span-2 row-start-1 row-start-2 rs ruby rule rules run running runs runtime rust s safe safely safer same same-locale samp sans sans-serif scale scanned scanning scheme scoped scoping score scored script script- script-eval script-evaluation script-injection scripts scroll scrollbar scrolled scrollend scrolling scss seam search search-index section section- see seed segment segments sehen select select-none selection-bg selection-fg selector self self-contained self-hosted self-start self-stretch semantic semibold semver sentinel separator serialised serialize server server-rendered session set sets setting settles setup sh shadow shadow-[0_1px_3px_color-mix(in_srgb,var(--color-fg)_8%,transparent)] shadow-lg shadow-md shadowed shape share shared sharing shell ship shipped ships short shortcut should show shown shrink-0 sidebar sidebar- sidebar-toggle-island sidebar-tree-island sidebar-w sidecar signal silently similarity simple since single single-line single-object-literal singular site site-search site-tree-nav-island sitemap- sites size size-icon-lg skill skills skipped skipping skips slash slot slug slug-dir-parity slugs sm:block sm:border sm:border-muted sm:col-start-2 sm:flex sm:flex-row sm:gap-x-hsp-xl sm:grid sm:grid-cols-2 sm:grid-cols-[minmax(0,1fr)_auto] sm:grid-cols-subgrid sm:h-auto sm:hidden sm:items-center sm:justify-between sm:max-h-[80vh] sm:max-w-[52rem] sm:mr-0 sm:mx-auto sm:my-[10vh] sm:rounded-lg sm:row-span-2 sm:row-start-1 small smol-toml smooth snapping snapshot snapshots so soft soft-nav solid some somehow source sources space-y-vsp-2xs space-y-vsp-lg space-y-vsp-sm spacing spacing-0 spacing-px span spans spec specifiers specify spelling splitter spread spurious sql square sr-only src stable stack stale standalone start state state- state:state- statement status stay staying sticky still stock stop stops stored straddles stray strict string strings strip stripe strips stroke-linecap stroke-linejoin stroke-width strong stronger stub-rendered style style-attribute styled styles stylesheet sub subagents subsequent substitute substitution subtracting success successful summary sup supply supported surface surfaces survives svg swap swapped swaps swift switcher switching symlink synchronous synchronously syntactically syntax t tab tab-item tab-panel tabindex table tablist tabpanel tabs tabs-container tabs-content tabs-nav tabular-nums tag tag- tag-item- tagged tags tags:audit take tar tbody td temp-element template temporary temporary-element terminal terms test-results tested text text-accent text-bg text-body text-caption text-center text-chat-assistant-text text-chat-user-text text-code-fg text-danger text-decoration text-display text-fg text-fg/60 text-heading text-info text-left text-micro text-muted text-muted/50 text-right text-scale-2xl text-scale-2xs text-scale-lg text-scale-md text-scale-sm text-scale-xl text-scale-xs text-small text-title text-warning text/css text/csv text/html text/javascript text/jsx text/markdown text/mdx text/plain text/tab-separated-values text/tsx text/typescript text/x-c text/x-csharp text/x-go text/x-java-source text/x-kotlin text/x-python text/x-ruby text/x-rust text/x-scss text/x-shellscript text/x-swift textarea tfoot tgz th than that the thead their them theme theme-color theme-pack theme-pack-changed theme-packs theme-packs/index.json theme-toggle theme/token then there these they this those though three threw through throw throws tighten time timeline tip title tkhd to toast toc toggle toggle- toggle-ai-chat toggle-design-token-panel toggles toggling token tokens tolerates toml too toolbar tooltip top top-0 top-[3.5rem] top-full top-hsp-2xs top-level total touches tr tracked tracking-wide tracking-wider trade-off trailing transferred transition transition-[background,color,border-color] transition-[left,color] transition-[right,color] transition-colors transition-transform translate-x-0 translated translations transparent tray treats tree tree-child- tree-item- tree-top- trigger trigger:ai-chat trigger:design-token-panel triggers true truncate truncated try ts tsv tsx turn twitter:card twitter:creator twitter:description twitter:image twitter:site twitter:title two txt type typeface typeof typescript typography u ul umschalten unable unavailable unbalanced unchanged und undefined under underline underlines understand unit-tested unknown unlike unlisted unmaintained unobserve unreadable unrelated unreleased unresolvable unresolved unset unsupported unterminated until unusable unwrapped up up-to-date update updated uppercase use used useful user uses using usual utf-8 utf8 utilities utility v v2 val value value-reader values var variable variant verbatim version version- version-menu version-switcher versions vertical via video video/mp4 video/quicktime video/webm viewer viewing viewport viewports virtual:zudo-doc-asset-bodies virtual:zudo-doc-chrome-bindings virtual:zudo-doc-design-token-panel-config virtual:zudo-doc-route-context visibility visible vocabulary void von vsp vsp-2xl vsp-2xs vsp-3xs vsp-lg vsp-md vsp-sm vsp-xl vsp-xs w w-1/2 w-[0.5rem] w-[0.625rem] w-[0.875rem] w-[1.125rem] w-[1.575rem] w-[1.5rem] w-[1.75rem] w-[12rem] w-[14px] w-[16px] w-[16rem] w-[18px] w-[1em] w-[2.5rem] w-[280px] w-[2rem] w-[320px] w-[360px] w-[6.5rem] w-[90vw] w-[calc(100vw-2rem)] w-[var(--zd-sidebar-w)] w-dvw w-full w-icon-lg w-icon-md w-icon-sm w-icon-xs walk walks want warn warning was watching way wbr wbr- we webm webp website weight went were what when where whereas whether which while whitespace-nowrap whitespace-pre whole whose wide wide-gamut wider-than-scrollbar width will window wins wird wired with without word wordmark working works worktrees would wrap wrapped wrapper wrappers wrapping wraps writing written wrong wrote wurde x xl:flex xl:hidden xml y-scrollbar yaml year yet yielded yields yml you your z-dropdown z-local-1 z-modal z-modal-backdrop z-popover z-sidebar z-toolbar zd-asset-code zd-asset-details-rail zd-asset-details-toggle zd-asset-filebar zd-asset-media-grid zd-asset-media-rail zd-asset-page zd-asset-pdf zd-asset-stage zd-content zd-desktop-sidebar-toggle zd-desktop-toc-toggle zd-doc-content-band zd-enlarge-btn zd-enlarge-dialog zd-enlarge-dialog-close zd-enlargeable zd-html-preview-code zd-mermaid-dialog zd-mermaid-enlargeable zd-mermaid-tool-btn zd-mermaid-toolbar zd-mermaid-transform zd-mermaid-viewport zd-sidebar-content-wrapper zd-sidebar-open zd-theme-pack-dialog-title zd-toc-col zdtp zfb zfb:after-swap zfb:before-preparation zfb:before-swap zip zod zoom zudo-design-token-panel zudo-design-tokens/v3 zudo-doc zudo-doc-asset-details-visible zudo-doc-code-wrap zudo-doc-design-token-panel-modal zudo-doc-design-tokens zudo-doc-sidebar-visible zudo-doc-sidebar-width zudo-doc-theme zudo-doc-theme-pack zudo-doc-toc-visible zudo-doc-tweak zum");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takazudo/zudo-doc",
3
- "version": "5.16.1",
3
+ "version": "5.17.0",
4
4
  "type": "module",
5
5
  "description": "zudo-doc framework primitives layer that sits on top of zfb's engine — sidebar, theme, TOC, breadcrumb, layouts, head injection, View Transitions, SSR-skip wrappers (per ADR-003).",
6
6
  "license": "MIT",
@@ -668,9 +668,9 @@
668
668
  ],
669
669
  "peerDependencies": {
670
670
  "@takazudo/zdtp": "^0.4.14",
671
- "@takazudo/zfb": "^2.14.3",
672
- "@takazudo/zfb-md-wasm": "^2.14.3",
673
- "@takazudo/zfb-runtime": "^2.14.3",
671
+ "@takazudo/zfb": "^2.15.0",
672
+ "@takazudo/zfb-md-wasm": "^2.15.0",
673
+ "@takazudo/zfb-runtime": "^2.15.0",
674
674
  "@takazudo/zudo-doc-history-server": "^5.15.0",
675
675
  "diff": "^8.0.0",
676
676
  "katex": "^0.16.0",
@@ -706,9 +706,9 @@
706
706
  "yaml": "^2.9.0"
707
707
  },
708
708
  "devDependencies": {
709
- "@takazudo/zfb": "2.14.3",
710
- "@takazudo/zfb-md-wasm": "2.14.3",
711
- "@takazudo/zfb-runtime": "2.14.3",
709
+ "@takazudo/zfb": "2.15.0",
710
+ "@takazudo/zfb-md-wasm": "2.15.0",
711
+ "@takazudo/zfb-runtime": "2.15.0",
712
712
  "@types/fs-extra": "^11.0.4",
713
713
  "@types/minimist": "^1.2.5",
714
714
  "@types/node": "^25.3.5",
@@ -720,7 +720,7 @@
720
720
  "typescript": "^5.0.0",
721
721
  "vitest": "^4.1.0",
722
722
  "zod": "^4.3.6",
723
- "@takazudo/zudo-doc-history-server": "5.16.1"
723
+ "@takazudo/zudo-doc-history-server": "5.17.0"
724
724
  },
725
725
  "scripts": {
726
726
  "gen:search-widget-script": "node scripts/gen-search-widget-script.mjs",
@@ -22,6 +22,17 @@ function escapeXml(str: string): string {
22
22
 
23
23
  export default function Sitemap(): string {
24
24
  if (!settings.sitemap) {
25
+ // Package-owned injection (routes.ts) now gates `/sitemap.xml` on
26
+ // `settings.sitemap` (#3931/#3933), so this branch is unreachable through
27
+ // the normal injected route on a `sitemap: false` host. It stays reachable
28
+ // only via a host-defined/manual route — e.g. a kept `pages/sitemap.xml.tsx`
29
+ // that re-exports this entrypoint despite the feature being off — which is
30
+ // exactly the misconfiguration this warning names.
31
+ console.warn(
32
+ "[zudo-doc] routes/sitemap.xml was rendered while settings.sitemap is false/unset; " +
33
+ "emitting an empty <urlset>. Set settings.sitemap: true to enable it, or remove " +
34
+ "the manual route that reached this entrypoint.",
35
+ );
25
36
  return `<?xml version="1.0" encoding="UTF-8"?>
26
37
  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
27
38
  </urlset>`;