@tenphi/renderer 0.24.0 → 0.25.1
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/client-navigation.js +9 -0
- package/dist/client/client-navigation.js.map +1 -1
- package/dist/client/prefetch-focus.d.ts +9 -0
- package/dist/client/prefetch-focus.d.ts.map +1 -0
- package/dist/client/prefetch-focus.js +26 -0
- package/dist/client/prefetch-focus.js.map +1 -0
- 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 +72 -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
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
//#region src/client/client-navigation.ts
|
|
2
|
+
let pageLoadNotified = false;
|
|
3
|
+
document.addEventListener("astro:page-load", () => {
|
|
4
|
+
pageLoadNotified = true;
|
|
5
|
+
}, { once: true });
|
|
6
|
+
window.addEventListener("load", () => {
|
|
7
|
+
window.setTimeout(() => {
|
|
8
|
+
if (!pageLoadNotified) document.dispatchEvent(new Event("astro:page-load"));
|
|
9
|
+
}, 0);
|
|
10
|
+
}, { once: true });
|
|
2
11
|
let router;
|
|
3
12
|
function loadRouter() {
|
|
4
13
|
return router ??= import("./navigation-router.js").catch((error) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-navigation.js","names":[],"sources":["../../src/client/client-navigation.ts"],"sourcesContent":["// Use Astro's public router without ClientRouter's vendor stylesheet. Cookbook\n// owns link interception and extracted accessibility styles; Astro owns fetch,\n// stylesheet readiness, script execution, history, and route announcements.\nlet router: Promise<typeof import(\"./navigation-router.js\")> | undefined;\nfunction loadRouter() {\n return (router ??= import(\"./navigation-router.js\").catch(\n (error: unknown) => {\n router = undefined;\n throw error;\n },\n ));\n}\n\nfunction navigationLink(target: EventTarget | undefined) {\n const link = target instanceof Element ? target.closest(\"a[href]\") : null;\n if (\n !(link instanceof HTMLAnchorElement) ||\n link.hasAttribute(\"download\") ||\n link.hasAttribute(\"data-astro-reload\") ||\n (link.target && link.target !== \"_self\")\n )\n return;\n const url = new URL(link.href);\n if (\n url.origin !== location.origin ||\n (!router &&\n url.pathname === location.pathname &&\n url.search === location.search &&\n url.hash)\n )\n return;\n // Heading links stay native until a page-navigation intent loads the router.\n return link;\n}\n\n// Download the router on navigation intent, rather than for every reader.\nfor (const name of [\"pointerover\", \"focusin\"]) {\n document.addEventListener(name, (event) => {\n if (navigationLink(event.composedPath()[0]))\n void loadRouter().catch(() => {\n // A later click can retry; native navigation remains the fallback.\n });\n });\n}\n\ndocument.addEventListener(\"click\", (event) => {\n if (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey\n )\n return;\n const link = navigationLink(event.composedPath()[0]);\n if (!link) return;\n event.preventDefault();\n void loadRouter()\n .then(({ navigate }) =>\n navigate(link.href, {\n sourceElement: link,\n history: link.dataset.astroHistory === \"replace\" ? \"replace\" : \"auto\",\n }),\n )\n .catch(() => location.assign(link.href));\n});\n"],"mappings":";
|
|
1
|
+
{"version":3,"file":"client-navigation.js","names":[],"sources":["../../src/client/client-navigation.ts"],"sourcesContent":["// Use Astro's public router without ClientRouter's vendor stylesheet. Cookbook\n// owns link interception and extracted accessibility styles; Astro owns fetch,\n// stylesheet readiness, script execution, history, and route announcements.\n// Prefetch expects an initial page-load event before later route swaps. When\n// the router is still lazy, supply it after all native load listeners finish.\nlet pageLoadNotified = false;\ndocument.addEventListener(\n \"astro:page-load\",\n () => {\n pageLoadNotified = true;\n },\n { once: true },\n);\nwindow.addEventListener(\n \"load\",\n () => {\n window.setTimeout(() => {\n if (!pageLoadNotified)\n document.dispatchEvent(new Event(\"astro:page-load\"));\n }, 0);\n },\n { once: true },\n);\n\nlet router: Promise<typeof import(\"./navigation-router.js\")> | undefined;\nfunction loadRouter() {\n return (router ??= import(\"./navigation-router.js\").catch(\n (error: unknown) => {\n router = undefined;\n throw error;\n },\n ));\n}\n\nfunction navigationLink(target: EventTarget | undefined) {\n const link = target instanceof Element ? target.closest(\"a[href]\") : null;\n if (\n !(link instanceof HTMLAnchorElement) ||\n link.hasAttribute(\"download\") ||\n link.hasAttribute(\"data-astro-reload\") ||\n (link.target && link.target !== \"_self\")\n )\n return;\n const url = new URL(link.href);\n if (\n url.origin !== location.origin ||\n (!router &&\n url.pathname === location.pathname &&\n url.search === location.search &&\n url.hash)\n )\n return;\n // Heading links stay native until a page-navigation intent loads the router.\n return link;\n}\n\n// Download the router on navigation intent, rather than for every reader.\nfor (const name of [\"pointerover\", \"focusin\"]) {\n document.addEventListener(name, (event) => {\n if (navigationLink(event.composedPath()[0]))\n void loadRouter().catch(() => {\n // A later click can retry; native navigation remains the fallback.\n });\n });\n}\n\ndocument.addEventListener(\"click\", (event) => {\n if (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey\n )\n return;\n const link = navigationLink(event.composedPath()[0]);\n if (!link) return;\n event.preventDefault();\n void loadRouter()\n .then(({ navigate }) =>\n navigate(link.href, {\n sourceElement: link,\n history: link.dataset.astroHistory === \"replace\" ? \"replace\" : \"auto\",\n }),\n )\n .catch(() => location.assign(link.href));\n});\n"],"mappings":";AAKA,IAAI,mBAAmB;AACvB,SAAS,iBACP,yBACM;CACJ,mBAAmB;AACrB,GACA,EAAE,MAAM,KAAK,CACf;AACA,OAAO,iBACL,cACM;CACJ,OAAO,iBAAiB;EACtB,IAAI,CAAC,kBACH,SAAS,cAAc,IAAI,MAAM,iBAAiB,CAAC;CACvD,GAAG,CAAC;AACN,GACA,EAAE,MAAM,KAAK,CACf;AAEA,IAAI;AACJ,SAAS,aAAa;CACpB,OAAQ,WAAW,OAAO,yBAAyB,CAAC,OACjD,UAAmB;EAClB,SAAS,KAAA;EACT,MAAM;CACR,CACF;AACF;AAEA,SAAS,eAAe,QAAiC;CACvD,MAAM,OAAO,kBAAkB,UAAU,OAAO,QAAQ,SAAS,IAAI;CACrE,IACE,EAAE,gBAAgB,sBAClB,KAAK,aAAa,UAAU,KAC5B,KAAK,aAAa,mBAAmB,KACpC,KAAK,UAAU,KAAK,WAAW,SAEhC;CACF,MAAM,MAAM,IAAI,IAAI,KAAK,IAAI;CAC7B,IACE,IAAI,WAAW,SAAS,UACvB,CAAC,UACA,IAAI,aAAa,SAAS,YAC1B,IAAI,WAAW,SAAS,UACxB,IAAI,MAEN;CAEF,OAAO;AACT;AAGA,KAAK,MAAM,QAAQ,CAAC,eAAe,SAAS,GAC1C,SAAS,iBAAiB,OAAO,UAAU;CACzC,IAAI,eAAe,MAAM,aAAa,CAAC,CAAC,EAAE,GACxC,WAAgB,CAAC,CAAC,YAAY,CAE9B,CAAC;AACL,CAAC;AAGH,SAAS,iBAAiB,UAAU,UAAU;CAC5C,IACE,MAAM,oBACN,MAAM,WAAW,KACjB,MAAM,WACN,MAAM,WACN,MAAM,YACN,MAAM,QAEN;CACF,MAAM,OAAO,eAAe,MAAM,aAAa,CAAC,CAAC,EAAE;CACnD,IAAI,CAAC,MAAM;CACX,MAAM,eAAe;CACrB,WAAgB,CAAC,CACd,MAAM,EAAE,eACP,SAAS,KAAK,MAAM;EAClB,eAAe;EACf,SAAS,KAAK,QAAQ,iBAAiB,YAAY,YAAY;CACjE,CAAC,CACH,CAAC,CACA,YAAY,SAAS,OAAO,KAAK,IAAI,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/client/prefetch-focus.d.ts
|
|
2
|
+
/** Keep Astro's hover strategy working for keyboard focus after body swaps. */
|
|
3
|
+
declare function initializePrefetchFocus(options: {
|
|
4
|
+
prefetchAll?: boolean;
|
|
5
|
+
defaultStrategy?: string;
|
|
6
|
+
}): void;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { initializePrefetchFocus };
|
|
9
|
+
//# sourceMappingURL=prefetch-focus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefetch-focus.d.ts","names":[],"sources":["../../src/client/prefetch-focus.ts"],"mappings":";;iBAGgB,wBAAwB;EACtC;EACA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { prefetch } from "astro:prefetch";
|
|
2
|
+
//#region src/client/prefetch-focus.ts
|
|
3
|
+
/** Keep Astro's hover strategy working for keyboard focus after body swaps. */
|
|
4
|
+
function initializePrefetchFocus(options) {
|
|
5
|
+
let swapped = false;
|
|
6
|
+
document.addEventListener("astro:after-swap", () => {
|
|
7
|
+
swapped = true;
|
|
8
|
+
}, { once: true });
|
|
9
|
+
let timeout;
|
|
10
|
+
document.addEventListener("focusin", (event) => {
|
|
11
|
+
if (!swapped) return;
|
|
12
|
+
const link = event.target instanceof Element ? event.target.closest("a") : null;
|
|
13
|
+
if (!(link instanceof HTMLAnchorElement)) return;
|
|
14
|
+
const strategy = link.dataset.astroPrefetch;
|
|
15
|
+
if (!(strategy === "hover" || (strategy === "" || strategy === void 0 && options.prefetchAll) && (options.defaultStrategy ?? "hover") === "hover")) return;
|
|
16
|
+
window.clearTimeout(timeout);
|
|
17
|
+
timeout = window.setTimeout(() => {
|
|
18
|
+
if (link.isConnected) prefetch(link.href);
|
|
19
|
+
}, 80);
|
|
20
|
+
});
|
|
21
|
+
document.addEventListener("focusout", () => window.clearTimeout(timeout));
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { initializePrefetchFocus };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=prefetch-focus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefetch-focus.js","names":[],"sources":["../../src/client/prefetch-focus.ts"],"sourcesContent":["import { prefetch } from \"astro:prefetch\";\n\n/** Keep Astro's hover strategy working for keyboard focus after body swaps. */\nexport function initializePrefetchFocus(options: {\n prefetchAll?: boolean;\n defaultStrategy?: string;\n}): void {\n // Astro 7.3 binds focus listeners to the initial body. Its page-load refresh\n // handles mouse listeners on new anchors, but does not rebind keyboard focus.\n // Use the public prefetch API only after swaps; Astro still owns\n // requests, cache reuse, deduplication, and connection checks.\n let swapped = false;\n document.addEventListener(\n \"astro:after-swap\",\n () => {\n swapped = true;\n },\n { once: true },\n );\n let timeout: number | undefined;\n document.addEventListener(\"focusin\", (event) => {\n if (!swapped) return;\n const link =\n event.target instanceof Element ? event.target.closest(\"a\") : null;\n if (!(link instanceof HTMLAnchorElement)) return;\n const strategy = link.dataset.astroPrefetch;\n const hover =\n strategy === \"hover\" ||\n ((strategy === \"\" || (strategy === undefined && options.prefetchAll)) &&\n (options.defaultStrategy ?? \"hover\") === \"hover\");\n if (!hover) return;\n window.clearTimeout(timeout);\n timeout = window.setTimeout(() => {\n if (link.isConnected) prefetch(link.href);\n }, 80);\n });\n document.addEventListener(\"focusout\", () => window.clearTimeout(timeout));\n}\n"],"mappings":";;;AAGA,SAAgB,wBAAwB,SAG/B;CAKP,IAAI,UAAU;CACd,SAAS,iBACP,0BACM;EACJ,UAAU;CACZ,GACA,EAAE,MAAM,KAAK,CACf;CACA,IAAI;CACJ,SAAS,iBAAiB,YAAY,UAAU;EAC9C,IAAI,CAAC,SAAS;EACd,MAAM,OACJ,MAAM,kBAAkB,UAAU,MAAM,OAAO,QAAQ,GAAG,IAAI;EAChE,IAAI,EAAE,gBAAgB,oBAAoB;EAC1C,MAAM,WAAW,KAAK,QAAQ;EAK9B,IAAI,EAHF,aAAa,YACX,aAAa,MAAO,aAAa,KAAA,KAAa,QAAQ,iBACrD,QAAQ,mBAAmB,aAAa,UACjC;EACZ,OAAO,aAAa,OAAO;EAC3B,UAAU,OAAO,iBAAiB;GAChC,IAAI,KAAK,aAAa,SAAS,KAAK,IAAI;EAC1C,GAAG,EAAE;CACP,CAAC;CACD,SAAS,iBAAiB,kBAAkB,OAAO,aAAa,OAAO,CAAC;AAC1E"}
|
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
|
},
|
|
@@ -1273,9 +1320,18 @@ function configuredCookbook(options) {
|
|
|
1273
1320
|
srcDir: context.config.srcDir
|
|
1274
1321
|
};
|
|
1275
1322
|
let markdownRenderer;
|
|
1323
|
+
const prefetch = context.config.prefetch ?? {
|
|
1324
|
+
prefetchAll: true,
|
|
1325
|
+
defaultStrategy: "hover"
|
|
1326
|
+
};
|
|
1327
|
+
if (prefetch !== false) {
|
|
1328
|
+
const focusScript = fileURLToPath(new URL("./client/prefetch-focus.js", import.meta.url));
|
|
1329
|
+
context.injectScript("page", `import { initializePrefetchFocus } from ${JSON.stringify(focusScript)}; initializePrefetchFocus(${JSON.stringify(typeof prefetch === "object" ? prefetch : {})});`);
|
|
1330
|
+
}
|
|
1276
1331
|
context.updateConfig({
|
|
1277
1332
|
...configuredSite && !context.config.site ? { site: configuredSite } : {},
|
|
1278
1333
|
base,
|
|
1334
|
+
prefetch,
|
|
1279
1335
|
markdown: {
|
|
1280
1336
|
syntaxHighlight: "shiki",
|
|
1281
1337
|
shikiConfig: cookbookShikiConfig(context.config.markdown.shikiConfig)
|
|
@@ -1364,6 +1420,7 @@ function configuredCookbook(options) {
|
|
|
1364
1420
|
}
|
|
1365
1421
|
} : documentedSite(loaded),
|
|
1366
1422
|
base: loaded.config.build.base,
|
|
1423
|
+
trailingSlash: loaded.config.build.trailingSlash,
|
|
1367
1424
|
search: loaded.config.search.enabled || typeof options.config?.components?.overrides?.Search === "string",
|
|
1368
1425
|
logo: siteLogo?.logo,
|
|
1369
1426
|
locales: loaded.config.locales,
|
|
@@ -1401,7 +1458,8 @@ function configuredCookbook(options) {
|
|
|
1401
1458
|
graph = await createDocsGraph({
|
|
1402
1459
|
root: projectRoot,
|
|
1403
1460
|
...graphConfig ? { config: graphConfig } : {},
|
|
1404
|
-
base: graphBase
|
|
1461
|
+
base: graphBase,
|
|
1462
|
+
trailingSlash: graphTrailingSlash
|
|
1405
1463
|
});
|
|
1406
1464
|
assertValidDocs(graph);
|
|
1407
1465
|
context.injectRoute({
|
|
@@ -1598,6 +1656,7 @@ function registerCookbookMarkdownPlugins(processor) {
|
|
|
1598
1656
|
const plugins = Array.isArray(options.rehypePlugins) ? options.rehypePlugins : [];
|
|
1599
1657
|
if (!plugins.includes(rehypeMermaid)) plugins.push(rehypeMermaid);
|
|
1600
1658
|
if (!plugins.includes(rehypeAlerts)) plugins.push(rehypeAlerts);
|
|
1659
|
+
if (!plugins.includes(rehypeTableAlignment)) plugins.push(rehypeTableAlignment);
|
|
1601
1660
|
if (!plugins.includes(rehypeTableScroll)) plugins.push(rehypeTableScroll);
|
|
1602
1661
|
if (!plugins.includes(rehypePageAffordances)) plugins.push(rehypePageAffordances);
|
|
1603
1662
|
options.rehypePlugins = plugins;
|
|
@@ -1606,6 +1665,7 @@ function registerCookbookMarkdownPlugins(processor) {
|
|
|
1606
1665
|
const plugins = Array.isArray(options.hastPlugins) ? options.hastPlugins : [];
|
|
1607
1666
|
if (!plugins.includes(satteriMermaid)) plugins.push(satteriMermaid);
|
|
1608
1667
|
if (!plugins.includes(satteriAlerts)) plugins.push(satteriAlerts);
|
|
1668
|
+
if (!plugins.includes(satteriTableAlignment)) plugins.push(satteriTableAlignment);
|
|
1609
1669
|
if (!plugins.includes(satteriTableScroll)) plugins.push(satteriTableScroll);
|
|
1610
1670
|
if (!plugins.includes(satteriPageAffordances)) plugins.push(satteriPageAffordances);
|
|
1611
1671
|
options.hastPlugins = plugins;
|