@artooi/ag-ui-web-component 0.32.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -60,6 +60,10 @@ var ICON_STOP = `<svg class="glyph glyph--solid" viewBox="0 0 24 24" aria-hidden
60
60
  var ICON_ATTACH = `<svg class="glyph" viewBox="0 0 24 24" aria-hidden="true"><path d="M17 8.5V15a5 5 0 0 1-10 0V7a3 3 0 0 1 6 0v7.5a1 1 0 0 1-2 0V8.5"/></svg>`;
61
61
  var ICON_VOICE = `<svg class="glyph" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 4a3 3 0 0 1 3 3v5a3 3 0 0 1-6 0V7a3 3 0 0 1 3-3z"/><path d="M5 11v1a7 7 0 0 0 14 0v-1"/><path d="M12 19v3"/></svg>`;
62
62
  var ICON_LAUNCHER = `<svg class="glyph" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5.5A2.5 2.5 0 0 1 6.5 3h11A2.5 2.5 0 0 1 20 5.5v8a2.5 2.5 0 0 1-2.5 2.5H9l-5 4z"/></svg>`;
63
+ var ICON_COPY = `<svg class="glyph" viewBox="0 0 24 24" aria-hidden="true"><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V6a2 2 0 0 1 2-2h8"/></svg>`;
64
+ var ICON_RETRY = `<svg class="glyph" viewBox="0 0 24 24" aria-hidden="true"><path d="M20 12a8 8 0 1 1-2.5-5.8"/><path d="M20 4v4h-4"/></svg>`;
65
+ var ICON_THUMB_UP = `<svg class="glyph" viewBox="0 0 24 24" aria-hidden="true"><path d="M7 10v10H4V10z"/><path d="M7 10l4.5-7a2 2 0 0 1 3.4 2L13.5 9H19a2 2 0 0 1 2 2.3l-1.1 6.4A2 2 0 0 1 17.9 20H7"/></svg>`;
66
+ var ICON_THUMB_DOWN = `<svg class="glyph" viewBox="0 0 24 24" aria-hidden="true"><path d="M17 14V4h3v10z"/><path d="M17 14l-4.5 7a2 2 0 0 1-3.4-2l1.4-4H5a2 2 0 0 1-2-2.3l1.1-6.4A2 2 0 0 1 6.1 4H17"/></svg>`;
63
67
  var ICON_FILE = `<svg class="glyph" viewBox="0 0 24 24" aria-hidden="true"><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"/><path d="M14 3v5h5"/></svg>`;
64
68
  var ICON_FILE_IMAGE = `<svg class="glyph" viewBox="0 0 24 24" aria-hidden="true"><rect x="3.5" y="4.5" width="17" height="15" rx="2.5"/><circle cx="9" cy="10" r="1.5"/><path d="M4.5 17.5 9 13.5l3.5 3 3-2.5 4.5 4"/></svg>`;
65
69
  var ICON_FILE_PDF = `<svg class="glyph" viewBox="0 0 24 24" aria-hidden="true"><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"/><path d="M14 3v5h5"/><rect class="glyph--solid" x="7.5" y="13.5" width="9" height="4.5" rx="1"/></svg>`;
@@ -74,7 +78,7 @@ import { randomUUID as randomUUID5 } from "@ag-ui/client";
74
78
  var PLACEHOLDER_RE = /\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g;
