@tenphi/renderer 0.22.0 → 0.23.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.
Files changed (81) hide show
  1. package/dist/client/code-copy.js +3 -3
  2. package/dist/client/code-copy.js.map +1 -1
  3. package/dist/client/heading-links.js +4 -4
  4. package/dist/client/heading-links.js.map +1 -1
  5. package/dist/client/navigation.js +3 -3
  6. package/dist/client/navigation.js.map +1 -1
  7. package/dist/client/search.js +1 -1
  8. package/dist/client/search.js.map +1 -1
  9. package/dist/client/table-of-contents.js +2 -2
  10. package/dist/client/table-of-contents.js.map +1 -1
  11. package/dist/components/Card.styles.js +1 -0
  12. package/dist/components/CodeGroup.astro +8 -1
  13. package/dist/components/CodeGroup.styles.js +1 -2
  14. package/dist/components/Document.styles.js +48 -32
  15. package/dist/components/EditLink.astro +1 -1
  16. package/dist/components/Header.styles.js +13 -13
  17. package/dist/components/HeaderLinks.astro +4 -8
  18. package/dist/components/HeaderLinks.styles.js +17 -17
  19. package/dist/components/Hero.styles.js +28 -30
  20. package/dist/components/Icon.astro +3 -3
  21. package/dist/components/LanguageSelect.styles.js +8 -8
  22. package/dist/components/MainContent.styles.js +4 -4
  23. package/dist/components/MainPane.styles.js +1 -1
  24. package/dist/components/MarkdownAlert.styles.js +16 -17
  25. package/dist/components/MarkdownCodeBlock.styles.js +31 -19
  26. package/dist/components/MarkdownContent.styles.js +47 -89
  27. package/dist/components/MarkdownHeading.styles.js +23 -24
  28. package/dist/components/MarkdownInlineCode.styles.js +1 -1
  29. package/dist/components/MarkdownTable.styles.js +5 -5
  30. package/dist/components/Mermaid.styles.js +4 -1
  31. package/dist/components/MermaidSource.styles.js +1 -1
  32. package/dist/components/MobileMenuFooter.styles.js +1 -1
  33. package/dist/components/MobileMenuToggle.styles.js +3 -3
  34. package/dist/components/MobileNavigationTabs.astro +3 -2
  35. package/dist/components/MobileNavigationTabs.styles.js +3 -3
  36. package/dist/components/MobileTableOfContents.styles.js +2 -2
  37. package/dist/components/PackageVersion.styles.js +1 -1
  38. package/dist/components/PageFrame.styles.js +6 -6
  39. package/dist/components/Pagination.astro +2 -2
  40. package/dist/components/Pagination.styles.js +10 -10
  41. package/dist/components/Preview.astro +3 -4
  42. package/dist/components/Preview.styles.js +2 -2
  43. package/dist/components/Search.styles.js +13 -13
  44. package/dist/components/SearchButton.styles.js +10 -10
  45. package/dist/components/SearchResults.styles.js +21 -31
  46. package/dist/components/SelectPopover.astro +6 -6
  47. package/dist/components/Sidebar.styles.js +58 -49
  48. package/dist/components/SidebarList.astro +9 -6
  49. package/dist/components/SiteLogo.astro +2 -2
  50. package/dist/components/SiteLogo.styles.js +4 -4
  51. package/dist/components/SyntaxHighlight.styles.js +69 -48
  52. package/dist/components/TableOfContents.styles.js +1 -1
  53. package/dist/components/TableOfContentsLayout.styles.js +7 -7
  54. package/dist/components/ThemeSelect.styles.js +12 -12
  55. package/dist/components/TopNavigation.styles.js +1 -1
  56. package/dist/components/VersionSwitcher.styles.js +1 -1
  57. package/dist/components/select-popover-styles.js +14 -14
  58. package/dist/components/tasty-states.js +10 -9
  59. package/dist/eslint-plugin.js +6 -9
  60. package/dist/eslint-plugin.js.map +1 -1
  61. package/dist/index.js +14 -11
  62. package/dist/index.js.map +1 -1
  63. package/dist/markdown/rendered-content.js +2 -2
  64. package/dist/markdown/rendered-content.js.map +1 -1
  65. package/dist/overrides/Header.astro +8 -12
  66. package/dist/overrides/Hero.astro +11 -6
  67. package/dist/overrides/MobileMenuFooter.astro +1 -1
  68. package/dist/overrides/MobileMenuToggle.astro +6 -5
  69. package/dist/overrides/PageFrame.astro +4 -3
  70. package/dist/overrides/Search.astro +7 -7
  71. package/dist/overrides/Sidebar.astro +2 -3
  72. package/dist/overrides/ThemeSelect.astro +2 -2
  73. package/dist/routes/Page.astro +11 -8
  74. package/dist/styling.js +1 -1
  75. package/dist/{tasty-states-_JhxFdK1.js → tasty-states-BIgiJQ3N.js} +7 -10
  76. package/dist/tasty-states-BIgiJQ3N.js.map +1 -0
  77. package/dist/theme/shiki-theme.d.ts.map +1 -1
  78. package/dist/theme/shiki-theme.js +37 -19
  79. package/dist/theme/shiki-theme.js.map +1 -1
  80. package/package.json +3 -3
  81. package/dist/tasty-states-_JhxFdK1.js.map +0 -1
