@tenphi/renderer 0.25.0 → 0.25.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/navigation-router.js +1 -0
- package/dist/client/navigation-router.js.map +1 -1
- package/dist/client/search.js +6 -1
- package/dist/client/search.js.map +1 -1
- package/dist/components/MarkdownTable.styles.js +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +63 -12
- package/dist/index.js.map +1 -1
- package/dist/localization.d.ts +3 -1
- package/dist/localization.d.ts.map +1 -1
- package/dist/localization.js +3 -2
- package/dist/localization.js.map +1 -1
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +2 -1
- package/dist/navigation.js.map +1 -1
- package/dist/overrides/Head.astro +2 -1
- package/dist/overrides/LanguageSelect.astro +2 -1
- package/dist/overrides/Search.astro +1 -2
- package/dist/page-metadata.d.ts +2 -1
- package/dist/page-metadata.d.ts.map +1 -1
- package/dist/page-metadata.js +5 -2
- package/dist/page-metadata.js.map +1 -1
- package/dist/route-context.d.ts +2 -1
- package/dist/route-context.d.ts.map +1 -1
- package/dist/route-context.js +2 -1
- package/dist/route-context.js.map +1 -1
- package/dist/routes/DocsPage.astro +5 -1
- package/dist/versioning.d.ts +4 -2
- package/dist/versioning.d.ts.map +1 -1
- package/dist/versioning.js +2 -3
- package/dist/versioning.js.map +1 -1
- package/package.json +2 -2
|
@@ -4,6 +4,7 @@ import { navigate } from "astro:transitions/client";
|
|
|
4
4
|
document.addEventListener("astro:before-swap", (event) => {
|
|
5
5
|
const transition = event;
|
|
6
6
|
transition.viewTransition.skipTransition();
|
|
7
|
+
transition.viewTransition.ready.catch(() => {});
|
|
7
8
|
for (const name of ["data-theme", "data-contrast"]) {
|
|
8
9
|
const value = document.documentElement.getAttribute(name);
|
|
9
10
|
if (value === null) transition.newDocument.documentElement.removeAttribute(name);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation-router.js","names":[],"sources":["../../src/client/navigation-router.ts"],"sourcesContent":["import type { TransitionBeforeSwapEvent } from \"astro:transitions/client\";\nimport { initializeTabs } from \"./tabs.js\";\nexport { navigate } from \"astro:transitions/client\";\n\n// Load swap behavior with the router, before the first client navigation.\ndocument.addEventListener(\"astro:before-swap\", (event) => {\n const transition = event as TransitionBeforeSwapEvent;\n // Instant swaps avoid the browser's default full-page crossfade.\n transition.viewTransition.skipTransition();\n for (const name of [\"data-theme\", \"data-contrast\"]) {\n const value = document.documentElement.getAttribute(name);\n if (value === null)\n transition.newDocument.documentElement.removeAttribute(name);\n else transition.newDocument.documentElement.setAttribute(name, value);\n }\n const sidebar = document.querySelector<HTMLElement>(\"#cookbook__sidebar\");\n const key =\n sidebar?.querySelector<HTMLElement>(\"cookbook-sidebar\")?.dataset.storageKey;\n const scroll = sidebar?.scrollTop ?? 0;\n const swap = transition.swap;\n transition.swap = () => {\n swap();\n const next = document.querySelector<HTMLElement>(\"#cookbook__sidebar\");\n if (\n next &&\n key &&\n next.querySelector<HTMLElement>(\"cookbook-sidebar\")?.dataset\n .storageKey === key &&\n matchMedia(\"(min-width: 50rem)\").matches\n )\n next.scrollTop = scroll;\n };\n});\n\ndocument.addEventListener(\"astro:after-swap\", () => {\n // Enhance incoming panels synchronously, before a frame can show every\n // no-JavaScript panel and then jump when page-load scripts hide them.\n initializeTabs();\n // Keep fragment navigation intact, but reset article scroll on page changes,\n // including Back/Forward. Sidebar scroll is independent of the document.\n if (!location.hash) {\n window.scrollTo({ top: 0, left: 0, behavior: \"instant\" });\n document.getElementById(\"main-content\")?.focus({ preventScroll: true });\n }\n});\n"],"mappings":";;;AAKA,SAAS,iBAAiB,sBAAsB,UAAU;CACxD,MAAM,aAAa;CAEnB,WAAW,eAAe,eAAe;CACzC,KAAK,MAAM,QAAQ,CAAC,cAAc,eAAe,GAAG;EAClD,MAAM,QAAQ,SAAS,gBAAgB,aAAa,IAAI;EACxD,IAAI,UAAU,MACZ,WAAW,YAAY,gBAAgB,gBAAgB,IAAI;OACxD,WAAW,YAAY,gBAAgB,aAAa,MAAM,KAAK;CACtE;CACA,MAAM,UAAU,SAAS,cAA2B,oBAAoB;CACxE,MAAM,MACJ,SAAS,cAA2B,kBAAkB,CAAC,EAAE,QAAQ;CACnE,MAAM,SAAS,SAAS,aAAa;CACrC,MAAM,OAAO,WAAW;CACxB,WAAW,aAAa;EACtB,KAAK;EACL,MAAM,OAAO,SAAS,cAA2B,oBAAoB;EACrE,IACE,QACA,OACA,KAAK,cAA2B,kBAAkB,CAAC,EAAE,QAClD,eAAe,OAClB,WAAW,oBAAoB,CAAC,CAAC,SAEjC,KAAK,YAAY;CACrB;AACF,CAAC;AAED,SAAS,iBAAiB,0BAA0B;CAGlD,eAAe;CAGf,IAAI,CAAC,SAAS,MAAM;EAClB,OAAO,SAAS;GAAE,KAAK;GAAG,MAAM;GAAG,UAAU;EAAU,CAAC;EACxD,SAAS,eAAe,cAAc,CAAC,EAAE,MAAM,EAAE,eAAe,KAAK,CAAC;CACxE;AACF,CAAC"}
|
|
1
|
+
{"version":3,"file":"navigation-router.js","names":[],"sources":["../../src/client/navigation-router.ts"],"sourcesContent":["import type { TransitionBeforeSwapEvent } from \"astro:transitions/client\";\nimport { initializeTabs } from \"./tabs.js\";\nexport { navigate } from \"astro:transitions/client\";\n\n// Load swap behavior with the router, before the first client navigation.\ndocument.addEventListener(\"astro:before-swap\", (event) => {\n const transition = event as TransitionBeforeSwapEvent;\n // Instant swaps avoid the browser's default full-page crossfade.\n transition.viewTransition.skipTransition();\n void transition.viewTransition.ready.catch(() => {\n // Skipping rejects `ready` with an AbortError that nothing else observes.\n });\n for (const name of [\"data-theme\", \"data-contrast\"]) {\n const value = document.documentElement.getAttribute(name);\n if (value === null)\n transition.newDocument.documentElement.removeAttribute(name);\n else transition.newDocument.documentElement.setAttribute(name, value);\n }\n const sidebar = document.querySelector<HTMLElement>(\"#cookbook__sidebar\");\n const key =\n sidebar?.querySelector<HTMLElement>(\"cookbook-sidebar\")?.dataset.storageKey;\n const scroll = sidebar?.scrollTop ?? 0;\n const swap = transition.swap;\n transition.swap = () => {\n swap();\n const next = document.querySelector<HTMLElement>(\"#cookbook__sidebar\");\n if (\n next &&\n key &&\n next.querySelector<HTMLElement>(\"cookbook-sidebar\")?.dataset\n .storageKey === key &&\n matchMedia(\"(min-width: 50rem)\").matches\n )\n next.scrollTop = scroll;\n };\n});\n\ndocument.addEventListener(\"astro:after-swap\", () => {\n // Enhance incoming panels synchronously, before a frame can show every\n // no-JavaScript panel and then jump when page-load scripts hide them.\n initializeTabs();\n // Keep fragment navigation intact, but reset article scroll on page changes,\n // including Back/Forward. Sidebar scroll is independent of the document.\n if (!location.hash) {\n window.scrollTo({ top: 0, left: 0, behavior: \"instant\" });\n document.getElementById(\"main-content\")?.focus({ preventScroll: true });\n }\n});\n"],"mappings":";;;AAKA,SAAS,iBAAiB,sBAAsB,UAAU;CACxD,MAAM,aAAa;CAEnB,WAAW,eAAe,eAAe;CACzC,WAAgB,eAAe,MAAM,YAAY,CAEjD,CAAC;CACD,KAAK,MAAM,QAAQ,CAAC,cAAc,eAAe,GAAG;EAClD,MAAM,QAAQ,SAAS,gBAAgB,aAAa,IAAI;EACxD,IAAI,UAAU,MACZ,WAAW,YAAY,gBAAgB,gBAAgB,IAAI;OACxD,WAAW,YAAY,gBAAgB,aAAa,MAAM,KAAK;CACtE;CACA,MAAM,UAAU,SAAS,cAA2B,oBAAoB;CACxE,MAAM,MACJ,SAAS,cAA2B,kBAAkB,CAAC,EAAE,QAAQ;CACnE,MAAM,SAAS,SAAS,aAAa;CACrC,MAAM,OAAO,WAAW;CACxB,WAAW,aAAa;EACtB,KAAK;EACL,MAAM,OAAO,SAAS,cAA2B,oBAAoB;EACrE,IACE,QACA,OACA,KAAK,cAA2B,kBAAkB,CAAC,EAAE,QAClD,eAAe,OAClB,WAAW,oBAAoB,CAAC,CAAC,SAEjC,KAAK,YAAY;CACrB;AACF,CAAC;AAED,SAAS,iBAAiB,0BAA0B;CAGlD,eAAe;CAGf,IAAI,CAAC,SAAS,MAAM;EAClB,OAAO,SAAS;GAAE,KAAK;GAAG,MAAM;GAAG,UAAU;EAAU,CAAC;EACxD,SAAS,eAAe,cAAc,CAAC,EAAE,MAAM,EAAE,eAAe,KAAK,CAAC;CACxE;AACF,CAAC"}
|
package/dist/client/search.js
CHANGED
|
@@ -43,7 +43,12 @@ function initializeSearch(element, options, development, base) {
|
|
|
43
43
|
return initialized ??= (async () => {
|
|
44
44
|
const { PagefindUI } = await import("@pagefind/default-ui");
|
|
45
45
|
const translations = JSON.parse(element.dataset.translations ?? "{}");
|
|
46
|
-
const format = (url) =>
|
|
46
|
+
const format = (url) => {
|
|
47
|
+
const trailingSlash = element.dataset.trailingSlash;
|
|
48
|
+
if (trailingSlash === "always") return url;
|
|
49
|
+
const page = url.replace(/\.html(?=#|$)/, "");
|
|
50
|
+
return trailingSlash === "never" ? page.replace(/(.)\/(#.*)?$/, "$1$2") : page;
|
|
51
|
+
};
|
|
47
52
|
new PagefindUI({
|
|
48
53
|
...options,
|
|
49
54
|
element: element.querySelector("[data-search-results]"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","names":[],"sources":["../../src/client/search.ts"],"sourcesContent":["type SearchResult = { url: string; sub_results?: SearchResult[] };\nimport type { TransitionBeforeSwapEvent } from \"astro:transitions/client\";\ntype PagefindOptions = Record<string, unknown> & {\n processResult?: (result: SearchResult) => SearchResult | void;\n};\n\n/** Own the dialog lifecycle; Pagefind owns indexing, filtering and result rendering. */\nexport function initializeSearch(\n element: HTMLElement,\n options: PagefindOptions,\n development: boolean,\n base: string,\n): void {\n if (element.dataset.initialized) return;\n element.dataset.initialized = \"true\";\n const listeners = new AbortController();\n // Astro strips transition attributes from unhydrated framework roots. Apply\n // the public persistence hook here and to the incoming matching search root.\n const persistenceKey = element.dataset.searchKey;\n if (persistenceKey)\n element.setAttribute(\"data-astro-transition-persist\", persistenceKey);\n const open = element.querySelector<HTMLButtonElement>(\"[data-open-modal]\")!;\n const close = element.querySelector<HTMLButtonElement>(\"[data-close-modal]\")!;\n const dialog = element.querySelector(\"dialog\")!;\n const frame = element.querySelector(\"[data-element=Frame]\")!;\n const status = element.querySelector<HTMLElement>(\"[data-search-status]\");\n const input = element.querySelector<HTMLInputElement>(\"[data-search-input]\");\n const clear = element.querySelector<HTMLButtonElement>(\"[data-clear-search]\");\n const shortcut = open.querySelector(\"kbd\")!;\n if (/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)) {\n shortcut.querySelector(\"kbd\")!.textContent = \"⌘\";\n open.setAttribute(\"aria-keyshortcuts\", \"Meta+K\");\n }\n delete shortcut.dataset.pending;\n let initialized: Promise<void> | undefined;\n let engineInput: HTMLInputElement | null = null;\n let returnFocus: HTMLElement | null = null;\n let closing = false;\n let generation = 0;\n const updateSearch = () => {\n if (clear) clear.hidden = !input?.value;\n if (engineInput) {\n engineInput.value = input?.value ?? \"\";\n engineInput.dispatchEvent(new Event(\"input\", { bubbles: true }));\n }\n };\n input?.addEventListener(\"input\", updateSearch);\n clear?.addEventListener(\"click\", () => {\n if (!input) return;\n input.value = \"\";\n updateSearch();\n input.focus();\n });\n const initialize = () => {\n if (development) return Promise.resolve();\n return (initialized ??= (async () => {\n // @ts-expect-error Pagefind publishes no declarations for its default UI.\n const { PagefindUI } = await import(\"@pagefind/default-ui\");\n const translations = JSON.parse(element.dataset.translations ?? \"{}\");\n const format = (url: string) =>\n element.hasAttribute(\"data-strip-trailing-slash\")\n ? url.replace(/(.)\\/(#.*)?$/, \"$1$2\")\n : url;\n new PagefindUI({\n ...options,\n element: element.querySelector(\"[data-search-results]\"),\n baseUrl: base,\n bundlePath: `${base.replace(/\\/$/, \"\")}/pagefind/`,\n showImages: false,\n showSubResults: true,\n translations,\n processResult(result: SearchResult) {\n result = options.processResult?.(result) ?? result;\n result.url = format(result.url);\n result.sub_results?.forEach((child) => {\n child.url = format(child.url);\n });\n return result;\n },\n });\n // Pagefind generates and controls these nodes; its UI API exposes only classes.\n engineInput = element.querySelector(\".pagefind-ui__search-input\");\n element.querySelector(\".pagefind-ui__form\")?.removeAttribute(\"role\");\n // Cookbook owns the field so focus stays within the opening tap on mobile.\n // Pagefind still owns query processing and its lazily rendered results.\n element\n .querySelectorAll<HTMLElement>(\n \".pagefind-ui__search-input, .pagefind-ui__search-clear\",\n )\n .forEach((control) => {\n control.hidden = true;\n control.tabIndex = -1;\n });\n updateSearch();\n })().catch((error: unknown) => {\n initialized = undefined;\n if (status) {\n status.hidden = false;\n // Reuse the localized Pagefind error, with a plain fallback.\n const translations = JSON.parse(element.dataset.translations ?? \"{}\");\n status.textContent =\n translations.error ?? \"Search could not load. Close and try again.\";\n }\n throw error;\n }));\n };\n const show = (trigger?: HTMLElement) => {\n if (dialog.open && !closing) return;\n generation += 1;\n closing = false;\n if (!dialog.open) {\n returnFocus =\n trigger ??\n (document.activeElement instanceof HTMLElement &&\n document.activeElement !== document.body\n ? document.activeElement\n : open);\n dialog.removeAttribute(\"data-open\");\n dialog.showModal();\n }\n // Do this synchronously, before the lazy import releases user activation.\n input?.focus({ preventScroll: true });\n // Establish the initial state after entering the top layer. The global\n // style renderer does not preserve @starting-style in server output.\n dialog.getBoundingClientRect();\n dialog.setAttribute(\"data-open\", \"\");\n document.body.setAttribute(\"data-search-modal-open\", \"\");\n if (!development && status) status.hidden = true;\n void initialize().catch(() => {\n /* Keep the close control usable when the search bundle fails. */\n });\n };\n const hide = async () => {\n if (!dialog.open || closing) return;\n closing = true;\n const current = ++generation;\n dialog.removeAttribute(\"data-open\");\n // Keep the modal in the top layer until its exit transition has finished.\n // This also works in browsers without discrete display/overlay transitions.\n await Promise.allSettled(\n dialog\n .getAnimations()\n .filter((animation) =>\n Number.isFinite(animation.effect?.getComputedTiming().endTime),\n )\n .map((animation) => animation.finished),\n );\n if (current === generation && dialog.open) dialog.close();\n };\n open.addEventListener(\"click\", () => {\n show(open);\n });\n open.disabled = false;\n close.addEventListener(\"click\", () => void hide());\n dialog.addEventListener(\"cancel\", (event) => {\n event.preventDefault();\n void hide();\n });\n dialog.addEventListener(\"click\", (event) => {\n if (!(event.target instanceof Element)) return;\n if (event.target.closest(\"a[href]\") || !frame.contains(event.target))\n void hide();\n });\n dialog.addEventListener(\"close\", () => {\n dialog.removeAttribute(\"data-open\");\n closing = false;\n document.body.removeAttribute(\"data-search-modal-open\");\n returnFocus?.focus();\n });\n document.addEventListener(\n \"astro:before-swap\",\n (event) => {\n // Keep the query and lazy engine for matching localized search shells,\n // while dismissing the modal before the destination content is displayed.\n generation += 1;\n returnFocus = null;\n if (dialog.open) dialog.close();\n dialog.removeAttribute(\"data-open\");\n document.body.removeAttribute(\"data-search-modal-open\");\n const next = (event as TransitionBeforeSwapEvent).newDocument;\n const nextRoot = persistenceKey\n ? [...next.querySelectorAll<HTMLElement>(\"site-search\")].find(\n (root) => root.dataset.searchKey === persistenceKey,\n )\n : undefined;\n if (nextRoot)\n nextRoot.setAttribute(\"data-astro-transition-persist\", persistenceKey!);\n else listeners.abort();\n },\n { signal: listeners.signal },\n );\n window.addEventListener(\n \"keydown\",\n (event) => {\n if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === \"k\") {\n event.preventDefault();\n if (dialog.open && !closing) void hide();\n else void show();\n }\n },\n { signal: listeners.signal },\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"search.js","names":[],"sources":["../../src/client/search.ts"],"sourcesContent":["type SearchResult = { url: string; sub_results?: SearchResult[] };\nimport type { TransitionBeforeSwapEvent } from \"astro:transitions/client\";\ntype PagefindOptions = Record<string, unknown> & {\n processResult?: (result: SearchResult) => SearchResult | void;\n};\n\n/** Own the dialog lifecycle; Pagefind owns indexing, filtering and result rendering. */\nexport function initializeSearch(\n element: HTMLElement,\n options: PagefindOptions,\n development: boolean,\n base: string,\n): void {\n if (element.dataset.initialized) return;\n element.dataset.initialized = \"true\";\n const listeners = new AbortController();\n // Astro strips transition attributes from unhydrated framework roots. Apply\n // the public persistence hook here and to the incoming matching search root.\n const persistenceKey = element.dataset.searchKey;\n if (persistenceKey)\n element.setAttribute(\"data-astro-transition-persist\", persistenceKey);\n const open = element.querySelector<HTMLButtonElement>(\"[data-open-modal]\")!;\n const close = element.querySelector<HTMLButtonElement>(\"[data-close-modal]\")!;\n const dialog = element.querySelector(\"dialog\")!;\n const frame = element.querySelector(\"[data-element=Frame]\")!;\n const status = element.querySelector<HTMLElement>(\"[data-search-status]\");\n const input = element.querySelector<HTMLInputElement>(\"[data-search-input]\");\n const clear = element.querySelector<HTMLButtonElement>(\"[data-clear-search]\");\n const shortcut = open.querySelector(\"kbd\")!;\n if (/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)) {\n shortcut.querySelector(\"kbd\")!.textContent = \"⌘\";\n open.setAttribute(\"aria-keyshortcuts\", \"Meta+K\");\n }\n delete shortcut.dataset.pending;\n let initialized: Promise<void> | undefined;\n let engineInput: HTMLInputElement | null = null;\n let returnFocus: HTMLElement | null = null;\n let closing = false;\n let generation = 0;\n const updateSearch = () => {\n if (clear) clear.hidden = !input?.value;\n if (engineInput) {\n engineInput.value = input?.value ?? \"\";\n engineInput.dispatchEvent(new Event(\"input\", { bubbles: true }));\n }\n };\n input?.addEventListener(\"input\", updateSearch);\n clear?.addEventListener(\"click\", () => {\n if (!input) return;\n input.value = \"\";\n updateSearch();\n input.focus();\n });\n const initialize = () => {\n if (development) return Promise.resolve();\n return (initialized ??= (async () => {\n // @ts-expect-error Pagefind publishes no declarations for its default UI.\n const { PagefindUI } = await import(\"@pagefind/default-ui\");\n const translations = JSON.parse(element.dataset.translations ?? \"{}\");\n // Pagefind names pages by their files: x/ for x/index.html, x.html otherwise.\n const format = (url: string) => {\n const trailingSlash = element.dataset.trailingSlash;\n if (trailingSlash === \"always\") return url;\n const page = url.replace(/\\.html(?=#|$)/, \"\");\n return trailingSlash === \"never\"\n ? page.replace(/(.)\\/(#.*)?$/, \"$1$2\")\n : page;\n };\n new PagefindUI({\n ...options,\n element: element.querySelector(\"[data-search-results]\"),\n baseUrl: base,\n bundlePath: `${base.replace(/\\/$/, \"\")}/pagefind/`,\n showImages: false,\n showSubResults: true,\n translations,\n processResult(result: SearchResult) {\n result = options.processResult?.(result) ?? result;\n result.url = format(result.url);\n result.sub_results?.forEach((child) => {\n child.url = format(child.url);\n });\n return result;\n },\n });\n // Pagefind generates and controls these nodes; its UI API exposes only classes.\n engineInput = element.querySelector(\".pagefind-ui__search-input\");\n element.querySelector(\".pagefind-ui__form\")?.removeAttribute(\"role\");\n // Cookbook owns the field so focus stays within the opening tap on mobile.\n // Pagefind still owns query processing and its lazily rendered results.\n element\n .querySelectorAll<HTMLElement>(\n \".pagefind-ui__search-input, .pagefind-ui__search-clear\",\n )\n .forEach((control) => {\n control.hidden = true;\n control.tabIndex = -1;\n });\n updateSearch();\n })().catch((error: unknown) => {\n initialized = undefined;\n if (status) {\n status.hidden = false;\n // Reuse the localized Pagefind error, with a plain fallback.\n const translations = JSON.parse(element.dataset.translations ?? \"{}\");\n status.textContent =\n translations.error ?? \"Search could not load. Close and try again.\";\n }\n throw error;\n }));\n };\n const show = (trigger?: HTMLElement) => {\n if (dialog.open && !closing) return;\n generation += 1;\n closing = false;\n if (!dialog.open) {\n returnFocus =\n trigger ??\n (document.activeElement instanceof HTMLElement &&\n document.activeElement !== document.body\n ? document.activeElement\n : open);\n dialog.removeAttribute(\"data-open\");\n dialog.showModal();\n }\n // Do this synchronously, before the lazy import releases user activation.\n input?.focus({ preventScroll: true });\n // Establish the initial state after entering the top layer. The global\n // style renderer does not preserve @starting-style in server output.\n dialog.getBoundingClientRect();\n dialog.setAttribute(\"data-open\", \"\");\n document.body.setAttribute(\"data-search-modal-open\", \"\");\n if (!development && status) status.hidden = true;\n void initialize().catch(() => {\n /* Keep the close control usable when the search bundle fails. */\n });\n };\n const hide = async () => {\n if (!dialog.open || closing) return;\n closing = true;\n const current = ++generation;\n dialog.removeAttribute(\"data-open\");\n // Keep the modal in the top layer until its exit transition has finished.\n // This also works in browsers without discrete display/overlay transitions.\n await Promise.allSettled(\n dialog\n .getAnimations()\n .filter((animation) =>\n Number.isFinite(animation.effect?.getComputedTiming().endTime),\n )\n .map((animation) => animation.finished),\n );\n if (current === generation && dialog.open) dialog.close();\n };\n open.addEventListener(\"click\", () => {\n show(open);\n });\n open.disabled = false;\n close.addEventListener(\"click\", () => void hide());\n dialog.addEventListener(\"cancel\", (event) => {\n event.preventDefault();\n void hide();\n });\n dialog.addEventListener(\"click\", (event) => {\n if (!(event.target instanceof Element)) return;\n if (event.target.closest(\"a[href]\") || !frame.contains(event.target))\n void hide();\n });\n dialog.addEventListener(\"close\", () => {\n dialog.removeAttribute(\"data-open\");\n closing = false;\n document.body.removeAttribute(\"data-search-modal-open\");\n returnFocus?.focus();\n });\n document.addEventListener(\n \"astro:before-swap\",\n (event) => {\n // Keep the query and lazy engine for matching localized search shells,\n // while dismissing the modal before the destination content is displayed.\n generation += 1;\n returnFocus = null;\n if (dialog.open) dialog.close();\n dialog.removeAttribute(\"data-open\");\n document.body.removeAttribute(\"data-search-modal-open\");\n const next = (event as TransitionBeforeSwapEvent).newDocument;\n const nextRoot = persistenceKey\n ? [...next.querySelectorAll<HTMLElement>(\"site-search\")].find(\n (root) => root.dataset.searchKey === persistenceKey,\n )\n : undefined;\n if (nextRoot)\n nextRoot.setAttribute(\"data-astro-transition-persist\", persistenceKey!);\n else listeners.abort();\n },\n { signal: listeners.signal },\n );\n window.addEventListener(\n \"keydown\",\n (event) => {\n if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === \"k\") {\n event.preventDefault();\n if (dialog.open && !closing) void hide();\n else void show();\n }\n },\n { signal: listeners.signal },\n );\n}\n"],"mappings":"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"}
|
|
@@ -22,6 +22,12 @@ export function MarkdownTableStyles() {
|
|
|
22
22
|
$: "th, td",
|
|
23
23
|
padding: "($gap * 1.5) ($gap * 2)",
|
|
24
24
|
verticalAlign: "top",
|
|
25
|
+
textAlign: {
|
|
26
|
+
"": null,
|
|
27
|
+
"@own(align=left)": "left",
|
|
28
|
+
"@own(align=center)": "center",
|
|
29
|
+
"@own(align=right)": "right",
|
|
30
|
+
},
|
|
25
31
|
// Change only color; border widths and styles belong to other rules or theme overrides.
|
|
26
32
|
// eslint-disable-next-line tasty/prefer-shorthand-property
|
|
27
33
|
borderColor: "#border",
|
|
@@ -36,7 +42,7 @@ export function MarkdownTableStyles() {
|
|
|
36
42
|
$: "th",
|
|
37
43
|
color: "#text",
|
|
38
44
|
fill: "#surface-2",
|
|
39
|
-
textAlign: "start",
|
|
45
|
+
textAlign: { "": "start", "@own(align)": null },
|
|
40
46
|
radius: {
|
|
41
47
|
"@own(:is(thead:first-child tr:first-child >) & :first-child & !:last-child)":
|
|
42
48
|
"($card-radius - $border-width) top-left",
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/plugin-contract.ts","../src/integration.ts"],"mappings":";;;;;KAEY;EAEN,WAAW,iBAAiB,QAAQ;;EAGpC,MAAM,iBAAiB;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/plugin-contract.ts","../src/integration.ts"],"mappings":";;;;;KAEY;EAEN,WAAW,iBAAiB,QAAQ;;EAGpC,MAAM,iBAAiB;;;;UCyGZ;EACf,SAAS;EACT;EACA;;EAEA,oBAAoB;;iBAGE,SACtB,UAAS,kBACR"}
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { createRequire } from "node:module";
|
|
|
10
10
|
import { cp, mkdir, readFile, readdir, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
11
11
|
import { dirname, extname, isAbsolute, join, resolve, sep } from "node:path";
|
|
12
12
|
import sharp from "sharp";
|
|
13
|
-
import { DOCS_FRONTMATTER_KEYS, assertValidDocs, createDocsGraph, renderAgentMarkdown, resolveColorTheme, resolveDocsProject } from "@tenphi/docs";
|
|
13
|
+
import { DOCS_FRONTMATTER_KEYS, assertValidDocs, createDocsGraph, renderAgentMarkdown, resolveColorTheme, resolveDocsProject, routePath, routeUrl } from "@tenphi/docs";
|
|
14
14
|
import { createHash, randomUUID } from "node:crypto";
|
|
15
15
|
import { fromHtml } from "hast-util-from-html";
|
|
16
16
|
import { existsSync } from "node:fs";
|
|
@@ -304,7 +304,7 @@ const alerts = {
|
|
|
304
304
|
};
|
|
305
305
|
/** Keep GitHub alert syntax useful in repository Markdown and MDX. */
|
|
306
306
|
function rehypeAlerts() {
|
|
307
|
-
return (tree) => visit(tree);
|
|
307
|
+
return (tree) => visit$1(tree);
|
|
308
308
|
}
|
|
309
309
|
const satteriAlerts = {
|
|
310
310
|
name: "cookbook:alerts",
|
|
@@ -316,12 +316,12 @@ const satteriAlerts = {
|
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
318
|
};
|
|
319
|
-
function visit(parent) {
|
|
319
|
+
function visit$1(parent) {
|
|
320
320
|
if (!parent.children) return;
|
|
321
321
|
for (const [index, child] of parent.children.entries()) {
|
|
322
322
|
const replacement = alert(child);
|
|
323
323
|
if (replacement) parent.children[index] = replacement;
|
|
324
|
-
else visit(child);
|
|
324
|
+
else visit$1(child);
|
|
325
325
|
}
|
|
326
326
|
}
|
|
327
327
|
function alert(blockquote) {
|
|
@@ -367,6 +367,53 @@ function alert(blockquote) {
|
|
|
367
367
|
};
|
|
368
368
|
}
|
|
369
369
|
//#endregion
|
|
370
|
+
//#region src/markdown/rehype-table-alignment.ts
|
|
371
|
+
const alignments = /* @__PURE__ */ new Set([
|
|
372
|
+
"left",
|
|
373
|
+
"center",
|
|
374
|
+
"right"
|
|
375
|
+
]);
|
|
376
|
+
/**
|
|
377
|
+
* Move GFM column alignment into a `data-align` modifier styled by
|
|
378
|
+
* `MarkdownTable`. Unified emits the obsolete `align` attribute and Sätteri an
|
|
379
|
+
* inline `text-align` style, which the Tasty-only output check rejects.
|
|
380
|
+
*/
|
|
381
|
+
function rehypeTableAlignment() {
|
|
382
|
+
return (tree) => visit(tree);
|
|
383
|
+
}
|
|
384
|
+
/** Sätteri adapter for Astro's default Markdown processor. */
|
|
385
|
+
const satteriTableAlignment = {
|
|
386
|
+
name: "cookbook:table-alignment",
|
|
387
|
+
element: {
|
|
388
|
+
filter: ["th", "td"],
|
|
389
|
+
visit(node, context) {
|
|
390
|
+
const replacement = alignedCell(node);
|
|
391
|
+
if (replacement) context.replaceNode(node, replacement);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
function visit(parent) {
|
|
396
|
+
if (!parent.children) return;
|
|
397
|
+
for (const [index, child] of parent.children.entries()) {
|
|
398
|
+
const replacement = alignedCell(child);
|
|
399
|
+
if (replacement) parent.children[index] = replacement;
|
|
400
|
+
else visit(child);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
function alignedCell(cell) {
|
|
404
|
+
if (cell.type !== "element" || cell.tagName !== "th" && cell.tagName !== "td") return;
|
|
405
|
+
const { align, style, ...properties } = cell.properties ?? {};
|
|
406
|
+
const alignment = (typeof align === "string" ? align : typeof style === "string" ? /^\s*text-align:\s*([a-z]+)\s*;?\s*$/i.exec(style)?.[1] : void 0)?.toLowerCase();
|
|
407
|
+
if (!alignment || !alignments.has(alignment)) return;
|
|
408
|
+
return {
|
|
409
|
+
...cell,
|
|
410
|
+
properties: {
|
|
411
|
+
...properties,
|
|
412
|
+
dataAlign: alignment
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
//#endregion
|
|
370
417
|
//#region src/markdown/rehype-table-scroll.ts
|
|
371
418
|
const containerElement = "Scroll";
|
|
372
419
|
/** Wrap Markdown tables in a dedicated horizontal scroll container. */
|
|
@@ -1002,9 +1049,6 @@ function outputPathForPublicAsset(publicPath, base) {
|
|
|
1002
1049
|
}
|
|
1003
1050
|
//#endregion
|
|
1004
1051
|
//#region src/agent-discovery.ts
|
|
1005
|
-
function sitePath(base, route) {
|
|
1006
|
-
return `${base === "/" ? "" : `/${base.replace(/^\/+|\/+$/g, "")}`}${route === "/" ? "/" : `${route}/`}`;
|
|
1007
|
-
}
|
|
1008
1052
|
function pageUrl(site, path) {
|
|
1009
1053
|
return site ? new URL(path, site).href : path;
|
|
1010
1054
|
}
|
|
@@ -1022,7 +1066,7 @@ function renderLlmsTxt(graph) {
|
|
|
1022
1066
|
const discoverable = new Set(graph.routes.filter((route) => route.discoverable !== false && route.sitemap !== false).map((route) => route.route));
|
|
1023
1067
|
for (const entry of graph.entries) {
|
|
1024
1068
|
if (!discoverable.has(entry.route)) continue;
|
|
1025
|
-
const url =
|
|
1069
|
+
const url = routeUrl(entry.route, build.base, site.url, build.trailingSlash);
|
|
1026
1070
|
lines.push(`- [${markdownLabel(entry.title)}](${url})${entry.description ? `: ${singleLine(entry.description)}` : ""}${site.seo?.copyPage === false ? "" : ` ([Markdown](${pageUrl(site.url, agentPagePath(entry.route, build.base))}))`}`);
|
|
1027
1071
|
}
|
|
1028
1072
|
return `${lines.join("\n")}\n`;
|
|
@@ -1049,7 +1093,7 @@ async function writeAgentDiscovery(output, graph) {
|
|
|
1049
1093
|
if (markdown) await writeFile(join(output, outputPathForPublicAsset(markdown, graph.config.build.base)), renderAgentMarkdown(entry, graph.config));
|
|
1050
1094
|
pages.push({
|
|
1051
1095
|
route: entry.route,
|
|
1052
|
-
url:
|
|
1096
|
+
url: routeUrl(entry.route, graph.config.build.base, graph.config.site.url, graph.config.build.trailingSlash),
|
|
1053
1097
|
canonical: route.canonical,
|
|
1054
1098
|
index: route.indexable !== false,
|
|
1055
1099
|
discoverable: route.discoverable !== false,
|
|
@@ -1160,6 +1204,7 @@ function configuredCookbook(options) {
|
|
|
1160
1204
|
let projectRoot = options.root;
|
|
1161
1205
|
let graphConfig = options.config;
|
|
1162
1206
|
let graphBase = "/";
|
|
1207
|
+
let graphTrailingSlash = "always";
|
|
1163
1208
|
let graph;
|
|
1164
1209
|
let siteIconBase = "/";
|
|
1165
1210
|
let siteIcons;
|
|
@@ -1171,7 +1216,8 @@ function configuredCookbook(options) {
|
|
|
1171
1216
|
const candidate = await createDocsGraph({
|
|
1172
1217
|
...projectRoot ? { root: projectRoot } : {},
|
|
1173
1218
|
...graphConfig ? { config: graphConfig } : {},
|
|
1174
|
-
base: graphBase
|
|
1219
|
+
base: graphBase,
|
|
1220
|
+
trailingSlash: graphTrailingSlash
|
|
1175
1221
|
});
|
|
1176
1222
|
assertValidDocs(candidate);
|
|
1177
1223
|
await validatePluginFrontmatter(candidate.entries, options.frontmatterSchema);
|
|
@@ -1236,6 +1282,7 @@ function configuredCookbook(options) {
|
|
|
1236
1282
|
};
|
|
1237
1283
|
siteIconBase = base;
|
|
1238
1284
|
graphBase = base;
|
|
1285
|
+
graphTrailingSlash = context.config.trailingSlash !== "ignore" ? context.config.trailingSlash : context.config.build.format === "directory" ? "always" : "index";
|
|
1239
1286
|
context.config.integrations.push(sitemap({
|
|
1240
1287
|
serialize: (item) => {
|
|
1241
1288
|
if (!graph?.config.locales) return item;
|
|
@@ -1244,7 +1291,7 @@ function configuredCookbook(options) {
|
|
|
1244
1291
|
...item,
|
|
1245
1292
|
links: localeAlternates(route, graph.routes.filter((route) => route.sitemap !== false), graph.config).map(({ lang, route }) => ({
|
|
1246
1293
|
lang,
|
|
1247
|
-
url: new URL(
|
|
1294
|
+
url: new URL(routePath(route, graphBase, graphTrailingSlash), item.url).href
|
|
1248
1295
|
}))
|
|
1249
1296
|
};
|
|
1250
1297
|
},
|
|
@@ -1373,6 +1420,7 @@ function configuredCookbook(options) {
|
|
|
1373
1420
|
}
|
|
1374
1421
|
} : documentedSite(loaded),
|
|
1375
1422
|
base: loaded.config.build.base,
|
|
1423
|
+
trailingSlash: loaded.config.build.trailingSlash,
|
|
1376
1424
|
search: loaded.config.search.enabled || typeof options.config?.components?.overrides?.Search === "string",
|
|
1377
1425
|
logo: siteLogo?.logo,
|
|
1378
1426
|
locales: loaded.config.locales,
|
|
@@ -1410,7 +1458,8 @@ function configuredCookbook(options) {
|
|
|
1410
1458
|
graph = await createDocsGraph({
|
|
1411
1459
|
root: projectRoot,
|
|
1412
1460
|
...graphConfig ? { config: graphConfig } : {},
|
|
1413
|
-
base: graphBase
|
|
1461
|
+
base: graphBase,
|
|
1462
|
+
trailingSlash: graphTrailingSlash
|
|
1414
1463
|
});
|
|
1415
1464
|
assertValidDocs(graph);
|
|
1416
1465
|
context.injectRoute({
|
|
@@ -1607,6 +1656,7 @@ function registerCookbookMarkdownPlugins(processor) {
|
|
|
1607
1656
|
const plugins = Array.isArray(options.rehypePlugins) ? options.rehypePlugins : [];
|
|
1608
1657
|
if (!plugins.includes(rehypeMermaid)) plugins.push(rehypeMermaid);
|
|
1609
1658
|
if (!plugins.includes(rehypeAlerts)) plugins.push(rehypeAlerts);
|
|
1659
|
+
if (!plugins.includes(rehypeTableAlignment)) plugins.push(rehypeTableAlignment);
|
|
1610
1660
|
if (!plugins.includes(rehypeTableScroll)) plugins.push(rehypeTableScroll);
|
|
1611
1661
|
if (!plugins.includes(rehypePageAffordances)) plugins.push(rehypePageAffordances);
|
|
1612
1662
|
options.rehypePlugins = plugins;
|
|
@@ -1615,6 +1665,7 @@ function registerCookbookMarkdownPlugins(processor) {
|
|
|
1615
1665
|
const plugins = Array.isArray(options.hastPlugins) ? options.hastPlugins : [];
|
|
1616
1666
|
if (!plugins.includes(satteriMermaid)) plugins.push(satteriMermaid);
|
|
1617
1667
|
if (!plugins.includes(satteriAlerts)) plugins.push(satteriAlerts);
|
|
1668
|
+
if (!plugins.includes(satteriTableAlignment)) plugins.push(satteriTableAlignment);
|
|
1618
1669
|
if (!plugins.includes(satteriTableScroll)) plugins.push(satteriTableScroll);
|
|
1619
1670
|
if (!plugins.includes(satteriPageAffordances)) plugins.push(satteriPageAffordances);
|
|
1620
1671
|
options.hastPlugins = plugins;
|