75
79
  function fillTemplate(template, values) {
76
80
  const missing = [];
77
- const text3 = template.replace(PLACEHOLDER_RE, (token, key) => {
81
+ const text4 = template.replace(PLACEHOLDER_RE, (token, key) => {
78
82
  const value = values[key];
79
83
  if (value === void 0 || value === null || value === "") {
80
84
  if (!missing.includes(key)) {
@@ -84,7 +88,7 @@ function fillTemplate(template, values) {
84
88
  }
85
89
  return String(value);
86
90
  });
87
- return { text: text3, missing };
91
+ return { text: text4, missing };
88
92
  }
89
93
 
90
94
  // src/skills/parse_skills.ts
@@ -433,8 +437,8 @@ function createPageStateTools(binding) {
433
437
  handler: () => binding.read()
434
438
  }
435
439
  ];
436
- const write = binding.write;
437
- if (write !== void 0) {
440
+ const write2 = binding.write;
441
+ if (write2 !== void 0) {
438
442
  tools.push({
439
443
  name: `set_${binding.name}`,
440
444
  description: `Update the "${binding.name}" state.`,
@@ -443,7 +447,7 @@ function createPageStateTools(binding) {
443
447
  [X_DESTRUCTIVE_KEY]: true,
444
448
  [X_SUMMARY_KEY]: `Update ${binding.name}`
445
449
  },
446
- handler: (args) => write(args)
450
+ handler: (args) => write2(args)
447
451
  });
448
452
  }
449
453
  return tools;
@@ -780,7 +784,7 @@ function attachCopyButtons(root, strings) {
780
784
  }
781
785
  }
782
786
  function button(code, strings) {
783
- const text3 = code.textContent;
787
+ const text4 = code.textContent;
784
788
  const copy = document.createElement("button");
785
789
  copy.type = "button";
786
790
  copy.className = "code-copy";
@@ -789,19 +793,19 @@ function button(code, strings) {
789
793
  copy.title = strings.copyCode;
790
794
  copy.setAttribute("aria-label", strings.copyCode);
791
795
  copy.addEventListener("click", () => {
792
- void writeText(text3).then((ok) => {
796
+ void writeText(text4).then((ok) => {
793
797
  confirm(copy, ok ? strings.copied : strings.copyFailed, strings);
794
798
  });
795
799
  });
796
800
  return copy;
797
801
  }
798
- async function writeText(text3) {
802
+ async function writeText(text4) {
799
803
  const clipboard = navigator.clipboard;
800
804
  if (clipboard === void 0) {
801
805
  return false;
802
806
  }
803
807
  try {
804
- await clipboard.writeText(text3);
808
+ await clipboard.writeText(text4);
805
809
  return true;
806
810
  } catch {
807
811
  return false;
@@ -1695,6 +1699,14 @@ var CheckpointMenu = class {
1695
1699
  }
1696
1700
  };
1697
1701
 
1702
+ // src/ui/clamp_launcher.ts
1703
+ function clampLauncher(launcher, viewport) {
1704
+ return {
1705
+ left: Math.max(0, Math.min(launcher.left, viewport.width - launcher.width)),
1706
+ top: Math.max(0, Math.min(launcher.top, viewport.height - launcher.height))
1707
+ };
1708
+ }
1709
+
1698
1710
  // src/ui/confirmation_card.ts
1699
1711
  function actionButton2(modifier, label) {
1700
1712
  const button2 = document.createElement("button");
@@ -1755,6 +1767,245 @@ function requestConfirmation(host, request, options = {}) {
1755
1767
  });
1756
1768
  }
1757
1769
 
1770
+ // src/ui/copy_payload.ts
1771
+ var BLOCK_TAGS = /* @__PURE__ */ new Set([
1772
+ "ADDRESS",
1773
+ "ARTICLE",
1774
+ "ASIDE",
1775
+ "BLOCKQUOTE",
1776
+ "DD",
1777
+ "DIV",
1778
+ "DL",
1779
+ "DT",
1780
+ "FIGCAPTION",
1781
+ "FIGURE",
1782
+ "FOOTER",
1783
+ "H1",
1784
+ "H2",
1785
+ "H3",
1786
+ "H4",
1787
+ "H5",
1788
+ "H6",
1789
+ "HEADER",
1790
+ "HR",
1791
+ "MAIN",
1792
+ "NAV",
1793
+ "OL",
1794
+ "P",
1795
+ "SECTION",
1796
+ "UL"
1797
+ ]);
1798
+ function copyPayload(root) {
1799
+ const clone2 = root.cloneNode(true);
1800
+ for (const control of Array.from(clone2.querySelectorAll("button"))) {
1801
+ control.remove();
1802
+ }
1803
+ return { text: normalise(serialise(clone2)), html: clone2.innerHTML };
1804
+ }
1805
+ function serialise(node) {
1806
+ if (node.nodeType === Node.TEXT_NODE) {
1807
+ return node.nodeValue.replace(/\s+/g, " ");
1808
+ }
1809
+ if (node.nodeType !== Node.ELEMENT_NODE) {
1810
+ return "";
1811
+ }
1812
+ const element = node;
1813
+ const tag = element.tagName;
1814
+ if (tag === "BR") {
1815
+ return "\n";
1816
+ }
1817
+ if (tag === "PRE") {
1818
+ return `
1819
+
1820
+ ${text2(element)}
1821
+
1822
+ `;
1823
+ }
1824
+ if (tag === "TABLE") {
1825
+ return `
1826
+
1827
+ ${tableText(element)}
1828
+
1829
+ `;
1830
+ }
1831
+ if (tag === "UL" || tag === "OL") {
1832
+ return `
1833
+
1834
+ ${listText(element, tag === "OL")}
1835
+
1836
+ `;
1837
+ }
1838
+ const inner = children(element);
1839
+ return BLOCK_TAGS.has(tag) ? `
1840
+
1841
+ ${inner}
1842
+
1843
+ ` : inner;
1844
+ }
1845
+ function children(element) {
1846
+ let joined = "";
1847
+ for (const child of Array.from(element.childNodes)) {
1848
+ joined += serialise(child);
1849
+ }
1850
+ return joined;
1851
+ }
1852
+ function listText(list, numbered) {
1853
+ return Array.from(list.children).map((item, index) => `${numbered ? `${index + 1}. ` : "- "}${children(item).trim()}`).join("\n");
1854
+ }
1855
+ function tableText(table) {
1856
+ return Array.from(table.querySelectorAll("tr")).map(
1857
+ (row) => Array.from(row.children).map((cell) => text2(cell).replace(/\s+/g, " ").trim()).join(" ")
1858
+ ).join("\n");
1859
+ }
1860
+ function text2(element) {
1861
+ return element.textContent;
1862
+ }
1863
+ function normalise(text4) {
1864
+ return text4.replace(/[^\S\n]+\n/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
1865
+ }
1866
+
1867
+ // src/ui/launcher_drag.ts
1868
+ var DRAG_THRESHOLD = 4;
1869
+ var STEP = 16;
1870
+ var COARSE_STEP = 64;
1871
+ function enableLauncherDrag(launcher, options) {
1872
+ let suppressClick = false;
1873
+ launcher.addEventListener(
1874
+ "click",
1875
+ (event) => {
1876
+ if (!suppressClick || event.detail === 0) {
1877
+ return;
1878
+ }
1879
+ suppressClick = false;
1880
+ event.stopPropagation();
1881
+ event.preventDefault();
1882
+ },
1883
+ true
1884
+ );
1885
+ launcher.addEventListener("pointerdown", (event) => {
1886
+ suppressClick = false;
1887
+ if (!options.enabled()) {
1888
+ return;
1889
+ }
1890
+ const start = options.rect();
1891
+ const originX = event.clientX;
1892
+ const originY = event.clientY;
1893
+ let dragging = false;
1894
+ const onMove = (move) => {
1895
+ const dx = move.clientX - originX;
1896
+ const dy = move.clientY - originY;
1897
+ if (!dragging && Math.hypot(dx, dy) < DRAG_THRESHOLD) {
1898
+ return;
1899
+ }
1900
+ dragging = true;
1901
+ launcher.setAttribute("data-dragging", "true");
1902
+ const next = clampLauncher(
1903
+ { ...start, left: start.left + dx, top: start.top + dy },
1904
+ options.viewport()
1905
+ );
1906
+ options.apply(next.left, next.top);
1907
+ };
1908
+ const onUp = (up) => {
1909
+ window.removeEventListener("pointermove", onMove);
1910
+ window.removeEventListener("pointerup", onUp);
1911
+ if (!dragging) {
1912
+ return;
1913
+ }
1914
+ launcher.removeAttribute("data-dragging");
1915
+ suppressClick = true;
1916
+ const next = clampLauncher(
1917
+ {
1918
+ ...start,
1919
+ left: start.left + (up.clientX - originX),
1920
+ top: start.top + (up.clientY - originY)
1921
+ },
1922
+ options.viewport()
1923
+ );
1924
+ options.commit(next.left, next.top);
1925
+ };
1926
+ window.addEventListener("pointermove", onMove);
1927
+ window.addEventListener("pointerup", onUp);
1928
+ });
1929
+ let pending = null;
1930
+ const settle = () => {
1931
+ if (pending === null) {
1932
+ return;
1933
+ }
1934
+ const { left, top } = pending;
1935
+ pending = null;
1936
+ options.commit(left, top);
1937
+ };
1938
+ launcher.addEventListener("keydown", (event) => {
1939
+ if (!options.enabled()) {
1940
+ return;
1941
+ }
1942
+ const step = event.shiftKey ? COARSE_STEP : STEP;
1943
+ const rect = options.rect();
1944
+ let moved = null;
1945
+ if (event.key === "ArrowLeft") {
1946
+ moved = { left: rect.left - step, top: rect.top };
1947
+ } else if (event.key === "ArrowRight") {
1948
+ moved = { left: rect.left + step, top: rect.top };
1949
+ } else if (event.key === "ArrowUp") {
1950
+ moved = { left: rect.left, top: rect.top - step };
1951
+ } else if (event.key === "ArrowDown") {
1952
+ moved = { left: rect.left, top: rect.top + step };
1953
+ }
1954
+ if (moved === null) {
1955
+ return;
1956
+ }
1957
+ event.preventDefault();
1958
+ const next = clampLauncher({ ...rect, ...moved }, options.viewport());
1959
+ options.apply(next.left, next.top);
1960
+ pending = next;
1961
+ });
1962
+ launcher.addEventListener("keyup", settle);
1963
+ launcher.addEventListener("blur", settle);
1964
+ }
1965
+
1966
+ // src/ui/launcher_placement.ts
1967
+ var EDGE_MARGIN = 24;
1968
+ function launcherPlacement(launcher, panel, viewport, margin = EDGE_MARGIN) {
1969
+ const roomRunningRight = viewport.width - launcher.left;
1970
+ const roomRunningLeft = launcher.left + launcher.width;
1971
+ const roomRunningDown = viewport.height - launcher.top;
1972
+ const roomRunningUp = launcher.top + launcher.height;
1973
+ const corner = {
1974
+ x: roomRunningRight >= roomRunningLeft ? "left" : "right",
1975
+ y: roomRunningDown >= roomRunningUp ? "top" : "bottom"
1976
+ };
1977
+ const wantedLeft = corner.x === "left" ? launcher.left : launcher.left + launcher.width - panel.width;
1978
+ const wantedTop = corner.y === "top" ? launcher.top : launcher.top + launcher.height - panel.height;
1979
+ const hostLeft = clamp(wantedLeft, margin, viewport.width - margin - panel.width);
1980
+ const hostTop = clamp(wantedTop, margin, viewport.height - margin - panel.height);
1981
+ const hostRight = hostLeft + panel.width;
1982
+ const hostBottom = hostTop + panel.height;
1983
+ return {
1984
+ corner,
1985
+ hostInset: inset({
1986
+ top: corner.y === "top" ? hostTop : null,
1987
+ right: corner.x === "right" ? viewport.width - hostRight : null,
1988
+ bottom: corner.y === "bottom" ? viewport.height - hostBottom : null,
1989
+ left: corner.x === "left" ? hostLeft : null
1990
+ }),
1991
+ // Measured from the host box's pinned corner to the launcher's matching
1992
+ // corner, so the launcher lands exactly where it was dropped.
1993
+ launcherInset: inset({
1994
+ top: corner.y === "top" ? launcher.top - hostTop : null,
1995
+ right: corner.x === "right" ? hostRight - (launcher.left + launcher.width) : null,
1996
+ bottom: corner.y === "bottom" ? hostBottom - (launcher.top + launcher.height) : null,
1997
+ left: corner.x === "left" ? launcher.left - hostLeft : null
1998
+ })
1999
+ };
2000
+ }
2001
+ function clamp(value, low, high) {
2002
+ return Math.max(low, Math.min(value, high));
2003
+ }
2004
+ function inset(sides) {
2005
+ const side = (value) => value === null ? "auto" : `${Math.round(value)}px`;
2006
+ return `${side(sides.top)} ${side(sides.right)} ${side(sides.bottom)} ${side(sides.left)}`;
2007
+ }
2008
+
1758
2009
  // src/ui/message_actions.ts
1759
2010
  var CONFIRM_MS2 = 1500;
1760
2011
  function attachMessageActions(bubble, options) {
@@ -1762,9 +2013,9 @@ function attachMessageActions(bubble, options) {
1762
2013
  return;
1763
2014
  }
1764
2015
  const bar = messageActionBar(bubble, options.strings);
1765
- const text3 = options.text;
1766
- if (text3 !== void 0) {
1767
- bar.appendChild(copyButton(options.strings, text3));
2016
+ const text4 = options.text;
2017
+ if (text4 !== void 0) {
2018
+ bar.appendChild(copyButton(options.strings, text4, options.html));
1768
2019
  }
1769
2020
  if (options.onFeedback !== void 0) {
1770
2021
  bar.append(
@@ -1790,36 +2041,63 @@ function existingBar(bubble) {
1790
2041
  const next = bubble.nextElementSibling;
1791
2042
  return next?.classList.contains("message-actions") === true ? next : null;
1792
2043
  }
1793
- function messageActionButton(modifier, label, glyph) {
2044
+ function messageActionButton(modifier, label, icon) {
1794
2045
  const button2 = document.createElement("button");
1795
2046
  button2.type = "button";
1796
2047
  button2.className = `message-action message-action--${modifier}`;
1797
2048
  button2.setAttribute("part", `message-action message-action-${modifier}`);
2049
+ setLabel(button2, label);
2050
+ const holder = document.createElement("span");
2051
+ holder.className = "message-action-icon";
2052
+ holder.setAttribute("part", `message-action-icon message-action-icon-${modifier}`);
2053
+ holder.setAttribute("aria-hidden", "true");
2054
+ holder.innerHTML = icon;
2055
+ button2.appendChild(holder);
2056
+ return button2;
2057
+ }
2058
+ function setLabel(button2, label) {
1798
2059
  button2.title = label;
1799
2060
  button2.setAttribute("aria-label", label);
1800
- const icon = document.createElement("span");
1801
- icon.setAttribute("aria-hidden", "true");
1802
- icon.textContent = glyph;
1803
- button2.appendChild(icon);
1804
- return button2;
2061
+ button2.dataset["tooltip"] = label;
1805
2062
  }
1806
- function copyButton(strings, text3) {
1807
- const button2 = messageActionButton("copy", strings.copyMessage, "\u2398");
2063
+ function copyButton(strings, text4, html2) {
2064
+ const button2 = messageActionButton("copy", strings.copyMessage, ICON_COPY);
1808
2065
  button2.addEventListener("click", () => {
1809
- void navigator.clipboard.writeText(text3()).then(
1810
- () => flash2(button2, strings.copied, strings.copyMessage),
1811
- // A denied clipboard permission is the common case, not an exception:
1812
- // say so on the button rather than throwing into an unhandled rejection.
1813
- () => flash2(button2, strings.copyFailed, strings.copyMessage)
1814
- );
2066
+ void write(text4(), html2?.()).then((ok) => {
2067
+ flash2(button2, ok ? strings.copied : strings.copyFailed, strings.copyMessage);
2068
+ });
1815
2069
  });
1816
2070
  return button2;
1817
2071
  }
2072
+ async function write(text4, html2) {
2073
+ const clipboard = navigator.clipboard;
2074
+ if (clipboard === void 0) {
2075
+ return false;
2076
+ }
2077
+ if (html2 !== void 0 && typeof ClipboardItem === "function") {
2078
+ try {
2079
+ await clipboard.write([
2080
+ new ClipboardItem({
2081
+ "text/plain": new Blob([text4], { type: "text/plain" }),
2082
+ "text/html": new Blob([html2], { type: "text/html" })
2083
+ })
2084
+ ]);
2085
+ return true;
2086
+ } catch {
2087
+ }
2088
+ }
2089
+ try {
2090
+ await clipboard.writeText(text4);
2091
+ return true;
2092
+ } catch {
2093
+ return false;
2094
+ }
2095
+ }
1818
2096
  function feedbackButton(rating, label, report) {
1819
2097
  const button2 = messageActionButton(
1820
2098
  rating === "up" ? "up" : "down",
1821
2099
  label,
1822
- rating === "up" ? "\u{1F44D}" : "\u{1F44E}"
2100
+ rating === "up" ? ICON_THUMB_UP : ICON_THUMB_DOWN
1823
2101
  );
1824
2102
  button2.addEventListener("click", () => {
1825
2103
  const pressed = button2.getAttribute("aria-pressed") === "true";
@@ -1830,12 +2108,10 @@ function feedbackButton(rating, label, report) {
1830
2108
  return button2;
1831
2109
  }
1832
2110
  function flash2(button2, message, label) {
1833
- button2.title = message;
1834
- button2.setAttribute("aria-label", message);
2111
+ setLabel(button2, message);
1835
2112
  button2.classList.add("message-action--confirmed");
1836
2113
  setTimeout(() => {
1837
- button2.title = label;
1838
- button2.setAttribute("aria-label", label);
2114
+ setLabel(button2, label);
1839
2115
  button2.classList.remove("message-action--confirmed");
1840
2116
  }, CONFIRM_MS2);
1841
2117
  }
@@ -1853,16 +2129,16 @@ function quotableSelection(container, roots = [], near) {
1853
2129
  const range = document.createRange();
1854
2130
  range.setStart(endpoints.startContainer, endpoints.startOffset);
1855
2131
  range.setEnd(endpoints.endContainer, endpoints.endOffset);
1856
- const text3 = renderedText(range).trim();
1857
- if (text3 === "") {
2132
+ const text4 = renderedText(range).trim();
2133
+ if (text4 === "") {
1858
2134
  continue;
1859
2135
  }
1860
- return { text: text3, rect: lineToHangFrom(range, near) };
2136
+ return { text: text4, rect: lineToHangFrom(range, near) };
1861
2137
  }
1862
2138
  return null;
1863
2139
  }
1864
- function asQuote(text3) {
1865
- const lines = tidy(text3);
2140
+ function asQuote(text4) {
2141
+ const lines = tidy(text4);
1866
2142
  if (lines.length === 0) {
1867
2143
  return "";
1868
2144
  }
@@ -1872,8 +2148,8 @@ function asQuote(text3) {
1872
2148
 
1873
2149
  `;
1874
2150
  }
1875
- function tidy(text3) {
1876
- const lines = text3.split(/\r\n?|\n/).map((line) => line.trimEnd());
2151
+ function tidy(text4) {
2152
+ const lines = text4.split(/\r\n?|\n/).map((line) => line.trimEnd());
1877
2153
  const indents = lines.filter((line) => line !== "").map(indentOf);
1878
2154
  const shared = indents.length === 0 ? 0 : Math.min(...indents);
1879
2155
  const kept = [];
@@ -1892,11 +2168,11 @@ function tidy(text3) {
1892
2168
  function indentOf(line) {
1893
2169
  return line.length - line.trimStart().length;
1894
2170
  }
1895
- function cap(text3) {
1896
- return text3.length > MAX_QUOTE_CHARS ? `${text3.slice(0, MAX_QUOTE_CHARS).trimEnd()}...` : text3;
2171
+ function cap(text4) {
2172
+ return text4.length > MAX_QUOTE_CHARS ? `${text4.slice(0, MAX_QUOTE_CHARS).trimEnd()}...` : text4;
1897
2173
  }
1898
2174
  function renderedText(range) {
1899
- let text3 = "";
2175
+ let text4 = "";
1900
2176
  for (const node of textNodesIn(range)) {
1901
2177
  const parent = node.parentElement;
1902
2178
  if (!isRendered(parent)) {
@@ -1904,15 +2180,15 @@ function renderedText(range) {
1904
2180
  }
1905
2181
  const from = node === range.startContainer ? range.startOffset : 0;
1906
2182
  const to = node === range.endContainer ? range.endOffset : node.data.length;
1907
- text3 += collapse(node.data.slice(from, to), parent);
2183
+ text4 += collapse(node.data.slice(from, to), parent);
1908
2184
  }
1909
- return text3;
2185
+ return text4;
1910
2186
  }
1911
- function collapse(text3, parent) {
2187
+ function collapse(text4, parent) {
1912
2188
  if (PREFORMATTED.has(whiteSpaceOf(parent))) {
1913
- return text3;
2189
+ return text4;
1914
2190
  }
1915
- return text3.replace(/[^\S\n]*\n[^\S\n]*/g, "\n").replace(/[^\S\n]+/g, " ");
2191
+ return text4.replace(/[^\S\n]*\n[^\S\n]*/g, "\n").replace(/[^\S\n]+/g, " ");
1916
2192
  }
1917
2193
  var PREFORMATTED = /* @__PURE__ */ new Set(["pre", "pre-wrap", "break-spaces"]);
1918
2194
  function whiteSpaceOf(element) {
@@ -2062,10 +2338,10 @@ function attachQuoteOffer(options) {
2062
2338
  event.preventDefault();
2063
2339
  });
2064
2340
  button2.addEventListener("click", () => {
2065
- const text3 = quoting;
2341
+ const text4 = quoting;
2066
2342
  window.getSelection()?.removeAllRanges();
2067
2343
  hide();
2068
- onQuote(text3);
2344
+ onQuote(text4);
2069
2345
  });
2070
2346
  return {
2071
2347
  element: button2,
@@ -2145,10 +2421,10 @@ function requestQuestion(host, request, options = {}) {
2145
2421
  radio.name = group;
2146
2422
  radio.value = choice;
2147
2423
  radio.setAttribute("part", "question-radio");
2148
- const text3 = document.createElement("span");
2149
- text3.setAttribute("part", "question-choice-text");
2150
- text3.textContent = choice;
2151
- label.append(radio, text3);
2424
+ const text4 = document.createElement("span");
2425
+ text4.setAttribute("part", "question-choice-text");
2426
+ text4.textContent = choice;
2427
+ label.append(radio, text4);
2152
2428
  form.appendChild(label);
2153
2429
  radios.push(radio);
2154
2430
  }
@@ -2165,10 +2441,10 @@ function requestQuestion(host, request, options = {}) {
2165
2441
  otherRadio.name = group;
2166
2442
  otherRadio.value = "";
2167
2443
  otherRadio.setAttribute("part", "question-radio");
2168
- const text3 = document.createElement("span");
2169
- text3.setAttribute("part", "question-choice-text");
2170
- text3.textContent = strings.otherOption;
2171
- label.append(otherRadio, text3);
2444
+ const text4 = document.createElement("span");
2445
+ text4.setAttribute("part", "question-choice-text");
2446
+ text4.textContent = strings.otherOption;
2447
+ label.append(otherRadio, text4);
2172
2448
  form.appendChild(label);
2173
2449
  input.disabled = true;
2174
2450
  }
@@ -2250,7 +2526,7 @@ function requestQuestion(host, request, options = {}) {
2250
2526
  });
2251
2527
  }
2252
2528
 
2253
- // node_modules/.pnpm/dompurify@3.4.13/node_modules/dompurify/dist/purify.es.mjs
2529
+ // node_modules/.pnpm/dompurify@3.4.14/node_modules/dompurify/dist/purify.es.mjs
2254
2530
  function _arrayLikeToArray(r, a) {
2255
2531
  (null == a || a > r.length) && (a = r.length);
2256
2532
  for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
@@ -2489,9 +2765,9 @@ var svgFilters = freeze(["feBlend", "feColorMatrix", "feComponentTransfer", "feC
2489
2765
  var svgDisallowed = freeze(["animate", "color-profile", "cursor", "discard", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignobject", "hatch", "hatchpath", "mesh", "meshgradient", "meshpatch", "meshrow", "missing-glyph", "script", "set", "solidcolor", "unknown", "use"]);
2490
2766
  var mathMl$1 = freeze(["math", "menclose", "merror", "mfenced", "mfrac", "mglyph", "mi", "mlabeledtr", "mmultiscripts", "mn", "mo", "mover", "mpadded", "mphantom", "mroot", "mrow", "ms", "mspace", "msqrt", "mstyle", "msub", "msup", "msubsup", "mtable", "mtd", "mtext", "mtr", "munder", "munderover", "mprescripts"]);
2491
2767
  var mathMlDisallowed = freeze(["maction", "maligngroup", "malignmark", "mlongdiv", "mscarries", "mscarry", "msgroup", "mstack", "msline", "msrow", "semantics", "annotation", "annotation-xml", "mprescripts", "none"]);
2492
- var text2 = freeze(["#text"]);
2768
+ var text3 = freeze(["#text"]);
2493
2769
  var html = freeze(["accept", "action", "align", "alt", "autocapitalize", "autocomplete", "autopictureinpicture", "autoplay", "background", "bgcolor", "border", "capture", "cellpadding", "cellspacing", "checked", "cite", "class", "clear", "color", "cols", "colspan", "command", "commandfor", "controls", "controlslist", "coords", "crossorigin", "datetime", "decoding", "default", "dir", "disabled", "disablepictureinpicture", "disableremoteplayback", "download", "draggable", "enctype", "enterkeyhint", "exportparts", "face", "for", "headers", "height", "hidden", "high", "href", "hreflang", "id", "inert", "inputmode", "integrity", "ismap", "kind", "label", "lang", "list", "loading", "loop", "low", "max", "maxlength", "media", "method", "min", "minlength", "multiple", "muted", "name", "nonce", "noshade", "novalidate", "nowrap", "open", "optimum", "part", "pattern", "placeholder", "playsinline", "popover", "popovertarget", "popovertargetaction", "poster", "preload", "pubdate", "radiogroup", "readonly", "rel", "required", "rev", "reversed", "role", "rows", "rowspan", "spellcheck", "scope", "selected", "shape", "size", "sizes", "slot", "span", "srclang", "start", "src", "srcset", "step", "style", "summary", "tabindex", "title", "translate", "type", "usemap", "valign", "value", "width", "wrap", "xmlns"]);
2494
- var svg = freeze(["accent-height", "accumulate", "additive", "alignment-baseline", "amplitude", "ascent", "attributename", "attributetype", "azimuth", "basefrequency", "baseline-shift", "begin", "bias", "by", "class", "clip", "clippathunits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "cx", "cy", "d", "dx", "dy", "diffuseconstant", "direction", "display", "divisor", "dominant-baseline", "dur", "edgemode", "elevation", "end", "exponent", "fill", "fill-opacity", "fill-rule", "filter", "filterunits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "fx", "fy", "g1", "g2", "glyph-name", "glyphref", "gradientunits", "gradienttransform", "height", "href", "id", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kerning", "keypoints", "keysplines", "keytimes", "lang", "lengthadjust", "letter-spacing", "kernelmatrix", "kernelunitlength", "lighting-color", "local", "marker-end", "marker-mid", "marker-start", "markerheight", "markerunits", "markerwidth", "maskcontentunits", "maskunits", "max", "mask", "mask-type", "media", "method", "mode", "min", "name", "numoctaves", "offset", "operator", "opacity", "order", "orient", "orientation", "origin", "overflow", "paint-order", "path", "pathlength", "patterncontentunits", "patterntransform", "patternunits", "points", "preservealpha", "preserveaspectratio", "primitiveunits", "r", "rx", "ry", "radius", "refx", "refy", "repeatcount", "repeatdur", "restart", "result", "rotate", "scale", "seed", "shape-rendering", "slope", "specularconstant", "specularexponent", "spreadmethod", "startoffset", "stddeviation", "stitchtiles", "stop-color", "stop-opacity", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke", "stroke-width", "style", "surfacescale", "systemlanguage", "tabindex", "tablevalues", "targetx", "targety", "transform", "transform-origin", "text-anchor", "text-decoration", "text-orientation", "text-rendering", "textlength", "type", "u1", "u2", "unicode", "values", "viewbox", "visibility", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "width", "word-spacing", "wrap", "writing-mode", "xchannelselector", "ychannelselector", "x", "x1", "x2", "xmlns", "y", "y1", "y2", "z", "zoomandpan"]);
2770
+ var svg = freeze(["accent-height", "accumulate", "additive", "alignment-baseline", "amplitude", "ascent", "attributename", "attributetype", "azimuth", "basefrequency", "baseline-shift", "begin", "bias", "by", "class", "clip", "clippathunits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "cx", "cy", "d", "dx", "dy", "diffuseconstant", "direction", "display", "divisor", "dominant-baseline", "dur", "edgemode", "elevation", "end", "exponent", "fill", "fill-opacity", "fill-rule", "filter", "filterunits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "fx", "fy", "g1", "g2", "glyph-name", "glyphref", "gradientunits", "gradienttransform", "height", "href", "id", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kerning", "keypoints", "keysplines", "keytimes", "lang", "lengthadjust", "letter-spacing", "kernelmatrix", "kernelunitlength", "lighting-color", "local", "marker-end", "marker-mid", "marker-start", "markerheight", "markerunits", "markerwidth", "maskcontentunits", "maskunits", "max", "mask", "mask-type", "media", "method", "mode", "min", "name", "numoctaves", "offset", "operator", "opacity", "order", "orient", "orientation", "origin", "overflow", "paint-order", "path", "pathlength", "patterncontentunits", "patterntransform", "patternunits", "pointer-events", "points", "preservealpha", "preserveaspectratio", "primitiveunits", "r", "rx", "ry", "radius", "refx", "refy", "repeatcount", "repeatdur", "restart", "result", "rotate", "scale", "seed", "shape-rendering", "slope", "specularconstant", "specularexponent", "spreadmethod", "startoffset", "stddeviation", "stitchtiles", "stop-color", "stop-opacity", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke", "stroke-width", "style", "surfacescale", "systemlanguage", "tabindex", "tablevalues", "targetx", "targety", "transform", "transform-origin", "text-anchor", "text-decoration", "text-orientation", "text-rendering", "textlength", "type", "u1", "u2", "unicode", "values", "vector-effect", "viewbox", "visibility", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "width", "word-spacing", "wrap", "writing-mode", "xchannelselector", "ychannelselector", "x", "x1", "x2", "xmlns", "y", "y1", "y2", "z", "zoomandpan"]);
2495
2771
  var mathMl = freeze(["accent", "accentunder", "align", "bevelled", "close", "columnalign", "columnlines", "columnspacing", "columnspan", "denomalign", "depth", "dir", "display", "displaystyle", "encoding", "fence", "frame", "height", "href", "id", "largeop", "length", "linethickness", "lquote", "lspace", "mathbackground", "mathcolor", "mathsize", "mathvariant", "maxsize", "minsize", "movablelimits", "notation", "numalign", "open", "rowalign", "rowlines", "rowspacing", "rowspan", "rspace", "rquote", "scriptlevel", "scriptminsize", "scriptsizemultiplier", "selection", "separator", "separators", "stretchy", "subscriptshift", "supscriptshift", "symmetric", "voffset", "width", "xmlns"]);
2496
2772
  var xml = freeze(["xlink:href", "xml:id", "xlink:title", "xml:space", "xmlns:xlink"]);
2497
2773
  var MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g);
@@ -2531,6 +2807,15 @@ var NODE_TYPE = {
2531
2807
  notation: 12
2532
2808
  // Deprecated
2533
2809
  };
2810
+ var LITERAL_TEXT_ELEMENT_NAMES = ["style", "script", "xmp", "iframe", "noembed", "noframes", "plaintext", "noscript"];
2811
+ var LITERAL_TEXT_ELEMENTS = freeze(addToSet({}, LITERAL_TEXT_ELEMENT_NAMES));
2812
+ var LITERAL_TEXT_CLOSE = (function() {
2813
+ const map = {};
2814
+ arrayForEach(LITERAL_TEXT_ELEMENT_NAMES, (name) => {
2815
+ map[name] = seal(new RegExp("</" + name + "(?=[\\t\\n\\f\\r />])", "i"));
2816
+ });
2817
+ return freeze(map);
2818
+ })();
2534
2819
  var getGlobal = function getGlobal2() {
2535
2820
  return typeof window === "undefined" ? null : window;
2536
2821
  };
@@ -2574,10 +2859,14 @@ var _createHooksMap = function _createHooksMap2() {
2574
2859
  var _resolveSetOption = function _resolveSetOption2(cfg, key, fallback, options) {
2575
2860
  return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback;
2576
2861
  };
2862
+ var _resolveObjectOption = function _resolveObjectOption2(cfg, key, makeFallback) {
2863
+ const value = objectHasOwnProperty(cfg, key) ? cfg[key] : void 0;
2864
+ return value && typeof value === "object" ? clone(value) : makeFallback();
2865
+ };
2577
2866
  function createDOMPurify() {
2578
2867
  let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal();
2579
2868
  const DOMPurify = (root) => createDOMPurify(root);
2580
- DOMPurify.version = "3.4.13";
2869
+ DOMPurify.version = "3.4.14";
2581
2870
  DOMPurify.removed = [];
2582
2871
  if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) {
2583
2872
  DOMPurify.isSupported = false;
@@ -2602,6 +2891,12 @@ function createDOMPurify() {
2602
2891
  const getNodeType = Node2 && Node2.prototype ? lookupGetter(Node2.prototype, "nodeType") : null;
2603
2892
  const getNodeName = Node2 && Node2.prototype ? lookupGetter(Node2.prototype, "nodeName") : null;
2604
2893
  const getOwnerDocument = Node2 && Node2.prototype ? lookupGetter(Node2.prototype, "ownerDocument") : null;
2894
+ const _readNodeType = function _readNodeType2(node) {
2895
+ return getNodeType ? getNodeType(node) : node.nodeType;
2896
+ };
2897
+ const _readNodeName = function _readNodeName2(node) {
2898
+ return getNodeName ? getNodeName(node) : node.nodeName;
2899
+ };
2605
2900
  if (typeof HTMLTemplateElement === "function") {
2606
2901
  const template = document2.createElement("template");
2607
2902
  if (template.content && template.content.ownerDocument) {
@@ -2650,7 +2945,7 @@ function createDOMPurify() {
2650
2945
  const MUSTACHE_EXPR$1 = MUSTACHE_EXPR, ERB_EXPR$1 = ERB_EXPR, TMPLIT_EXPR$1 = TMPLIT_EXPR, DATA_ATTR$1 = DATA_ATTR, ARIA_ATTR$1 = ARIA_ATTR, IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA, ATTR_WHITESPACE$1 = ATTR_WHITESPACE, CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;
2651
2946
  let IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
2652
2947
  let ALLOWED_TAGS2 = null;
2653
- const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text2]);
2948
+ const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text3]);
2654
2949
  let ALLOWED_ATTR2 = null;
2655
2950
  const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);
2656
2951
  let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {
@@ -2828,9 +3123,19 @@ function createDOMPurify() {
2828
3123
  IN_PLACE = cfg.IN_PLACE || false;
2829
3124
  IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI;
2830
3125
  NAMESPACE = typeof cfg.NAMESPACE === "string" ? cfg.NAMESPACE : HTML_NAMESPACE;
2831
- MATHML_TEXT_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "MATHML_TEXT_INTEGRATION_POINTS") && cfg.MATHML_TEXT_INTEGRATION_POINTS && typeof cfg.MATHML_TEXT_INTEGRATION_POINTS === "object" ? clone(cfg.MATHML_TEXT_INTEGRATION_POINTS) : addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS);
2832
- HTML_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "HTML_INTEGRATION_POINTS") && cfg.HTML_INTEGRATION_POINTS && typeof cfg.HTML_INTEGRATION_POINTS === "object" ? clone(cfg.HTML_INTEGRATION_POINTS) : addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS);
2833
- const customElementHandling = objectHasOwnProperty(cfg, "CUSTOM_ELEMENT_HANDLING") && cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING === "object" ? clone(cfg.CUSTOM_ELEMENT_HANDLING) : create(null);
3126
+ MATHML_TEXT_INTEGRATION_POINTS = _resolveObjectOption(
3127
+ cfg,
3128
+ "MATHML_TEXT_INTEGRATION_POINTS",
3129
+ () => addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS)
3130
+ // Default built-in map
3131
+ );
3132
+ HTML_INTEGRATION_POINTS = _resolveObjectOption(
3133
+ cfg,
3134
+ "HTML_INTEGRATION_POINTS",
3135
+ () => addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS)
3136
+ // Default built-in map
3137
+ );
3138
+ const customElementHandling = _resolveObjectOption(cfg, "CUSTOM_ELEMENT_HANDLING", () => create(null));
2834
3139
  CUSTOM_ELEMENT_HANDLING = create(null);
2835
3140
  if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) {
2836
3141
  CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck;
@@ -2849,7 +3154,7 @@ function createDOMPurify() {
2849
3154
  RETURN_DOM = true;
2850
3155
  }
2851
3156
  if (USE_PROFILES) {
2852
- ALLOWED_TAGS2 = addToSet({}, text2);
3157
+ ALLOWED_TAGS2 = addToSet({}, text3);
2853
3158
  ALLOWED_ATTR2 = create(null);
2854
3159
  if (USE_PROFILES.html === true) {
2855
3160
  addToSet(ALLOWED_TAGS2, html$1);
@@ -2893,15 +3198,6 @@ function createDOMPurify() {
2893
3198
  addToSet(ALLOWED_ATTR2, cfg.ADD_ATTR, transformCaseFunc);
2894
3199
  }
2895
3200
  }
2896
- if (objectHasOwnProperty(cfg, "ADD_URI_SAFE_ATTR") && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) {
2897
- addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
2898
- }
2899
- if (objectHasOwnProperty(cfg, "FORBID_CONTENTS") && arrayIsArray(cfg.FORBID_CONTENTS)) {
2900
- if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
2901
- FORBID_CONTENTS = clone(FORBID_CONTENTS);
2902
- }
2903
- addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
2904
- }
2905
3201
  if (objectHasOwnProperty(cfg, "ADD_FORBID_CONTENTS") && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
2906
3202
  if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
2907
3203
  FORBID_CONTENTS = clone(FORBID_CONTENTS);
@@ -3018,6 +3314,16 @@ function createDOMPurify() {
3018
3314
  }
3019
3315
  }
3020
3316
  };
3317
+ const _stripAttributeNode = function _stripAttributeNode2(element, attribute, name) {
3318
+ try {
3319
+ element.removeAttributeNode(attribute);
3320
+ } catch (_2) {
3321
+ try {
3322
+ element.removeAttribute(name);
3323
+ } catch (_3) {
3324
+ }
3325
+ }
3326
+ };
3021
3327
  const _neutralizeRoot = function _neutralizeRoot2(root) {
3022
3328
  _neutralizeSubtree(root);
3023
3329
  const childNodes = getChildNodes(root);
@@ -3039,27 +3345,35 @@ function createDOMPurify() {
3039
3345
  const attribute = attributes[i];
3040
3346
  const name = attribute && attribute.name;
3041
3347
  if (typeof name === "string") {
3042
- try {
3043
- root.removeAttribute(name);
3044
- } catch (_2) {
3045
- }
3348
+ _stripAttributeNode(root, attribute, name);
3046
3349
  }
3047
3350
  }
3048
3351
  }
3049
3352
  };
3050
- const _removeAttribute = function _removeAttribute2(name, element) {
3353
+ const _removeAttribute = function _removeAttribute2(name, element, attr) {
3354
+ if (!attr) {
3355
+ try {
3356
+ attr = element.getAttributeNode(name);
3357
+ } catch (_2) {
3358
+ attr = null;
3359
+ }
3360
+ }
3361
+ arrayPush(DOMPurify.removed, {
3362
+ attribute: attr || null,
3363
+ from: element
3364
+ });
3051
3365
  try {
3052
- arrayPush(DOMPurify.removed, {
3053
- attribute: element.getAttributeNode(name),
3054
- from: element
3055
- });
3366
+ if (attr) {
3367
+ element.removeAttributeNode(attr);
3368
+ } else {
3369
+ element.removeAttribute(name);
3370
+ }
3056
3371
  } catch (_2) {
3057
- arrayPush(DOMPurify.removed, {
3058
- attribute: null,
3059
- from: element
3060
- });
3372
+ try {
3373
+ element.removeAttribute(name);
3374
+ } catch (_3) {
3375
+ }
3061
3376
  }
3062
- element.removeAttribute(name);
3063
3377
  if (name === "is") {
3064
3378
  if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
3065
3379
  try {
@@ -3085,17 +3399,14 @@ function createDOMPurify() {
3085
3399
  if (typeof name !== "string" || ALLOWED_ATTR2[transformCaseFunc(name)]) {
3086
3400
  continue;
3087
3401
  }
3088
- try {
3089
- element.removeAttribute(name);
3090
- } catch (_2) {
3091
- }
3402
+ _stripAttributeNode(element, attribute, name);
3092
3403
  }
3093
3404
  };
3094
3405
  const _neutralizeSubtree = function _neutralizeSubtree2(root) {
3095
3406
  const stack = [root];
3096
3407
  while (stack.length > 0) {
3097
3408
  const node = stack.pop();
3098
- const nodeType = getNodeType ? getNodeType(node) : node.nodeType;
3409
+ const nodeType = _readNodeType(node);
3099
3410
  if (nodeType === NODE_TYPE.element) {
3100
3411
  _stripDisallowedAttributes(node);
3101
3412
  }
@@ -3107,6 +3418,15 @@ function createDOMPurify() {
3107
3418
  }
3108
3419
  }
3109
3420
  };
3421
+ const _isPatchLinkageAttribute = function _isPatchLinkageAttribute2(lcName, lcTag) {
3422
+ if (!SAFE_FOR_XML) {
3423
+ return false;
3424
+ }
3425
+ if (lcName === "patchsrc") {
3426
+ return true;
3427
+ }
3428
+ return lcName === "for" && lcTag !== "label" && lcTag !== "output";
3429
+ };
3110
3430
  const _neutralizePatchLinkage = function _neutralizePatchLinkage2(root) {
3111
3431
  if (!SAFE_FOR_XML) {
3112
3432
  return;
@@ -3114,7 +3434,7 @@ function createDOMPurify() {
3114
3434
  const stack = [root];
3115
3435
  while (stack.length > 0) {
3116
3436
  const node = stack.pop();
3117
- const nodeType = getNodeType ? getNodeType(node) : node.nodeType;
3437
+ const nodeType = _readNodeType(node);
3118
3438
  if (nodeType === NODE_TYPE.processingInstruction || nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, node.data)) {
3119
3439
  try {
3120
3440
  remove(node);
@@ -3124,12 +3444,12 @@ function createDOMPurify() {
3124
3444
  }
3125
3445
  if (nodeType === NODE_TYPE.element) {
3126
3446
  const element = node;
3127
- const lcTag = transformCaseFunc(getNodeName ? getNodeName(node) : node.nodeName);
3447
+ const lcTag = transformCaseFunc(_readNodeName(node));
3128
3448
  try {
3129
3449
  if (element.hasAttribute && element.hasAttribute("patchsrc")) {
3130
3450
  element.removeAttribute("patchsrc");
3131
3451
  }
3132
- if (element.hasAttribute && element.hasAttribute("for") && lcTag !== "label" && lcTag !== "output") {
3452
+ if (element.hasAttribute && element.hasAttribute("for") && _isPatchLinkageAttribute("for", lcTag)) {
3133
3453
  element.removeAttribute("for");
3134
3454
  }
3135
3455
  } catch (_2) {
@@ -3284,7 +3604,7 @@ function createDOMPurify() {
3284
3604
  if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.textContent) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.innerHTML)) {
3285
3605
  return true;
3286
3606
  }
3287
- if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === "style" && _isNode(currentNode.firstElementChild)) {
3607
+ if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && LITERAL_TEXT_ELEMENTS[tagName] && (_isNode(currentNode.firstElementChild) || typeof currentNode.textContent === "string" && regExpTest(LITERAL_TEXT_CLOSE[tagName], currentNode.textContent))) {
3288
3608
  return true;
3289
3609
  }
3290
3610
  if (currentNode.nodeType === NODE_TYPE.processingInstruction) {
@@ -3295,14 +3615,21 @@ function createDOMPurify() {
3295
3615
  }
3296
3616
  return false;
3297
3617
  };
3298
- const _sanitizeDisallowedNode = function _sanitizeDisallowedNode2(currentNode, tagName, root) {
3299
- if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
3300
- if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
3301
- return false;
3302
- }
3303
- if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {
3304
- return false;
3618
+ const _matchesNameCheck = function _matchesNameCheck2(check, name) {
3619
+ if (check instanceof RegExp) {
3620
+ return regExpTest(check, name);
3621
+ }
3622
+ if (check instanceof Function) {
3623
+ for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
3624
+ args[_key - 2] = arguments[_key];
3305
3625
  }
3626
+ return Boolean(check(name, ...args));
3627
+ }
3628
+ return false;
3629
+ };
3630
+ const _sanitizeDisallowedNode = function _sanitizeDisallowedNode2(currentNode, tagName, root) {
3631
+ if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
3632
+ return false;
3306
3633
  }
3307
3634
  if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
3308
3635
  const parentNode = getParentNode(currentNode);
@@ -3324,28 +3651,31 @@ function createDOMPurify() {
3324
3651
  }
3325
3652
  return set === defaultSet || set === setConfigSet ? clone(set) : set;
3326
3653
  };
3654
+ const _handleHookDetachedNode = function _handleHookDetachedNode2(currentNode, root) {
3655
+ if (currentNode === root || getParentNode(currentNode) !== null) {
3656
+ return false;
3657
+ }
3658
+ if (IN_PLACE) {
3659
+ _neutralizeSubtree(currentNode);
3660
+ }
3661
+ return true;
3662
+ };
3327
3663
  const _sanitizeElements = function _sanitizeElements2(currentNode, root) {
3328
3664
  _executeHooks(hooks.beforeSanitizeElements, currentNode, null);
3329
- if (currentNode !== root && getParentNode(currentNode) === null) {
3330
- if (IN_PLACE) {
3331
- _neutralizeSubtree(currentNode);
3332
- }
3665
+ if (_handleHookDetachedNode(currentNode, root)) {
3333
3666
  return true;
3334
3667
  }
3335
3668
  if (_isClobbered(currentNode)) {
3336
3669
  _forceRemove(currentNode);
3337
3670
  return true;
3338
3671
  }
3339
- const tagName = transformCaseFunc(getNodeName ? getNodeName(currentNode) : currentNode.nodeName);
3672
+ const tagName = transformCaseFunc(_readNodeName(currentNode));
3340
3673
  ALLOWED_TAGS2 = _forkSharedAllowlist(hooks.uponSanitizeElement, ALLOWED_TAGS2, DEFAULT_ALLOWED_TAGS, SET_CONFIG_ALLOWED_TAGS);
3341
3674
  _executeHooks(hooks.uponSanitizeElement, currentNode, {
3342
3675
  tagName,
3343
3676
  allowedTags: ALLOWED_TAGS2
3344
3677
  });
3345
- if (currentNode !== root && getParentNode(currentNode) === null) {
3346
- if (IN_PLACE) {
3347
- _neutralizeSubtree(currentNode);
3348
- }
3678
+ if (_handleHookDetachedNode(currentNode, root)) {
3349
3679
  return true;
3350
3680
  }
3351
3681
  if (_isUnsafeNode(currentNode, tagName)) {
@@ -3359,7 +3689,7 @@ function createDOMPurify() {
3359
3689
  }
3360
3690
  return removed;
3361
3691
  }
3362
- const nt2 = getNodeType ? getNodeType(currentNode) : currentNode.nodeType;
3692
+ const nt2 = _readNodeType(currentNode);
3363
3693
  if (nt2 === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
3364
3694
  _forceRemove(currentNode);
3365
3695
  return true;
@@ -3384,38 +3714,43 @@ function createDOMPurify() {
3384
3714
  if (FORBID_ATTR[lcName]) {
3385
3715
  return false;
3386
3716
  }
3387
- if (SAFE_FOR_XML && lcName === "patchsrc") {
3388
- return false;
3389
- }
3390
- if (SAFE_FOR_XML && lcName === "for" && lcTag !== "label" && lcTag !== "output") {
3717
+ if (_isPatchLinkageAttribute(lcName, lcTag)) {
3391
3718
  return false;
3392
3719
  }
3393
3720
  if (SANITIZE_DOM && (lcName === "id" || lcName === "name") && (value in document2 || value in formElement)) {
3394
3721
  return false;
3395
3722
  }
3396
3723
  const nameIsPermitted = ALLOWED_ATTR2[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
3397
- if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName)) ;
3398
- else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) ;
3399
- else if (!nameIsPermitted) {
3400
- if (
3401
- // First condition does a very basic check if a) it's basically a valid custom element tagname AND
3402
- // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
3403
- // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
3404
- _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName, lcTag)) || // Alternative, second condition checks if it's an `is`-attribute, AND
3405
- // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
3406
- lcName === "is" && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))
3407
- ) ;
3408
- else {
3409
- return false;
3410
- }
3411
- } else if (URI_SAFE_ATTRIBUTES[lcName]) ;
3412
- else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) ;
3413
- else if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]) ;
3414
- else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) ;
3415
- else if (value) {
3416
- return false;
3417
- } else ;
3418
- return true;
3724
+ if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName)) {
3725
+ return true;
3726
+ }
3727
+ if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) {
3728
+ return true;
3729
+ }
3730
+ if (!nameIsPermitted) {
3731
+ return (
3732
+ // Condition a) covers a basically valid custom element tag name whose
3733
+ // tag passes the configured tagNameCheck and whose attribute name
3734
+ // passes the configured attributeNameCheck ...
3735
+ _isBasicCustomElement(lcTag) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName, lcTag) || // Condition b) covers an `is` attribute whose value passes the
3736
+ // configured tagNameCheck while customized built-in elements are
3737
+ // allowed.
3738
+ lcName === "is" && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value)
3739
+ );
3740
+ }
3741
+ if (URI_SAFE_ATTRIBUTES[lcName]) {
3742
+ return true;
3743
+ }
3744
+ if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) {
3745
+ return true;
3746
+ }
3747
+ if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]) {
3748
+ return true;
3749
+ }
3750
+ if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) {
3751
+ return true;
3752
+ }
3753
+ return !value;
3419
3754
  };
3420
3755
  const RESERVED_CUSTOM_ELEMENT_NAMES = addToSet({}, ["annotation-xml", "color-profile", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "missing-glyph"]);
3421
3756
  const _isBasicCustomElement = function _isBasicCustomElement2(tagName) {
@@ -3479,33 +3814,33 @@ function createDOMPurify() {
3479
3814
  _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
3480
3815
  value = hookEvent.attrValue;
3481
3816
  if (SANITIZE_NAMED_PROPS && (lcName === "id" || lcName === "name") && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
3482
- _removeAttribute(name, currentNode);
3817
+ _removeAttribute(name, currentNode, attr);
3483
3818
  value = SANITIZE_NAMED_PROPS_PREFIX + value;
3484
3819
  }
3485
3820
  if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
3486
- _removeAttribute(name, currentNode);
3821
+ _removeAttribute(name, currentNode, attr);
3487
3822
  continue;
3488
3823
  }
3489
3824
  if (lcName === "attributename" && stringMatch(value, "href")) {
3490
- _removeAttribute(name, currentNode);
3825
+ _removeAttribute(name, currentNode, attr);
3491
3826
  continue;
3492
3827
  }
3493
3828
  if (hookEvent.forceKeepAttr) {
3494
3829
  continue;
3495
3830
  }
3496
3831
  if (!hookEvent.keepAttr) {
3497
- _removeAttribute(name, currentNode);
3832
+ _removeAttribute(name, currentNode, attr);
3498
3833
  continue;
3499
3834
  }
3500
3835
  if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(SELF_CLOSING_TAG, value)) {
3501
- _removeAttribute(name, currentNode);
3836
+ _removeAttribute(name, currentNode, attr);
3502
3837
  continue;
3503
3838
  }
3504
3839
  if (SAFE_FOR_TEMPLATES) {
3505
3840
  value = _stripTemplateExpressions(value);
3506
3841
  }
3507
3842
  if (!_isValidAttribute(lcTag, lcName, value)) {
3508
- _removeAttribute(name, currentNode);
3843
+ _removeAttribute(name, currentNode, attr);
3509
3844
  continue;
3510
3845
  }
3511
3846
  value = _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value);
@@ -3526,8 +3861,7 @@ function createDOMPurify() {
3526
3861
  if (_isDocumentFragment(shadowNode.content)) {
3527
3862
  _sanitizeShadowDOM2(shadowNode.content);
3528
3863
  }
3529
- const shadowNodeType = getNodeType ? getNodeType(shadowNode) : shadowNode.nodeType;
3530
- if (shadowNodeType === NODE_TYPE.element) {
3864
+ if (_readNodeType(shadowNode) === NODE_TYPE.element) {
3531
3865
  const innerSr = getShadowRoot(shadowNode);
3532
3866
  if (_isDocumentFragment(innerSr)) {
3533
3867
  _sanitizeAttachedShadowRoots(innerSr);
@@ -3549,7 +3883,7 @@ function createDOMPurify() {
3549
3883
  continue;
3550
3884
  }
3551
3885
  const node = item.node;
3552
- const nodeType = getNodeType ? getNodeType(node) : node.nodeType;
3886
+ const nodeType = _readNodeType(node);
3553
3887
  const isElement = nodeType === NODE_TYPE.element;
3554
3888
  const childNodes = getChildNodes(node);
3555
3889
  if (childNodes) {
@@ -3621,7 +3955,7 @@ function createDOMPurify() {
3621
3955
  const inPlace = IN_PLACE && typeof dirty !== "string" && _isNode(dirty);
3622
3956
  if (inPlace) {
3623
3957
  _neutralizePatchLinkage(dirty);
3624
- const nn2 = getNodeName ? getNodeName(dirty) : dirty.nodeName;
3958
+ const nn2 = _readNodeName(dirty);
3625
3959
  if (typeof nn2 === "string") {
3626
3960
  const tagName = transformCaseFunc(nn2);
3627
3961
  if (!ALLOWED_TAGS2[tagName] || FORBID_TAGS[tagName]) {
@@ -3776,7 +4110,7 @@ function createDOMPurify() {
3776
4110
  }
3777
4111
  var purify = createDOMPurify();
3778
4112
 
3779
- // node_modules/.pnpm/marked@18.0.9/node_modules/marked/lib/marked.esm.js
4113
+ // node_modules/.pnpm/marked@18.0.10/node_modules/marked/lib/marked.esm.js
3780
4114
  function C() {
3781
4115
  return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
3782
4116
  }
@@ -3792,7 +4126,7 @@ function A(l3) {
3792
4126
  return s || (s = l3(n), e[n] = s), s;
3793
4127
  };
3794
4128
  }
3795
- function k(l3, e = "") {
4129
+ function d(l3, e = "") {
3796
4130
  let t = typeof l3 == "string" ? l3 : l3.source, n = { replace: (s, r) => {
3797
4131
  let i = typeof r == "string" ? r : r.source;
3798
4132
  return i = i.replace(m.caret, "$1"), t = t.replace(s, i), n;
@@ -3814,24 +4148,24 @@ var q = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
3814
4148
  var Pe = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
3815
4149
  var U = / {0,3}(?:[*+-]|\d{1,9}[.)])/;
3816
4150
  var oe = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/;
3817
- var ae = k(oe).replace(/bull/g, U).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}(?:\s|$)/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex();
3818
- var Se = k(oe).replace(/bull/g, U).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}(?:\s|$)/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
4151
+ var ae = d(oe).replace(/bull/g, U).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}(?:\s|$)/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex();
4152
+ var Se = d(oe).replace(/bull/g, U).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}(?:\s|$)/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
3819
4153
  var K = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table|[ \t]+\n)[^\n]+)*)/;
3820
4154
  var _e = /^[^\n]+/;
3821
4155
  var W = /(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/;
3822
- var $e = k(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", W).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
3823
- var Le = k(/^(bull)([ \t][^\n]*?)?(?:\n|$)/).replace(/bull/g, U).getRegex();
4156
+ var $e = d(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", W).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
4157
+ var Le = d(/^(bull)([ \t][^\n]*?)?(?:\n|$)/).replace(/bull/g, U).getRegex();
3824
4158
  var Q = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
3825
4159
  var X = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
3826
- var Me = k("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n*|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>[^\\n]*\\n*|$)|<![A-Z][\\s\\S]*?(?:>[^\\n]*\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>[^\\n]*\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))", "i").replace("comment", X).replace("tag", Q).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
3827
- var le = (l3) => k(K).replace("hr", q).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~~~)[^\\n]*\\n").replace("list", l3).replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", Q).getRegex();
4160
+ var Me = d("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n*|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>[^\\n]*\\n*|$)|<![A-Z][\\s\\S]*?(?:>[^\\n]*\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>[^\\n]*\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))", "i").replace("comment", X).replace("tag", Q).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
4161
+ var le = (l3) => d(K).replace("hr", q).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list", l3).replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", Q).getRegex();
3828
4162
  var ze = le(/ {0,3}(?:[*+-]|1[.)])[ \t]+[^ \t\n]/);
3829
4163
  var Ee = le(/ {0,3}(?:[*+-]|\d{1,9}[.)])(?:[ \t]|\n|$)/);
3830
- var Ce = k(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", Ee).getRegex();
4164
+ var Ce = d(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", Ee).getRegex();
3831
4165
  var J = { blockquote: Ce, code: we, def: $e, fences: ye, heading: Pe, hr: q, html: Me, lheading: ae, list: Le, newline: Oe, paragraph: ze, table: z, text: _e };
3832
- var se = k("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", q).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3} )[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~~~)[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", Q).getRegex();
3833
- var Ae = { ...J, lheading: Se, table: se, paragraph: k(K).replace("hr", q).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", se).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~~~)[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", Q).getRegex() };
3834
- var Ie = { ...J, html: k(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", X).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, heading: /^(#{1,6})(.*)(?:\n+|$)/, fences: z, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: k(K).replace("hr", q).replace("heading", ` *#{1,6} *[^
4166
+ var se = d("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", q).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3} )[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", Q).getRegex();
4167
+ var Ae = { ...J, lheading: Se, table: se, paragraph: d(K).replace("hr", q).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", se).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", Q).getRegex() };
4168
+ var Ie = { ...J, html: d(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", X).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, heading: /^(#{1,6})(.*)(?:\n+|$)/, fences: z, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: d(K).replace("hr", q).replace("heading", ` *#{1,6} *[^
3835
4169
  ]`).replace("lheading", ae).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() };
3836
4170
  var Be = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
3837
4171
  var De = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
@@ -3840,42 +4174,42 @@ var qe = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}
3840
4174
  var _ = /[\p{P}\p{S}]/u;
3841
4175
  var I = /[\s\p{P}\p{S}]/u;
3842
4176
  var v = /[^\s\p{P}\p{S}]/u;
3843
- var ve = k(/^((?![*_])punctSpace)/, "u").replace(/punctSpace/g, I).getRegex();
4177
+ var ve = d(/^((?![*_])punctSpace)/, "u").replace(/punctSpace/g, I).getRegex();
3844
4178
  var He = /[\p{Pi}\p{Ps}"']/u;
3845
4179
  var ue = /(?!~)[\p{P}\p{S}]/u;
3846
4180
  var Ze = /(?!~)[\s\p{P}\p{S}]/u;
3847
4181
  var Ge = /(?:[^\s\p{P}\p{S}]|~)/u;
3848
- var Qe = k(/link|precode-code|html/, "g").replace("link", /\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-", Te ? "(?<!`)()" : "(^^|[^`])").replace("code", /(?<b>`+)[^`]+\k<b>(?!`)/).replace("html", /<(?! )[^<>]*?>/).getRegex();
4182
+ var Qe = d(/link|precode-code|html/, "g").replace("link", /\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-", Te ? "(?<!`)()" : "(^^|[^`])").replace("code", /(?<b>`+)[^`]+\k<b>(?!`)/).replace("html", /<(?! )[^<>]*?>/).getRegex();
3849
4183
  var ce = /^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/;
3850
- var Ne = k(ce, "u").replace(/punct/g, _).getRegex();
3851
- var je = k(ce, "u").replace(/punct/g, ue).getRegex();
4184
+ var Ne = d(ce, "u").replace(/punct/g, _).getRegex();
4185
+ var je = d(ce, "u").replace(/punct/g, ue).getRegex();
3852
4186
  var Fe = /^(?:\*+(?:((?!\*)(?!openQuote)punct)|([^\s*]))?)|^_+(?:((?!_)(?!openQuote)punct)|([^\s_]))?/;
3853
- var Ue = k(Fe, "u").replace(/openQuote/g, He).replace(/punct/g, _).getRegex();
4187
+ var Ue = d(Fe, "u").replace(/openQuote/g, He).replace(/punct/g, _).getRegex();
3854
4188
  var he = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)";
3855
- var Ke = k(he, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, I).replace(/punct/g, _).getRegex();
3856
- var We = k(he, "gu").replace(/notPunctSpace/g, Ge).replace(/punctSpace/g, Ze).replace(/punct/g, ue).getRegex();
4189
+ var Ke = d(he, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, I).replace(/punct/g, _).getRegex();
4190
+ var We = d(he, "gu").replace(/notPunctSpace/g, Ge).replace(/punctSpace/g, Ze).replace(/punct/g, ue).getRegex();
3857
4191
  var Xe = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)[\\s](\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|(?:(?!\\*)punct|notPunctSpace)(\\*+)(?!\\*)(?=notPunctSpace)";
3858
- var Je = k(Xe, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, I).replace(/punct/g, _).getRegex();
3859
- var Ve = k("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, I).replace(/punct/g, _).getRegex();
4192
+ var Je = d(Xe, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, I).replace(/punct/g, _).getRegex();
4193
+ var Ve = d("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, I).replace(/punct/g, _).getRegex();
3860
4194
  var Ye = "^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)[\\s](_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)|(?:(?!_)punct|notPunctSpace)(_+)(?!_)(?=notPunctSpace)";
3861
- var et = k(Ye, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, I).replace(/punct/g, _).getRegex();
3862
- var tt = k(/^~~?(?:((?!~)punct)|[^\s~])/, "u").replace(/punct/g, _).getRegex();
4195
+ var et = d(Ye, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, I).replace(/punct/g, _).getRegex();
4196
+ var tt = d(/^~~?(?:((?!~)punct)|[^\s~])/, "u").replace(/punct/g, _).getRegex();
3863
4197
  var nt = "^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)";
3864
- var rt = k(nt, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, I).replace(/punct/g, _).getRegex();
3865
- var st = k(/\\(punct)/, "gu").replace(/punct/g, _).getRegex();
3866
- var it = k(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
3867
- var ot = k(X).replace("(?:-->|$)", "-->").getRegex();
3868
- var at = k("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment", ot).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
4198
+ var rt = d(nt, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, I).replace(/punct/g, _).getRegex();
4199
+ var st = d(/\\(punct)/, "gu").replace(/punct/g, _).getRegex();
4200
+ var it = d(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
4201
+ var ot = d(X).replace("(?:-->|$)", "-->").getRegex();
4202
+ var at = d("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment", ot).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
3869
4203
  var G = /(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/;
3870
- var lt = k(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label", G).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]+|(?=\))/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
3871
- var de = k(/^!?\[(label)\]\[(ref)\]/).replace("label", G).replace("ref", W).getRegex();
3872
- var ke = k(/^!?\[(ref)\](?:\[\])?/).replace("ref", W).getRegex();
3873
- var pt = k("reflink|nolink(?!\\()", "g").replace("reflink", de).replace("nolink", ke).getRegex();
4204
+ var lt = d(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label", G).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]+|(?=\))/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
4205
+ var de = d(/^!?\[(label)\]\[(ref)\]/).replace("label", G).replace("ref", W).getRegex();
4206
+ var ke = d(/^!?\[(ref)\](?:\[\])?/).replace("ref", W).getRegex();
4207
+ var pt = d("reflink|nolink(?!\\()", "g").replace("reflink", de).replace("nolink", ke).getRegex();
3874
4208
  var ie = /[hH][tT][tT][pP][sS]?|[fF][tT][pP]/;
3875
4209
  var V = { _backpedal: z, anyPunctuation: st, autolink: it, blockSkip: Qe, br: pe, code: De, del: z, delLDelim: z, delRDelim: z, emStrongLDelim: Ne, emStrongRDelimAst: Ke, emStrongRDelimUnd: Ve, escape: Be, link: lt, nolink: ke, punctuation: ve, reflink: de, reflinkSearch: pt, tag: at, text: qe, url: z };
3876
- var ut = { ...V, emStrongLDelim: Ue, emStrongRDelimAst: Je, emStrongRDelimUnd: et, link: k(/^!?\[(label)\]\((.*?)\)/).replace("label", G).getRegex(), reflink: k(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", G).getRegex() };
3877
- var F = { ...V, emStrongRDelimAst: We, emStrongLDelim: je, delLDelim: tt, delRDelim: rt, url: k(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol", ie).replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, text: k(/^(`+|~+|[^`~])(?:(?=[`~])|(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol", ie).getRegex() };
3878
- var ct = { ...F, br: k(pe).replace("{2,}", "*").getRegex(), text: k(F.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex() };
4210
+ var ut = { ...V, emStrongLDelim: Ue, emStrongRDelimAst: Je, emStrongRDelimUnd: et, link: d(/^!?\[(label)\]\((.*?)\)/).replace("label", G).getRegex(), reflink: d(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", G).getRegex() };
4211
+ var F = { ...V, emStrongRDelimAst: We, emStrongLDelim: je, delLDelim: tt, delRDelim: rt, url: d(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol", ie).replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, text: d(/^(`+|~+|[^`~])(?:(?=[`~])|(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol", ie).getRegex() };
4212
+ var ct = { ...F, br: d(pe).replace("{2,}", "*").getRegex(), text: d(F.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex() };
3879
4213
  var H = { normal: J, gfm: Ae, pedantic: Ie };
3880
4214
  var B = { normal: V, gfm: F, breaks: ct, pedantic: ut };
3881
4215
  var ht = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" };
@@ -4021,20 +4355,20 @@ ${u}` : u, r = r ? `${r}
4021
4355
  ${c}` : c;
4022
4356
  let h = this.lexer.state.top;
4023
4357
  if (this.lexer.state.top = true, this.lexer.blockTokens(c, i, true), this.lexer.state.top = h, n.length === 0) break;
4024
- let d = i.at(-1);
4025
- if (d?.type === "code") break;
4026
- if (d?.type === "blockquote") {
4027
- let T = d, g = n.join(`
4358
+ let k = i.at(-1);
4359
+ if (k?.type === "code") break;
4360
+ if (k?.type === "blockquote") {
4361
+ let T = k, g = n.join(`
4028
4362
  `), w = T.raw + `
4029
4363
  ` + g.replace(this.rules.other.blockquoteSetextReplace2, ""), M = this.blockquote(w);
4030
4364
  i[i.length - 1] = M, s = `${s}
4031
4365
  ${g}`, r = r.substring(0, r.length - T.text.length) + M.text;
4032
4366
  break;
4033
- } else if (d?.type === "list") {
4034
- let T = d, g = T.raw + `
4367
+ } else if (k?.type === "list") {
4368
+ let T = k, g = T.raw + `
4035
4369
  ` + n.join(`
4036
4370
  `), w = this.list(g);
4037
- i[i.length - 1] = w, s = s.substring(0, s.length - d.raw.length) + w.raw, r = r.substring(0, r.length - T.raw.length) + w.raw, n = g.substring(i.at(-1).raw.length).split(`
4371
+ i[i.length - 1] = w, s = s.substring(0, s.length - k.raw.length) + w.raw, r = r.substring(0, r.length - T.raw.length) + w.raw, n = g.substring(i.at(-1).raw.length).split(`
4038
4372
  `);
4039
4373
  continue;
4040
4374
  }
@@ -4053,23 +4387,23 @@ ${g}`, r = r.substring(0, r.length - T.text.length) + M.text;
4053
4387
  if (!(t = i.exec(e)) || this.rules.block.hr.test(e)) break;
4054
4388
  u = t[0], e = e.substring(u.length);
4055
4389
  let h = me(t[2].split(`
4056
- `, 1)[0], t[1].length), d = e.split(`
4390
+ `, 1)[0], t[1].length), k = e.split(`
4057
4391
  `, 1)[0], T = !h.trim(), g = 0;
4058
- if (this.options.pedantic ? (g = 2, c = h.trimStart()) : T ? g = t[1].length + 1 : (g = h.search(this.rules.other.nonSpaceChar), g = g > 4 ? 1 : g, c = h.slice(g), g += t[1].length), T && this.rules.other.blankLine.test(d) && (u += d + `
4059
- `, e = e.substring(d.length + 1), a = true), !a) {
4392
+ if (this.options.pedantic ? (g = 2, c = h.trimStart()) : T ? g = t[1].length + 1 : (g = h.search(this.rules.other.nonSpaceChar), g = g > 4 ? 1 : g, c = h.slice(g), g += t[1].length), T && this.rules.other.blankLine.test(k) && (u += k + `
4393
+ `, e = e.substring(k.length + 1), a = true), !a) {
4060
4394
  let w = this.rules.other.nextBulletRegex(g), M = this.rules.other.hrRegex(g), ne = this.rules.other.fencesBeginRegex(g), re = this.rules.other.headingBeginRegex(g), be = this.rules.other.htmlBeginRegex(g), Re = this.rules.other.blockquoteBeginRegex(g);
4061
4395
  for (; e; ) {
4062
4396
  let N = e.split(`
4063
4397
  `, 1)[0], D;
4064
- if (d = N, this.options.pedantic ? (d = d.replace(this.rules.other.listReplaceNesting, " "), D = d) : D = d.replace(this.rules.other.tabCharGlobal, " "), ne.test(d) || re.test(d) || be.test(d) || Re.test(d) || w.test(d) || M.test(d)) break;
4065
- if (D.search(this.rules.other.nonSpaceChar) >= g || !d.trim()) c += `
4398
+ if (k = N, this.options.pedantic ? (k = k.replace(this.rules.other.listReplaceNesting, " "), D = k) : D = k.replace(this.rules.other.tabCharGlobal, " "), ne.test(k) || re.test(k) || be.test(k) || Re.test(k) || w.test(k) || M.test(k)) break;
4399
+ if (D.search(this.rules.other.nonSpaceChar) >= g || !k.trim()) c += `
4066
4400
  ` + D.slice(g);
4067
4401
  else {
4068
4402
  if (T || h.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4 || ne.test(h) || re.test(h) || M.test(h)) break;
4069
4403
  c += `
4070
- ` + d;
4404
+ ` + k;
4071
4405
  }
4072
- T = !d.trim(), u += N + `
4406
+ T = !k.trim(), u += N + `
4073
4407
  `, e = e.substring(N.length + 1), h = D.slice(g);
4074
4408
  }
4075
4409
  }
@@ -4079,8 +4413,11 @@ ${g}`, r = r.substring(0, r.length - T.text.length) + M.text;
4079
4413
  if (p) p.raw = p.raw.trimEnd(), p.text = p.text.trimEnd();
4080
4414
  else return;
4081
4415
  r.raw = r.raw.trimEnd();
4416
+ for (let a of r.items) if (this.lexer.state.top = false, a.tokens = this.lexer.blockTokens(a.text, []), !r.loose) {
4417
+ let u = a.tokens.filter((h) => h.type === "space"), c = u.length > 0 && u.some((h) => this.rules.other.anyLine.test(h.raw));
4418
+ r.loose = c;
4419
+ }
4082
4420
  for (let a of r.items) {
4083
- this.lexer.state.top = false, a.tokens = this.lexer.blockTokens(a.text, []);
4084
4421
  let u = a.tokens[0];
4085
4422
  if (a.task && (u?.type === "text" || u?.type === "paragraph")) {
4086
4423
  a.text = a.text.replace(this.rules.other.listReplaceTask, ""), u.raw = u.raw.replace(this.rules.other.listReplaceTask, ""), u.text = u.text.replace(this.rules.other.listReplaceTask, "");
@@ -4094,10 +4431,6 @@ ${g}`, r = r.substring(0, r.length - T.text.length) + M.text;
4094
4431
  a.checked = h.checked, r.loose ? a.tokens[0] && ["paragraph", "text"].includes(a.tokens[0].type) && "tokens" in a.tokens[0] && a.tokens[0].tokens ? (a.tokens[0].raw = h.raw + a.tokens[0].raw, a.tokens[0].text = h.raw + a.tokens[0].text, a.tokens[0].tokens.unshift(h)) : a.tokens.unshift({ type: "paragraph", raw: h.raw, text: h.raw, tokens: [h] }) : a.tokens.unshift(h);
4095
4432
  }
4096
4433
  } else a.task && (a.task = false);
4097
- if (!r.loose) {
4098
- let c = a.tokens.filter((d) => d.type === "space"), h = c.length > 0 && c.some((d) => this.rules.other.anyLine.test(d.raw));
4099
- r.loose = h;
4100
- }
4101
4434
  }
4102
4435
  if (r.loose) for (let a of r.items) {
4103
4436
  a.loose = true;
@@ -4201,8 +4534,8 @@ ${g}`, r = r.substring(0, r.length - T.text.length) + M.text;
4201
4534
  let s = this.rules.inline.emStrongLDelim.exec(e);
4202
4535
  if (!s || !s[1] && !s[2] && !s[3] && !s[4] || s[4] && n.match(this.rules.other.unicodeAlphaNumeric)) return;
4203
4536
  if (!(s[1] || s[3] || "") || !n || this.rules.inline.punctuation.exec(n)) {
4204
- let i = [...s[0]].length - 1, o, p, a = i, u = 0, c = s[0][0], h = n === c, d = c === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
4205
- for (d.lastIndex = 0, t = t.slice(-1 * e.length + i); (s = d.exec(t)) !== null; ) {
4537
+ let i = [...s[0]].length - 1, o, p, a = i, u = 0, c = s[0][0], h = n === c, k = c === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
4538
+ for (k.lastIndex = 0, t = t.slice(-1 * e.length + i); (s = k.exec(t)) !== null; ) {
4206
4539
  if (o = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !o) continue;
4207
4540
  if (p = [...o].length, s[3] || s[4]) {
4208
4541
  a += p;
@@ -4250,8 +4583,8 @@ ${g}`, r = r.substring(0, r.length - T.text.length) + M.text;
4250
4583
  }
4251
4584
  if (a -= p, a > 0) continue;
4252
4585
  p = Math.min(p, p + a);
4253
- let c = [...s[0]][0].length, h = e.slice(0, i + s.index + c + p), d = h.slice(i, -i);
4254
- return { type: "del", raw: h, text: d, tokens: this.lexer.inlineTokens(d) };
4586
+ let c = [...s[0]][0].length, h = e.slice(0, i + s.index + c + p), k = h.slice(i, -i);
4587
+ return { type: "del", raw: h, text: k, tokens: this.lexer.inlineTokens(k) };
4255
4588
  }
4256
4589
  }
4257
4590
  }
@@ -4423,7 +4756,7 @@ var x = class l {
4423
4756
  let o = Object.keys(this.tokens.links);
4424
4757
  o.length > 0 && (n = n.replace(this.tokenizer.rules.inline.reflinkSearch, (p) => o.includes(p.slice(p.lastIndexOf("[") + 1, -1)) ? "[" + "a".repeat(p.length - 2) + "]" : p));
4425
4758
  }
4426
- n = n.replace(this.tokenizer.rules.inline.anyPunctuation, "++"), n = n.replace(this.tokenizer.rules.inline.blockSkip, (o, p, a) => {
4759
+ n = n.replace(this.tokenizer.rules.inline.anyPunctuation, (o) => "+".repeat(o.length)), n = n.replace(this.tokenizer.rules.inline.blockSkip, (o, p, a) => {
4427
4760
  let u = a ? a.length : 0;
4428
4761
  return o.slice(0, u) + "[" + "a".repeat(o.length - u - 2) + "]";
4429
4762
  }), n = this.options.hooks?.emStrongMask?.call({ lexer: this }, n) ?? n;
@@ -4969,8 +5302,8 @@ var Z = class {
4969
5302
  if (i.hooks && (i.hooks.options = i, i.hooks.block = e), i.async) return (async () => {
4970
5303
  let p = i.hooks ? await i.hooks.preprocess(n) : n, u = await (i.hooks ? await i.hooks.provideLexer(e) : e ? x.lex : x.lexInline)(p, i), c = i.hooks ? await i.hooks.processAllTokens(u) : u;
4971
5304
  i.walkTokens && await Promise.all(this.walkTokens(c, i.walkTokens));
4972
- let d = await (i.hooks ? await i.hooks.provideParser(e) : e ? b.parse : b.parseInline)(c, i);
4973
- return i.hooks ? await i.hooks.postprocess(d) : d;
5305
+ let k = await (i.hooks ? await i.hooks.provideParser(e) : e ? b.parse : b.parseInline)(c, i);
5306
+ return i.hooks ? await i.hooks.postprocess(k) : k;
4974
5307
  })().catch(o);
4975
5308
  try {
4976
5309
  i.hooks && (n = i.hooks.preprocess(n));
@@ -5103,46 +5436,43 @@ function sanitizer() {
5103
5436
  }
5104
5437
  return purifier;
5105
5438
  }
5106
- function renderMarkdown(text3, options) {
5439
+ function renderMarkdown(text4, options) {
5107
5440
  const allowImages = options?.allowImages === true;
5108
- const rendered = parser.parse(text3, { async: false });
5441
+ const rendered = parser.parse(text4, { async: false });
5109
5442
  return sanitizer().sanitize(rendered, allowImages ? SANITIZE_CONFIG_WITH_IMAGES : SANITIZE_CONFIG).trim();
5110
5443
  }
5111
5444
 
5112
5445
  // src/ui/resize_handle.ts
5113
5446
  var MIN_WIDTH = 280;
5114
5447
  var MIN_HEIGHT = 240;
5115
- function createResizeHandle(options) {
5448
+ var STEP2 = 16;
5449
+ var COARSE_STEP2 = 64;
5450
+ function createResizeHandle(grip, options) {
5116
5451
  const handle = document.createElement("div");
5117
- handle.className = "resize-handle";
5118
- handle.setAttribute("part", "resize-handle");
5452
+ handle.className = `resize-handle resize-handle--${gripName(grip)}`;
5453
+ handle.setAttribute("part", `resize-handle resize-handle-${gripName(grip)}`);
5119
5454
  handle.setAttribute("role", "separator");
5455
+ if (grip.x === void 0) {
5456
+ handle.setAttribute("aria-orientation", "horizontal");
5457
+ } else if (grip.y === void 0) {
5458
+ handle.setAttribute("aria-orientation", "vertical");
5459
+ }
5120
5460
  handle.setAttribute("aria-label", options.label);
5121
5461
  handle.tabIndex = 0;
5122
- const sizeAt = (axis, anchor, rect, x2, y2) => {
5123
- const width = anchor.x === "right" ? rect.right - x2 : x2 - rect.left;
5124
- const clamped = { width: Math.max(MIN_WIDTH, width) };
5125
- if (axis !== "both") {
5126
- return clamped;
5127
- }
5128
- const height = anchor.y === "bottom" ? rect.bottom - y2 : y2 - rect.top;
5129
- return { ...clamped, height: Math.max(MIN_HEIGHT, height) };
5130
- };
5131
5462
  handle.addEventListener("pointerdown", (event) => {
5132
5463
  const axis = options.axis();
5133
- if (axis === "none") {
5464
+ if (axis === "none" || !movable(grip, axis)) {
5134
5465
  return;
5135
5466
  }
5136
- const anchor = options.anchor();
5137
5467
  const rect = options.rect();
5138
5468
  const onMove = (move) => {
5139
- options.apply(sizeAt(axis, anchor, rect, move.clientX, move.clientY));
5469
+ options.apply(boxAt(grip, axis, rect, move.clientX, move.clientY));
5140
5470
  };
5141
5471
  const onUp = (up) => {
5142
5472
  window.removeEventListener("pointermove", onMove);
5143
5473
  window.removeEventListener("pointerup", onUp);
5144
5474
  handle.removeAttribute("data-dragging");
5145
- options.commit(sizeAt(axis, anchor, rect, up.clientX, up.clientY));
5475
+ options.commit(boxAt(grip, axis, rect, up.clientX, up.clientY));
5146
5476
  };
5147
5477
  handle.setAttribute("data-dragging", "true");
5148
5478
  window.addEventListener("pointermove", onMove);
@@ -5154,34 +5484,28 @@ function createResizeHandle(options) {
5154
5484
  if (pending === null) {
5155
5485
  return;
5156
5486
  }
5157
- const size = pending;
5487
+ const box = pending;
5158
5488
  pending = null;
5159
- options.commit(size);
5489
+ options.commit(box);
5160
5490
  };
5161
5491
  handle.addEventListener("keydown", (event) => {
5162
5492
  const axis = options.axis();
5163
- if (axis === "none") {
5493
+ if (axis === "none" || !movable(grip, axis)) {
5164
5494
  return;
5165
5495
  }
5166
- const anchor = options.anchor();
5496
+ const step = event.shiftKey ? COARSE_STEP2 : STEP2;
5167
5497
  const rect = options.rect();
5168
- const step = event.shiftKey ? 64 : 16;
5169
- const outward = anchor.x === "right" ? -1 : 1;
5170
- const width = rect.right - rect.left;
5171
- const height = rect.bottom - rect.top;
5172
- let next = null;
5173
- if (event.key === "ArrowLeft") {
5174
- next = { width: Math.max(MIN_WIDTH, width - step * outward) };
5175
- } else if (event.key === "ArrowRight") {
5176
- next = { width: Math.max(MIN_WIDTH, width + step * outward) };
5177
- } else if (axis === "both" && (event.key === "ArrowUp" || event.key === "ArrowDown")) {
5178
- const grow = event.key === (anchor.y === "bottom" ? "ArrowUp" : "ArrowDown");
5179
- next = { height: Math.max(MIN_HEIGHT, height + (grow ? step : -step)) };
5498
+ const delta = ARROWS[event.key];
5499
+ if (delta === void 0) {
5500
+ return;
5180
5501
  }
5181
- if (next === null) {
5502
+ if (delta.x !== 0 && grip.x === void 0 || delta.y !== 0 && grip.y === void 0) {
5182
5503
  return;
5183
5504
  }
5184
5505
  event.preventDefault();
5506
+ const x2 = (grip.x === "left" ? rect.left : rect.right) + delta.x * step;
5507
+ const y2 = (grip.y === "top" ? rect.top : rect.bottom) + delta.y * step;
5508
+ const next = boxAt(grip, axis, rect, x2, y2);
5185
5509
  options.apply(next);
5186
5510
  pending = next;
5187
5511
  });
@@ -5189,6 +5513,26 @@ function createResizeHandle(options) {
5189
5513
  handle.addEventListener("blur", settle);
5190
5514
  return handle;
5191
5515
  }
5516
+ var ARROWS = {
5517
+ ArrowLeft: { x: -1, y: 0 },
5518
+ ArrowRight: { x: 1, y: 0 },
5519
+ ArrowUp: { x: 0, y: -1 },
5520
+ ArrowDown: { x: 0, y: 1 }
5521
+ };
5522
+ function gripName(grip) {
5523
+ return [grip.y, grip.x].filter((side) => side !== void 0).join("-");
5524
+ }
5525
+ function movable(grip, axis) {
5526
+ return axis === "both" || grip.x !== void 0;
5527
+ }
5528
+ function boxAt(grip, axis, rect, x2, y2) {
5529
+ const left = grip.x === "left" ? Math.min(x2, rect.right - MIN_WIDTH) : rect.left;
5530
+ const right = grip.x === "right" ? Math.max(x2, rect.left + MIN_WIDTH) : rect.right;
5531
+ const vertical = axis === "both";
5532
+ const top = vertical && grip.y === "top" ? Math.min(y2, rect.bottom - MIN_HEIGHT) : rect.top;
5533
+ const bottom = vertical && grip.y === "bottom" ? Math.max(y2, rect.top + MIN_HEIGHT) : rect.bottom;
5534
+ return { left, top, right, bottom };
5535
+ }
5192
5536
 
5193
5537
  // src/ui/reveal_words.ts
5194
5538
  function collectTextNodes(root, out) {
@@ -5226,7 +5570,7 @@ function wrapWords(root) {
5226
5570
  }
5227
5571
 
5228
5572
  // src/ui/run_notice.ts
5229
- function renderRunNotice(icon, text3, kind) {
5573
+ function renderRunNotice(icon, text4, kind) {
5230
5574
  const notice = document.createElement("div");
5231
5575
  notice.className = `run-notice run-notice--${kind}`;
5232
5576
  notice.setAttribute("part", `run-notice run-notice-${kind}`);
@@ -5239,7 +5583,7 @@ function renderRunNotice(icon, text3, kind) {
5239
5583
  const label = document.createElement("span");
5240
5584
  label.className = "run-notice-text";
5241
5585
  label.setAttribute("part", "run-notice-text");
5242
- label.textContent = text3;
5586
+ label.textContent = text4;
5243
5587
  notice.append(glyph, label);
5244
5588
  return notice;
5245
5589
  }
@@ -5495,6 +5839,30 @@ var STYLES = `
5495
5839
  --_text: var(--ag-ui-text, var(--_fg));
5496
5840
  --_surface: var(--ag-ui-surface, transparent);
5497
5841
 
5842
+ /* Message action row: the control box and the mark inside it. The box has a
5843
+ floor of 24px so it stays a reliable target at every density. */
5844
+ --_action-size: var(--ag-ui-action-size, 28px);
5845
+ --_action-icon-size: var(--ag-ui-action-icon-size, 15px);
5846
+ --_tooltip-bg: var(--ag-ui-tooltip-bg, #1f2430);
5847
+ --_tooltip-fg: var(--ag-ui-tooltip-fg, #f5f6fa);
5848
+
5849
+ /* Text and marks drawn on top of the accent and danger fills. Separate
5850
+ tokens because they are not free: a host that themes the accent to a pale
5851
+ colour has white-on-pale with no way to correct it, which is the one
5852
+ theming change that makes a control unreadable rather than merely off. */
5853
+ --_on-accent: var(--ag-ui-on-accent, #ffffff);
5854
+ --_on-danger: var(--ag-ui-on-danger, #ffffff);
5855
+
5856
+ /* Resize grips: the corner squares and the edge strips between them. Wide
5857
+ enough to hit without being wide enough to swallow a click on the content
5858
+ underneath, and adjustable for a host with a coarser pointer. */
5859
+ --_grip-corner: var(--ag-ui-grip-corner, 14px);
5860
+ --_grip-edge: var(--ag-ui-grip-edge, 6px);
5861
+ --_grip-edge-docked: var(--ag-ui-grip-edge-docked, 8px);
5862
+ /* The mark drawn inside a grip, as opposed to the area it answers to. */
5863
+ --_grip-mark-length: var(--ag-ui-grip-mark-length, 28px);
5864
+ --_grip-mark-thickness: var(--ag-ui-grip-mark-thickness, 3px);
5865
+
5498
5866
  /* Status accents for tool-call cards. */
5499
5867
  --_success: var(--ag-ui-success, #15803d);
5500
5868
  --_danger: var(--ag-ui-danger, #b91c1c);
@@ -5505,6 +5873,12 @@ var STYLES = `
5505
5873
  --_tool-icon-done: var(--ag-ui-tool-icon-done, "\u2713");
5506
5874
  --_tool-icon-error: var(--ag-ui-tool-icon-error, "\u2715");
5507
5875
  --_tool-icon-declined: var(--ag-ui-tool-icon-declined, "\u2298");
5876
+
5877
+ /* Disclosure marks on every expandable row. Tokenised for the same reason
5878
+ the status icons above are: a host re-theming one set and not the other
5879
+ ends up with two vocabularies in one transcript. */
5880
+ --_disclosure-collapsed: var(--ag-ui-disclosure-collapsed, "\u25B8");
5881
+ --_disclosure-expanded: var(--ag-ui-disclosure-expanded, "\u25BE");
5508
5882
  --_tool-spin-duration: var(--ag-ui-tool-spin-duration, 0.7s);
5509
5883
 
5510
5884
  /* Answer well (opt-in via data-answer-well) \u2014 boxes a whole assistant turn. */
@@ -5785,6 +6159,9 @@ var STYLES = `
5785
6159
  font: inherit;
5786
6160
  cursor: pointer;
5787
6161
  pointer-events: auto;
6162
+ /* A touch drag on the launcher moves it; without this the page scrolls under
6163
+ the finger instead and the launcher never moves at all. */
6164
+ touch-action: none;
5788
6165
  opacity: 0;
5789
6166
  transform: scale(0.4);
5790
6167
  visibility: hidden;
@@ -5814,6 +6191,15 @@ var STYLES = `
5814
6191
  transform: scale(0.94);
5815
6192
  }
5816
6193
 
6194
+ /* A drag is a press and a hover at the same time, so both scale rules above are
6195
+ live throughout it. Cancelling them is what keeps the launcher the size of
6196
+ the thing under the pointer while it travels; the position itself comes from
6197
+ inset, which nothing here transitions, so it tracks the pointer exactly. */
6198
+ :host([collapsed]) .launcher[data-dragging] {
6199
+ transform: none;
6200
+ cursor: grabbing;
6201
+ }
6202
+
5817
6203
  .launcher .icon-holder {
5818
6204
  width: var(--_launcher-icon-size);
5819
6205
  height: var(--_launcher-icon-size);
@@ -6008,6 +6394,31 @@ var STYLES = `
6008
6394
  transform-origin: bottom left;
6009
6395
  }
6010
6396
 
6397
+ /* Once the launcher has been dragged the element places itself, and stamps the
6398
+ corner it chose to open away from. The morph has to start at that same
6399
+ corner: scaling out of the one the placement originally guessed reads as the
6400
+ panel leaping across the screen before it opens.
6401
+
6402
+ Equal specificity to the placement rule above, so source order is what lets
6403
+ the stamped value win -- the same arrangement the resize grip uses, and the
6404
+ same trap. Write these with = on the whole hyphenated token; a ~= would match
6405
+ whitespace-separated words and so could never match at all. */
6406
+ :host([data-expand-corner="top-left"]) .chat {
6407
+ transform-origin: top left;
6408
+ }
6409
+
6410
+ :host([data-expand-corner="top-right"]) .chat {
6411
+ transform-origin: top right;
6412
+ }
6413
+
6414
+ :host([data-expand-corner="bottom-left"]) .chat {
6415
+ transform-origin: bottom left;
6416
+ }
6417
+
6418
+ :host([data-expand-corner="bottom-right"]) .chat {
6419
+ transform-origin: bottom right;
6420
+ }
6421
+
6011
6422
  /* The two in-flow placements keep the original collapse: hide the body, let
6012
6423
  the host shrink to the header bar. */
6013
6424
  :host([collapsed]:is([placement="embedded"], [placement="page"])) {
@@ -6433,11 +6844,11 @@ var STYLES = `
6433
6844
  }
6434
6845
 
6435
6846
  .thoughts-toggle::before {
6436
- content: "\u25BE ";
6847
+ content: var(--_disclosure-expanded) " ";
6437
6848
  }
6438
6849
 
6439
6850
  .thoughts-toggle[aria-expanded="false"]::before {
6440
- content: "\u25B8 ";
6851
+ content: var(--_disclosure-collapsed) " ";
6441
6852
  }
6442
6853
 
6443
6854
  /* A gentle pulse on the label while reasoning is still streaming. */
@@ -6779,14 +7190,14 @@ var STYLES = `
6779
7190
  }
6780
7191
 
6781
7192
  .subagent-row::after {
6782
- content: "\u25B8";
7193
+ content: var(--_disclosure-collapsed);
6783
7194
  flex: none;
6784
7195
  margin-left: auto;
6785
7196
  color: var(--_accent);
6786
7197
  }
6787
7198
 
6788
7199
  .subagent-row[aria-expanded="true"]::after {
6789
- content: "\u25BE";
7200
+ content: var(--_disclosure-expanded);
6790
7201
  }
6791
7202
 
6792
7203
  .subagent-row:disabled::after {
@@ -6913,16 +7324,23 @@ var STYLES = `
6913
7324
  }
6914
7325
 
6915
7326
  .tool-call-toggle::before {
6916
- content: "\u25B8 ";
7327
+ content: var(--_disclosure-collapsed) " ";
6917
7328
  }
6918
7329
 
6919
7330
  .tool-call-toggle[aria-expanded="true"]::before {
6920
- content: "\u25BE ";
7331
+ content: var(--_disclosure-expanded) " ";
6921
7332
  }
6922
7333
 
6923
- /* Resize handle: a corner grip on a floating panel, an edge grip on a docked
6924
- one. Absent entirely where the placement is full-bleed, since there is
6925
- nothing to drag. */
7334
+ /* Resize grips: every edge and every corner, so the panel can be dragged from
7335
+ whichever side the reader is already near. Absent entirely where the
7336
+ placement is full-bleed, since there is nothing to drag.
7337
+
7338
+ The whole set is always laid out. Which edges the *layout* pins is not a
7339
+ question the stylesheet needs to answer any more -- it decided where the one
7340
+ grip went, and there is no longer one grip. The element still measures and
7341
+ stamps data-resize-anchor, because it decides what a drag on a pinned edge
7342
+ costs in position and which grip carries the tab stop, but no rule here
7343
+ reads it. */
6926
7344
  .resize-handle {
6927
7345
  position: absolute;
6928
7346
  z-index: 2;
@@ -6935,95 +7353,102 @@ var STYLES = `
6935
7353
  outline-offset: -2px;
6936
7354
  }
6937
7355
 
6938
- /* The grip sits on the corner opposite the panel's anchor, because a resize
6939
- measures from whichever edge is not moving.
7356
+ /* Corners first in the file and last in the DOM, so they take the pointer
7357
+ where they overlap an edge strip. */
7358
+ .resize-handle--top-left,
7359
+ .resize-handle--top-right,
7360
+ .resize-handle--bottom-left,
7361
+ .resize-handle--bottom-right {
7362
+ width: var(--_grip-corner);
7363
+ height: var(--_grip-corner);
7364
+ }
6940
7365
 
6941
- Default is floating: pinned bottom-right, so the grip is top-left. */
6942
- .resize-handle {
7366
+ .resize-handle--top-left {
6943
7367
  top: 0;
6944
7368
  left: 0;
6945
- width: 14px;
6946
- height: 14px;
6947
7369
  cursor: nwse-resize;
6948
7370
  }
6949
7371
 
6950
- /* Placement is only the opening guess, and these two rules are all it is good
6951
- for. Embedded sits in normal flow, pinned top-left, so it grows bottom-right;
6952
- bottom-left is pinned there, so its free corner is top-right. */
6953
- :host([placement="embedded"]) .resize-handle {
6954
- top: auto;
6955
- left: auto;
7372
+ .resize-handle--top-right {
7373
+ top: 0;
6956
7374
  right: 0;
6957
- bottom: 0;
6958
- cursor: nwse-resize;
7375
+ cursor: nesw-resize;
6959
7376
  }
6960
7377
 
6961
- :host([placement="bottom-left"]) .resize-handle {
6962
- left: auto;
6963
- right: 0;
7378
+ .resize-handle--bottom-left {
7379
+ bottom: 0;
7380
+ left: 0;
6964
7381
  cursor: nesw-resize;
6965
7382
  }
6966
7383
 
6967
- /* Then the measurement corrects it. Which edges are held still belongs to the
6968
- host's layout, not to placement -- a floating panel a host right-aligns is
6969
- anchored bottom-left -- so the element measures them and stamps a single
6970
- hyphenated "<y>-<x>" token here. Equal specificity to the rules above, so
6971
- source order is what lets the measured value win.
6972
-
6973
- Two traps, both of which silently draw the grip on the corner that moves:
6974
-
6975
- Never write these as [data-resize-anchor~="left"]. The stamped value is one
6976
- hyphenated token and ~= matches whitespace-separated words, so it can never
6977
- match.
6978
-
6979
- Each rule must set both sides of its axis, not only the side it moves, or it
6980
- cannot undo a placement guess that flipped the other way. */
6981
- :host([data-resize-anchor$="-left"]) .resize-handle {
6982
- left: auto;
7384
+ .resize-handle--bottom-right {
7385
+ bottom: 0;
6983
7386
  right: 0;
7387
+ cursor: nwse-resize;
7388
+ }
7389
+
7390
+ /* Edge strips, held clear of the corners at both ends so a corner drag is
7391
+ never swallowed by the edge next to it. */
7392
+ .resize-handle--left,
7393
+ .resize-handle--right {
7394
+ top: var(--_grip-corner);
7395
+ bottom: var(--_grip-corner);
7396
+ width: var(--_grip-edge);
7397
+ cursor: ew-resize;
6984
7398
  }
6985
7399
 
6986
- :host([data-resize-anchor$="-right"]) .resize-handle {
7400
+ .resize-handle--left {
6987
7401
  left: 0;
6988
- right: auto;
6989
7402
  }
6990
7403
 
6991
- :host([data-resize-anchor^="top-"]) .resize-handle {
6992
- top: auto;
6993
- bottom: 0;
7404
+ .resize-handle--right {
7405
+ right: 0;
6994
7406
  }
6995
7407
 
6996
- :host([data-resize-anchor^="bottom-"]) .resize-handle {
6997
- top: 0;
6998
- bottom: auto;
7408
+ .resize-handle--top,
7409
+ .resize-handle--bottom {
7410
+ left: var(--_grip-corner);
7411
+ right: var(--_grip-corner);
7412
+ height: var(--_grip-edge);
7413
+ cursor: ns-resize;
6999
7414
  }
7000
7415
 
7001
- /* One axis flipped means the drag runs along the other diagonal. */
7002
- :host([data-resize-anchor="top-left"]) .resize-handle,
7003
- :host([data-resize-anchor="bottom-right"]) .resize-handle {
7004
- cursor: nwse-resize;
7416
+ .resize-handle--top {
7417
+ top: 0;
7005
7418
  }
7006
7419
 
7007
- :host([data-resize-anchor="top-right"]) .resize-handle,
7008
- :host([data-resize-anchor="bottom-left"]) .resize-handle {
7009
- cursor: nesw-resize;
7420
+ .resize-handle--bottom {
7421
+ bottom: 0;
7010
7422
  }
7011
7423
 
7012
- /* Docked: the placement owns the height, so only the inner edge is the user's --
7013
- an edge, not a corner, so this outranks the measured anchor by coming after. */
7014
- :host([placement="sidebar"]) .resize-handle,
7015
- :host([placement="side"]) .resize-handle {
7016
- top: 0;
7017
- bottom: auto;
7018
- width: 8px;
7019
- height: 100%;
7020
- cursor: ew-resize;
7424
+ /* Docked: the placement owns the height, so the horizontal edges and every
7425
+ corner are inert and must not advertise a drag that does nothing. The two
7426
+ vertical edges remain, which is the same affordance these placements had
7427
+ when there was one grip -- now on both sides, since either may be the inner
7428
+ one depending on which side the rail is docked to. */
7429
+ :host([placement="sidebar"]) .resize-handle--top,
7430
+ :host([placement="sidebar"]) .resize-handle--bottom,
7431
+ :host([placement="sidebar"]) .resize-handle--top-left,
7432
+ :host([placement="sidebar"]) .resize-handle--top-right,
7433
+ :host([placement="sidebar"]) .resize-handle--bottom-left,
7434
+ :host([placement="sidebar"]) .resize-handle--bottom-right,
7435
+ :host([placement="side"]) .resize-handle--top,
7436
+ :host([placement="side"]) .resize-handle--bottom,
7437
+ :host([placement="side"]) .resize-handle--top-left,
7438
+ :host([placement="side"]) .resize-handle--top-right,
7439
+ :host([placement="side"]) .resize-handle--bottom-left,
7440
+ :host([placement="side"]) .resize-handle--bottom-right {
7441
+ display: none;
7021
7442
  }
7022
7443
 
7023
- /* Docked to the left, so the inner edge is the right-hand one. */
7024
- :host([placement="sidebar"][data-side="left"]) .resize-handle {
7025
- left: auto;
7026
- right: 0;
7444
+ /* The vertical edges run the full height once no corner shares them. */
7445
+ :host([placement="sidebar"]) .resize-handle--left,
7446
+ :host([placement="sidebar"]) .resize-handle--right,
7447
+ :host([placement="side"]) .resize-handle--left,
7448
+ :host([placement="side"]) .resize-handle--right {
7449
+ top: 0;
7450
+ bottom: 0;
7451
+ width: var(--_grip-edge-docked);
7027
7452
  }
7028
7453
 
7029
7454
  /* Full-bleed: nothing to drag. */
@@ -7032,9 +7457,62 @@ var STYLES = `
7032
7457
  display: none;
7033
7458
  }
7034
7459
 
7035
- .resize-handle[data-dragging] {
7460
+ /* The visible mark on a grip.
7461
+
7462
+ Filling the whole strip was what the single corner grip did, and at 14px
7463
+ square nobody ever saw it. On a strip running the length of an edge the same
7464
+ fill reads as a border the panel grew -- square ended, stopping short of the
7465
+ corner radius at both ends, and easily mistaken for a rendering fault rather
7466
+ than for something to grab.
7467
+
7468
+ So the hit area stays the full strip and the mark is a short pill centred on
7469
+ it, which cannot be read as an edge of anything and never meets the radius.
7470
+
7471
+ It shows on hover and focus as well as during the drag. With eight grips, a
7472
+ mark that appears only once you are already dragging is a mark that never
7473
+ told anyone the grips were there. */
7474
+ .resize-handle::after {
7475
+ content: "";
7476
+ position: absolute;
7477
+ top: 50%;
7478
+ left: 50%;
7479
+ transform: translate(-50%, -50%);
7480
+ border-radius: 999px;
7036
7481
  background: var(--_accent);
7037
- opacity: 0.35;
7482
+ opacity: 0;
7483
+ transition: opacity var(--_motion) var(--_ease);
7484
+ }
7485
+
7486
+ .resize-handle--top::after,
7487
+ .resize-handle--bottom::after {
7488
+ width: var(--_grip-mark-length);
7489
+ height: var(--_grip-mark-thickness);
7490
+ }
7491
+
7492
+ .resize-handle--left::after,
7493
+ .resize-handle--right::after {
7494
+ width: var(--_grip-mark-thickness);
7495
+ height: var(--_grip-mark-length);
7496
+ }
7497
+
7498
+ /* A corner has no length to run along, so it gets a dot instead of a pill. */
7499
+ .resize-handle--top-left::after,
7500
+ .resize-handle--top-right::after,
7501
+ .resize-handle--bottom-left::after,
7502
+ .resize-handle--bottom-right::after {
7503
+ width: var(--_grip-mark-thickness);
7504
+ height: var(--_grip-mark-thickness);
7505
+ }
7506
+
7507
+ .resize-handle:hover::after,
7508
+ .resize-handle:focus-visible::after {
7509
+ opacity: 0.5;
7510
+ }
7511
+
7512
+ /* Equal specificity to the pair above, so source order is what makes the drag
7513
+ the stronger of the two states. */
7514
+ .resize-handle[data-dragging]::after {
7515
+ opacity: 0.9;
7038
7516
  }
7039
7517
 
7040
7518
  /* \u2500\u2500 Composer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
@@ -7148,7 +7626,7 @@ var STYLES = `
7148
7626
  border: none;
7149
7627
  border-radius: 50%;
7150
7628
  background: var(--_accent);
7151
- color: #ffffff;
7629
+ color: var(--_on-accent);
7152
7630
  font: inherit;
7153
7631
  line-height: 1;
7154
7632
  cursor: pointer;
@@ -7222,13 +7700,13 @@ var STYLES = `
7222
7700
  /* Recording: a red tint + a gentle pulse so it's clearly "live". */
7223
7701
  .voice-btn[data-state="recording"] {
7224
7702
  background: var(--_danger);
7225
- color: #ffffff;
7703
+ color: var(--_on-danger);
7226
7704
  animation: ag-ui-voice-pulse 1.2s ease-in-out infinite;
7227
7705
  }
7228
7706
 
7229
7707
  .voice-btn[data-state="recording"]:hover {
7230
7708
  background: var(--_danger);
7231
- color: #ffffff;
7709
+ color: var(--_on-danger);
7232
7710
  }
7233
7711
 
7234
7712
  @keyframes ag-ui-voice-pulse {
@@ -7518,7 +7996,7 @@ var STYLES = `
7518
7996
  .confirm-btn--confirm {
7519
7997
  border-color: var(--_accent);
7520
7998
  background: var(--_accent);
7521
- color: #ffffff;
7999
+ color: var(--_on-accent);
7522
8000
  }
7523
8001
 
7524
8002
  /* The session waiver. Deliberately the quietest of the three: it is the widest
@@ -7586,16 +8064,29 @@ var STYLES = `
7586
8064
  margin-top: -6px;
7587
8065
  }
7588
8066
 
8067
+ /* The row's controls are icon-only, so the box is the whole target. Sized from
8068
+ a variable a host can raise, with a floor rather than a fixed height: the
8069
+ compact density shrinks the font, and a target that shrinks with it lands
8070
+ under the 24px minimum that makes a control reliably tappable. It used to,
8071
+ at roughly 20px square. */
7589
8072
  .message-action {
8073
+ display: inline-flex;
8074
+ align-items: center;
8075
+ justify-content: center;
8076
+ box-sizing: border-box;
8077
+ min-width: var(--_action-size);
8078
+ min-height: var(--_action-size);
8079
+ padding: 4px;
7590
8080
  border: none;
7591
8081
  border-radius: 6px;
7592
- padding: 2px 6px;
7593
8082
  font: inherit;
7594
8083
  line-height: 1.2;
7595
8084
  cursor: pointer;
7596
8085
  background: transparent;
7597
8086
  color: var(--_muted);
7598
8087
  opacity: 0.75;
8088
+ /* The tooltip below is positioned against this box. */
8089
+ position: relative;
7599
8090
  }
7600
8091
 
7601
8092
  .message-action:hover,
@@ -7604,6 +8095,61 @@ var STYLES = `
7604
8095
  background: var(--_border);
7605
8096
  }
7606
8097
 
8098
+ .message-action-icon {
8099
+ display: inline-flex;
8100
+ width: var(--_action-icon-size);
8101
+ height: var(--_action-icon-size);
8102
+ }
8103
+
8104
+ .message-action-icon .glyph {
8105
+ width: 100%;
8106
+ height: 100%;
8107
+ }
8108
+
8109
+ /* The label, drawn rather than left to the browser.
8110
+
8111
+ A title attribute is the usual answer and covers only half the readers: it
8112
+ never appears on keyboard focus, so tabbing onto an icon-only control shows
8113
+ nothing at all. The attribute stays for the pointer users who expect it, and
8114
+ this shows the same words on hover and on focus alike.
8115
+
8116
+ Left-aligned rather than centred because the row sits at the left edge of an
8117
+ answer inside a scrolling column, and a centred tooltip on the first control
8118
+ is clipped by that column. Growing rightward keeps it inside.
8119
+
8120
+ Not exposed to assistive technology: the button already carries the same
8121
+ string as its accessible name, and this would be a second copy of it. */
8122
+ .message-action::after {
8123
+ content: attr(data-tooltip);
8124
+ position: absolute;
8125
+ bottom: calc(100% + 4px);
8126
+ left: 0;
8127
+ z-index: 3;
8128
+ padding: 3px 6px;
8129
+ border-radius: 4px;
8130
+ background: var(--_tooltip-bg);
8131
+ color: var(--_tooltip-fg);
8132
+ font-size: 11px;
8133
+ line-height: 1.4;
8134
+ white-space: nowrap;
8135
+ pointer-events: none;
8136
+ opacity: 0;
8137
+ transition: opacity var(--_motion) var(--_ease);
8138
+ }
8139
+
8140
+ .message-action:hover::after,
8141
+ .message-action:focus-visible::after {
8142
+ opacity: 1;
8143
+ }
8144
+
8145
+ /* Touch has no hover to reveal it, and a tooltip that latches open under a
8146
+ finger covers the answer it belongs to. */
8147
+ @media (hover: none) {
8148
+ .message-action::after {
8149
+ content: none;
8150
+ }
8151
+ }
8152
+
7607
8153
  .message-action[aria-pressed="true"] {
7608
8154
  opacity: 1;
7609
8155
  color: var(--_accent);
@@ -7661,7 +8207,7 @@ var STYLES = `
7661
8207
  .approval-btn--approve {
7662
8208
  border-color: var(--_accent);
7663
8209
  background: var(--_accent);
7664
- color: #ffffff;
8210
+ color: var(--_on-accent);
7665
8211
  }
7666
8212
 
7667
8213
  /* Question card \u2014 the built-in ask_user prompt (radios and/or free text). */
@@ -7727,7 +8273,7 @@ var STYLES = `
7727
8273
  font-weight: 600;
7728
8274
  cursor: pointer;
7729
8275
  background: var(--_accent);
7730
- color: #ffffff;
8276
+ color: var(--_on-accent);
7731
8277
  }
7732
8278
 
7733
8279
  .question-btn:disabled {
@@ -7996,7 +8542,7 @@ var STYLES = `
7996
8542
  font-weight: 600;
7997
8543
  border-color: var(--_accent);
7998
8544
  background: var(--_accent);
7999
- color: #ffffff;
8545
+ color: var(--_on-accent);
8000
8546
  }
8001
8547
 
8002
8548
  .checkpoint-fork:hover {
@@ -8171,7 +8717,7 @@ var STYLES = `
8171
8717
  border: none;
8172
8718
  border-radius: 6px;
8173
8719
  background: var(--_danger);
8174
- color: #ffffff;
8720
+ color: var(--_on-danger);
8175
8721
  padding: 3px 10px;
8176
8722
  font: inherit;
8177
8723
  cursor: pointer;
@@ -8748,11 +9294,11 @@ function resultLabels(strings) {
8748
9294
  [TOOL_CALL_STATUS.DECLINED]: strings.declinedLabel
8749
9295
  };
8750
9296
  }
8751
- function formatPayload(text3) {
9297
+ function formatPayload(text4) {
8752
9298
  try {
8753
- return JSON.stringify(JSON.parse(text3), null, 2);
9299
+ return JSON.stringify(JSON.parse(text4), null, 2);
8754
9300
  } catch {
8755
- return text3;
9301
+ return text4;
8756
9302
  }
8757
9303
  }
8758
9304
  var ToolCallCard = class {
@@ -8901,7 +9447,7 @@ var ToolCallCard = class {
8901
9447
  * Flip the status pill to `status` and fill in the result region, whose
8902
9448
  * heading names the outcome (result / error / declined).
8903
9449
  */
8904
- settle(status, text3) {
9450
+ settle(status, text4) {
8905
9451
  if (this.#settled) {
8906
9452
  return;
8907
9453
  }
@@ -8911,8 +9457,8 @@ var ToolCallCard = class {
8911
9457
  this.#resultLabel.textContent = resultLabels(this.#strings)[status];
8912
9458
  this.#renderPayload(
8913
9459
  this.#resultBody,
8914
- { kind: "result", toolName: this.#name, status, text: text3 },
8915
- formatPayload(text3)
9460
+ { kind: "result", toolName: this.#name, status, text: text4 },
9461
+ formatPayload(text4)
8916
9462
  );
8917
9463
  this.#resultSection.hidden = false;
8918
9464
  }
@@ -9072,7 +9618,7 @@ var VoiceInput = class {
9072
9618
  this.#setState("transcribing");
9073
9619
  const audio = new Blob(this.#chunks, { type: mimeType || "audio/webm" });
9074
9620
  try {
9075
- const text3 = await this.#transcribe(audio);
9621
+ const text4 = await this.#transcribe(audio);
9076
9622
  this.#setState("idle");
9077
9623
  if (this.#hitCap) {
9078
9624
  this.element.title = this.#strings.recordingLimit.replace(
@@ -9080,8 +9626,8 @@ var VoiceInput = class {
9080
9626
  String(MAX_RECORDING_MS / 6e4)
9081
9627
  );
9082
9628
  }
9083
- if (text3 !== "") {
9084
- this.#onText(text3);
9629
+ if (text4 !== "") {
9630
+ this.#onText(text4);
9085
9631
  }
9086
9632
  } catch (error) {
9087
9633
  this.#fail(error instanceof Error ? error.message : this.#strings.transcriptionFailed);
@@ -9711,9 +10257,9 @@ function isOwnedSuffix(suffix) {
9711
10257
  function deriveTitle(messages) {
9712
10258
  for (const message of messages) {
9713
10259
  if (message.role === "user") {
9714
- const text3 = cleanText(message.content);
9715
- if (text3 !== "") {
9716
- return truncate(text3, TITLE_LIMIT);
10260
+ const text4 = cleanText(message.content);
10261
+ if (text4 !== "") {
10262
+ return truncate(text4, TITLE_LIMIT);
9717
10263
  }
9718
10264
  }
9719
10265
  }
@@ -9721,9 +10267,9 @@ function deriveTitle(messages) {
9721
10267
  }
9722
10268
  function derivePreview(messages) {
9723
10269
  for (const message of [...messages].reverse()) {
9724
- const text3 = cleanText(message.content);
9725
- if (text3 !== "") {
9726
- return truncate(text3, PREVIEW_LIMIT);
10270
+ const text4 = cleanText(message.content);
10271
+ if (text4 !== "") {
10272
+ return truncate(text4, PREVIEW_LIMIT);
9727
10273
  }
9728
10274
  }
9729
10275
  return "";
@@ -9731,8 +10277,8 @@ function derivePreview(messages) {
9731
10277
  function cleanText(content) {
9732
10278
  return typeof content === "string" ? content.replace(/\s+/g, " ").trim() : "";
9733
10279
  }
9734
- function truncate(text3, limit) {
9735
- return text3.length <= limit ? text3 : `${text3.slice(0, limit - 1).trimEnd()}\u2026`;
10280
+ function truncate(text4, limit) {
10281
+ return text4.length <= limit ? text4 : `${text4.slice(0, limit - 1).trimEnd()}\u2026`;
9736
10282
  }
9737
10283
 
9738
10284
  // src/core/create_http_agent.ts
@@ -10136,6 +10682,18 @@ function isCredentialsMode(value) {
10136
10682
  var COLLAPSED_KEY = "ag-ui-chat:collapsed";
10137
10683
  var SIZE_KEY = "ag-ui-chat:size";
10138
10684
  var THEME_KEY = "ag-ui-chat:theme";
10685
+ var LAUNCHER_KEY = "ag-ui-chat:launcher";
10686
+ var DRAGGABLE_PLACEMENTS = /* @__PURE__ */ new Set([null, "", "floating", "bottom-left"]);
10687
+ var RESIZE_GRIPS = [
10688
+ { y: "top" },
10689
+ { y: "bottom" },
10690
+ { x: "left" },
10691
+ { x: "right" },
10692
+ { x: "left", y: "top" },
10693
+ { x: "right", y: "top" },
10694
+ { x: "left", y: "bottom" },
10695
+ { x: "right", y: "bottom" }
10696
+ ];
10139
10697
  var QUOTE_GAP = 6;
10140
10698
  var CLAIMED_NAMESPACES = /* @__PURE__ */ new Set();
10141
10699
  var AgUiChat = class extends HTMLElement {
@@ -10547,6 +11105,32 @@ var AgUiChat = class extends HTMLElement {
10547
11105
  #emptyWrap;
10548
11106
  /** Upload tray; created on connect only when `data-attachments-url` is set. */
10549
11107
  #attachTray = null;
11108
+ /**
11109
+ * Where the user dragged the launcher, in viewport coordinates, or null
11110
+ * while the host's own CSS still places it. Set means this element owns its
11111
+ * position -- see #applyLauncherPlacement for what that costs the host.
11112
+ */
11113
+ #launcherPos = null;
11114
+ /**
11115
+ * The corner the panel opens away from, once this element is placing itself.
11116
+ * Null means the host's layout still decides, and the anchor is measured.
11117
+ */
11118
+ #expandCorner = null;
11119
+ /**
11120
+ * The edges the layout is holding still, as last measured. Cached because a
11121
+ * resize reads it per pointer move and measuring forces a reflow -- thirty a
11122
+ * second while the panel is already being laid out on every one of them.
11123
+ */
11124
+ #anchor = { x: "right", y: "bottom" };
11125
+ /** The eight grips, by name, so the keyboard-reachable one can be moved. */
11126
+ #resizeHandles = /* @__PURE__ */ new Map();
11127
+ /**
11128
+ * Re-clamp the dragged launcher when the window changes size. Bound once as
11129
+ * a field so `removeEventListener` on disconnect gets the same reference.
11130
+ */
11131
+ #onViewportResize = () => {
11132
+ this.#restoreLauncherPosition();
11133
+ };
10550
11134
  /** Mic button mount point (input row); the control mounts on connect when enabled. */
10551
11135
  #voiceSlot;
10552
11136
  /** Voice-input control; created on connect when transcription is available. */
@@ -10755,6 +11339,7 @@ var AgUiChat = class extends HTMLElement {
10755
11339
  }
10756
11340
  if (name === "placement") {
10757
11341
  this.#releaseOwnedAxes();
11342
+ this.#releaseLauncherPosition();
10758
11343
  requestAnimationFrame(() => this.#syncResizeAnchor());
10759
11344
  return;
10760
11345
  }
@@ -11102,7 +11687,10 @@ var AgUiChat = class extends HTMLElement {
11102
11687
  connectedCallback() {
11103
11688
  this.#storageNs = this.#claimNamespace();
11104
11689
  this.#applySize(this.#readSize());
11105
- requestAnimationFrame(() => this.#syncResizeAnchor());
11690
+ requestAnimationFrame(() => {
11691
+ this.#restoreLauncherPosition();
11692
+ this.#syncResizeAnchor();
11693
+ });
11106
11694
  this.#strings = mergeUiStrings({ ...this.#readStringOverrides(), ...this.strings });
11107
11695
  if (this.getAttribute("data-theme-toggle") !== null) {
11108
11696
  const saved = this.#readScopedItem(THEME_KEY);
@@ -11123,6 +11711,7 @@ var AgUiChat = class extends HTMLElement {
11123
11711
  this.#builtinStore = namespace === "" ? this.conversationStore : new SessionStorageStore(namespace);
11124
11712
  this.conversationStore = this.#builtinStore;
11125
11713
  }
11714
+ window.addEventListener("resize", this.#onViewportResize);
11126
11715
  this.#wireThreadStore();
11127
11716
  this.#wireAttachments();
11128
11717
  this.#wireVoice();
@@ -11185,6 +11774,7 @@ var AgUiChat = class extends HTMLElement {
11185
11774
  */
11186
11775
  disconnectedCallback() {
11187
11776
  this.#connected = false;
11777
+ window.removeEventListener("resize", this.#onViewportResize);
11188
11778
  if (this.#claimedNs !== null) {
11189
11779
  CLAIMED_NAMESPACES.delete(this.#claimedNs);
11190
11780
  this.#claimedNs = null;
@@ -11257,6 +11847,7 @@ var AgUiChat = class extends HTMLElement {
11257
11847
  this.#fileInput.accept = accept;
11258
11848
  this.#attachButton.hidden = false;
11259
11849
  this.#enableDragAndDrop();
11850
+ this.#enablePaste();
11260
11851
  }
11261
11852
  /** The built-in multipart upload handler for `data-attachments-url`, or `null`. */
11262
11853
  #defaultUploadHandler(url) {
@@ -11286,7 +11877,7 @@ var AgUiChat = class extends HTMLElement {
11286
11877
  }
11287
11878
  this.#voice = new VoiceInput({
11288
11879
  transcribe,
11289
- onText: (text3) => this.#insertVoiceText(text3),
11880
+ onText: (text4) => this.#insertVoiceText(text4),
11290
11881
  strings: this.#strings
11291
11882
  });
11292
11883
  this.#voiceSlot.appendChild(this.#voice.element);
@@ -11303,9 +11894,9 @@ var AgUiChat = class extends HTMLElement {
11303
11894
  });
11304
11895
  }
11305
11896
  /** Drop a voice transcript into the composer (appended to any typed text). */
11306
- #insertVoiceText(text3) {
11897
+ #insertVoiceText(text4) {
11307
11898
  const current = this.#input.value.trim();
11308
- this.#input.value = current === "" ? text3 : `${current} ${text3}`;
11899
+ this.#input.value = current === "" ? text4 : `${current} ${text4}`;
11309
11900
  this.#onInput();
11310
11901
  this.#input.focus();
11311
11902
  }
@@ -11323,8 +11914,8 @@ var AgUiChat = class extends HTMLElement {
11323
11914
  *
11324
11915
  * No-ops on text that is empty or only whitespace.
11325
11916
  */
11326
- quote(text3) {
11327
- const quoted = asQuote(text3);
11917
+ quote(text4) {
11918
+ const quoted = asQuote(text4);
11328
11919
  if (quoted === "") {
11329
11920
  return;
11330
11921
  }
@@ -11363,7 +11954,7 @@ ${quoted}`;
11363
11954
  within,
11364
11955
  label: this.#strings.quoteSelection,
11365
11956
  exclude: this,
11366
- onQuote: (text3) => this.quote(text3)
11957
+ onQuote: (text4) => this.quote(text4)
11367
11958
  });
11368
11959
  this.#pageQuote = offer;
11369
11960
  return () => {
@@ -11491,6 +12082,37 @@ ${quoted}`;
11491
12082
  }
11492
12083
  });
11493
12084
  }
12085
+ /**
12086
+ * Accept files pasted into the composer.
12087
+ *
12088
+ * The whole tray already exists behind this: a paste is one more way to hand
12089
+ * it a `File`, alongside the picker and a drop.
12090
+ *
12091
+ * Two rules keep it from stealing a paste that was never about files.
12092
+ * `clipboardData.files` is empty for text, so ordinary pasting is untouched.
12093
+ * And the default is only prevented when the clipboard carries **no text**:
12094
+ * copying a rich selection that happens to contain an image puts both on the
12095
+ * clipboard, and swallowing the words someone meant to paste in order to
12096
+ * attach a picture they did not is the worse of the two failures.
12097
+ */
12098
+ #enablePaste() {
12099
+ this.#chat.addEventListener("paste", (event) => {
12100
+ const clipboard = event.clipboardData ?? null;
12101
+ if (clipboard === null) {
12102
+ return;
12103
+ }
12104
+ const files = Array.from(clipboard.files);
12105
+ if (files.length === 0) {
12106
+ return;
12107
+ }
12108
+ if (clipboard.getData("text/plain") === "") {
12109
+ event.preventDefault();
12110
+ }
12111
+ for (const file of files) {
12112
+ this.#attachTray?.add(named(file));
12113
+ }
12114
+ });
12115
+ }
11494
12116
  /**
11495
12117
  * When `data-threads-url` is set, route thread enumeration / load / rename /
11496
12118
  * delete through that server endpoint (wrapping the current store as the
@@ -11598,18 +12220,18 @@ ${quoted}`;
11598
12220
  void this.sendMessage(`/${skill.name}`);
11599
12221
  return;
11600
12222
  }
11601
- const { text: text3, missing } = fillTemplate(skill.prompt, this.skillContext());
12223
+ const { text: text4, missing } = fillTemplate(skill.prompt, this.skillContext());
11602
12224
  if (missing.length > 0) {
11603
12225
  this.#skillHint.textContent = this.#strings.skillNeeds.replace("{title}", skill.title).replace("{fields}", missing.join(", "));
11604
12226
  this.#skillHint.hidden = false;
11605
- this.#input.value = text3;
12227
+ this.#input.value = text4;
11606
12228
  this.#autoGrow();
11607
12229
  this.#input.focus();
11608
- this.#selectFirstPlaceholder(text3);
12230
+ this.#selectFirstPlaceholder(text4);
11609
12231
  return;
11610
12232
  }
11611
12233
  this.#skillHint.hidden = true;
11612
- this.#input.value = text3;
12234
+ this.#input.value = text4;
11613
12235
  this.#autoGrow();
11614
12236
  if (skill.sendImmediately === false) {
11615
12237
  this.#input.focus();
@@ -11623,9 +12245,9 @@ ${quoted}`;
11623
12245
  * Typing then replaces it, which is the shortest path from "this skill needs
11624
12246
  * a topic" to a sendable prompt.
11625
12247
  */
11626
- #selectFirstPlaceholder(text3) {
11627
- const start = text3.indexOf("{");
11628
- this.#input.setSelectionRange(start, text3.indexOf("}", start) + 1);
12248
+ #selectFirstPlaceholder(text4) {
12249
+ const start = text4.indexOf("{");
12250
+ this.#input.setSelectionRange(start, text4.indexOf("}", start) + 1);
11629
12251
  }
11630
12252
  /** Whether the widget is collapsed (reflected as the `collapsed` attribute). */
11631
12253
  get collapsed() {
@@ -11642,6 +12264,9 @@ ${quoted}`;
11642
12264
  * its own chrome.
11643
12265
  */
11644
12266
  setCollapsed(collapsed) {
12267
+ if (!collapsed) {
12268
+ this.#restoreLauncherPosition();
12269
+ }
11645
12270
  if (collapsed) {
11646
12271
  this.setAttribute("collapsed", "");
11647
12272
  } else {
@@ -11714,13 +12339,32 @@ ${quoted}`;
11714
12339
  const before = this.getBoundingClientRect();
11715
12340
  const width = this.style.getPropertyValue("--ag-ui-width");
11716
12341
  const height = this.style.getPropertyValue("--ag-ui-height");
11717
- this.#applySize({ width: before.width + 1, height: before.height + 1 });
11718
- const after = this.getBoundingClientRect();
12342
+ const shrunk = this.#probeAnchor(before, -1);
12343
+ const grown = shrunk.x === null || shrunk.y === null ? this.#probeAnchor(before, 1) : shrunk;
11719
12344
  this.#restoreProperty("--ag-ui-width", width);
11720
12345
  this.#restoreProperty("--ag-ui-height", height);
11721
12346
  return {
11722
- x: Math.abs(after.left - before.left) < 0.5 ? "left" : "right",
11723
- y: Math.abs(after.top - before.top) < 0.5 ? "top" : "bottom"
12347
+ // Neither direction moved it: the axis cannot be resized at all, so the
12348
+ // floating default is the best answer available and is the one the
12349
+ // stylesheet would have used with no measurement at all.
12350
+ x: shrunk.x ?? grown.x ?? "right",
12351
+ y: shrunk.y ?? grown.y ?? "bottom"
12352
+ };
12353
+ }
12354
+ /**
12355
+ * Which edge each axis holds still when the panel changes size by `delta`.
12356
+ *
12357
+ * Null for an axis whose size did not change: nothing moved, so nothing was
12358
+ * learned, and reporting the unmoved edge as the pinned one would be exactly
12359
+ * backwards.
12360
+ */
12361
+ #probeAnchor(before, delta) {
12362
+ this.#applySize({ width: before.width + delta, height: before.height + delta });
12363
+ const after = this.getBoundingClientRect();
12364
+ const moved = (a, b2) => Math.abs(a - b2) >= 0.5;
12365
+ return {
12366
+ x: moved(after.width, before.width) ? moved(after.left, before.left) ? "right" : "left" : null,
12367
+ y: moved(after.height, before.height) ? moved(after.top, before.top) ? "bottom" : "top" : null
11724
12368
  };
11725
12369
  }
11726
12370
  /** Stamp the measured anchor so the shadow CSS can place the grip. */
@@ -11728,8 +12372,10 @@ ${quoted}`;
11728
12372
  if (!this.#connected) {
11729
12373
  return;
11730
12374
  }
11731
- const anchor = this.#measureAnchor();
12375
+ const anchor = this.#expandCorner ?? this.#measureAnchor();
12376
+ this.#anchor = anchor;
11732
12377
  this.setAttribute("data-resize-anchor", `${anchor.y}-${anchor.x}`);
12378
+ this.#focusableGrip();
11733
12379
  }
11734
12380
  /** Put a custom property back to a previous value, or remove it if there was none. */
11735
12381
  #restoreProperty(name, value) {
@@ -11778,6 +12424,203 @@ ${quoted}`;
11778
12424
  this.style.removeProperty("--ag-ui-width");
11779
12425
  }
11780
12426
  }
12427
+ /**
12428
+ * Whether this placement lets the launcher be dragged, read per interaction
12429
+ * because `placement` is a live attribute. `data-launcher-drag="false"` opts
12430
+ * a host out without giving up the launcher itself.
12431
+ */
12432
+ #launcherDraggable() {
12433
+ return this.getAttribute("data-launcher-drag") !== "false" && DRAGGABLE_PLACEMENTS.has(this.getAttribute("placement"));
12434
+ }
12435
+ /** The viewport the launcher and the panel both have to fit inside. */
12436
+ #viewport() {
12437
+ return { width: window.innerWidth, height: window.innerHeight };
12438
+ }
12439
+ /**
12440
+ * The launcher's box in viewport coordinates, with its transform divided out.
12441
+ *
12442
+ * The launcher is scaled in four states -- the collapse animation, hover,
12443
+ * press, and the resting scale(0.4) it sits at while the panel is open -- and
12444
+ * `getBoundingClientRect` reports every one of them. A drag that started from
12445
+ * that rect would begin a couple of pixels off, because a press is one of
12446
+ * those states.
12447
+ *
12448
+ * So the size comes from `offsetWidth`/`offsetHeight`, which are layout
12449
+ * metrics no transform reaches, and the position from the rect's *centre*,
12450
+ * which a centred scale is the one point that cannot move.
12451
+ */
12452
+ #launcherBox() {
12453
+ const width = this.#launcher.offsetWidth;
12454
+ const height = this.#launcher.offsetHeight;
12455
+ const dragged = this.#launcherPos;
12456
+ if (dragged !== null) {
12457
+ return { left: dragged.left, top: dragged.top, width, height };
12458
+ }
12459
+ const rect = this.#launcher.getBoundingClientRect();
12460
+ return {
12461
+ left: rect.left + rect.width / 2 - width / 2,
12462
+ top: rect.top + rect.height / 2 - height / 2,
12463
+ width,
12464
+ height
12465
+ };
12466
+ }
12467
+ /**
12468
+ * Place the host box and the launcher for the position the user dragged to.
12469
+ *
12470
+ * This writes `--ag-ui-inset`, which is a host-facing property: an inline
12471
+ * value outranks the page's own rule for it, exactly as a dragged width
12472
+ * outranks a placement's. That is the intent -- the user moved it -- and it
12473
+ * is why switching to a placement that owns its position hands the property
12474
+ * back rather than leaving a stale inline one behind.
12475
+ */
12476
+ #applyLauncherPlacement(at2) {
12477
+ if (!this.#launcherDraggable()) {
12478
+ return;
12479
+ }
12480
+ this.#launcherPos = at2;
12481
+ const panel = this.getBoundingClientRect();
12482
+ const placement = launcherPlacement(
12483
+ this.#launcherBox(),
12484
+ { width: panel.width, height: panel.height },
12485
+ this.#viewport()
12486
+ );
12487
+ this.style.setProperty("--ag-ui-inset", placement.hostInset);
12488
+ this.style.setProperty("--ag-ui-launcher-inset", placement.launcherInset);
12489
+ this.#expandCorner = placement.corner;
12490
+ this.setAttribute("data-expand-corner", `${placement.corner.y}-${placement.corner.x}`);
12491
+ this.#syncResizeAnchor();
12492
+ }
12493
+ /** Move the launcher live during a drag, without persisting. */
12494
+ #moveLauncher(left, top) {
12495
+ this.#applyLauncherPlacement({ left, top });
12496
+ }
12497
+ /** Move the launcher and remember where, per tab, like the dragged size. */
12498
+ #commitLauncher(left, top) {
12499
+ this.#moveLauncher(left, top);
12500
+ this.#storeLauncherPosition();
12501
+ }
12502
+ /** Write the current launcher position, if this element owns one. */
12503
+ #storeLauncherPosition() {
12504
+ const position = this.#launcherPos;
12505
+ if (position === null) {
12506
+ return;
12507
+ }
12508
+ writeStoredItem(this.#storageKey(LAUNCHER_KEY), JSON.stringify(position));
12509
+ }
12510
+ /**
12511
+ * Re-apply the dragged position against the current viewport: on connect,
12512
+ * whenever the window resizes, and before an expand. The viewport that
12513
+ * stored a position may since have shrunk, and a launcher past the edge is
12514
+ * unreachable -- it is the only way back to a collapsed conversation.
12515
+ */
12516
+ #restoreLauncherPosition() {
12517
+ const stored = this.#launcherPos ?? this.#readLauncherPosition();
12518
+ if (stored === null) {
12519
+ return;
12520
+ }
12521
+ const box = this.#launcherBox();
12522
+ this.#applyLauncherPlacement(
12523
+ clampLauncher({ ...box, left: stored.left, top: stored.top }, this.#viewport())
12524
+ );
12525
+ }
12526
+ /** The persisted launcher position for this instance, or null. */
12527
+ #readLauncherPosition() {
12528
+ const raw = this.#readScopedItem(LAUNCHER_KEY);
12529
+ if (raw === null) {
12530
+ return null;
12531
+ }
12532
+ try {
12533
+ const parsed = JSON.parse(raw);
12534
+ if (typeof parsed !== "object" || parsed === null) {
12535
+ return null;
12536
+ }
12537
+ const { left, top } = parsed;
12538
+ return typeof left === "number" && typeof top === "number" ? { left, top } : null;
12539
+ } catch {
12540
+ return null;
12541
+ }
12542
+ }
12543
+ /**
12544
+ * Give the position back to the host when the new placement owns it, the way
12545
+ * #releaseOwnedAxes gives back a size. Without this a dragged inset survives
12546
+ * the switch inline and pins a sidebar to wherever the floating launcher was.
12547
+ */
12548
+ #releaseLauncherPosition() {
12549
+ if (this.#launcherDraggable()) {
12550
+ return;
12551
+ }
12552
+ this.#launcherPos = null;
12553
+ this.#expandCorner = null;
12554
+ this.style.removeProperty("--ag-ui-inset");
12555
+ this.style.removeProperty("--ag-ui-launcher-inset");
12556
+ this.removeAttribute("data-expand-corner");
12557
+ }
12558
+ /**
12559
+ * Apply the box a grip is asking for.
12560
+ *
12561
+ * The size is the easy half. The other half is that **dragging the edge the
12562
+ * layout is holding still moves the panel as well as resizing it**, and the
12563
+ * layout cannot express that on its own: a floating panel pinned bottom-right
12564
+ * cannot grow rightward, because its right edge is what the placement fixed.
12565
+ * So a grip on a pinned edge takes the position over -- which is the same
12566
+ * ownership the launcher drag takes, written the same way.
12567
+ *
12568
+ * A grip on a free edge writes nothing but the size, exactly as before, so a
12569
+ * host positioning the panel with its own rule keeps that rule until someone
12570
+ * drags the edge it was holding.
12571
+ */
12572
+ #applyResize(grip, box) {
12573
+ this.#applySize({ width: box.right - box.left, height: box.bottom - box.top });
12574
+ if (grip.x !== this.#anchor.x && grip.y !== this.#anchor.y) {
12575
+ return;
12576
+ }
12577
+ const viewport = this.#viewport();
12578
+ const anchor = this.#anchor;
12579
+ const side = (value) => `${Math.round(value)}px`;
12580
+ this.style.setProperty(
12581
+ "--ag-ui-inset",
12582
+ [
12583
+ anchor.y === "top" ? side(box.top) : "auto",
12584
+ anchor.x === "right" ? side(viewport.width - box.right) : "auto",
12585
+ anchor.y === "bottom" ? side(viewport.height - box.bottom) : "auto",
12586
+ anchor.x === "left" ? side(box.left) : "auto"
12587
+ ].join(" ")
12588
+ );
12589
+ if (this.#launcherPos !== null) {
12590
+ const size = this.#launcher.offsetWidth;
12591
+ this.#launcherPos = {
12592
+ left: anchor.x === "left" ? box.left : box.right - size,
12593
+ top: anchor.y === "top" ? box.top : box.bottom - size
12594
+ };
12595
+ }
12596
+ }
12597
+ /** Finish a resize: keep the box, remember it, and re-read the pinned edges. */
12598
+ #commitResize(grip, box) {
12599
+ this.#applyResize(grip, box);
12600
+ this.#persistSize({ width: box.right - box.left, height: box.bottom - box.top });
12601
+ this.#storeLauncherPosition();
12602
+ this.#syncResizeAnchor();
12603
+ }
12604
+ /**
12605
+ * Put the tab stop on the grip diagonally opposite the pinned corner.
12606
+ *
12607
+ * That is the corner a resize grows the panel from, so an arrow key there
12608
+ * changes the size and never the position -- the behaviour the single grip
12609
+ * this replaced had, kept for the one path that cannot simply grab a
12610
+ * different edge.
12611
+ */
12612
+ #focusableGrip() {
12613
+ const free = `${this.#anchor.y === "top" ? "bottom" : "top"}-${this.#anchor.x === "left" ? "right" : "left"}`;
12614
+ for (const [name, handle] of this.#resizeHandles) {
12615
+ const reachable = name === free;
12616
+ handle.tabIndex = reachable ? 0 : -1;
12617
+ if (reachable) {
12618
+ handle.removeAttribute("aria-hidden");
12619
+ } else {
12620
+ handle.setAttribute("aria-hidden", "true");
12621
+ }
12622
+ }
12623
+ }
11781
12624
  /** Persist a dragged size per tab, alongside the collapsed/theme preferences. */
11782
12625
  #persistSize(size) {
11783
12626
  const stored = { ...this.#readSize(), ...size };
@@ -12146,11 +12989,11 @@ ${quoted}`;
12146
12989
  * the full transcript — tool calls and their results — not just the prose.
12147
12990
  */
12148
12991
  #renderHistoricMessage(message) {
12149
- const text3 = typeof message.content === "string" ? message.content : "";
12992
+ const text4 = typeof message.content === "string" ? message.content : "";
12150
12993
  if (message.role === MESSAGE_ROLE.USER) {
12151
12994
  const attachments = messageAttachments(message);
12152
- if (text3 !== "" || attachments.length > 0) {
12153
- const bubble = this.appendMessage(MESSAGE_ROLE.USER, text3);
12995
+ if (text4 !== "" || attachments.length > 0) {
12996
+ const bubble = this.appendMessage(MESSAGE_ROLE.USER, text4);
12154
12997
  if (attachments.length > 0) {
12155
12998
  bubble.appendChild(renderAttachmentChips(attachments));
12156
12999
  }
@@ -12158,8 +13001,8 @@ ${quoted}`;
12158
13001
  return;
12159
13002
  }
12160
13003
  if (message.role === MESSAGE_ROLE.ASSISTANT) {
12161
- if (text3 !== "") {
12162
- const restoredBubble = this.appendMessage(MESSAGE_ROLE.ASSISTANT, text3);
13004
+ if (text4 !== "") {
13005
+ const restoredBubble = this.appendMessage(MESSAGE_ROLE.ASSISTANT, text4);
12163
13006
  restoredBubble.classList.add("message--restored");
12164
13007
  this.#attachActions(restoredBubble);
12165
13008
  }
@@ -12453,19 +13296,27 @@ ${quoted}`;
12453
13296
  this.#badge
12454
13297
  );
12455
13298
  this.#launcher.addEventListener("click", () => this.setCollapsed(false));
12456
- this.#chat.append(
12457
- createResizeHandle({
13299
+ enableLauncherDrag(this.#launcher, {
13300
+ enabled: () => this.collapsed && this.#launcherDraggable(),
13301
+ rect: () => this.#launcherBox(),
13302
+ viewport: () => this.#viewport(),
13303
+ apply: (left, top) => this.#moveLauncher(left, top),
13304
+ commit: (left, top) => this.#commitLauncher(left, top)
13305
+ });
13306
+ for (const grip of RESIZE_GRIPS) {
13307
+ const handle = createResizeHandle(grip, {
12458
13308
  axis: () => this.#resizeAxis(),
12459
- anchor: () => this.#measureAnchor(),
12460
13309
  rect: () => this.getBoundingClientRect(),
12461
- apply: (size) => this.#applySize(size),
12462
- commit: (size) => {
12463
- this.#persistSize(size);
12464
- this.#syncResizeAnchor();
12465
- },
13310
+ apply: (box) => this.#applyResize(grip, box),
13311
+ commit: (box) => this.#commitResize(grip, box),
12466
13312
  label: this.#strings.resizePanel
12467
- })
12468
- );
13313
+ });
13314
+ handle.tabIndex = -1;
13315
+ handle.setAttribute("aria-hidden", "true");
13316
+ this.#resizeHandles.set(gripName(grip), handle);
13317
+ this.#chat.appendChild(handle);
13318
+ }
13319
+ this.#focusableGrip();
12469
13320
  this.#adoptStyles();
12470
13321
  this.#root.append(this.#announcer, this.#chat, this.#launcher);
12471
13322
  }
@@ -12859,13 +13710,18 @@ ${quoted}`;
12859
13710
  strings: this.#strings,
12860
13711
  // Read at click time, not captured: a bubble rendered from markdown
12861
13712
  // holds its text in the DOM, and that is what the user sees and means
12862
- // to copy.
12863
- ...copyable ? { text: () => bubble.textContent } : {},
13713
+ // to copy. Serialised rather than read off `textContent`, which welds
13714
+ // a table into one run of digits and picks up the code blocks' own
13715
+ // copy buttons on the way past.
13716
+ ...copyable ? {
13717
+ text: () => copyPayload(bubble).text,
13718
+ html: () => copyPayload(bubble).html
13719
+ } : {},
12864
13720
  ...rateable ? {
12865
13721
  onFeedback: (rating) => {
12866
13722
  this.dispatchEvent(
12867
13723
  new CustomEvent(FEEDBACK_EVENT, {
12868
- detail: { content: bubble.textContent, rating },
13724
+ detail: { content: copyPayload(bubble).text, rating },
12869
13725
  bubbles: true,
12870
13726
  composed: true
12871
13727
  })
@@ -12881,7 +13737,7 @@ ${quoted}`;
12881
13737
  /** Move the Retry button onto `bar`, taking it off whoever held it. */
12882
13738
  #moveRetryTo(bar) {
12883
13739
  this.#retryOwner?.querySelector(".message-action--retry")?.remove();
12884
- const retry = messageActionButton("retry", this.#strings.retryMessage, "\u21BB");
13740
+ const retry = messageActionButton("retry", this.#strings.retryMessage, ICON_RETRY);
12885
13741
  retry.addEventListener("click", () => {
12886
13742
  void this.retryLastTurn();
12887
13743
  });
@@ -13144,7 +14000,11 @@ ${quoted}`;
13144
14000
  this.#closeSubAgent(subagentRunId, SUBAGENT_PHASE.FINISHED, null);
13145
14001
  },
13146
14002
  onSubAgentError: (subagentRunId, message) => {
13147
- this.#closeSubAgent(subagentRunId, SUBAGENT_PHASE.FAILED, message);
14003
+ this.#closeSubAgent(
14004
+ subagentRunId,
14005
+ SUBAGENT_PHASE.FAILED,
14006
+ message === "" ? this.#strings.subAgentFailed : message
14007
+ );
13148
14008
  },
13149
14009
  onMessagesSnapshot: () => {
13150
14010
  this.#appendNotice("\u{1F504}", this.#strings.historyReplaced, "history-replaced");
@@ -13491,8 +14351,8 @@ ${quoted}`;
13491
14351
  this.#appendNotice("\u2728", this.#strings.usingSkill.replace("{name}", skill), "skill");
13492
14352
  return true;
13493
14353
  }
13494
- #appendNotice(icon, text3, kind) {
13495
- this.#ensureGroup().appendChild(renderRunNotice(icon, text3, kind));
14354
+ #appendNotice(icon, text4, kind) {
14355
+ this.#ensureGroup().appendChild(renderRunNotice(icon, text4, kind));
13496
14356
  this.#updateEmptyState();
13497
14357
  this.#scroller.follow();
13498
14358
  }
@@ -13699,6 +14559,16 @@ function confirmPhrase(interrupt) {
13699
14559
  function restoredToolCalls(value) {
13700
14560
  return Array.isArray(value) ? value.filter(isRestoredToolCall) : [];
13701
14561
  }
14562
+ function named(file) {
14563
+ if (file.name !== "") {
14564
+ return file;
14565
+ }
14566
+ const subtype = file.type.split("/")[1] ?? file.type;
14567
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
14568
+ return new File([file], subtype === "" ? `pasted-${stamp}` : `pasted-${stamp}.${subtype}`, {
14569
+ type: file.type
14570
+ });
14571
+ }
13702
14572
  function isRestoredToolCall(value) {
13703
14573
  if (typeof value !== "object" || value === null) {
13704
14574
  return false;
@@ -13758,7 +14628,7 @@ function setControlValue(el2, value) {
13758
14628
  }
13759
14629
 
13760
14630
  // src/version.ts
13761
- var VERSION = "0.32.0";
14631
+ var VERSION = "0.33.0";
13762
14632
  export {
13763
14633
  ATTACHMENT_EVENT,
13764
14634
  AgUiChat,
@@ -13850,6 +14720,6 @@ export {
13850
14720
  /*! Bundled license information:
13851
14721
 
13852
14722
  dompurify/dist/purify.es.mjs:
13853
- (*! @license DOMPurify 3.4.13 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.13/LICENSE *)
14723
+ (*! @license DOMPurify 3.4.14 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.14/LICENSE *)
13854
14724
  */
13855
14725
  //# sourceMappingURL=index.js.map