@@ -22,17 +22,17 @@ var CookbookCodeBlock = class extends HTMLElement {
22
22
  try {
23
23
  await writeClipboard(code);
24
24
  } catch {
25
- button.dataset.copyState = "error";
25
+ this.dataset.copyState = "error";
26
26
  button.setAttribute("aria-label", message("codeCopyError"));
27
27
  button.title = message("codeCopyError");
28
28
  return;
29
29
  }
30
- button.dataset.copyState = "copied";
30
+ this.dataset.copyState = "copied";
31
31
  button.setAttribute("aria-label", message("codeCopied"));
32
32
  button.title = message("codeCopied");
33
33
  if (this.#resetTimer !== void 0) window.clearTimeout(this.#resetTimer);
34
34
  this.#resetTimer = window.setTimeout(() => {
35
- delete button.dataset.copyState;
35
+ delete this.dataset.copyState;
36
36
  button.setAttribute("aria-label", message("copyCode"));
37
37
  button.title = message("copyCode");
38
38
  this.#resetTimer = void 0;
@@ -1 +1 @@
1
- {"version":3,"file":"code-copy.js","names":[],"sources":["../../src/client/code-copy.ts"],"sourcesContent":["import { message } from \"./messages.js\";\n\nclass CookbookCodeBlock extends HTMLElement {\n #resetTimer: number | undefined;\n\n connectedCallback() {\n const button = this.querySelector<HTMLButtonElement>(\"[data-copy-code]\");\n if (button) {\n button.setAttribute(\"aria-label\", message(\"copyCode\"));\n button.title = message(\"copyCode\");\n }\n this.addEventListener(\"click\", this.#copy);\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"click\", this.#copy);\n if (this.#resetTimer !== undefined) {\n window.clearTimeout(this.#resetTimer);\n }\n }\n\n #copy = async (event: MouseEvent) => {\n const target = event.target;\n const button =\n target instanceof Element\n ? target.closest<HTMLButtonElement>(\"[data-copy-code]\")\n : undefined;\n const code = this.querySelector<HTMLElement>(\"pre code\");\n if (!button || !this.contains(button) || !code) return;\n\n try {\n await writeClipboard(code);\n } catch {\n button.dataset.copyState = \"error\";\n button.setAttribute(\"aria-label\", message(\"codeCopyError\"));\n button.title = message(\"codeCopyError\");\n return;\n }\n\n button.dataset.copyState = \"copied\";\n button.setAttribute(\"aria-label\", message(\"codeCopied\"));\n button.title = message(\"codeCopied\");\n\n if (this.#resetTimer !== undefined) {\n window.clearTimeout(this.#resetTimer);\n }\n this.#resetTimer = window.setTimeout(() => {\n delete button.dataset.copyState;\n button.setAttribute(\"aria-label\", message(\"copyCode\"));\n button.title = message(\"copyCode\");\n this.#resetTimer = undefined;\n }, 2_000);\n };\n}\n\nasync function writeClipboard(code: HTMLElement): Promise<void> {\n const value = code.textContent ?? \"\";\n if (navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(value);\n return;\n }\n\n const selection = window.getSelection();\n const previousRanges = selection\n ? Array.from({ length: selection.rangeCount }, (_, index) =>\n selection.getRangeAt(index),\n )\n : [];\n const range = document.createRange();\n range.selectNodeContents(code);\n selection?.removeAllRanges();\n selection?.addRange(range);\n const copied = document.execCommand(\"copy\");\n selection?.removeAllRanges();\n for (const previousRange of previousRanges)\n selection?.addRange(previousRange);\n if (!copied) throw new Error(\"Clipboard unavailable\");\n}\n\nif (!customElements.get(\"cookbook-code-block\")) {\n customElements.define(\"cookbook-code-block\", CookbookCodeBlock);\n}\n"],"mappings":";;AAEA,IAAM,oBAAN,cAAgC,YAAY;CAC1C;CAEA,oBAAoB;EAClB,MAAM,SAAS,KAAK,cAAiC,kBAAkB;EACvE,IAAI,QAAQ;GACV,OAAO,aAAa,cAAc,QAAQ,UAAU,CAAC;GACrD,OAAO,QAAQ,QAAQ,UAAU;EACnC;EACA,KAAK,iBAAiB,SAAS,KAAK,KAAK;CAC3C;CAEA,uBAAuB;EACrB,KAAK,oBAAoB,SAAS,KAAK,KAAK;EAC5C,IAAI,KAAK,gBAAgB,KAAA,GACvB,OAAO,aAAa,KAAK,WAAW;CAExC;CAEA,QAAQ,OAAO,UAAsB;EACnC,MAAM,SAAS,MAAM;EACrB,MAAM,SACJ,kBAAkB,UACd,OAAO,QAA2B,kBAAkB,IACpD,KAAA;EACN,MAAM,OAAO,KAAK,cAA2B,UAAU;EACvD,IAAI,CAAC,UAAU,CAAC,KAAK,SAAS,MAAM,KAAK,CAAC,MAAM;EAEhD,IAAI;GACF,MAAM,eAAe,IAAI;EAC3B,QAAQ;GACN,OAAO,QAAQ,YAAY;GAC3B,OAAO,aAAa,cAAc,QAAQ,eAAe,CAAC;GAC1D,OAAO,QAAQ,QAAQ,eAAe;GACtC;EACF;EAEA,OAAO,QAAQ,YAAY;EAC3B,OAAO,aAAa,cAAc,QAAQ,YAAY,CAAC;EACvD,OAAO,QAAQ,QAAQ,YAAY;EAEnC,IAAI,KAAK,gBAAgB,KAAA,GACvB,OAAO,aAAa,KAAK,WAAW;EAEtC,KAAK,cAAc,OAAO,iBAAiB;GACzC,OAAO,OAAO,QAAQ;GACtB,OAAO,aAAa,cAAc,QAAQ,UAAU,CAAC;GACrD,OAAO,QAAQ,QAAQ,UAAU;GACjC,KAAK,cAAc,KAAA;EACrB,GAAG,GAAK;CACV;AACF;AAEA,eAAe,eAAe,MAAkC;CAC9D,MAAM,QAAQ,KAAK,eAAe;CAClC,IAAI,UAAU,WAAW,WAAW;EAClC,MAAM,UAAU,UAAU,UAAU,KAAK;EACzC;CACF;CAEA,MAAM,YAAY,OAAO,aAAa;CACtC,MAAM,iBAAiB,YACnB,MAAM,KAAK,EAAE,QAAQ,UAAU,WAAW,IAAI,GAAG,UAC/C,UAAU,WAAW,KAAK,CAC5B,IACA,CAAC;CACL,MAAM,QAAQ,SAAS,YAAY;CACnC,MAAM,mBAAmB,IAAI;CAC7B,WAAW,gBAAgB;CAC3B,WAAW,SAAS,KAAK;CACzB,MAAM,SAAS,SAAS,YAAY,MAAM;CAC1C,WAAW,gBAAgB;CAC3B,KAAK,MAAM,iBAAiB,gBAC1B,WAAW,SAAS,aAAa;CACnC,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,uBAAuB;AACtD;AAEA,IAAI,CAAC,eAAe,IAAI,qBAAqB,GAC3C,eAAe,OAAO,uBAAuB,iBAAiB"}
1
+ {"version":3,"file":"code-copy.js","names":[],"sources":["../../src/client/code-copy.ts"],"sourcesContent":["import { message } from \"./messages.js\";\n\nclass CookbookCodeBlock extends HTMLElement {\n #resetTimer: number | undefined;\n\n connectedCallback() {\n const button = this.querySelector<HTMLButtonElement>(\"[data-copy-code]\");\n if (button) {\n button.setAttribute(\"aria-label\", message(\"copyCode\"));\n button.title = message(\"copyCode\");\n }\n this.addEventListener(\"click\", this.#copy);\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"click\", this.#copy);\n if (this.#resetTimer !== undefined) {\n window.clearTimeout(this.#resetTimer);\n }\n }\n\n #copy = async (event: MouseEvent) => {\n const target = event.target;\n const button =\n target instanceof Element\n ? target.closest<HTMLButtonElement>(\"[data-copy-code]\")\n : undefined;\n const code = this.querySelector<HTMLElement>(\"pre code\");\n if (!button || !this.contains(button) || !code) return;\n\n try {\n await writeClipboard(code);\n } catch {\n this.dataset.copyState = \"error\";\n button.setAttribute(\"aria-label\", message(\"codeCopyError\"));\n button.title = message(\"codeCopyError\");\n return;\n }\n\n this.dataset.copyState = \"copied\";\n button.setAttribute(\"aria-label\", message(\"codeCopied\"));\n button.title = message(\"codeCopied\");\n\n if (this.#resetTimer !== undefined) {\n window.clearTimeout(this.#resetTimer);\n }\n this.#resetTimer = window.setTimeout(() => {\n delete this.dataset.copyState;\n button.setAttribute(\"aria-label\", message(\"copyCode\"));\n button.title = message(\"copyCode\");\n this.#resetTimer = undefined;\n }, 2_000);\n };\n}\n\nasync function writeClipboard(code: HTMLElement): Promise<void> {\n const value = code.textContent ?? \"\";\n if (navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(value);\n return;\n }\n\n const selection = window.getSelection();\n const previousRanges = selection\n ? Array.from({ length: selection.rangeCount }, (_, index) =>\n selection.getRangeAt(index),\n )\n : [];\n const range = document.createRange();\n range.selectNodeContents(code);\n selection?.removeAllRanges();\n selection?.addRange(range);\n const copied = document.execCommand(\"copy\");\n selection?.removeAllRanges();\n for (const previousRange of previousRanges)\n selection?.addRange(previousRange);\n if (!copied) throw new Error(\"Clipboard unavailable\");\n}\n\nif (!customElements.get(\"cookbook-code-block\")) {\n customElements.define(\"cookbook-code-block\", CookbookCodeBlock);\n}\n"],"mappings":";;AAEA,IAAM,oBAAN,cAAgC,YAAY;CAC1C;CAEA,oBAAoB;EAClB,MAAM,SAAS,KAAK,cAAiC,kBAAkB;EACvE,IAAI,QAAQ;GACV,OAAO,aAAa,cAAc,QAAQ,UAAU,CAAC;GACrD,OAAO,QAAQ,QAAQ,UAAU;EACnC;EACA,KAAK,iBAAiB,SAAS,KAAK,KAAK;CAC3C;CAEA,uBAAuB;EACrB,KAAK,oBAAoB,SAAS,KAAK,KAAK;EAC5C,IAAI,KAAK,gBAAgB,KAAA,GACvB,OAAO,aAAa,KAAK,WAAW;CAExC;CAEA,QAAQ,OAAO,UAAsB;EACnC,MAAM,SAAS,MAAM;EACrB,MAAM,SACJ,kBAAkB,UACd,OAAO,QAA2B,kBAAkB,IACpD,KAAA;EACN,MAAM,OAAO,KAAK,cAA2B,UAAU;EACvD,IAAI,CAAC,UAAU,CAAC,KAAK,SAAS,MAAM,KAAK,CAAC,MAAM;EAEhD,IAAI;GACF,MAAM,eAAe,IAAI;EAC3B,QAAQ;GACN,KAAK,QAAQ,YAAY;GACzB,OAAO,aAAa,cAAc,QAAQ,eAAe,CAAC;GAC1D,OAAO,QAAQ,QAAQ,eAAe;GACtC;EACF;EAEA,KAAK,QAAQ,YAAY;EACzB,OAAO,aAAa,cAAc,QAAQ,YAAY,CAAC;EACvD,OAAO,QAAQ,QAAQ,YAAY;EAEnC,IAAI,KAAK,gBAAgB,KAAA,GACvB,OAAO,aAAa,KAAK,WAAW;EAEtC,KAAK,cAAc,OAAO,iBAAiB;GACzC,OAAO,KAAK,QAAQ;GACpB,OAAO,aAAa,cAAc,QAAQ,UAAU,CAAC;GACrD,OAAO,QAAQ,QAAQ,UAAU;GACjC,KAAK,cAAc,KAAA;EACrB,GAAG,GAAK;CACV;AACF;AAEA,eAAe,eAAe,MAAkC;CAC9D,MAAM,QAAQ,KAAK,eAAe;CAClC,IAAI,UAAU,WAAW,WAAW;EAClC,MAAM,UAAU,UAAU,UAAU,KAAK;EACzC;CACF;CAEA,MAAM,YAAY,OAAO,aAAa;CACtC,MAAM,iBAAiB,YACnB,MAAM,KAAK,EAAE,QAAQ,UAAU,WAAW,IAAI,GAAG,UAC/C,UAAU,WAAW,KAAK,CAC5B,IACA,CAAC;CACL,MAAM,QAAQ,SAAS,YAAY;CACnC,MAAM,mBAAmB,IAAI;CAC7B,WAAW,gBAAgB;CAC3B,WAAW,SAAS,KAAK;CACzB,MAAM,SAAS,SAAS,YAAY,MAAM;CAC1C,WAAW,gBAAgB;CAC3B,KAAK,MAAM,iBAAiB,gBAC1B,WAAW,SAAS,aAAa;CACnC,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,uBAAuB;AACtD;AAEA,IAAI,CAAC,eAAe,IAAI,qBAAqB,GAC3C,eAAe,OAAO,uBAAuB,iBAAiB"}
@@ -2,16 +2,16 @@ import { t as message } from "../messages-bS8G9Pj8.js";
2
2
  //#region src/client/heading-links.ts
3
3
  /** Keep real fragment links as the no-JavaScript and modified-click fallback. */
4
4
  function initializeHeadingLinks() {
5
- for (const content of document.querySelectorAll(".cookbook-markdown-content")) {
5
+ for (const content of document.querySelectorAll("[data-element=Markdown]")) {
6
6
  let status = content.querySelector("[data-heading-copy-status]");
7
7
  if (!status) {
8
8
  status = document.createElement("span");
9
- status.className = "sr-only";
9
+ status.dataset.srOnly = "";
10
10
  status.dataset.headingCopyStatus = "";
11
11
  status.setAttribute("role", "status");
12
12
  content.append(status);
13
13
  }
14
- for (const link of content.querySelectorAll(".cookbook-heading-wrapper > .cookbook-anchor-link[href^=\"#\"]")) {
14
+ for (const link of content.querySelectorAll("[data-element=MarkdownHeading] > [data-element=Anchor][href^=\"#\"]")) {
15
15
  if (link.dataset.copyReady) continue;
16
16
  link.dataset.copyReady = "true";
17
17
  const heading = link.previousElementSibling?.textContent?.trim() ?? "section";
@@ -63,7 +63,7 @@ async function copyLink(value) {
63
63
  return;
64
64
  }
65
65
  const input = document.createElement("textarea");
66
- input.className = "sr-only";
66
+ input.dataset.srOnly = "";
67
67
  input.value = value;
68
68
  input.readOnly = true;
69
69
  const focused = document.activeElement;
@@ -1 +1 @@
1
- {"version":3,"file":"heading-links.js","names":["uiMessage","message"],"sources":["../../src/client/heading-links.ts"],"sourcesContent":["import { message as uiMessage } from \"./messages.js\";\n/** Keep real fragment links as the no-JavaScript and modified-click fallback. */\nexport function initializeHeadingLinks(): void {\n for (const content of document.querySelectorAll(\n \".cookbook-markdown-content\",\n )) {\n let status = content.querySelector<HTMLElement>(\n \"[data-heading-copy-status]\",\n );\n if (!status) {\n status = document.createElement(\"span\");\n status.className = \"sr-only\";\n status.dataset.headingCopyStatus = \"\";\n status.setAttribute(\"role\", \"status\");\n content.append(status);\n }\n\n for (const link of content.querySelectorAll<HTMLAnchorElement>(\n '.cookbook-heading-wrapper > .cookbook-anchor-link[href^=\"#\"]',\n )) {\n if (link.dataset.copyReady) continue;\n link.dataset.copyReady = \"true\";\n const heading =\n link.previousElementSibling?.textContent?.trim() ?? \"section\";\n const label = uiMessage(\"copyHeading\").replace(\"{heading}\", heading);\n link.setAttribute(\"role\", \"button\");\n link.setAttribute(\"aria-label\", label);\n link.title = label;\n let timer: number | undefined;\n let attempt = 0;\n\n link.addEventListener(\"keydown\", (event) => {\n if (\n event.key !== \" \" ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n event.shiftKey\n )\n return;\n event.preventDefault();\n if (!event.repeat) link.click();\n });\n link.addEventListener(\"click\", async (event) => {\n if (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n event.shiftKey\n )\n return;\n event.preventDefault();\n window.clearTimeout(timer);\n delete link.dataset.copyState;\n status.textContent = \"\";\n const currentAttempt = ++attempt;\n let message: string;\n let state: string;\n try {\n const url = new URL(link.getAttribute(\"href\")!, window.location.href);\n await copyLink(url.href);\n message = uiMessage(\"linkCopied\");\n state = \"copied\";\n } catch {\n message = uiMessage(\"linkCopyError\");\n state = \"error\";\n }\n if (currentAttempt !== attempt || !link.isConnected) return;\n link.dataset.copyState = state;\n link.setAttribute(\"aria-label\", message);\n link.title = message;\n status.textContent = `${message}: ${heading}`;\n timer = window.setTimeout(() => {\n delete link.dataset.copyState;\n link.setAttribute(\"aria-label\", label);\n link.title = label;\n }, 2_000);\n });\n }\n }\n}\n\nasync function copyLink(value: string): Promise<void> {\n if (navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(value);\n return;\n }\n\n // Older browsers and insecure local previews may not expose Clipboard API.\n const input = document.createElement(\"textarea\");\n input.className = \"sr-only\";\n input.value = value;\n input.readOnly = true;\n const focused = document.activeElement;\n const selection = window.getSelection();\n const ranges = selection\n ? Array.from({ length: selection.rangeCount }, (_, index) =>\n selection.getRangeAt(index),\n )\n : [];\n document.body.append(input);\n try {\n input.focus({ preventScroll: true });\n input.select();\n if (!document.execCommand(\"copy\")) throw new Error(\"Clipboard unavailable\");\n } finally {\n input.remove();\n if (focused instanceof HTMLElement) focused.focus({ preventScroll: true });\n selection?.removeAllRanges();\n for (const range of ranges) selection?.addRange(range);\n }\n}\n"],"mappings":";;;AAEA,SAAgB,yBAA+B;CAC7C,KAAK,MAAM,WAAW,SAAS,iBAC7B,4BACF,GAAG;EACD,IAAI,SAAS,QAAQ,cACnB,4BACF;EACA,IAAI,CAAC,QAAQ;GACX,SAAS,SAAS,cAAc,MAAM;GACtC,OAAO,YAAY;GACnB,OAAO,QAAQ,oBAAoB;GACnC,OAAO,aAAa,QAAQ,QAAQ;GACpC,QAAQ,OAAO,MAAM;EACvB;EAEA,KAAK,MAAM,QAAQ,QAAQ,iBACzB,gEACF,GAAG;GACD,IAAI,KAAK,QAAQ,WAAW;GAC5B,KAAK,QAAQ,YAAY;GACzB,MAAM,UACJ,KAAK,wBAAwB,aAAa,KAAK,KAAK;GACtD,MAAM,QAAQA,QAAU,aAAa,CAAC,CAAC,QAAQ,aAAa,OAAO;GACnE,KAAK,aAAa,QAAQ,QAAQ;GAClC,KAAK,aAAa,cAAc,KAAK;GACrC,KAAK,QAAQ;GACb,IAAI;GACJ,IAAI,UAAU;GAEd,KAAK,iBAAiB,YAAY,UAAU;IAC1C,IACE,MAAM,QAAQ,OACd,MAAM,UACN,MAAM,WACN,MAAM,WACN,MAAM,UAEN;IACF,MAAM,eAAe;IACrB,IAAI,CAAC,MAAM,QAAQ,KAAK,MAAM;GAChC,CAAC;GACD,KAAK,iBAAiB,SAAS,OAAO,UAAU;IAC9C,IACE,MAAM,oBACN,MAAM,WAAW,KACjB,MAAM,UACN,MAAM,WACN,MAAM,WACN,MAAM,UAEN;IACF,MAAM,eAAe;IACrB,OAAO,aAAa,KAAK;IACzB,OAAO,KAAK,QAAQ;IACpB,OAAO,cAAc;IACrB,MAAM,iBAAiB,EAAE;IACzB,IAAIC;IACJ,IAAI;IACJ,IAAI;KAEF,MAAM,SAAS,IADC,IAAI,KAAK,aAAa,MAAM,GAAI,OAAO,SAAS,IAC/C,CAAC,CAAC,IAAI;KACvB,YAAUD,QAAU,YAAY;KAChC,QAAQ;IACV,QAAQ;KACN,YAAUA,QAAU,eAAe;KACnC,QAAQ;IACV;IACA,IAAI,mBAAmB,WAAW,CAAC,KAAK,aAAa;IACrD,KAAK,QAAQ,YAAY;IACzB,KAAK,aAAa,cAAcC,SAAO;IACvC,KAAK,QAAQA;IACb,OAAO,cAAc,GAAGA,UAAQ,IAAI;IACpC,QAAQ,OAAO,iBAAiB;KAC9B,OAAO,KAAK,QAAQ;KACpB,KAAK,aAAa,cAAc,KAAK;KACrC,KAAK,QAAQ;IACf,GAAG,GAAK;GACV,CAAC;EACH;CACF;AACF;AAEA,eAAe,SAAS,OAA8B;CACpD,IAAI,UAAU,WAAW,WAAW;EAClC,MAAM,UAAU,UAAU,UAAU,KAAK;EACzC;CACF;CAGA,MAAM,QAAQ,SAAS,cAAc,UAAU;CAC/C,MAAM,YAAY;CAClB,MAAM,QAAQ;CACd,MAAM,WAAW;CACjB,MAAM,UAAU,SAAS;CACzB,MAAM,YAAY,OAAO,aAAa;CACtC,MAAM,SAAS,YACX,MAAM,KAAK,EAAE,QAAQ,UAAU,WAAW,IAAI,GAAG,UAC/C,UAAU,WAAW,KAAK,CAC5B,IACA,CAAC;CACL,SAAS,KAAK,OAAO,KAAK;CAC1B,IAAI;EACF,MAAM,MAAM,EAAE,eAAe,KAAK,CAAC;EACnC,MAAM,OAAO;EACb,IAAI,CAAC,SAAS,YAAY,MAAM,GAAG,MAAM,IAAI,MAAM,uBAAuB;CAC5E,UAAU;EACR,MAAM,OAAO;EACb,IAAI,mBAAmB,aAAa,QAAQ,MAAM,EAAE,eAAe,KAAK,CAAC;EACzE,WAAW,gBAAgB;EAC3B,KAAK,MAAM,SAAS,QAAQ,WAAW,SAAS,KAAK;CACvD;AACF"}
1
+ {"version":3,"file":"heading-links.js","names":["uiMessage","message"],"sources":["../../src/client/heading-links.ts"],"sourcesContent":["import { message as uiMessage } from \"./messages.js\";\n/** Keep real fragment links as the no-JavaScript and modified-click fallback. */\nexport function initializeHeadingLinks(): void {\n for (const content of document.querySelectorAll(\"[data-element=Markdown]\")) {\n let status = content.querySelector<HTMLElement>(\n \"[data-heading-copy-status]\",\n );\n if (!status) {\n status = document.createElement(\"span\");\n status.dataset.srOnly = \"\";\n status.dataset.headingCopyStatus = \"\";\n status.setAttribute(\"role\", \"status\");\n content.append(status);\n }\n\n for (const link of content.querySelectorAll<HTMLAnchorElement>(\n '[data-element=MarkdownHeading] > [data-element=Anchor][href^=\"#\"]',\n )) {\n if (link.dataset.copyReady) continue;\n link.dataset.copyReady = \"true\";\n const heading =\n link.previousElementSibling?.textContent?.trim() ?? \"section\";\n const label = uiMessage(\"copyHeading\").replace(\"{heading}\", heading);\n link.setAttribute(\"role\", \"button\");\n link.setAttribute(\"aria-label\", label);\n link.title = label;\n let timer: number | undefined;\n let attempt = 0;\n\n link.addEventListener(\"keydown\", (event) => {\n if (\n event.key !== \" \" ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n event.shiftKey\n )\n return;\n event.preventDefault();\n if (!event.repeat) link.click();\n });\n link.addEventListener(\"click\", async (event) => {\n if (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n event.shiftKey\n )\n return;\n event.preventDefault();\n window.clearTimeout(timer);\n delete link.dataset.copyState;\n status.textContent = \"\";\n const currentAttempt = ++attempt;\n let message: string;\n let state: string;\n try {\n const url = new URL(link.getAttribute(\"href\")!, window.location.href);\n await copyLink(url.href);\n message = uiMessage(\"linkCopied\");\n state = \"copied\";\n } catch {\n message = uiMessage(\"linkCopyError\");\n state = \"error\";\n }\n if (currentAttempt !== attempt || !link.isConnected) return;\n link.dataset.copyState = state;\n link.setAttribute(\"aria-label\", message);\n link.title = message;\n status.textContent = `${message}: ${heading}`;\n timer = window.setTimeout(() => {\n delete link.dataset.copyState;\n link.setAttribute(\"aria-label\", label);\n link.title = label;\n }, 2_000);\n });\n }\n }\n}\n\nasync function copyLink(value: string): Promise<void> {\n if (navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(value);\n return;\n }\n\n // Older browsers and insecure local previews may not expose Clipboard API.\n const input = document.createElement(\"textarea\");\n input.dataset.srOnly = \"\";\n input.value = value;\n input.readOnly = true;\n const focused = document.activeElement;\n const selection = window.getSelection();\n const ranges = selection\n ? Array.from({ length: selection.rangeCount }, (_, index) =>\n selection.getRangeAt(index),\n )\n : [];\n document.body.append(input);\n try {\n input.focus({ preventScroll: true });\n input.select();\n if (!document.execCommand(\"copy\")) throw new Error(\"Clipboard unavailable\");\n } finally {\n input.remove();\n if (focused instanceof HTMLElement) focused.focus({ preventScroll: true });\n selection?.removeAllRanges();\n for (const range of ranges) selection?.addRange(range);\n }\n}\n"],"mappings":";;;AAEA,SAAgB,yBAA+B;CAC7C,KAAK,MAAM,WAAW,SAAS,iBAAiB,yBAAyB,GAAG;EAC1E,IAAI,SAAS,QAAQ,cACnB,4BACF;EACA,IAAI,CAAC,QAAQ;GACX,SAAS,SAAS,cAAc,MAAM;GACtC,OAAO,QAAQ,SAAS;GACxB,OAAO,QAAQ,oBAAoB;GACnC,OAAO,aAAa,QAAQ,QAAQ;GACpC,QAAQ,OAAO,MAAM;EACvB;EAEA,KAAK,MAAM,QAAQ,QAAQ,iBACzB,qEACF,GAAG;GACD,IAAI,KAAK,QAAQ,WAAW;GAC5B,KAAK,QAAQ,YAAY;GACzB,MAAM,UACJ,KAAK,wBAAwB,aAAa,KAAK,KAAK;GACtD,MAAM,QAAQA,QAAU,aAAa,CAAC,CAAC,QAAQ,aAAa,OAAO;GACnE,KAAK,aAAa,QAAQ,QAAQ;GAClC,KAAK,aAAa,cAAc,KAAK;GACrC,KAAK,QAAQ;GACb,IAAI;GACJ,IAAI,UAAU;GAEd,KAAK,iBAAiB,YAAY,UAAU;IAC1C,IACE,MAAM,QAAQ,OACd,MAAM,UACN,MAAM,WACN,MAAM,WACN,MAAM,UAEN;IACF,MAAM,eAAe;IACrB,IAAI,CAAC,MAAM,QAAQ,KAAK,MAAM;GAChC,CAAC;GACD,KAAK,iBAAiB,SAAS,OAAO,UAAU;IAC9C,IACE,MAAM,oBACN,MAAM,WAAW,KACjB,MAAM,UACN,MAAM,WACN,MAAM,WACN,MAAM,UAEN;IACF,MAAM,eAAe;IACrB,OAAO,aAAa,KAAK;IACzB,OAAO,KAAK,QAAQ;IACpB,OAAO,cAAc;IACrB,MAAM,iBAAiB,EAAE;IACzB,IAAIC;IACJ,IAAI;IACJ,IAAI;KAEF,MAAM,SAAS,IADC,IAAI,KAAK,aAAa,MAAM,GAAI,OAAO,SAAS,IAC/C,CAAC,CAAC,IAAI;KACvB,YAAUD,QAAU,YAAY;KAChC,QAAQ;IACV,QAAQ;KACN,YAAUA,QAAU,eAAe;KACnC,QAAQ;IACV;IACA,IAAI,mBAAmB,WAAW,CAAC,KAAK,aAAa;IACrD,KAAK,QAAQ,YAAY;IACzB,KAAK,aAAa,cAAcC,SAAO;IACvC,KAAK,QAAQA;IACb,OAAO,cAAc,GAAGA,UAAQ,IAAI;IACpC,QAAQ,OAAO,iBAAiB;KAC9B,OAAO,KAAK,QAAQ;KACpB,KAAK,aAAa,cAAc,KAAK;KACrC,KAAK,QAAQ;IACf,GAAG,GAAK;GACV,CAAC;EACH;CACF;AACF;AAEA,eAAe,SAAS,OAA8B;CACpD,IAAI,UAAU,WAAW,WAAW;EAClC,MAAM,UAAU,UAAU,UAAU,KAAK;EACzC;CACF;CAGA,MAAM,QAAQ,SAAS,cAAc,UAAU;CAC/C,MAAM,QAAQ,SAAS;CACvB,MAAM,QAAQ;CACd,MAAM,WAAW;CACjB,MAAM,UAAU,SAAS;CACzB,MAAM,YAAY,OAAO,aAAa;CACtC,MAAM,SAAS,YACX,MAAM,KAAK,EAAE,QAAQ,UAAU,WAAW,IAAI,GAAG,UAC/C,UAAU,WAAW,KAAK,CAC5B,IACA,CAAC;CACL,SAAS,KAAK,OAAO,KAAK;CAC1B,IAAI;EACF,MAAM,MAAM,EAAE,eAAe,KAAK,CAAC;EACnC,MAAM,OAAO;EACb,IAAI,CAAC,SAAS,YAAY,MAAM,GAAG,MAAM,IAAI,MAAM,uBAAuB;CAC5E,UAAU;EACR,MAAM,OAAO;EACb,IAAI,mBAAmB,aAAa,QAAQ,MAAM,EAAE,eAAe,KAAK,CAAC;EACzE,WAAW,gBAAgB;EAC3B,KAAK,MAAM,SAAS,QAAQ,WAAW,SAAS,KAAK;CACvD;AACF"}
@@ -8,7 +8,7 @@ var CookbookSidebarPane = class extends HTMLElement {
8
8
  this.#listeners?.abort();
9
9
  this.#listeners = new AbortController();
10
10
  const { signal } = this.#listeners;
11
- this.#trigger = document.querySelector(".td-menu-button[popovertarget=\"cookbook__sidebar\"]") ?? void 0;
11
+ this.#trigger = document.querySelector("[data-element=MobileMenuToggle][popovertarget=\"cookbook__sidebar\"]") ?? void 0;
12
12
  const desktop = matchMedia("(min-width: 50rem)");
13
13
  const syncViewport = () => {
14
14
  if (desktop.matches) {
@@ -31,7 +31,7 @@ var CookbookSidebarPane = class extends HTMLElement {
31
31
  if (open) {
32
32
  this.getBoundingClientRect();
33
33
  this.setAttribute("data-open", "");
34
- for (const element of document.querySelectorAll(".header, .main-frame, .cookbook-skip-link")) {
34
+ for (const element of document.querySelectorAll("[data-element=HeaderFrame], [data-element=MainFrame], [data-element=SkipLink]")) {
35
35
  this.#inert.set(element, element.inert);
36
36
  element.inert = true;
37
37
  }
@@ -44,7 +44,7 @@ var CookbookSidebarPane = class extends HTMLElement {
44
44
  }, { signal });
45
45
  this.addEventListener("keydown", (event) => {
46
46
  if (desktop.matches || !this.matches(":popover-open")) return;
47
- const sections = this.querySelector(".td-mobile-tabs details[open]");
47
+ const sections = this.querySelector("[data-element=MobileNavigationTabs] details[open]");
48
48
  if (event.key === "Escape" && sections) {
49
49
  event.preventDefault();
50
50
  sections.open = false;
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.js","names":[],"sources":["../../src/client/navigation.ts"],"sourcesContent":["import { initializePopoverMotion } from \"./popover-motion.js\";\n\nclass CookbookSidebarPane extends HTMLElement {\n #listeners?: AbortController;\n #inert = new Map<HTMLElement, boolean>();\n #trigger: HTMLButtonElement | undefined;\n\n connectedCallback() {\n this.#listeners?.abort();\n this.#listeners = new AbortController();\n const { signal } = this.#listeners;\n this.#trigger =\n document.querySelector<HTMLButtonElement>(\n '.td-menu-button[popovertarget=\"cookbook__sidebar\"]',\n ) ?? undefined;\n const desktop = matchMedia(\"(min-width: 50rem)\");\n const syncViewport = () => {\n if (desktop.matches) {\n if (this.matches(\":popover-open\")) this.hidePopover();\n this.#release();\n this.popover = null;\n this.removeAttribute(\"role\");\n this.removeAttribute(\"aria-modal\");\n } else {\n this.popover = \"auto\";\n this.setAttribute(\"role\", \"dialog\");\n this.setAttribute(\"aria-modal\", \"true\");\n }\n };\n syncViewport();\n desktop.addEventListener(\"change\", syncViewport, { signal });\n this.addEventListener(\n \"toggle\",\n () => {\n const open = !desktop.matches && this.matches(\":popover-open\");\n this.#trigger?.setAttribute(\"aria-expanded\", String(open));\n if (open) {\n // Establish the closed position after the popover enters the top\n // layer so its attribute change transitions from an actual layout.\n // Tasty's global SSR renderer does not preserve @starting-style.\n this.getBoundingClientRect();\n this.setAttribute(\"data-open\", \"\");\n for (const element of document.querySelectorAll<HTMLElement>(\n \".header, .main-frame, .cookbook-skip-link\",\n )) {\n this.#inert.set(element, element.inert);\n element.inert = true;\n }\n this.querySelector<HTMLElement>(\"[autofocus]\")?.focus({\n preventScroll: true,\n });\n } else {\n const restoreFocus =\n this.contains(document.activeElement) ||\n document.activeElement === document.body;\n this.#release();\n if (restoreFocus && !desktop.matches) this.#trigger?.focus();\n }\n },\n { signal },\n );\n this.addEventListener(\n \"keydown\",\n (event) => {\n if (desktop.matches || !this.matches(\":popover-open\")) return;\n const sections = this.querySelector<HTMLDetailsElement>(\n \".td-mobile-tabs details[open]\",\n );\n if (event.key === \"Escape\" && sections) {\n event.preventDefault();\n sections.open = false;\n sections.querySelector(\"summary\")?.focus();\n return;\n }\n if (event.key !== \"Tab\") return;\n const focusable = Array.from(\n this.querySelectorAll<HTMLElement>(\n 'a[href], button:not([disabled]), select:not([disabled]), input:not([disabled]), summary, [tabindex=\"0\"]',\n ),\n ).filter(\n (element) =>\n element.tabIndex >= 0 && element.getClientRects().length > 0,\n );\n const first = focusable[0];\n const last = focusable.at(-1);\n if (!first || !last) {\n event.preventDefault();\n this.focus();\n return;\n }\n if (\n event.shiftKey &&\n (document.activeElement === first || document.activeElement === this)\n ) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n },\n { signal },\n );\n this.addEventListener(\n \"click\",\n (event) => {\n if (\n !event.defaultPrevented &&\n event.target instanceof Element &&\n event.target.closest(\"a[href]\") &&\n this.matches(\":popover-open\")\n )\n this.hidePopover();\n },\n { signal },\n );\n }\n\n #release() {\n this.removeAttribute(\"data-open\");\n for (const [element, inert] of this.#inert) element.inert = inert;\n this.#inert.clear();\n this.#trigger?.setAttribute(\"aria-expanded\", \"false\");\n }\n\n disconnectedCallback() {\n this.#listeners?.abort();\n this.#release();\n }\n}\n\nclass CookbookHeaderLinks extends HTMLElement {\n #listeners?: AbortController;\n connectedCallback() {\n this.#listeners?.abort();\n this.#listeners = new AbortController();\n const { signal } = this.#listeners;\n const panel = this.querySelector<HTMLElement>(\"[popover]\");\n const desktop = matchMedia(\"(min-width: 50rem)\");\n const close = () => {\n if (panel?.matches(\":popover-open\")) panel.hidePopover();\n };\n if (panel) initializePopoverMotion(panel, signal);\n desktop.addEventListener(\n \"change\",\n () => {\n if (desktop.matches) close();\n },\n { signal },\n );\n panel?.addEventListener(\n \"click\",\n (event) => {\n if (event.target instanceof Element && event.target.closest(\"a[href]\"))\n close();\n },\n { signal },\n );\n }\n disconnectedCallback() {\n this.#listeners?.abort();\n }\n}\n\nif (!customElements.get(\"cookbook-sidebar-pane\"))\n customElements.define(\"cookbook-sidebar-pane\", CookbookSidebarPane);\nif (!customElements.get(\"cookbook-header-links\"))\n customElements.define(\"cookbook-header-links\", CookbookHeaderLinks);\n"],"mappings":"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"}
1
+ {"version":3,"file":"navigation.js","names":[],"sources":["../../src/client/navigation.ts"],"sourcesContent":["import { initializePopoverMotion } from \"./popover-motion.js\";\n\nclass CookbookSidebarPane extends HTMLElement {\n #listeners?: AbortController;\n #inert = new Map<HTMLElement, boolean>();\n #trigger: HTMLButtonElement | undefined;\n\n connectedCallback() {\n this.#listeners?.abort();\n this.#listeners = new AbortController();\n const { signal } = this.#listeners;\n this.#trigger =\n document.querySelector<HTMLButtonElement>(\n '[data-element=MobileMenuToggle][popovertarget=\"cookbook__sidebar\"]',\n ) ?? undefined;\n const desktop = matchMedia(\"(min-width: 50rem)\");\n const syncViewport = () => {\n if (desktop.matches) {\n if (this.matches(\":popover-open\")) this.hidePopover();\n this.#release();\n this.popover = null;\n this.removeAttribute(\"role\");\n this.removeAttribute(\"aria-modal\");\n } else {\n this.popover = \"auto\";\n this.setAttribute(\"role\", \"dialog\");\n this.setAttribute(\"aria-modal\", \"true\");\n }\n };\n syncViewport();\n desktop.addEventListener(\"change\", syncViewport, { signal });\n this.addEventListener(\n \"toggle\",\n () => {\n const open = !desktop.matches && this.matches(\":popover-open\");\n this.#trigger?.setAttribute(\"aria-expanded\", String(open));\n if (open) {\n // Establish the closed position after the popover enters the top\n // layer so its attribute change transitions from an actual layout.\n // Tasty's global SSR renderer does not preserve @starting-style.\n this.getBoundingClientRect();\n this.setAttribute(\"data-open\", \"\");\n for (const element of document.querySelectorAll<HTMLElement>(\n \"[data-element=HeaderFrame], [data-element=MainFrame], [data-element=SkipLink]\",\n )) {\n this.#inert.set(element, element.inert);\n element.inert = true;\n }\n this.querySelector<HTMLElement>(\"[autofocus]\")?.focus({\n preventScroll: true,\n });\n } else {\n const restoreFocus =\n this.contains(document.activeElement) ||\n document.activeElement === document.body;\n this.#release();\n if (restoreFocus && !desktop.matches) this.#trigger?.focus();\n }\n },\n { signal },\n );\n this.addEventListener(\n \"keydown\",\n (event) => {\n if (desktop.matches || !this.matches(\":popover-open\")) return;\n const sections = this.querySelector<HTMLDetailsElement>(\n \"[data-element=MobileNavigationTabs] details[open]\",\n );\n if (event.key === \"Escape\" && sections) {\n event.preventDefault();\n sections.open = false;\n sections.querySelector(\"summary\")?.focus();\n return;\n }\n if (event.key !== \"Tab\") return;\n const focusable = Array.from(\n this.querySelectorAll<HTMLElement>(\n 'a[href], button:not([disabled]), select:not([disabled]), input:not([disabled]), summary, [tabindex=\"0\"]',\n ),\n ).filter(\n (element) =>\n element.tabIndex >= 0 && element.getClientRects().length > 0,\n );\n const first = focusable[0];\n const last = focusable.at(-1);\n if (!first || !last) {\n event.preventDefault();\n this.focus();\n return;\n }\n if (\n event.shiftKey &&\n (document.activeElement === first || document.activeElement === this)\n ) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n },\n { signal },\n );\n this.addEventListener(\n \"click\",\n (event) => {\n if (\n !event.defaultPrevented &&\n event.target instanceof Element &&\n event.target.closest(\"a[href]\") &&\n this.matches(\":popover-open\")\n )\n this.hidePopover();\n },\n { signal },\n );\n }\n\n #release() {\n this.removeAttribute(\"data-open\");\n for (const [element, inert] of this.#inert) element.inert = inert;\n this.#inert.clear();\n this.#trigger?.setAttribute(\"aria-expanded\", \"false\");\n }\n\n disconnectedCallback() {\n this.#listeners?.abort();\n this.#release();\n }\n}\n\nclass CookbookHeaderLinks extends HTMLElement {\n #listeners?: AbortController;\n connectedCallback() {\n this.#listeners?.abort();\n this.#listeners = new AbortController();\n const { signal } = this.#listeners;\n const panel = this.querySelector<HTMLElement>(\"[popover]\");\n const desktop = matchMedia(\"(min-width: 50rem)\");\n const close = () => {\n if (panel?.matches(\":popover-open\")) panel.hidePopover();\n };\n if (panel) initializePopoverMotion(panel, signal);\n desktop.addEventListener(\n \"change\",\n () => {\n if (desktop.matches) close();\n },\n { signal },\n );\n panel?.addEventListener(\n \"click\",\n (event) => {\n if (event.target instanceof Element && event.target.closest(\"a[href]\"))\n close();\n },\n { signal },\n );\n }\n disconnectedCallback() {\n this.#listeners?.abort();\n }\n}\n\nif (!customElements.get(\"cookbook-sidebar-pane\"))\n customElements.define(\"cookbook-sidebar-pane\", CookbookSidebarPane);\nif (!customElements.get(\"cookbook-header-links\"))\n customElements.define(\"cookbook-header-links\", CookbookHeaderLinks);\n"],"mappings":"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"}
@@ -6,7 +6,7 @@ function initializeSearch(element, options, development, base) {
6
6
  const open = element.querySelector("[data-open-modal]");
7
7
  const close = element.querySelector("[data-close-modal]");
8
8
  const dialog = element.querySelector("dialog");
9
- const frame = element.querySelector(".dialog-frame");
9
+ const frame = element.querySelector("[data-element=Frame]");
10
10
  const status = element.querySelector("[data-search-status]");
11
11
  const input = element.querySelector("[data-search-input]");
12
12
  const clear = element.querySelector("[data-clear-search]");
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","names":[],"sources":["../../src/client/search.ts"],"sourcesContent":["type SearchResult = { url: string; sub_results?: SearchResult[] };\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 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(\".dialog-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 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 window.addEventListener(\"keydown\", (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}\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[] };\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 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 window.addEventListener(\"keydown\", (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}\n"],"mappings":"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"}
@@ -33,7 +33,7 @@ var CookbookTableOfContents = class extends HTMLElement {
33
33
  };
34
34
  #sync = () => {
35
35
  this.#frame = 0;
36
- const marker = (document.querySelector(".header")?.getBoundingClientRect().bottom ?? 0) + 24;
36
+ const marker = (document.querySelector("[data-element=HeaderFrame]")?.getBoundingClientRect().bottom ?? 0) + 24;
37
37
  let current = this.#entries[0];
38
38
  for (const entry of this.#entries) {
39
39
  if (entry.heading.getBoundingClientRect().top > marker + 2) break;
@@ -44,7 +44,7 @@ var CookbookTableOfContents = class extends HTMLElement {
44
44
  this.#active?.removeAttribute("aria-current");
45
45
  current.link.setAttribute("aria-current", "location");
46
46
  this.#active = current.link;
47
- const sidebar = this.closest(".right-sidebar");
47
+ const sidebar = this.closest("[data-element=Content]");
48
48
  if (!sidebar || sidebar.getClientRects().length === 0) return;
49
49
  const sidebarRect = sidebar.getBoundingClientRect();
50
50
  const linkRect = current.link.getBoundingClientRect();
@@ -1 +1 @@
1
- {"version":3,"file":"table-of-contents.js","names":[],"sources":["../../src/client/table-of-contents.ts"],"sourcesContent":["class CookbookTableOfContents extends HTMLElement {\n #entries: Array<{ link: HTMLAnchorElement; heading: HTMLElement }> = [];\n #active?: HTMLAnchorElement;\n #listeners?: AbortController;\n #frame = 0;\n\n connectedCallback() {\n this.#listeners?.abort();\n this.#listeners = new AbortController();\n this.#entries = Array.from(\n this.querySelectorAll<HTMLAnchorElement>('nav a[href^=\"#\"]'),\n ).flatMap((link) => {\n const heading = document.getElementById(\n decodeURIComponent(link.hash.slice(1)),\n );\n return heading ? [{ link, heading }] : [];\n });\n if (this.#entries.length === 0) return;\n\n const options = { signal: this.#listeners.signal };\n window.addEventListener(\"scroll\", this.#schedule, {\n ...options,\n passive: true,\n });\n window.addEventListener(\"resize\", this.#schedule, options);\n window.addEventListener(\"hashchange\", this.#schedule, options);\n this.#schedule();\n }\n\n disconnectedCallback() {\n this.#listeners?.abort();\n cancelAnimationFrame(this.#frame);\n }\n\n #schedule = () => {\n if (!this.#frame) this.#frame = requestAnimationFrame(this.#sync);\n };\n\n #sync = () => {\n this.#frame = 0;\n const header = document.querySelector<HTMLElement>(\".header\");\n const marker = (header?.getBoundingClientRect().bottom ?? 0) + 24;\n let current = this.#entries[0];\n for (const entry of this.#entries) {\n if (entry.heading.getBoundingClientRect().top > marker + 2) break;\n current = entry;\n }\n if (\n window.scrollY > 0 &&\n window.scrollY + window.innerHeight >=\n document.documentElement.scrollHeight - 2\n )\n current = this.#entries.at(-1);\n if (!current || current.link === this.#active) return;\n\n this.#active?.removeAttribute(\"aria-current\");\n current.link.setAttribute(\"aria-current\", \"location\");\n this.#active = current.link;\n\n const sidebar = this.closest<HTMLElement>(\".right-sidebar\");\n if (!sidebar || sidebar.getClientRects().length === 0) return;\n const sidebarRect = sidebar.getBoundingClientRect();\n const linkRect = current.link.getBoundingClientRect();\n if (linkRect.top < sidebarRect.top + 16)\n sidebar.scrollTop += linkRect.top - sidebarRect.top - 16;\n else if (linkRect.bottom > sidebarRect.bottom - 16)\n sidebar.scrollTop += linkRect.bottom - sidebarRect.bottom + 16;\n };\n}\n\nif (!customElements.get(\"cookbook-table-of-contents\"))\n customElements.define(\"cookbook-table-of-contents\", CookbookTableOfContents);\n"],"mappings":";AAAA,IAAM,0BAAN,cAAsC,YAAY;CAChD,WAAqE,CAAC;CACtE;CACA;CACA,SAAS;CAET,oBAAoB;EAClB,KAAK,YAAY,MAAM;EACvB,KAAK,aAAa,IAAI,gBAAgB;EACtC,KAAK,WAAW,MAAM,KACpB,KAAK,iBAAoC,oBAAkB,CAC7D,CAAC,CAAC,SAAS,SAAS;GAClB,MAAM,UAAU,SAAS,eACvB,mBAAmB,KAAK,KAAK,MAAM,CAAC,CAAC,CACvC;GACA,OAAO,UAAU,CAAC;IAAE;IAAM;GAAQ,CAAC,IAAI,CAAC;EAC1C,CAAC;EACD,IAAI,KAAK,SAAS,WAAW,GAAG;EAEhC,MAAM,UAAU,EAAE,QAAQ,KAAK,WAAW,OAAO;EACjD,OAAO,iBAAiB,UAAU,KAAK,WAAW;GAChD,GAAG;GACH,SAAS;EACX,CAAC;EACD,OAAO,iBAAiB,UAAU,KAAK,WAAW,OAAO;EACzD,OAAO,iBAAiB,cAAc,KAAK,WAAW,OAAO;EAC7D,KAAK,UAAU;CACjB;CAEA,uBAAuB;EACrB,KAAK,YAAY,MAAM;EACvB,qBAAqB,KAAK,MAAM;CAClC;CAEA,kBAAkB;EAChB,IAAI,CAAC,KAAK,QAAQ,KAAK,SAAS,sBAAsB,KAAK,KAAK;CAClE;CAEA,cAAc;EACZ,KAAK,SAAS;EAEd,MAAM,UADS,SAAS,cAA2B,SAC9B,CAAC,EAAE,sBAAsB,CAAC,CAAC,UAAU,KAAK;EAC/D,IAAI,UAAU,KAAK,SAAS;EAC5B,KAAK,MAAM,SAAS,KAAK,UAAU;GACjC,IAAI,MAAM,QAAQ,sBAAsB,CAAC,CAAC,MAAM,SAAS,GAAG;GAC5D,UAAU;EACZ;EACA,IACE,OAAO,UAAU,KACjB,OAAO,UAAU,OAAO,eACtB,SAAS,gBAAgB,eAAe,GAE1C,UAAU,KAAK,SAAS,GAAG,EAAE;EAC/B,IAAI,CAAC,WAAW,QAAQ,SAAS,KAAK,SAAS;EAE/C,KAAK,SAAS,gBAAgB,cAAc;EAC5C,QAAQ,KAAK,aAAa,gBAAgB,UAAU;EACpD,KAAK,UAAU,QAAQ;EAEvB,MAAM,UAAU,KAAK,QAAqB,gBAAgB;EAC1D,IAAI,CAAC,WAAW,QAAQ,eAAe,CAAC,CAAC,WAAW,GAAG;EACvD,MAAM,cAAc,QAAQ,sBAAsB;EAClD,MAAM,WAAW,QAAQ,KAAK,sBAAsB;EACpD,IAAI,SAAS,MAAM,YAAY,MAAM,IACnC,QAAQ,aAAa,SAAS,MAAM,YAAY,MAAM;OACnD,IAAI,SAAS,SAAS,YAAY,SAAS,IAC9C,QAAQ,aAAa,SAAS,SAAS,YAAY,SAAS;CAChE;AACF;AAEA,IAAI,CAAC,eAAe,IAAI,4BAA4B,GAClD,eAAe,OAAO,8BAA8B,uBAAuB"}
1
+ {"version":3,"file":"table-of-contents.js","names":[],"sources":["../../src/client/table-of-contents.ts"],"sourcesContent":["class CookbookTableOfContents extends HTMLElement {\n #entries: Array<{ link: HTMLAnchorElement; heading: HTMLElement }> = [];\n #active?: HTMLAnchorElement;\n #listeners?: AbortController;\n #frame = 0;\n\n connectedCallback() {\n this.#listeners?.abort();\n this.#listeners = new AbortController();\n this.#entries = Array.from(\n this.querySelectorAll<HTMLAnchorElement>('nav a[href^=\"#\"]'),\n ).flatMap((link) => {\n const heading = document.getElementById(\n decodeURIComponent(link.hash.slice(1)),\n );\n return heading ? [{ link, heading }] : [];\n });\n if (this.#entries.length === 0) return;\n\n const options = { signal: this.#listeners.signal };\n window.addEventListener(\"scroll\", this.#schedule, {\n ...options,\n passive: true,\n });\n window.addEventListener(\"resize\", this.#schedule, options);\n window.addEventListener(\"hashchange\", this.#schedule, options);\n this.#schedule();\n }\n\n disconnectedCallback() {\n this.#listeners?.abort();\n cancelAnimationFrame(this.#frame);\n }\n\n #schedule = () => {\n if (!this.#frame) this.#frame = requestAnimationFrame(this.#sync);\n };\n\n #sync = () => {\n this.#frame = 0;\n const header = document.querySelector<HTMLElement>(\n \"[data-element=HeaderFrame]\",\n );\n const marker = (header?.getBoundingClientRect().bottom ?? 0) + 24;\n let current = this.#entries[0];\n for (const entry of this.#entries) {\n if (entry.heading.getBoundingClientRect().top > marker + 2) break;\n current = entry;\n }\n if (\n window.scrollY > 0 &&\n window.scrollY + window.innerHeight >=\n document.documentElement.scrollHeight - 2\n )\n current = this.#entries.at(-1);\n if (!current || current.link === this.#active) return;\n\n this.#active?.removeAttribute(\"aria-current\");\n current.link.setAttribute(\"aria-current\", \"location\");\n this.#active = current.link;\n\n const sidebar = this.closest<HTMLElement>(\"[data-element=Content]\");\n if (!sidebar || sidebar.getClientRects().length === 0) return;\n const sidebarRect = sidebar.getBoundingClientRect();\n const linkRect = current.link.getBoundingClientRect();\n if (linkRect.top < sidebarRect.top + 16)\n sidebar.scrollTop += linkRect.top - sidebarRect.top - 16;\n else if (linkRect.bottom > sidebarRect.bottom - 16)\n sidebar.scrollTop += linkRect.bottom - sidebarRect.bottom + 16;\n };\n}\n\nif (!customElements.get(\"cookbook-table-of-contents\"))\n customElements.define(\"cookbook-table-of-contents\", CookbookTableOfContents);\n"],"mappings":";AAAA,IAAM,0BAAN,cAAsC,YAAY;CAChD,WAAqE,CAAC;CACtE;CACA;CACA,SAAS;CAET,oBAAoB;EAClB,KAAK,YAAY,MAAM;EACvB,KAAK,aAAa,IAAI,gBAAgB;EACtC,KAAK,WAAW,MAAM,KACpB,KAAK,iBAAoC,oBAAkB,CAC7D,CAAC,CAAC,SAAS,SAAS;GAClB,MAAM,UAAU,SAAS,eACvB,mBAAmB,KAAK,KAAK,MAAM,CAAC,CAAC,CACvC;GACA,OAAO,UAAU,CAAC;IAAE;IAAM;GAAQ,CAAC,IAAI,CAAC;EAC1C,CAAC;EACD,IAAI,KAAK,SAAS,WAAW,GAAG;EAEhC,MAAM,UAAU,EAAE,QAAQ,KAAK,WAAW,OAAO;EACjD,OAAO,iBAAiB,UAAU,KAAK,WAAW;GAChD,GAAG;GACH,SAAS;EACX,CAAC;EACD,OAAO,iBAAiB,UAAU,KAAK,WAAW,OAAO;EACzD,OAAO,iBAAiB,cAAc,KAAK,WAAW,OAAO;EAC7D,KAAK,UAAU;CACjB;CAEA,uBAAuB;EACrB,KAAK,YAAY,MAAM;EACvB,qBAAqB,KAAK,MAAM;CAClC;CAEA,kBAAkB;EAChB,IAAI,CAAC,KAAK,QAAQ,KAAK,SAAS,sBAAsB,KAAK,KAAK;CAClE;CAEA,cAAc;EACZ,KAAK,SAAS;EAId,MAAM,UAHS,SAAS,cACtB,4BAEmB,CAAC,EAAE,sBAAsB,CAAC,CAAC,UAAU,KAAK;EAC/D,IAAI,UAAU,KAAK,SAAS;EAC5B,KAAK,MAAM,SAAS,KAAK,UAAU;GACjC,IAAI,MAAM,QAAQ,sBAAsB,CAAC,CAAC,MAAM,SAAS,GAAG;GAC5D,UAAU;EACZ;EACA,IACE,OAAO,UAAU,KACjB,OAAO,UAAU,OAAO,eACtB,SAAS,gBAAgB,eAAe,GAE1C,UAAU,KAAK,SAAS,GAAG,EAAE;EAC/B,IAAI,CAAC,WAAW,QAAQ,SAAS,KAAK,SAAS;EAE/C,KAAK,SAAS,gBAAgB,cAAc;EAC5C,QAAQ,KAAK,aAAa,gBAAgB,UAAU;EACpD,KAAK,UAAU,QAAQ;EAEvB,MAAM,UAAU,KAAK,QAAqB,wBAAwB;EAClE,IAAI,CAAC,WAAW,QAAQ,eAAe,CAAC,CAAC,WAAW,GAAG;EACvD,MAAM,cAAc,QAAQ,sBAAsB;EAClD,MAAM,WAAW,QAAQ,KAAK,sBAAsB;EACpD,IAAI,SAAS,MAAM,YAAY,MAAM,IACnC,QAAQ,aAAa,SAAS,MAAM,YAAY,MAAM;OACnD,IAAI,SAAS,SAAS,YAAY,SAAS,IAC9C,QAAQ,aAAa,SAAS,SAAS,YAAY,SAAS;CAChE;AACF;AAEA,IAAI,CAAC,eAAe,IAAI,4BAA4B,GAClD,eAAe,OAAO,8BAA8B,uBAAuB"}
@@ -7,6 +7,7 @@ configureCookbookStates();
7
7
  export const CardRoot = defineComponent("Card", {
8
8
  as: "article",
9
9
  "data-element": "Card",
10
+ "data-block": "",
10
11
  styles: {
11
12
  display: "grid",
12
13
  gap: "1.5x",
@@ -24,10 +24,17 @@ const highlight = codeGroupHighlighting();
24
24
  <cookbook-code-block
25
25
  class="td-code-block"
26
26
  data-element="MarkdownCodeBlock"
27
+ data-diff={
28
+ item.language === "diff" || item.language === "patch"
29
+ ? ""
30
+ : undefined
31
+ }
27
32
  >
28
33
  <Code
29
34
  code={item.code}
30
- lang={item.language ?? "text"}
35
+ lang={
36
+ item.language === "patch" ? "diff" : (item.language ?? "text")
37
+ }
31
38
  theme={highlight.theme}
32
39
  transformers={highlight.transformers}
33
40
  embeddedLangs={highlight.langs}
@@ -15,10 +15,9 @@ export const CodeGroupRoot = defineComponent("CodeGroup", {
15
15
  blockMargin: "$margin-block-start $margin-block-end",
16
16
  inlineMargin: "0",
17
17
  },
18
- Pre: { $: "pre" },
18
+ Pre: { $: "pre", preset: "code" },
19
19
  Code: {
20
20
  $: "pre code",
21
- preset: "code",
22
21
  color: "#syntax-text",
23
22
  whiteSpace: "pre",
24
23
  },
@@ -29,7 +29,7 @@ export default function DocumentStyles() {
29
29
  resolveComponentStyles("Layout", {
30
30
  overflow: {
31
31
  "": null,
32
- ":has(#cookbook__sidebar:popover-open) & @mobile": "hidden",
32
+ ":has(#cookbook__sidebar:popover-open) & !@md": "hidden",
33
33
  },
34
34
  colorScheme: {
35
35
  "": "dark",
@@ -38,21 +38,21 @@ export default function DocumentStyles() {
38
38
  },
39
39
  "$docs-nav-height": {
40
40
  "": "4.5rem",
41
- ":has(.td-top-tabs)": "7.25rem",
42
- "@mobile": "3.5rem",
43
- "@mobile & [data-has-sidebar]": "6.5rem",
41
+ ":has(TopNavigation)": "7.25rem",
42
+ "!@md": "3.5rem",
43
+ "!@md & [data-has-sidebar]": "6.5rem",
44
44
  },
45
45
  "$docs-nav-pad-x": {
46
46
  "": "clamp(1.25rem, 2.5vw, 2rem)",
47
- "@mobile": "1rem",
47
+ "!@md": "1rem",
48
48
  },
49
- "$docs-nav-gap": { "": "0.75rem", "@mobile": "0.5rem" },
49
+ "$docs-nav-gap": { "": "0.75rem", "!@md": "0.5rem" },
50
50
  "$docs-sidebar-pad-x": "1.5rem",
51
51
  "$docs-content-pad-x": {
52
- "": "clamp(1.5rem, 4vw, 4rem)",
53
- "@mobile": "1rem",
52
+ "": "clamp(1.5rem, calc((100% - $content-width) / 2), 4rem)",
53
+ "!@md": "1rem",
54
54
  },
55
- "$docs-menu-button-size": { "": "2.5rem", "@mobile": "2.25rem" },
55
+ "$docs-menu-button-size": { "": "2.5rem", "!@md": "2.25rem" },
56
56
  "$docs-mobile-toc-height": "0rem",
57
57
  Islands: {
58
58
  $: "astro-island, astro-slot, astro-static-slot",
@@ -144,46 +144,62 @@ export default function DocumentStyles() {
144
144
  },
145
145
  },
146
146
  Hidden: {
147
- $: ":where(*), :where(.cookbook-hidden)",
147
+ $: ":where(*)",
148
148
  hide: {
149
149
  "": null,
150
- "@own([hidden] | .cookbook-hidden)": true,
150
+ "@own([hidden] | hidden)": true,
151
151
  },
152
152
  },
153
153
  PrintHidden: {
154
- $: ".cookbook-print-hidden",
155
- display: { "@media:print": "none" },
154
+ $: "*",
155
+ display: { "": null, "@own(print-hidden) & @media:print": "none" },
156
156
  },
157
157
  DesktopBlock: {
158
- $: ":is(.md\\:cookbook-block)",
159
- display: { "": "block", "@mobile": "none" },
158
+ $: "*",
159
+ display: {
160
+ "": null,
161
+ "@own(desktop-block)": "block",
162
+ "@own(desktop-block) & !@md": "none",
163
+ },
160
164
  },
161
165
  DesktopFlex: {
162
- $: ":is(.md\\:cookbook-flex)",
163
- display: { "": "flex", "@mobile": "none" },
166
+ $: "*",
167
+ display: {
168
+ "": null,
169
+ "@own(desktop-flex)": "flex",
170
+ "@own(desktop-flex) & !@md": "none",
171
+ },
164
172
  },
165
173
  ScreenReaderOnly: {
166
- $: ".sr-only",
167
- "$visually-hidden-size": "1px",
168
- position: "absolute",
169
- inlineSize: "$visually-hidden-size",
170
- blockSize: "$visually-hidden-size",
171
- padding: "0",
172
- margin: "($visually-hidden-size * -1)",
173
- overflow: "hidden",
174
- clip: "rect(0, 0, 0, 0)",
175
- whiteSpace: "nowrap",
176
- border: "0",
174
+ $: "*",
175
+ "$visually-hidden-size": { "": null, "@own(sr-only)": "1px" },
176
+ position: { "": null, "@own(sr-only)": "absolute" },
177
+ inlineSize: { "": null, "@own(sr-only)": "$visually-hidden-size" },
178
+ blockSize: { "": null, "@own(sr-only)": "$visually-hidden-size" },
179
+ padding: { "": null, "@own(sr-only)": "0" },
180
+ margin: { "": null, "@own(sr-only)": "($visually-hidden-size * -1)" },
181
+ overflow: { "": null, "@own(sr-only)": "hidden" },
182
+ clip: { "": null, "@own(sr-only)": "rect(0, 0, 0, 0)" },
183
+ whiteSpace: { "": null, "@own(sr-only)": "nowrap" },
184
+ border: { "": null, "@own(sr-only)": "0" },
177
185
  },
178
186
  Strong: { $: ":where(strong), :where(b)", preset: "strong" },
179
187
  Link: { $: "a", color: "#accent-text" },
180
188
  NarrowBlock: {
181
- $: ":is(.lg\\:cookbook-hidden)",
182
- display: { "": "none", "@narrow-layout": "block" },
189
+ $: "*",
190
+ display: {
191
+ "": null,
192
+ "@own(narrow)": "none",
193
+ "@own(narrow) & !@lg": "block",
194
+ },
183
195
  },
184
196
  MobileBlock: {
185
- $: ":is(.md\\:cookbook-hidden)",
186
- display: { "": "none", "@mobile": "block" },
197
+ $: "*",
198
+ display: {
199
+ "": null,
200
+ "@own(mobile)": "none",
201
+ "@own(mobile) & !@md": "block",
202
+ },
187
203
  },
188
204
  Code: {
189
205
  $: ":where(code), :where(kbd), :where(samp), :where(pre)",
@@ -4,7 +4,7 @@ const { editUrl } = Astro.locals.cookbookRoute;
4
4
 
5
5
  {
6
6
  editUrl && (
7
- <a data-element="MetaLink" href={editUrl} class="cookbook-print-hidden">
7
+ <a data-element="MetaLink" href={editUrl} data-print-hidden="">
8
8
  {Astro.locals.t("page.editLink")}
9
9
  </a>
10
10
  )
@@ -16,8 +16,8 @@ export const HeaderRoot = defineComponent("Header", {
16
16
  Primary: {
17
17
  display: "flex",
18
18
  alignItems: "center",
19
- gap: { "": "clamp(0.5rem, 1.5vw, 1.5rem)", "@mobile": "0.5rem" },
20
- blockSize: { "": "4.5rem", "@mobile": "3.5rem" },
19
+ gap: { "": "clamp(0.5rem, 1.5vw, 1.5rem)", "!@md": "0.5rem" },
20
+ blockSize: { "": "4.5rem", "!@md": "3.5rem" },
21
21
  flexShrink: "0",
22
22
  },
23
23
  Title: {
@@ -28,7 +28,7 @@ export const HeaderRoot = defineComponent("Header", {
28
28
  overflow: "hidden",
29
29
  flexShrink: "1",
30
30
  inlineSize: "min 0",
31
- inlineMargin: { "": "0 end", "@mobile": "auto end" },
31
+ inlineMargin: { "": "0 end", "!@md": "auto end" },
32
32
  },
33
33
  LogoLink: {
34
34
  display: "inline-grid",
@@ -38,14 +38,14 @@ export const HeaderRoot = defineComponent("Header", {
38
38
  textDecoration: "none",
39
39
  },
40
40
  Logo: {
41
- inlineSize: { "": "2rem", "@mobile": "1.75rem" },
42
- blockSize: { "": "2rem", "@mobile": "1.75rem" },
41
+ inlineSize: { "": "2rem", "!@md": "1.75rem" },
42
+ blockSize: { "": "2rem", "!@md": "1.75rem" },
43
43
  },
44
44
  SiteTitle: {
45
45
  inlineSize: "min 0",
46
46
  overflow: "hidden",
47
47
  color: "#text",
48
- preset: { "": "h4", "@mobile": "h5" },
48
+ preset: { "": "h4", "!@md": "h5" },
49
49
  textDecoration: "none",
50
50
  whiteSpace: "nowrap",
51
51
  textOverflow: "ellipsis",
@@ -54,10 +54,10 @@ export const HeaderRoot = defineComponent("Header", {
54
54
  $: "Primary > Search",
55
55
  display: "flex",
56
56
  alignItems: "center",
57
- flexGrow: { "": "1", "@mobile": "0" },
58
- flexShrink: { "": "1", "@mobile": "0" },
59
- inlineSize: { "": "min 0", "@mobile": "$docs-menu-button-size" },
60
- inlineMargin: { "": "auto", "@mobile": "0" },
57
+ flexGrow: { "": "1", "!@md": "0" },
58
+ flexShrink: { "": "1", "!@md": "0" },
59
+ inlineSize: { "": "min 0", "!@md": "$docs-menu-button-size" },
60
+ inlineMargin: { "": "auto", "!@md": "0" },
61
61
  },
62
62
  SearchElement: {
63
63
  $: "Search site-search",
@@ -66,7 +66,7 @@ export const HeaderRoot = defineComponent("Header", {
66
66
  },
67
67
  Tools: {
68
68
  display: "flex",
69
- hide: { "": false, "@mobile": true },
69
+ hide: { "": false, "!@md": true },
70
70
  flow: "row",
71
71
  alignItems: "center",
72
72
  justifyContent: "flex-end",
@@ -78,7 +78,7 @@ export const HeaderRoot = defineComponent("Header", {
78
78
  },
79
79
  MobileTheme: {
80
80
  display: "grid",
81
- hide: { "": true, "@mobile": false },
81
+ hide: { "": true, "!@md": false },
82
82
  flexShrink: "0",
83
83
  order: "1",
84
84
  inlineSize: "$docs-menu-button-size",
@@ -86,7 +86,7 @@ export const HeaderRoot = defineComponent("Header", {
86
86
  },
87
87
  MobileLanguage: {
88
88
  display: "grid",
89
- hide: { "": true, "@mobile": false },
89
+ hide: { "": true, "!@md": false },
90
90
  flexShrink: "0",
91
91
  order: "1",
92
92
  inlineSize: "$docs-menu-button-size",
@@ -23,7 +23,7 @@ const ui = messages(Astro.locals.cookbookRoute?.lang ?? "en", content);
23
23
  {
24
24
  links.length > 0 && (
25
25
  <HeaderLinksRoot>
26
- <nav class="td-header-links__desktop" aria-label={ui.headerLinks}>
26
+ <nav data-element="Desktop" aria-label={ui.headerLinks}>
27
27
  {links.map((link) => (
28
28
  <a
29
29
  href={href(link.link)}
@@ -37,7 +37,7 @@ const ui = messages(Astro.locals.cookbookRoute?.lang ?? "en", content);
37
37
  </nav>
38
38
  <button
39
39
  type="button"
40
- class="td-header-links__trigger"
40
+ data-element="Trigger"
41
41
  popovertarget="cookbook-header-links"
42
42
  aria-label={ui.more}
43
43
  title={ui.more}
@@ -56,14 +56,10 @@ const ui = messages(Astro.locals.cookbookRoute?.lang ?? "en", content);
56
56
  </>
57
57
  </svg>
58
58
  </button>
59
- <div
60
- id="cookbook-header-links"
61
- popover="auto"
62
- class="td-header-links__panel"
63
- >
59
+ <div id="cookbook-header-links" popover="auto" data-element="Panel">
64
60
  <button
65
61
  type="button"
66
- class="td-header-links__close"
62
+ data-element="Close"
67
63
  popovertarget="cookbook-header-links"
68
64
  popovertargetaction="hide"
69
65
  aria-label={ui.closeMore}