@artooi/ag-ui-web-component 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/CHANGELOG.md +76 -1
  2. package/README.md +235 -47
  3. package/dist/ag-ui-web-component.bundle.js +451 -46
  4. package/dist/ag-ui-web-component.bundle.js.map +4 -4
  5. package/dist/constants.d.ts +34 -0
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/{ag_ui_chat.d.ts → core/ag_ui_chat.d.ts} +63 -6
  8. package/dist/core/ag_ui_chat.d.ts.map +1 -0
  9. package/dist/core/agui_client.d.ts.map +1 -0
  10. package/dist/core/conversation_store.d.ts.map +1 -0
  11. package/dist/core/create_http_agent.d.ts.map +1 -0
  12. package/dist/core/define_ag_ui_chat.d.ts.map +1 -0
  13. package/dist/dom/animations.d.ts +71 -0
  14. package/dist/dom/animations.d.ts.map +1 -0
  15. package/dist/{dom_driver.d.ts → dom/dom_driver.d.ts} +7 -1
  16. package/dist/dom/dom_driver.d.ts.map +1 -0
  17. package/dist/dom/native_setter.d.ts +5 -0
  18. package/dist/dom/native_setter.d.ts.map +1 -0
  19. package/dist/index.d.ts +19 -16
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +3886 -388
  22. package/dist/index.js.map +4 -4
  23. package/dist/skills/fill_template.d.ts +17 -0
  24. package/dist/skills/fill_template.d.ts.map +1 -0
  25. package/dist/skills/parse_skills.d.ts +8 -0
  26. package/dist/skills/parse_skills.d.ts.map +1 -0
  27. package/dist/skills/skill.d.ts +24 -0
  28. package/dist/skills/skill.d.ts.map +1 -0
  29. package/dist/{client_tool_registry.d.ts → tools/client_tool_registry.d.ts} +6 -1
  30. package/dist/tools/client_tool_registry.d.ts.map +1 -0
  31. package/dist/tools/is_destructive.d.ts.map +1 -0
  32. package/dist/tools/is_navigates.d.ts.map +1 -0
  33. package/dist/tools/page_map.d.ts.map +1 -0
  34. package/dist/tools/route_map.d.ts +40 -0
  35. package/dist/tools/route_map.d.ts.map +1 -0
  36. package/dist/tools/state_hook.d.ts.map +1 -0
  37. package/dist/ui/confirmation_card.d.ts +22 -0
  38. package/dist/ui/confirmation_card.d.ts.map +1 -0
  39. package/dist/ui/render_markdown.d.ts +13 -0
  40. package/dist/ui/render_markdown.d.ts.map +1 -0
  41. package/dist/ui/reveal_words.d.ts +8 -0
  42. package/dist/ui/reveal_words.d.ts.map +1 -0
  43. package/dist/ui/skills_menu.d.ts +35 -0
  44. package/dist/ui/skills_menu.d.ts.map +1 -0
  45. package/dist/ui/styles.d.ts +2 -0
  46. package/dist/ui/styles.d.ts.map +1 -0
  47. package/dist/ui/tool_call_card.d.ts +35 -0
  48. package/dist/ui/tool_call_card.d.ts.map +1 -0
  49. package/package.json +5 -3
  50. package/src/constants.ts +38 -0
  51. package/src/core/ag_ui_chat.ts +786 -0
  52. package/src/{agui_client.ts → core/agui_client.ts} +1 -1
  53. package/src/{define_ag_ui_chat.ts → core/define_ag_ui_chat.ts} +1 -1
  54. package/src/dom/animations.ts +201 -0
  55. package/src/{dom_driver.ts → dom/dom_driver.ts} +35 -2
  56. package/src/dom/native_setter.ts +42 -0
  57. package/src/index.ts +61 -32
  58. package/src/skills/fill_template.ts +32 -0
  59. package/src/skills/parse_skills.ts +26 -0
  60. package/src/skills/skill.ts +23 -0
  61. package/src/{client_tool_registry.ts → tools/client_tool_registry.ts} +6 -4
  62. package/src/{is_destructive.ts → tools/is_destructive.ts} +1 -1
  63. package/src/{is_navigates.ts → tools/is_navigates.ts} +1 -1
  64. package/src/tools/route_map.ts +140 -0
  65. package/src/{state_hook.ts → tools/state_hook.ts} +1 -1
  66. package/src/ui/confirmation_card.ts +71 -0
  67. package/src/ui/render_markdown.ts +68 -0
  68. package/src/ui/reveal_words.ts +41 -0
  69. package/src/ui/skills_menu.ts +171 -0
  70. package/src/ui/styles.ts +631 -0
  71. package/src/{tool_call_card.ts → ui/tool_call_card.ts} +50 -19
  72. package/src/version.ts +1 -1
  73. package/dist/ag_ui_chat.d.ts.map +0 -1
  74. package/dist/agui_client.d.ts.map +0 -1
  75. package/dist/animations.d.ts +0 -33
  76. package/dist/animations.d.ts.map +0 -1
  77. package/dist/client_tool_registry.d.ts.map +0 -1
  78. package/dist/confirmation_modal.d.ts +0 -14
  79. package/dist/confirmation_modal.d.ts.map +0 -1
  80. package/dist/conversation_store.d.ts.map +0 -1
  81. package/dist/create_http_agent.d.ts.map +0 -1
  82. package/dist/define_ag_ui_chat.d.ts.map +0 -1
  83. package/dist/dom_driver.d.ts.map +0 -1
  84. package/dist/is_destructive.d.ts.map +0 -1
  85. package/dist/is_navigates.d.ts.map +0 -1
  86. package/dist/page_map.d.ts.map +0 -1
  87. package/dist/route_map.d.ts +0 -27
  88. package/dist/route_map.d.ts.map +0 -1
  89. package/dist/state_hook.d.ts.map +0 -1
  90. package/dist/styles.d.ts +0 -2
  91. package/dist/styles.d.ts.map +0 -1
  92. package/dist/tool_call_card.d.ts +0 -29
  93. package/dist/tool_call_card.d.ts.map +0 -1
  94. package/src/ag_ui_chat.ts +0 -411
  95. package/src/animations.ts +0 -86
  96. package/src/confirmation_modal.ts +0 -69
  97. package/src/route_map.ts +0 -83
  98. package/src/styles.ts +0 -296
  99. /package/dist/{agui_client.d.ts → core/agui_client.d.ts} +0 -0
  100. /package/dist/{conversation_store.d.ts → core/conversation_store.d.ts} +0 -0
  101. /package/dist/{create_http_agent.d.ts → core/create_http_agent.d.ts} +0 -0
  102. /package/dist/{define_ag_ui_chat.d.ts → core/define_ag_ui_chat.d.ts} +0 -0
  103. /package/dist/{is_destructive.d.ts → tools/is_destructive.d.ts} +0 -0
  104. /package/dist/{is_navigates.d.ts → tools/is_navigates.d.ts} +0 -0
  105. /package/dist/{page_map.d.ts → tools/page_map.d.ts} +0 -0
  106. /package/dist/{state_hook.d.ts → tools/state_hook.d.ts} +0 -0
  107. /package/src/{conversation_store.ts → core/conversation_store.ts} +0 -0
  108. /package/src/{create_http_agent.ts → core/create_http_agent.ts} +0 -0
  109. /package/src/{page_map.ts → tools/page_map.ts} +0 -0
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
- // src/agui_client.ts
2
- import { randomUUID } from "@ag-ui/client";
3
-
4
1
  // src/constants.ts
5
2
  var ELEMENT_TAG = "ag-ui-chat";
6
3
  var SUBMIT_EVENT = "ag-ui-submit";
4
+ var TOGGLE_EVENT = "ag-ui-toggle";
7
5
  var MESSAGE_ROLE = {
8
6
  USER: "user",
9
7
  ASSISTANT: "assistant"
10
8
  };
11
9
  var X_DESTRUCTIVE_KEY = "x-destructive";
10
+ var X_CONFIRM_KEY = "x-confirm";
11
+ var X_SUMMARY_KEY = "x-summary";
12
12
  var X_NAVIGATES_KEY = "x-navigates";
13
13
  var MAX_TOOL_ROUNDS = 10;
14
14
  var TOOL_CALL_STATUS = {
@@ -17,137 +17,54 @@ var TOOL_CALL_STATUS = {
17
17
  ERROR: "error",
18
18
  DECLINED: "declined"
19
19
  };
20
+ var TOOL_DISPLAY = {
21
+ MINIMAL: "minimal",
22
+ COMPACT: "compact",
23
+ FULL: "full"
24
+ };
20
25
 
21
- // src/agui_client.ts
22
- var AgUiClient = class {
23
- #agent;
24
- #handlers;
25
- #getTools;
26
- #getContext;
27
- #executeTool;
28
- #onPersist;
29
- constructor(config) {
30
- this.#agent = config.agent;
31
- this.#handlers = config.handlers;
32
- this.#getTools = config.getTools ?? (() => []);
33
- this.#getContext = config.getContext ?? (() => []);
34
- this.#executeTool = config.executeTool ?? null;
35
- this.#onPersist = config.onPersist ?? (() => {
36
- });
37
- }
38
- /** Whether a run is currently in flight. */
39
- get running() {
40
- return this.#agent.isRunning;
41
- }
42
- /** The current conversation history (for persistence / rehydration). */
43
- get messages() {
44
- return this.#agent.messages;
45
- }
46
- /**
47
- * Append a user message and run the agent to completion.
48
- *
49
- * When the agent calls frontend tools, this executes them and re-runs the
50
- * agent with the results, looping until the agent stops calling frontend
51
- * tools (bounded by {@link MAX_TOOL_ROUNDS}).
52
- */
53
- async send(content) {
54
- this.#agent.addMessage({ id: randomUUID(), role: "user", content });
55
- this.#onPersist(this.#agent.messages);
56
- await this.#run();
57
- }
58
- /**
59
- * Resume the run loop after a navigating tool's result was supplied
60
- * post-reload (via {@link addToolResult}). Unlike {@link send}, adds no user
61
- * message — it simply continues the conversation already in history.
62
- */
63
- async resume() {
64
- await this.#run();
65
- }
66
- /** Append a frontend tool result to history (used by the resume path). */
67
- addToolResult(toolCallId, content) {
68
- this.#agent.addMessage({ id: randomUUID(), role: "tool", content, toolCallId });
69
- this.#onPersist(this.#agent.messages);
70
- }
71
- async #run() {
72
- try {
73
- await this.#runLoop();
74
- } catch (error) {
75
- this.#handlers.onError(error instanceof Error ? error.message : String(error));
76
- }
77
- }
78
- async #runLoop() {
79
- for (let round = 0; round < MAX_TOOL_ROUNDS; round += 1) {
80
- const pending = [];
81
- await this.#agent.runAgent(
82
- { tools: this.#getTools(), context: this.#getContext() },
83
- this.#buildSubscriber(pending)
84
- );
85
- this.#onPersist(this.#agent.messages);
86
- if (this.#executeTool === null || pending.length === 0) {
87
- return;
88
- }
89
- let executed = false;
90
- for (const call of pending) {
91
- const result = await this.#executeTool(call);
92
- if (result === null) {
93
- continue;
94
- }
95
- if (result.halt === true) {
96
- return;
97
- }
98
- this.#agent.addMessage({
99
- id: randomUUID(),
100
- role: "tool",
101
- content: result.content,
102
- toolCallId: call.id
103
- });
104
- this.#onPersist(this.#agent.messages);
105
- executed = true;
106
- }
107
- if (!executed) {
108
- return;
26
+ // src/skills/fill_template.ts
27
+ var PLACEHOLDER_RE = /\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g;
28
+ function fillTemplate(template, values) {
29
+ const missing = [];
30
+ const text2 = template.replace(PLACEHOLDER_RE, (token, key) => {
31
+ const value = values[key];
32
+ if (value === void 0 || value === null || value === "") {
33
+ if (!missing.includes(key)) {
34
+ missing.push(key);
109
35
  }
36
+ return token;
110
37
  }
38
+ return String(value);
39
+ });
40
+ return { text: text2, missing };
41
+ }
42
+
43
+ // src/skills/parse_skills.ts
44
+ function isSkill(value) {
45
+ if (typeof value !== "object" || value === null) {
46
+ return false;
111
47
  }
112
- #buildSubscriber(pending) {
113
- const h = this.#handlers;
114
- return {
115
- onRunInitialized() {
116
- h.onRunStart();
117
- },
118
- onTextMessageContentEvent({ textMessageBuffer }) {
119
- h.onTextDelta(textMessageBuffer);
120
- },
121
- onTextMessageEndEvent({ textMessageBuffer }) {
122
- h.onTextEnd(textMessageBuffer);
123
- },
124
- onToolCallEndEvent({ event, toolCallName, toolCallArgs }) {
125
- const call = {
126
- id: event.toolCallId,
127
- name: toolCallName,
128
- args: toolCallArgs
129
- };
130
- pending.push(call);
131
- h.onToolCall(call);
132
- },
133
- onRunErrorEvent({ event }) {
134
- h.onError(event.message);
135
- },
136
- onRunFinalized() {
137
- h.onRunEnd();
138
- }
139
- };
48
+ const record = value;
49
+ return typeof record["name"] === "string" && typeof record["title"] === "string" && typeof record["prompt"] === "string";
50
+ }
51
+ function parseSkills(value) {
52
+ if (!Array.isArray(value)) {
53
+ return [];
140
54
  }
141
- };
55
+ return value.filter(isSkill);
56
+ }
142
57
 
143
- // src/client_tool_registry.ts
58
+ // src/tools/client_tool_registry.ts
144
59
  var ClientToolRegistry = class {
145
60
  #tools = /* @__PURE__ */ new Map();
146
- /** Register a tool. Throws if the name is already taken. */
61
+ /**
62
+ * Register a tool, replacing any existing one with the same name.
63
+ *
64
+ * Idempotent on the name so re-fired host refs / React StrictMode's
65
+ * double-invoke don't throw — re-registering is a replace, not an error.
66
+ */
147
67
  register(tool) {
148
- if (this.#tools.has(tool.name)) {
149
- throw new Error(`tool "${tool.name}" already registered`);
150
- }
151
68
  this.#tools.set(tool.name, tool);
152
69
  }
153
70
  has(name) {
@@ -171,131 +88,17 @@ var ClientToolRegistry = class {
171
88
  }
172
89
  };
173
90
 
174
- // src/confirmation_modal.ts
175
- function requestConfirmation(host, request) {
176
- return new Promise((resolve) => {
177
- const overlay = document.createElement("div");
178
- overlay.className = "modal-overlay";
179
- const dialog = document.createElement("div");
180
- dialog.className = "modal";
181
- const title = document.createElement("div");
182
- title.className = "modal-title";
183
- title.textContent = "Confirm action";
184
- const body = document.createElement("div");
185
- body.className = "modal-body";
186
- body.textContent = `Run \u201C${request.toolName}\u201D?`;
187
- const args = document.createElement("pre");
188
- args.className = "modal-args";
189
- args.textContent = JSON.stringify(request.args, null, 2);
190
- const actions = document.createElement("div");
191
- actions.className = "modal-actions";
192
- const cancel = document.createElement("button");
193
- cancel.className = "modal-btn modal-btn--cancel";
194
- cancel.type = "button";
195
- cancel.textContent = "Cancel";
196
- const confirm = document.createElement("button");
197
- confirm.className = "modal-btn modal-btn--confirm";
198
- confirm.type = "button";
199
- confirm.textContent = "Run";
200
- const close = (accepted) => {
201
- overlay.remove();
202
- resolve(accepted);
203
- };
204
- cancel.addEventListener("click", () => close(false));
205
- confirm.addEventListener("click", () => close(true));
206
- overlay.addEventListener("click", (event) => {
207
- if (event.target === overlay) {
208
- close(false);
209
- }
210
- });
211
- actions.append(cancel, confirm);
212
- dialog.append(title, body, args, actions);
213
- overlay.append(dialog);
214
- host.appendChild(overlay);
215
- confirm.focus();
216
- });
217
- }
218
-
219
- // src/conversation_store.ts
220
- import { randomUUID as randomUUID2 } from "@ag-ui/client";
221
- var THREAD_KEY = "ag-ui-chat:thread";
222
- var MESSAGES_PREFIX = "ag-ui-chat:messages:";
223
- var CHECKPOINT_PREFIX = "ag-ui-chat:checkpoint:";
224
- var SessionStorageStore = class {
225
- threadId() {
226
- const existing = sessionStorage.getItem(THREAD_KEY);
227
- if (existing !== null) {
228
- return existing;
229
- }
230
- const id = randomUUID2();
231
- sessionStorage.setItem(THREAD_KEY, id);
232
- return id;
233
- }
234
- loadMessages(threadId) {
235
- return Promise.resolve(this.#readJson(MESSAGES_PREFIX + threadId));
236
- }
237
- saveMessages(threadId, messages) {
238
- sessionStorage.setItem(MESSAGES_PREFIX + threadId, JSON.stringify(messages));
239
- }
240
- loadCheckpoint(threadId) {
241
- return this.#readJson(CHECKPOINT_PREFIX + threadId);
242
- }
243
- saveCheckpoint(threadId, checkpoint) {
244
- const key = CHECKPOINT_PREFIX + threadId;
245
- if (checkpoint === null) {
246
- sessionStorage.removeItem(key);
247
- return;
248
- }
249
- sessionStorage.setItem(key, JSON.stringify(checkpoint));
250
- }
251
- clear(threadId) {
252
- sessionStorage.removeItem(MESSAGES_PREFIX + threadId);
253
- sessionStorage.removeItem(CHECKPOINT_PREFIX + threadId);
254
- sessionStorage.removeItem(THREAD_KEY);
255
- }
256
- /** Parse a stored JSON value, returning `null` when absent or corrupt. */
257
- #readJson(key) {
258
- const raw = sessionStorage.getItem(key);
259
- if (raw === null) {
260
- return null;
261
- }
262
- try {
263
- return JSON.parse(raw);
264
- } catch {
265
- return null;
266
- }
267
- }
268
- };
269
-
270
- // src/create_http_agent.ts
271
- import { HttpAgent } from "@ag-ui/client";
272
- function createHttpAgent(options) {
273
- return new HttpAgent({
274
- url: options.endpoint,
275
- headers: options.headers ?? {},
276
- // HttpAgent invokes its configured fetch as a method (`this.fetch(...)`),
277
- // which would rebind the global `fetch` to the agent instance and trigger
278
- // "Illegal invocation" in browsers. Wrap it so `fetch` is always called as
279
- // a free function with the correct receiver.
280
- fetch: (url, init) => fetch(url, init),
281
- // Spread conditionally: under `exactOptionalPropertyTypes` an explicit
282
- // `undefined` is not assignable to these optional config fields.
283
- ...options.threadId !== void 0 ? { threadId: options.threadId } : {},
284
- ...options.initialMessages !== void 0 ? { initialMessages: [...options.initialMessages] } : {}
285
- });
286
- }
287
-
288
- // src/is_destructive.ts
91
+ // src/tools/is_destructive.ts
289
92
  function isDestructive(parameters) {
290
93
  return parameters[X_DESTRUCTIVE_KEY] === true;
291
94
  }
292
95
 
293
- // src/is_navigates.ts
96
+ // src/tools/is_navigates.ts
294
97
  function isNavigates(parameters) {
295
98
  return parameters[X_NAVIGATES_KEY] === true;
296
99
  }
297
100
 
298
- // src/page_map.ts
101
+ // src/tools/page_map.ts
299
102
  function createPageMapContext(getPageMap, autoInject) {
300
103
  if (!autoInject || getPageMap === null) {
301
104
  return [];
@@ -303,11 +106,31 @@ function createPageMapContext(getPageMap, autoInject) {
303
106
  return [{ description: "page_map", value: JSON.stringify(getPageMap()) }];
304
107
  }
305
108
 
306
- // src/route_map.ts
307
- function withQuery(path, params) {
308
- if (params === void 0) {
309
- return path;
109
+ // src/tools/route_map.ts
110
+ var PATH_PARAM_RE = /:([A-Za-z_][A-Za-z0-9_]*)/g;
111
+ function pathParamNames(path) {
112
+ const names = [];
113
+ for (const match of path.matchAll(PATH_PARAM_RE)) {
114
+ const name = match[1];
115
+ if (name !== void 0) {
116
+ names.push(name);
117
+ }
310
118
  }
119
+ return names;
120
+ }
121
+ function fillPath(routeId, path, params) {
122
+ const leftover = { ...params };
123
+ const filled = path.replace(PATH_PARAM_RE, (_match, name) => {
124
+ const value = params[name];
125
+ if (value === void 0 || value === null || String(value) === "") {
126
+ throw new Error(`route "${routeId}" requires path param "${name}"`);
127
+ }
128
+ delete leftover[name];
129
+ return encodeURIComponent(String(value));
130
+ });
131
+ return { path: filled, leftover };
132
+ }
133
+ function withQuery(path, params) {
311
134
  const usp = new URLSearchParams();
312
135
  for (const [key, value] of Object.entries(params)) {
313
136
  usp.set(key, String(value));
@@ -319,13 +142,13 @@ function createRouteTools(getRouteMap, getNavigate) {
319
142
  return [
320
143
  {
321
144
  name: "list_routes",
322
- description: "List the routes the app can navigate to.",
145
+ description: "List the routes the app can navigate to. Each route's `pathParams` names the dynamic segments to pass as `params` to `navigate_to_route`.",
323
146
  parameters: { type: "object", properties: {}, required: [] },
324
- handler: () => getRouteMap()
147
+ handler: () => getRouteMap().map((route) => ({ ...route, pathParams: pathParamNames(route.path) }))
325
148
  },
326
149
  {
327
150
  name: "navigate_to_route",
328
- description: "Navigate to one of the app's routes by its id.",
151
+ description: "Navigate to one of the app's routes by its id, filling any dynamic `:name` path segments (and extra query params) from `params`.",
329
152
  parameters: {
330
153
  type: "object",
331
154
  properties: {
@@ -341,7 +164,9 @@ function createRouteTools(getRouteMap, getNavigate) {
341
164
  if (route === void 0) {
342
165
  throw new Error(`unknown route "${String(routeId)}"`);
343
166
  }
344
- const path = withQuery(route.path, args["params"]);
167
+ const provided = args["params"] ?? {};
168
+ const { path: filledPath, leftover } = fillPath(route.id, route.path, provided);
169
+ const path = withQuery(filledPath, leftover);
345
170
  const navigate = getNavigate();
346
171
  if (navigate !== null) {
347
172
  navigate(path);
@@ -354,7 +179,7 @@ function createRouteTools(getRouteMap, getNavigate) {
354
179
  ];
355
180
  }
356
181
 
357
- // src/state_hook.ts
182
+ // src/tools/state_hook.ts
358
183
  function createStateHookTools(hook) {
359
184
  const tools = [
360
185
  {
@@ -376,33 +201,2744 @@ function createStateHookTools(hook) {
376
201
  return tools;
377
202
  }
378
203
 
379
- // src/styles.ts
380
- var STYLES = `
381
- :host {
382
- /* Colors */
383
- --ag-ui-bg: #ffffff;
384
- --ag-ui-fg: #1a1a2e;
385
- --ag-ui-accent: #4f46e5;
386
- --ag-ui-user-bg: #4f46e5;
387
- --ag-ui-user-fg: #ffffff;
388
- --ag-ui-assistant-bg: #f1f1f6;
389
- --ag-ui-input-bg: var(--ag-ui-bg);
390
- --ag-ui-tool-bg: var(--ag-ui-assistant-bg);
391
- --ag-ui-tool-fg: var(--ag-ui-accent);
392
- --ag-ui-header-bg: var(--ag-ui-accent);
393
- --ag-ui-header-fg: #ffffff;
394
- --ag-ui-border: #e2e2ec;
395
- --ag-ui-radius: 12px;
204
+ // src/ui/confirmation_card.ts
205
+ function actionButton(modifier, label) {
206
+ const button = document.createElement("button");
207
+ button.type = "button";
208
+ button.className = `confirm-btn confirm-btn--${modifier}`;
209
+ button.textContent = label;
210
+ return button;
211
+ }
212
+ function requestConfirmation(host, request) {
213
+ return new Promise((resolve) => {
214
+ const card = document.createElement("div");
215
+ card.className = "confirm";
216
+ card.setAttribute("data-tool-name", request.toolName);
217
+ card.setAttribute("role", "group");
218
+ card.setAttribute("aria-label", "Confirm action");
219
+ const body = document.createElement("div");
220
+ body.className = "confirm-body";
221
+ body.textContent = request.message ?? `Run \u201C${request.toolName}\u201D?`;
222
+ const args = document.createElement("pre");
223
+ args.className = "confirm-args";
224
+ args.textContent = JSON.stringify(request.args, null, 2);
225
+ const actions = document.createElement("div");
226
+ actions.className = "confirm-actions";
227
+ const cancel = actionButton("cancel", "Cancel");
228
+ const confirm = actionButton("confirm", "Confirm");
229
+ const close = (accepted) => {
230
+ cancel.disabled = true;
231
+ confirm.disabled = true;
232
+ card.setAttribute("data-resolved", accepted ? "confirmed" : "declined");
233
+ resolve(accepted);
234
+ };
235
+ cancel.addEventListener("click", () => close(false));
236
+ confirm.addEventListener("click", () => close(true));
237
+ actions.append(cancel, confirm);
238
+ card.append(body, args, actions);
239
+ host.appendChild(card);
240
+ confirm.focus();
241
+ });
242
+ }
396
243
 
397
- /* Status accents for tool-call cards. */
398
- --ag-ui-success: #15803d;
399
- --ag-ui-danger: #b91c1c;
244
+ // node_modules/.pnpm/dompurify@3.4.7/node_modules/dompurify/dist/purify.es.mjs
245
+ function _arrayLikeToArray(r, a) {
246
+ (null == a || a > r.length) && (a = r.length);
247
+ for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
248
+ return n;
249
+ }
250
+ function _arrayWithHoles(r) {
251
+ if (Array.isArray(r)) return r;
252
+ }
253
+ function _iterableToArrayLimit(r, l3) {
254
+ var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
255
+ if (null != t) {
256
+ var e, n, i, u, a = [], f = true, o = false;
257
+ try {
258
+ if (i = (t = t.call(r)).next, 0 === l3) ;
259
+ else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l3); f = true) ;
260
+ } catch (r2) {
261
+ o = true, n = r2;
262
+ } finally {
263
+ try {
264
+ if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
265
+ } finally {
266
+ if (o) throw n;
267
+ }
268
+ }
269
+ return a;
270
+ }
271
+ }
272
+ function _nonIterableRest() {
273
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
274
+ }
275
+ function _slicedToArray(r, e) {
276
+ return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
277
+ }
278
+ function _unsupportedIterableToArray(r, a) {
279
+ if (r) {
280
+ if ("string" == typeof r) return _arrayLikeToArray(r, a);
281
+ var t = {}.toString.call(r).slice(8, -1);
282
+ return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
283
+ }
284
+ }
285
+ var entries = Object.entries;
286
+ var setPrototypeOf = Object.setPrototypeOf;
287
+ var isFrozen = Object.isFrozen;
288
+ var getPrototypeOf = Object.getPrototypeOf;
289
+ var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
290
+ var freeze = Object.freeze;
291
+ var seal = Object.seal;
292
+ var create = Object.create;
293
+ var _ref = typeof Reflect !== "undefined" && Reflect;
294
+ var apply = _ref.apply;
295
+ var construct = _ref.construct;
296
+ if (!freeze) {
297
+ freeze = function freeze2(x2) {
298
+ return x2;
299
+ };
300
+ }
301
+ if (!seal) {
302
+ seal = function seal2(x2) {
303
+ return x2;
304
+ };
305
+ }
306
+ if (!apply) {
307
+ apply = function apply2(func, thisArg) {
308
+ for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
309
+ args[_key - 2] = arguments[_key];
310
+ }
311
+ return func.apply(thisArg, args);
312
+ };
313
+ }
314
+ if (!construct) {
315
+ construct = function construct2(Func) {
316
+ for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
317
+ args[_key2 - 1] = arguments[_key2];
318
+ }
319
+ return new Func(...args);
320
+ };
321
+ }
322
+ var arrayForEach = unapply(Array.prototype.forEach);
323
+ var arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);
324
+ var arrayPop = unapply(Array.prototype.pop);
325
+ var arrayPush = unapply(Array.prototype.push);
326
+ var arraySplice = unapply(Array.prototype.splice);
327
+ var arrayIsArray = Array.isArray;
328
+ var stringToLowerCase = unapply(String.prototype.toLowerCase);
329
+ var stringToString = unapply(String.prototype.toString);
330
+ var stringMatch = unapply(String.prototype.match);
331
+ var stringReplace = unapply(String.prototype.replace);
332
+ var stringIndexOf = unapply(String.prototype.indexOf);
333
+ var stringTrim = unapply(String.prototype.trim);
334
+ var numberToString = unapply(Number.prototype.toString);
335
+ var booleanToString = unapply(Boolean.prototype.toString);
336
+ var bigintToString = typeof BigInt === "undefined" ? null : unapply(BigInt.prototype.toString);
337
+ var symbolToString = typeof Symbol === "undefined" ? null : unapply(Symbol.prototype.toString);
338
+ var objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
339
+ var objectToString = unapply(Object.prototype.toString);
340
+ var regExpTest = unapply(RegExp.prototype.test);
341
+ var typeErrorCreate = unconstruct(TypeError);
342
+ function unapply(func) {
343
+ return function(thisArg) {
344
+ if (thisArg instanceof RegExp) {
345
+ thisArg.lastIndex = 0;
346
+ }
347
+ for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
348
+ args[_key3 - 1] = arguments[_key3];
349
+ }
350
+ return apply(func, thisArg, args);
351
+ };
352
+ }
353
+ function unconstruct(Func) {
354
+ return function() {
355
+ for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
356
+ args[_key4] = arguments[_key4];
357
+ }
358
+ return construct(Func, args);
359
+ };
360
+ }
361
+ function addToSet(set, array) {
362
+ let transformCaseFunc = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : stringToLowerCase;
363
+ if (setPrototypeOf) {
364
+ setPrototypeOf(set, null);
365
+ }
366
+ if (!arrayIsArray(array)) {
367
+ return set;
368
+ }
369
+ let l3 = array.length;
370
+ while (l3--) {
371
+ let element = array[l3];
372
+ if (typeof element === "string") {
373
+ const lcElement = transformCaseFunc(element);
374
+ if (lcElement !== element) {
375
+ if (!isFrozen(array)) {
376
+ array[l3] = lcElement;
377
+ }
378
+ element = lcElement;
379
+ }
380
+ }
381
+ set[element] = true;
382
+ }
383
+ return set;
384
+ }
385
+ function cleanArray(array) {
386
+ for (let index = 0; index < array.length; index++) {
387
+ const isPropertyExist = objectHasOwnProperty(array, index);
388
+ if (!isPropertyExist) {
389
+ array[index] = null;
390
+ }
391
+ }
392
+ return array;
393
+ }
394
+ function clone(object) {
395
+ const newObject = create(null);
396
+ for (const _ref2 of entries(object)) {
397
+ var _ref3 = _slicedToArray(_ref2, 2);
398
+ const property = _ref3[0];
399
+ const value = _ref3[1];
400
+ const isPropertyExist = objectHasOwnProperty(object, property);
401
+ if (isPropertyExist) {
402
+ if (arrayIsArray(value)) {
403
+ newObject[property] = cleanArray(value);
404
+ } else if (value && typeof value === "object" && value.constructor === Object) {
405
+ newObject[property] = clone(value);
406
+ } else {
407
+ newObject[property] = value;
408
+ }
409
+ }
410
+ }
411
+ return newObject;
412
+ }
413
+ function stringifyValue(value) {
414
+ switch (typeof value) {
415
+ case "string": {
416
+ return value;
417
+ }
418
+ case "number": {
419
+ return numberToString(value);
420
+ }
421
+ case "boolean": {
422
+ return booleanToString(value);
423
+ }
424
+ case "bigint": {
425
+ return bigintToString ? bigintToString(value) : "0";
426
+ }
427
+ case "symbol": {
428
+ return symbolToString ? symbolToString(value) : "Symbol()";
429
+ }
430
+ case "undefined": {
431
+ return objectToString(value);
432
+ }
433
+ case "function":
434
+ case "object": {
435
+ if (value === null) {
436
+ return objectToString(value);
437
+ }
438
+ const valueAsRecord = value;
439
+ const valueToString = lookupGetter(valueAsRecord, "toString");
440
+ if (typeof valueToString === "function") {
441
+ const stringified = valueToString(valueAsRecord);
442
+ return typeof stringified === "string" ? stringified : objectToString(stringified);
443
+ }
444
+ return objectToString(value);
445
+ }
446
+ default: {
447
+ return objectToString(value);
448
+ }
449
+ }
450
+ }
451
+ function lookupGetter(object, prop) {
452
+ while (object !== null) {
453
+ const desc = getOwnPropertyDescriptor(object, prop);
454
+ if (desc) {
455
+ if (desc.get) {
456
+ return unapply(desc.get);
457
+ }
458
+ if (typeof desc.value === "function") {
459
+ return unapply(desc.value);
460
+ }
461
+ }
462
+ object = getPrototypeOf(object);
463
+ }
464
+ function fallbackValue() {
465
+ return null;
466
+ }
467
+ return fallbackValue;
468
+ }
469
+ function isRegex(value) {
470
+ try {
471
+ regExpTest(value, "");
472
+ return true;
473
+ } catch (_unused) {
474
+ return false;
475
+ }
476
+ }
477
+ var html$1 = freeze(["a", "abbr", "acronym", "address", "area", "article", "aside", "audio", "b", "bdi", "bdo", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "content", "data", "datalist", "dd", "decorator", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "element", "em", "fieldset", "figcaption", "figure", "font", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "img", "input", "ins", "kbd", "label", "legend", "li", "main", "map", "mark", "marquee", "menu", "menuitem", "meter", "nav", "nobr", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "search", "section", "select", "shadow", "slot", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "tr", "track", "tt", "u", "ul", "var", "video", "wbr"]);
478
+ var svg$1 = freeze(["svg", "a", "altglyph", "altglyphdef", "altglyphitem", "animatecolor", "animatemotion", "animatetransform", "circle", "clippath", "defs", "desc", "ellipse", "enterkeyhint", "exportparts", "filter", "font", "g", "glyph", "glyphref", "hkern", "image", "inputmode", "line", "lineargradient", "marker", "mask", "metadata", "mpath", "part", "path", "pattern", "polygon", "polyline", "radialgradient", "rect", "stop", "style", "switch", "symbol", "text", "textpath", "title", "tref", "tspan", "view", "vkern"]);
479
+ var svgFilters = freeze(["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence"]);
480
+ 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"]);
481
+ 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"]);
482
+ var mathMlDisallowed = freeze(["maction", "maligngroup", "malignmark", "mlongdiv", "mscarries", "mscarry", "msgroup", "mstack", "msline", "msrow", "semantics", "annotation", "annotation-xml", "mprescripts", "none"]);
483
+ var text = freeze(["#text"]);
484
+ 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"]);
485
+ 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", "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-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"]);
486
+ 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"]);
487
+ var xml = freeze(["xlink:href", "xml:id", "xlink:title", "xml:space", "xmlns:xlink"]);
488
+ var MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g);
489
+ var ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g);
490
+ var TMPLIT_EXPR = seal(/\${[\w\W]*/g);
491
+ var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/);
492
+ var ARIA_ATTR = seal(/^aria-[\-\w]+$/);
493
+ var IS_ALLOWED_URI = seal(
494
+ /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i
495
+ // eslint-disable-line no-useless-escape
496
+ );
497
+ var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
498
+ var ATTR_WHITESPACE = seal(
499
+ /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g
500
+ // eslint-disable-line no-control-regex
501
+ );
502
+ var DOCTYPE_NAME = seal(/^html$/i);
503
+ var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
504
+ var NODE_TYPE = {
505
+ element: 1,
506
+ attribute: 2,
507
+ text: 3,
508
+ cdataSection: 4,
509
+ entityReference: 5,
510
+ // Deprecated
511
+ entityNode: 6,
512
+ // Deprecated
513
+ progressingInstruction: 7,
514
+ comment: 8,
515
+ document: 9,
516
+ documentType: 10,
517
+ documentFragment: 11,
518
+ notation: 12
519
+ // Deprecated
520
+ };
521
+ var getGlobal = function getGlobal2() {
522
+ return typeof window === "undefined" ? null : window;
523
+ };
524
+ var _createTrustedTypesPolicy = function _createTrustedTypesPolicy2(trustedTypes, purifyHostElement) {
525
+ if (typeof trustedTypes !== "object" || typeof trustedTypes.createPolicy !== "function") {
526
+ return null;
527
+ }
528
+ let suffix = null;
529
+ const ATTR_NAME = "data-tt-policy-suffix";
530
+ if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {
531
+ suffix = purifyHostElement.getAttribute(ATTR_NAME);
532
+ }
533
+ const policyName = "dompurify" + (suffix ? "#" + suffix : "");
534
+ try {
535
+ return trustedTypes.createPolicy(policyName, {
536
+ createHTML(html2) {
537
+ return html2;
538
+ },
539
+ createScriptURL(scriptUrl) {
540
+ return scriptUrl;
541
+ }
542
+ });
543
+ } catch (_2) {
544
+ console.warn("TrustedTypes policy " + policyName + " could not be created.");
545
+ return null;
546
+ }
547
+ };
548
+ var _createHooksMap = function _createHooksMap2() {
549
+ return {
550
+ afterSanitizeAttributes: [],
551
+ afterSanitizeElements: [],
552
+ afterSanitizeShadowDOM: [],
553
+ beforeSanitizeAttributes: [],
554
+ beforeSanitizeElements: [],
555
+ beforeSanitizeShadowDOM: [],
556
+ uponSanitizeAttribute: [],
557
+ uponSanitizeElement: [],
558
+ uponSanitizeShadowNode: []
559
+ };
560
+ };
561
+ function createDOMPurify() {
562
+ let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal();
563
+ const DOMPurify = (root) => createDOMPurify(root);
564
+ DOMPurify.version = "3.4.7";
565
+ DOMPurify.removed = [];
566
+ if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) {
567
+ DOMPurify.isSupported = false;
568
+ return DOMPurify;
569
+ }
570
+ let document2 = window2.document;
571
+ const originalDocument = document2;
572
+ const currentScript = originalDocument.currentScript;
573
+ window2.DocumentFragment;
574
+ const HTMLTemplateElement = window2.HTMLTemplateElement, Node2 = window2.Node, Element = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap;
575
+ _window$NamedNodeMap === void 0 ? window2.NamedNodeMap || window2.MozNamedAttrMap : _window$NamedNodeMap;
576
+ window2.HTMLFormElement;
577
+ const DOMParser = window2.DOMParser, trustedTypes = window2.trustedTypes;
578
+ const ElementPrototype = Element.prototype;
579
+ const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
580
+ const remove = lookupGetter(ElementPrototype, "remove");
581
+ const getNextSibling = lookupGetter(ElementPrototype, "nextSibling");
582
+ const getChildNodes = lookupGetter(ElementPrototype, "childNodes");
583
+ const getParentNode = lookupGetter(ElementPrototype, "parentNode");
584
+ const getShadowRoot = lookupGetter(ElementPrototype, "shadowRoot");
585
+ const getAttributes = lookupGetter(ElementPrototype, "attributes");
586
+ const getNodeType = Node2 && Node2.prototype ? lookupGetter(Node2.prototype, "nodeType") : null;
587
+ const getNodeName = Node2 && Node2.prototype ? lookupGetter(Node2.prototype, "nodeName") : null;
588
+ if (typeof HTMLTemplateElement === "function") {
589
+ const template = document2.createElement("template");
590
+ if (template.content && template.content.ownerDocument) {
591
+ document2 = template.content.ownerDocument;
592
+ }
593
+ }
594
+ let trustedTypesPolicy;
595
+ let emptyHTML = "";
596
+ const _document = document2, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName;
597
+ const importNode = originalDocument.importNode;
598
+ let hooks = _createHooksMap();
599
+ DOMPurify.isSupported = typeof entries === "function" && typeof getParentNode === "function" && implementation && implementation.createHTMLDocument !== void 0;
600
+ 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;
601
+ let IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
602
+ let ALLOWED_TAGS2 = null;
603
+ const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);
604
+ let ALLOWED_ATTR2 = null;
605
+ const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);
606
+ let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {
607
+ tagNameCheck: {
608
+ writable: true,
609
+ configurable: false,
610
+ enumerable: true,
611
+ value: null
612
+ },
613
+ attributeNameCheck: {
614
+ writable: true,
615
+ configurable: false,
616
+ enumerable: true,
617
+ value: null
618
+ },
619
+ allowCustomizedBuiltInElements: {
620
+ writable: true,
621
+ configurable: false,
622
+ enumerable: true,
623
+ value: false
624
+ }
625
+ }));
626
+ let FORBID_TAGS = null;
627
+ let FORBID_ATTR = null;
628
+ const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {
629
+ tagCheck: {
630
+ writable: true,
631
+ configurable: false,
632
+ enumerable: true,
633
+ value: null
634
+ },
635
+ attributeCheck: {
636
+ writable: true,
637
+ configurable: false,
638
+ enumerable: true,
639
+ value: null
640
+ }
641
+ }));
642
+ let ALLOW_ARIA_ATTR = true;
643
+ let ALLOW_DATA_ATTR = true;
644
+ let ALLOW_UNKNOWN_PROTOCOLS = false;
645
+ let ALLOW_SELF_CLOSE_IN_ATTR = true;
646
+ let SAFE_FOR_TEMPLATES = false;
647
+ let SAFE_FOR_XML = true;
648
+ let WHOLE_DOCUMENT = false;
649
+ let SET_CONFIG = false;
650
+ let FORCE_BODY = false;
651
+ let RETURN_DOM = false;
652
+ let RETURN_DOM_FRAGMENT = false;
653
+ let RETURN_TRUSTED_TYPE = false;
654
+ let SANITIZE_DOM = true;
655
+ let SANITIZE_NAMED_PROPS = false;
656
+ const SANITIZE_NAMED_PROPS_PREFIX = "user-content-";
657
+ let KEEP_CONTENT = true;
658
+ let IN_PLACE = false;
659
+ let USE_PROFILES = {};
660
+ let FORBID_CONTENTS = null;
661
+ const DEFAULT_FORBID_CONTENTS = addToSet({}, ["annotation-xml", "audio", "colgroup", "desc", "foreignobject", "head", "iframe", "math", "mi", "mn", "mo", "ms", "mtext", "noembed", "noframes", "noscript", "plaintext", "script", "style", "svg", "template", "thead", "title", "video", "xmp"]);
662
+ let DATA_URI_TAGS = null;
663
+ const DEFAULT_DATA_URI_TAGS = addToSet({}, ["audio", "video", "img", "source", "image", "track"]);
664
+ let URI_SAFE_ATTRIBUTES = null;
665
+ const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ["alt", "class", "for", "id", "label", "name", "pattern", "placeholder", "role", "summary", "title", "value", "style", "xmlns"]);
666
+ const MATHML_NAMESPACE = "http://www.w3.org/1998/Math/MathML";
667
+ const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
668
+ const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
669
+ let NAMESPACE = HTML_NAMESPACE;
670
+ let IS_EMPTY_INPUT = false;
671
+ let ALLOWED_NAMESPACES = null;
672
+ const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
673
+ let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ["mi", "mo", "mn", "ms", "mtext"]);
674
+ let HTML_INTEGRATION_POINTS = addToSet({}, ["annotation-xml"]);
675
+ const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ["title", "style", "font", "a", "script"]);
676
+ let PARSER_MEDIA_TYPE = null;
677
+ const SUPPORTED_PARSER_MEDIA_TYPES = ["application/xhtml+xml", "text/html"];
678
+ const DEFAULT_PARSER_MEDIA_TYPE = "text/html";
679
+ let transformCaseFunc = null;
680
+ let CONFIG = null;
681
+ const formElement = document2.createElement("form");
682
+ const isRegexOrFunction = function isRegexOrFunction2(testValue) {
683
+ return testValue instanceof RegExp || testValue instanceof Function;
684
+ };
685
+ const _parseConfig = function _parseConfig2() {
686
+ let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
687
+ if (CONFIG && CONFIG === cfg) {
688
+ return;
689
+ }
690
+ if (!cfg || typeof cfg !== "object") {
691
+ cfg = {};
692
+ }
693
+ cfg = clone(cfg);
694
+ PARSER_MEDIA_TYPE = // eslint-disable-next-line unicorn/prefer-includes
695
+ SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;
696
+ transformCaseFunc = PARSER_MEDIA_TYPE === "application/xhtml+xml" ? stringToString : stringToLowerCase;
697
+ ALLOWED_TAGS2 = objectHasOwnProperty(cfg, "ALLOWED_TAGS") && arrayIsArray(cfg.ALLOWED_TAGS) ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
698
+ ALLOWED_ATTR2 = objectHasOwnProperty(cfg, "ALLOWED_ATTR") && arrayIsArray(cfg.ALLOWED_ATTR) ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
699
+ ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, "ALLOWED_NAMESPACES") && arrayIsArray(cfg.ALLOWED_NAMESPACES) ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
700
+ URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, "ADD_URI_SAFE_ATTR") && arrayIsArray(cfg.ADD_URI_SAFE_ATTR) ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
701
+ DATA_URI_TAGS = objectHasOwnProperty(cfg, "ADD_DATA_URI_TAGS") && arrayIsArray(cfg.ADD_DATA_URI_TAGS) ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
702
+ FORBID_CONTENTS = objectHasOwnProperty(cfg, "FORBID_CONTENTS") && arrayIsArray(cfg.FORBID_CONTENTS) ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
703
+ FORBID_TAGS = objectHasOwnProperty(cfg, "FORBID_TAGS") && arrayIsArray(cfg.FORBID_TAGS) ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
704
+ FORBID_ATTR = objectHasOwnProperty(cfg, "FORBID_ATTR") && arrayIsArray(cfg.FORBID_ATTR) ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
705
+ USE_PROFILES = objectHasOwnProperty(cfg, "USE_PROFILES") ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === "object" ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false;
706
+ ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
707
+ ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
708
+ ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false;
709
+ ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false;
710
+ SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false;
711
+ SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false;
712
+ WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false;
713
+ RETURN_DOM = cfg.RETURN_DOM || false;
714
+ RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false;
715
+ RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
716
+ FORCE_BODY = cfg.FORCE_BODY || false;
717
+ SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
718
+ SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false;
719
+ KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
720
+ IN_PLACE = cfg.IN_PLACE || false;
721
+ IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI;
722
+ NAMESPACE = typeof cfg.NAMESPACE === "string" ? cfg.NAMESPACE : HTML_NAMESPACE;
723
+ 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({}, ["mi", "mo", "mn", "ms", "mtext"]);
724
+ HTML_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "HTML_INTEGRATION_POINTS") && cfg.HTML_INTEGRATION_POINTS && typeof cfg.HTML_INTEGRATION_POINTS === "object" ? clone(cfg.HTML_INTEGRATION_POINTS) : addToSet({}, ["annotation-xml"]);
725
+ const customElementHandling = objectHasOwnProperty(cfg, "CUSTOM_ELEMENT_HANDLING") && cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING === "object" ? clone(cfg.CUSTOM_ELEMENT_HANDLING) : create(null);
726
+ CUSTOM_ELEMENT_HANDLING = create(null);
727
+ if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) {
728
+ CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck;
729
+ }
730
+ if (objectHasOwnProperty(customElementHandling, "attributeNameCheck") && isRegexOrFunction(customElementHandling.attributeNameCheck)) {
731
+ CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck;
732
+ }
733
+ if (objectHasOwnProperty(customElementHandling, "allowCustomizedBuiltInElements") && typeof customElementHandling.allowCustomizedBuiltInElements === "boolean") {
734
+ CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements;
735
+ }
736
+ if (SAFE_FOR_TEMPLATES) {
737
+ ALLOW_DATA_ATTR = false;
738
+ }
739
+ if (RETURN_DOM_FRAGMENT) {
740
+ RETURN_DOM = true;
741
+ }
742
+ if (USE_PROFILES) {
743
+ ALLOWED_TAGS2 = addToSet({}, text);
744
+ ALLOWED_ATTR2 = create(null);
745
+ if (USE_PROFILES.html === true) {
746
+ addToSet(ALLOWED_TAGS2, html$1);
747
+ addToSet(ALLOWED_ATTR2, html);
748
+ }
749
+ if (USE_PROFILES.svg === true) {
750
+ addToSet(ALLOWED_TAGS2, svg$1);
751
+ addToSet(ALLOWED_ATTR2, svg);
752
+ addToSet(ALLOWED_ATTR2, xml);
753
+ }
754
+ if (USE_PROFILES.svgFilters === true) {
755
+ addToSet(ALLOWED_TAGS2, svgFilters);
756
+ addToSet(ALLOWED_ATTR2, svg);
757
+ addToSet(ALLOWED_ATTR2, xml);
758
+ }
759
+ if (USE_PROFILES.mathMl === true) {
760
+ addToSet(ALLOWED_TAGS2, mathMl$1);
761
+ addToSet(ALLOWED_ATTR2, mathMl);
762
+ addToSet(ALLOWED_ATTR2, xml);
763
+ }
764
+ }
765
+ EXTRA_ELEMENT_HANDLING.tagCheck = null;
766
+ EXTRA_ELEMENT_HANDLING.attributeCheck = null;
767
+ if (objectHasOwnProperty(cfg, "ADD_TAGS")) {
768
+ if (typeof cfg.ADD_TAGS === "function") {
769
+ EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
770
+ } else if (arrayIsArray(cfg.ADD_TAGS)) {
771
+ if (ALLOWED_TAGS2 === DEFAULT_ALLOWED_TAGS) {
772
+ ALLOWED_TAGS2 = clone(ALLOWED_TAGS2);
773
+ }
774
+ addToSet(ALLOWED_TAGS2, cfg.ADD_TAGS, transformCaseFunc);
775
+ }
776
+ }
777
+ if (objectHasOwnProperty(cfg, "ADD_ATTR")) {
778
+ if (typeof cfg.ADD_ATTR === "function") {
779
+ EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
780
+ } else if (arrayIsArray(cfg.ADD_ATTR)) {
781
+ if (ALLOWED_ATTR2 === DEFAULT_ALLOWED_ATTR) {
782
+ ALLOWED_ATTR2 = clone(ALLOWED_ATTR2);
783
+ }
784
+ addToSet(ALLOWED_ATTR2, cfg.ADD_ATTR, transformCaseFunc);
785
+ }
786
+ }
787
+ if (objectHasOwnProperty(cfg, "ADD_URI_SAFE_ATTR") && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) {
788
+ addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
789
+ }
790
+ if (objectHasOwnProperty(cfg, "FORBID_CONTENTS") && arrayIsArray(cfg.FORBID_CONTENTS)) {
791
+ if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
792
+ FORBID_CONTENTS = clone(FORBID_CONTENTS);
793
+ }
794
+ addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
795
+ }
796
+ if (objectHasOwnProperty(cfg, "ADD_FORBID_CONTENTS") && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
797
+ if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
798
+ FORBID_CONTENTS = clone(FORBID_CONTENTS);
799
+ }
800
+ addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
801
+ }
802
+ if (KEEP_CONTENT) {
803
+ ALLOWED_TAGS2["#text"] = true;
804
+ }
805
+ if (WHOLE_DOCUMENT) {
806
+ addToSet(ALLOWED_TAGS2, ["html", "head", "body"]);
807
+ }
808
+ if (ALLOWED_TAGS2.table) {
809
+ addToSet(ALLOWED_TAGS2, ["tbody"]);
810
+ delete FORBID_TAGS.tbody;
811
+ }
812
+ if (cfg.TRUSTED_TYPES_POLICY) {
813
+ if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== "function") {
814
+ throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');
815
+ }
816
+ if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== "function") {
817
+ throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
818
+ }
819
+ trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
820
+ emptyHTML = trustedTypesPolicy.createHTML("");
821
+ } else {
822
+ if (trustedTypesPolicy === void 0) {
823
+ trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
824
+ }
825
+ if (trustedTypesPolicy !== null && typeof emptyHTML === "string") {
826
+ emptyHTML = trustedTypesPolicy.createHTML("");
827
+ }
828
+ }
829
+ if ((hooks.uponSanitizeElement.length > 0 || hooks.uponSanitizeAttribute.length > 0) && ALLOWED_TAGS2 === DEFAULT_ALLOWED_TAGS) {
830
+ ALLOWED_TAGS2 = clone(ALLOWED_TAGS2);
831
+ }
832
+ if (hooks.uponSanitizeAttribute.length > 0 && ALLOWED_ATTR2 === DEFAULT_ALLOWED_ATTR) {
833
+ ALLOWED_ATTR2 = clone(ALLOWED_ATTR2);
834
+ }
835
+ if (freeze) {
836
+ freeze(cfg);
837
+ }
838
+ CONFIG = cfg;
839
+ };
840
+ const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);
841
+ const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);
842
+ const _checkValidNamespace = function _checkValidNamespace2(element) {
843
+ let parent = getParentNode(element);
844
+ if (!parent || !parent.tagName) {
845
+ parent = {
846
+ namespaceURI: NAMESPACE,
847
+ tagName: "template"
848
+ };
849
+ }
850
+ const tagName = stringToLowerCase(element.tagName);
851
+ const parentTagName = stringToLowerCase(parent.tagName);
852
+ if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
853
+ return false;
854
+ }
855
+ if (element.namespaceURI === SVG_NAMESPACE) {
856
+ if (parent.namespaceURI === HTML_NAMESPACE) {
857
+ return tagName === "svg";
858
+ }
859
+ if (parent.namespaceURI === MATHML_NAMESPACE) {
860
+ return tagName === "svg" && (parentTagName === "annotation-xml" || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
861
+ }
862
+ return Boolean(ALL_SVG_TAGS[tagName]);
863
+ }
864
+ if (element.namespaceURI === MATHML_NAMESPACE) {
865
+ if (parent.namespaceURI === HTML_NAMESPACE) {
866
+ return tagName === "math";
867
+ }
868
+ if (parent.namespaceURI === SVG_NAMESPACE) {
869
+ return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName];
870
+ }
871
+ return Boolean(ALL_MATHML_TAGS[tagName]);
872
+ }
873
+ if (element.namespaceURI === HTML_NAMESPACE) {
874
+ if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
875
+ return false;
876
+ }
877
+ if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
878
+ return false;
879
+ }
880
+ return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
881
+ }
882
+ if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && ALLOWED_NAMESPACES[element.namespaceURI]) {
883
+ return true;
884
+ }
885
+ return false;
886
+ };
887
+ const _forceRemove = function _forceRemove2(node) {
888
+ arrayPush(DOMPurify.removed, {
889
+ element: node
890
+ });
891
+ try {
892
+ getParentNode(node).removeChild(node);
893
+ } catch (_2) {
894
+ remove(node);
895
+ }
896
+ };
897
+ const _removeAttribute = function _removeAttribute2(name, element) {
898
+ try {
899
+ arrayPush(DOMPurify.removed, {
900
+ attribute: element.getAttributeNode(name),
901
+ from: element
902
+ });
903
+ } catch (_2) {
904
+ arrayPush(DOMPurify.removed, {
905
+ attribute: null,
906
+ from: element
907
+ });
908
+ }
909
+ element.removeAttribute(name);
910
+ if (name === "is") {
911
+ if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
912
+ try {
913
+ _forceRemove(element);
914
+ } catch (_2) {
915
+ }
916
+ } else {
917
+ try {
918
+ element.setAttribute(name, "");
919
+ } catch (_2) {
920
+ }
921
+ }
922
+ }
923
+ };
924
+ const _initDocument = function _initDocument2(dirty) {
925
+ let doc = null;
926
+ let leadingWhitespace = null;
927
+ if (FORCE_BODY) {
928
+ dirty = "<remove></remove>" + dirty;
929
+ } else {
930
+ const matches = stringMatch(dirty, /^[\r\n\t ]+/);
931
+ leadingWhitespace = matches && matches[0];
932
+ }
933
+ if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && NAMESPACE === HTML_NAMESPACE) {
934
+ dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + "</body></html>";
935
+ }
936
+ const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
937
+ if (NAMESPACE === HTML_NAMESPACE) {
938
+ try {
939
+ doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
940
+ } catch (_2) {
941
+ }
942
+ }
943
+ if (!doc || !doc.documentElement) {
944
+ doc = implementation.createDocument(NAMESPACE, "template", null);
945
+ try {
946
+ doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
947
+ } catch (_2) {
948
+ }
949
+ }
950
+ const body = doc.body || doc.documentElement;
951
+ if (dirty && leadingWhitespace) {
952
+ body.insertBefore(document2.createTextNode(leadingWhitespace), body.childNodes[0] || null);
953
+ }
954
+ if (NAMESPACE === HTML_NAMESPACE) {
955
+ return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? "html" : "body")[0];
956
+ }
957
+ return WHOLE_DOCUMENT ? doc.documentElement : body;
958
+ };
959
+ const _createNodeIterator = function _createNodeIterator2(root) {
960
+ return createNodeIterator.call(
961
+ root.ownerDocument || root,
962
+ root,
963
+ // eslint-disable-next-line no-bitwise
964
+ NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION,
965
+ null
966
+ );
967
+ };
968
+ const _scrubTemplateExpressions = function _scrubTemplateExpressions2(node) {
969
+ node.normalize();
970
+ const walker = createNodeIterator.call(
971
+ node.ownerDocument || node,
972
+ node,
973
+ // eslint-disable-next-line no-bitwise
974
+ NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_CDATA_SECTION | NodeFilter.SHOW_PROCESSING_INSTRUCTION,
975
+ null
976
+ );
977
+ let currentNode = walker.nextNode();
978
+ while (currentNode) {
979
+ let data = currentNode.data;
980
+ arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
981
+ data = stringReplace(data, expr, " ");
982
+ });
983
+ currentNode.data = data;
984
+ currentNode = walker.nextNode();
985
+ }
986
+ };
987
+ const _isClobbered = function _isClobbered2(element) {
988
+ const realTagName = getNodeName ? getNodeName(element) : null;
989
+ if (typeof realTagName !== "string") {
990
+ return false;
991
+ }
992
+ if (transformCaseFunc(realTagName) !== "form") {
993
+ return false;
994
+ }
995
+ return typeof element.nodeName !== "string" || typeof element.textContent !== "string" || typeof element.removeChild !== "function" || // Realm-safe NamedNodeMap detection: equality against the cached
996
+ // prototype getter. Clobbered .attributes (e.g. <input name="attributes">)
997
+ // makes the direct read diverge from the cached read; a clean form
998
+ // (same-realm OR foreign-realm) has both reads pointing at the same
999
+ // canonical NamedNodeMap.
1000
+ element.attributes !== getAttributes(element) || typeof element.removeAttribute !== "function" || typeof element.setAttribute !== "function" || typeof element.namespaceURI !== "string" || typeof element.insertBefore !== "function" || typeof element.hasChildNodes !== "function" || // NodeType clobbering probe. Cached Node.prototype.nodeType getter
1001
+ // returns the integer 1 for any Element regardless of realm; direct
1002
+ // read on a clobbered form (e.g. <input name="nodeType">) returns
1003
+ // the named child element. Cheap addition — nodeType is read from
1004
+ // an internal slot, no serialization cost — and removes a residual
1005
+ // clobbering surface used by several mXSS / PI / comment branches
1006
+ // in _sanitizeElements that compare currentNode.nodeType directly.
1007
+ element.nodeType !== getNodeType(element) || // HTMLFormElement has [LegacyOverrideBuiltIns]: a descendant named
1008
+ // "childNodes" shadows the prototype getter. Direct reads of
1009
+ // form.childNodes from a clobbered form return the named child
1010
+ // instead of the real NodeList, so any walk that reads it directly
1011
+ // skips the form's real children. Compare the direct read to the
1012
+ // cached Node.prototype getter — when the form's named-property
1013
+ // getter intercepts the read, the two values differ and we flag
1014
+ // the form. This catches every clobbering child type (input,
1015
+ // select, etc.) regardless of whether the named child happens to
1016
+ // carry a numeric .length, which a typeof-based probe would miss
1017
+ // (e.g. HTMLSelectElement.length is a defined unsigned-long).
1018
+ element.childNodes !== getChildNodes(element);
1019
+ };
1020
+ const _isDocumentFragment = function _isDocumentFragment2(value) {
1021
+ if (!getNodeType || typeof value !== "object" || value === null) {
1022
+ return false;
1023
+ }
1024
+ try {
1025
+ return getNodeType(value) === NODE_TYPE.documentFragment;
1026
+ } catch (_2) {
1027
+ return false;
1028
+ }
1029
+ };
1030
+ const _isNode = function _isNode2(value) {
1031
+ if (!getNodeType || typeof value !== "object" || value === null) {
1032
+ return false;
1033
+ }
1034
+ try {
1035
+ return typeof getNodeType(value) === "number";
1036
+ } catch (_2) {
1037
+ return false;
1038
+ }
1039
+ };
1040
+ function _executeHooks(hooks2, currentNode, data) {
1041
+ arrayForEach(hooks2, (hook) => {
1042
+ hook.call(DOMPurify, currentNode, data, CONFIG);
1043
+ });
1044
+ }
1045
+ const _sanitizeElements = function _sanitizeElements2(currentNode) {
1046
+ let content = null;
1047
+ _executeHooks(hooks.beforeSanitizeElements, currentNode, null);
1048
+ if (_isClobbered(currentNode)) {
1049
+ _forceRemove(currentNode);
1050
+ return true;
1051
+ }
1052
+ const tagName = transformCaseFunc(currentNode.nodeName);
1053
+ _executeHooks(hooks.uponSanitizeElement, currentNode, {
1054
+ tagName,
1055
+ allowedTags: ALLOWED_TAGS2
1056
+ });
1057
+ if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) {
1058
+ _forceRemove(currentNode);
1059
+ return true;
1060
+ }
1061
+ if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === "style" && _isNode(currentNode.firstElementChild)) {
1062
+ _forceRemove(currentNode);
1063
+ return true;
1064
+ }
1065
+ if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
1066
+ _forceRemove(currentNode);
1067
+ return true;
1068
+ }
1069
+ if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\w]/g, currentNode.data)) {
1070
+ _forceRemove(currentNode);
1071
+ return true;
1072
+ }
1073
+ if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS2[tagName]) {
1074
+ if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
1075
+ if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
1076
+ return false;
1077
+ }
1078
+ if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {
1079
+ return false;
1080
+ }
1081
+ }
1082
+ if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
1083
+ const parentNode = getParentNode(currentNode);
1084
+ const childNodes = getChildNodes(currentNode);
1085
+ if (childNodes && parentNode) {
1086
+ const childCount = childNodes.length;
1087
+ for (let i = childCount - 1; i >= 0; --i) {
1088
+ const childClone = cloneNode(childNodes[i], true);
1089
+ parentNode.insertBefore(childClone, getNextSibling(currentNode));
1090
+ }
1091
+ }
1092
+ }
1093
+ _forceRemove(currentNode);
1094
+ return true;
1095
+ }
1096
+ const nt2 = getNodeType ? getNodeType(currentNode) : currentNode.nodeType;
1097
+ if (nt2 === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
1098
+ _forceRemove(currentNode);
1099
+ return true;
1100
+ }
1101
+ if ((tagName === "noscript" || tagName === "noembed" || tagName === "noframes") && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
1102
+ _forceRemove(currentNode);
1103
+ return true;
1104
+ }
1105
+ if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
1106
+ content = currentNode.textContent;
1107
+ arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
1108
+ content = stringReplace(content, expr, " ");
1109
+ });
1110
+ if (currentNode.textContent !== content) {
1111
+ arrayPush(DOMPurify.removed, {
1112
+ element: currentNode.cloneNode()
1113
+ });
1114
+ currentNode.textContent = content;
1115
+ }
1116
+ }
1117
+ _executeHooks(hooks.afterSanitizeElements, currentNode, null);
1118
+ return false;
1119
+ };
1120
+ const _isValidAttribute = function _isValidAttribute2(lcTag, lcName, value) {
1121
+ if (FORBID_ATTR[lcName]) {
1122
+ return false;
1123
+ }
1124
+ if (SANITIZE_DOM && (lcName === "id" || lcName === "name") && (value in document2 || value in formElement)) {
1125
+ return false;
1126
+ }
1127
+ const nameIsPermitted = ALLOWED_ATTR2[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
1128
+ if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName)) ;
1129
+ else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) ;
1130
+ else if (!nameIsPermitted || FORBID_ATTR[lcName]) {
1131
+ if (
1132
+ // First condition does a very basic check if a) it's basically a valid custom element tagname AND
1133
+ // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
1134
+ // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
1135
+ _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
1136
+ // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
1137
+ 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))
1138
+ ) ;
1139
+ else {
1140
+ return false;
1141
+ }
1142
+ } else if (URI_SAFE_ATTRIBUTES[lcName]) ;
1143
+ else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) ;
1144
+ else if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]) ;
1145
+ else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) ;
1146
+ else if (value) {
1147
+ return false;
1148
+ } else ;
1149
+ return true;
1150
+ };
1151
+ 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"]);
1152
+ const _isBasicCustomElement = function _isBasicCustomElement2(tagName) {
1153
+ return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName);
1154
+ };
1155
+ const _sanitizeAttributes = function _sanitizeAttributes2(currentNode) {
1156
+ _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
1157
+ const attributes = currentNode.attributes;
1158
+ if (!attributes || _isClobbered(currentNode)) {
1159
+ return;
1160
+ }
1161
+ const hookEvent = {
1162
+ attrName: "",
1163
+ attrValue: "",
1164
+ keepAttr: true,
1165
+ allowedAttributes: ALLOWED_ATTR2,
1166
+ forceKeepAttr: void 0
1167
+ };
1168
+ let l3 = attributes.length;
1169
+ while (l3--) {
1170
+ const attr = attributes[l3];
1171
+ const name = attr.name, namespaceURI = attr.namespaceURI, attrValue = attr.value;
1172
+ const lcName = transformCaseFunc(name);
1173
+ const initValue = attrValue;
1174
+ let value = name === "value" ? initValue : stringTrim(initValue);
1175
+ hookEvent.attrName = lcName;
1176
+ hookEvent.attrValue = value;
1177
+ hookEvent.keepAttr = true;
1178
+ hookEvent.forceKeepAttr = void 0;
1179
+ _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
1180
+ value = hookEvent.attrValue;
1181
+ if (SANITIZE_NAMED_PROPS && (lcName === "id" || lcName === "name") && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
1182
+ _removeAttribute(name, currentNode);
1183
+ value = SANITIZE_NAMED_PROPS_PREFIX + value;
1184
+ }
1185
+ if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
1186
+ _removeAttribute(name, currentNode);
1187
+ continue;
1188
+ }
1189
+ if (lcName === "attributename" && stringMatch(value, "href")) {
1190
+ _removeAttribute(name, currentNode);
1191
+ continue;
1192
+ }
1193
+ if (hookEvent.forceKeepAttr) {
1194
+ continue;
1195
+ }
1196
+ if (!hookEvent.keepAttr) {
1197
+ _removeAttribute(name, currentNode);
1198
+ continue;
1199
+ }
1200
+ if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
1201
+ _removeAttribute(name, currentNode);
1202
+ continue;
1203
+ }
1204
+ if (SAFE_FOR_TEMPLATES) {
1205
+ arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
1206
+ value = stringReplace(value, expr, " ");
1207
+ });
1208
+ }
1209
+ const lcTag = transformCaseFunc(currentNode.nodeName);
1210
+ if (!_isValidAttribute(lcTag, lcName, value)) {
1211
+ _removeAttribute(name, currentNode);
1212
+ continue;
1213
+ }
1214
+ if (trustedTypesPolicy && typeof trustedTypes === "object" && typeof trustedTypes.getAttributeType === "function") {
1215
+ if (namespaceURI) ;
1216
+ else {
1217
+ switch (trustedTypes.getAttributeType(lcTag, lcName)) {
1218
+ case "TrustedHTML": {
1219
+ value = trustedTypesPolicy.createHTML(value);
1220
+ break;
1221
+ }
1222
+ case "TrustedScriptURL": {
1223
+ value = trustedTypesPolicy.createScriptURL(value);
1224
+ break;
1225
+ }
1226
+ }
1227
+ }
1228
+ }
1229
+ if (value !== initValue) {
1230
+ try {
1231
+ if (namespaceURI) {
1232
+ currentNode.setAttributeNS(namespaceURI, name, value);
1233
+ } else {
1234
+ currentNode.setAttribute(name, value);
1235
+ }
1236
+ if (_isClobbered(currentNode)) {
1237
+ _forceRemove(currentNode);
1238
+ } else {
1239
+ arrayPop(DOMPurify.removed);
1240
+ }
1241
+ } catch (_2) {
1242
+ _removeAttribute(name, currentNode);
1243
+ }
1244
+ }
1245
+ }
1246
+ _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
1247
+ };
1248
+ const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {
1249
+ let shadowNode = null;
1250
+ const shadowIterator = _createNodeIterator(fragment);
1251
+ _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);
1252
+ while (shadowNode = shadowIterator.nextNode()) {
1253
+ _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
1254
+ _sanitizeElements(shadowNode);
1255
+ _sanitizeAttributes(shadowNode);
1256
+ if (_isDocumentFragment(shadowNode.content)) {
1257
+ _sanitizeShadowDOM2(shadowNode.content);
1258
+ }
1259
+ const shadowNodeType = getNodeType ? getNodeType(shadowNode) : shadowNode.nodeType;
1260
+ if (shadowNodeType === NODE_TYPE.element) {
1261
+ const innerSr = getShadowRoot ? getShadowRoot(shadowNode) : shadowNode.shadowRoot;
1262
+ if (_isDocumentFragment(innerSr)) {
1263
+ _sanitizeAttachedShadowRoots2(innerSr);
1264
+ _sanitizeShadowDOM2(innerSr);
1265
+ }
1266
+ }
1267
+ }
1268
+ _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
1269
+ };
1270
+ const _sanitizeAttachedShadowRoots2 = function _sanitizeAttachedShadowRoots(root) {
1271
+ const nodeType = getNodeType ? getNodeType(root) : root.nodeType;
1272
+ if (nodeType === NODE_TYPE.element) {
1273
+ const sr = getShadowRoot ? getShadowRoot(root) : root.shadowRoot;
1274
+ if (_isDocumentFragment(sr)) {
1275
+ _sanitizeAttachedShadowRoots2(sr);
1276
+ _sanitizeShadowDOM2(sr);
1277
+ }
1278
+ }
1279
+ const childNodes = getChildNodes ? getChildNodes(root) : root.childNodes;
1280
+ if (!childNodes) {
1281
+ return;
1282
+ }
1283
+ const snapshot = [];
1284
+ arrayForEach(childNodes, (child) => {
1285
+ arrayPush(snapshot, child);
1286
+ });
1287
+ for (const child of snapshot) {
1288
+ _sanitizeAttachedShadowRoots2(child);
1289
+ }
1290
+ if (nodeType === NODE_TYPE.element) {
1291
+ const rootName = getNodeName ? getNodeName(root) : null;
1292
+ if (typeof rootName === "string" && transformCaseFunc(rootName) === "template") {
1293
+ const content = root.content;
1294
+ if (_isDocumentFragment(content)) {
1295
+ _sanitizeAttachedShadowRoots2(content);
1296
+ }
1297
+ }
1298
+ }
1299
+ };
1300
+ DOMPurify.sanitize = function(dirty) {
1301
+ let cfg = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
1302
+ let body = null;
1303
+ let importedNode = null;
1304
+ let currentNode = null;
1305
+ let returnNode = null;
1306
+ IS_EMPTY_INPUT = !dirty;
1307
+ if (IS_EMPTY_INPUT) {
1308
+ dirty = "<!-->";
1309
+ }
1310
+ if (typeof dirty !== "string" && !_isNode(dirty)) {
1311
+ dirty = stringifyValue(dirty);
1312
+ if (typeof dirty !== "string") {
1313
+ throw typeErrorCreate("dirty is not a string, aborting");
1314
+ }
1315
+ }
1316
+ if (!DOMPurify.isSupported) {
1317
+ return dirty;
1318
+ }
1319
+ if (!SET_CONFIG) {
1320
+ _parseConfig(cfg);
1321
+ }
1322
+ DOMPurify.removed = [];
1323
+ if (typeof dirty === "string") {
1324
+ IN_PLACE = false;
1325
+ }
1326
+ if (IN_PLACE) {
1327
+ const nn = getNodeName ? getNodeName(dirty) : dirty.nodeName;
1328
+ if (typeof nn === "string") {
1329
+ const tagName = transformCaseFunc(nn);
1330
+ if (!ALLOWED_TAGS2[tagName] || FORBID_TAGS[tagName]) {
1331
+ throw typeErrorCreate("root node is forbidden and cannot be sanitized in-place");
1332
+ }
1333
+ }
1334
+ if (_isClobbered(dirty)) {
1335
+ throw typeErrorCreate("root node is clobbered and cannot be sanitized in-place");
1336
+ }
1337
+ _sanitizeAttachedShadowRoots2(dirty);
1338
+ } else if (_isNode(dirty)) {
1339
+ body = _initDocument("<!---->");
1340
+ importedNode = body.ownerDocument.importNode(dirty, true);
1341
+ if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === "BODY") {
1342
+ body = importedNode;
1343
+ } else if (importedNode.nodeName === "HTML") {
1344
+ body = importedNode;
1345
+ } else {
1346
+ body.appendChild(importedNode);
1347
+ }
1348
+ _sanitizeAttachedShadowRoots2(importedNode);
1349
+ } else {
1350
+ if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && // eslint-disable-next-line unicorn/prefer-includes
1351
+ dirty.indexOf("<") === -1) {
1352
+ return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
1353
+ }
1354
+ body = _initDocument(dirty);
1355
+ if (!body) {
1356
+ return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : "";
1357
+ }
1358
+ }
1359
+ if (body && FORCE_BODY) {
1360
+ _forceRemove(body.firstChild);
1361
+ }
1362
+ const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);
1363
+ while (currentNode = nodeIterator.nextNode()) {
1364
+ _sanitizeElements(currentNode);
1365
+ _sanitizeAttributes(currentNode);
1366
+ if (_isDocumentFragment(currentNode.content)) {
1367
+ _sanitizeShadowDOM2(currentNode.content);
1368
+ }
1369
+ }
1370
+ if (IN_PLACE) {
1371
+ if (SAFE_FOR_TEMPLATES) {
1372
+ _scrubTemplateExpressions(dirty);
1373
+ }
1374
+ return dirty;
1375
+ }
1376
+ if (RETURN_DOM) {
1377
+ if (SAFE_FOR_TEMPLATES) {
1378
+ _scrubTemplateExpressions(body);
1379
+ }
1380
+ if (RETURN_DOM_FRAGMENT) {
1381
+ returnNode = createDocumentFragment.call(body.ownerDocument);
1382
+ while (body.firstChild) {
1383
+ returnNode.appendChild(body.firstChild);
1384
+ }
1385
+ } else {
1386
+ returnNode = body;
1387
+ }
1388
+ if (ALLOWED_ATTR2.shadowroot || ALLOWED_ATTR2.shadowrootmode) {
1389
+ returnNode = importNode.call(originalDocument, returnNode, true);
1390
+ }
1391
+ return returnNode;
1392
+ }
1393
+ let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
1394
+ if (WHOLE_DOCUMENT && ALLOWED_TAGS2["!doctype"] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
1395
+ serializedHTML = "<!DOCTYPE " + body.ownerDocument.doctype.name + ">\n" + serializedHTML;
1396
+ }
1397
+ if (SAFE_FOR_TEMPLATES) {
1398
+ arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
1399
+ serializedHTML = stringReplace(serializedHTML, expr, " ");
1400
+ });
1401
+ }
1402
+ return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
1403
+ };
1404
+ DOMPurify.setConfig = function() {
1405
+ let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
1406
+ _parseConfig(cfg);
1407
+ SET_CONFIG = true;
1408
+ };
1409
+ DOMPurify.clearConfig = function() {
1410
+ CONFIG = null;
1411
+ SET_CONFIG = false;
1412
+ };
1413
+ DOMPurify.isValidAttribute = function(tag, attr, value) {
1414
+ if (!CONFIG) {
1415
+ _parseConfig({});
1416
+ }
1417
+ const lcTag = transformCaseFunc(tag);
1418
+ const lcName = transformCaseFunc(attr);
1419
+ return _isValidAttribute(lcTag, lcName, value);
1420
+ };
1421
+ DOMPurify.addHook = function(entryPoint, hookFunction) {
1422
+ if (typeof hookFunction !== "function") {
1423
+ return;
1424
+ }
1425
+ arrayPush(hooks[entryPoint], hookFunction);
1426
+ };
1427
+ DOMPurify.removeHook = function(entryPoint, hookFunction) {
1428
+ if (hookFunction !== void 0) {
1429
+ const index = arrayLastIndexOf(hooks[entryPoint], hookFunction);
1430
+ return index === -1 ? void 0 : arraySplice(hooks[entryPoint], index, 1)[0];
1431
+ }
1432
+ return arrayPop(hooks[entryPoint]);
1433
+ };
1434
+ DOMPurify.removeHooks = function(entryPoint) {
1435
+ hooks[entryPoint] = [];
1436
+ };
1437
+ DOMPurify.removeAllHooks = function() {
1438
+ hooks = _createHooksMap();
1439
+ };
1440
+ return DOMPurify;
1441
+ }
1442
+ var purify = createDOMPurify();
1443
+
1444
+ // node_modules/.pnpm/marked@18.0.4/node_modules/marked/lib/marked.esm.js
1445
+ function M() {
1446
+ return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
1447
+ }
1448
+ var T = M();
1449
+ function N(l3) {
1450
+ T = l3;
1451
+ }
1452
+ var _ = { exec: () => null };
1453
+ function E(l3) {
1454
+ let e = [];
1455
+ return (t) => {
1456
+ let n = Math.max(0, Math.min(3, t - 1)), s = e[n];
1457
+ return s || (s = l3(n), e[n] = s), s;
1458
+ };
1459
+ }
1460
+ function d(l3, e = "") {
1461
+ let t = typeof l3 == "string" ? l3 : l3.source, n = { replace: (s, r) => {
1462
+ let i = typeof r == "string" ? r : r.source;
1463
+ return i = i.replace(m.caret, "$1"), t = t.replace(s, i), n;
1464
+ }, getRegex: () => new RegExp(t, e) };
1465
+ return n;
1466
+ }
1467
+ var Te = ((l3 = "") => {
1468
+ try {
1469
+ return !!new RegExp("(?<=1)(?<!1)" + l3);
1470
+ } catch {
1471
+ return false;
1472
+ }
1473
+ })();
1474
+ var m = { codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm, outputLinkReplace: /\\([\[\]])/g, indentCodeCompensation: /^(\s+)(?:```)/, beginningSpace: /^\s+/, endingHash: /#$/, startingSpaceChar: /^ /, endingSpaceChar: / $/, nonSpaceChar: /[^ ]/, newLineCharGlobal: /\n/g, tabCharGlobal: /\t/g, multipleSpaceGlobal: /\s+/g, blankLine: /^[ \t]*$/, doubleBlankLine: /\n[ \t]*\n[ \t]*$/, blockquoteStart: /^ {0,3}>/, blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, listIsTask: /^\[[ xX]\] +\S/, listReplaceTask: /^\[[ xX]\] +/, listTaskCheckbox: /\[[ xX]\]/, anyLine: /\n.*\n/, hrefBrackets: /^<(.*)>$/, tableDelimiter: /[:|]/, tableAlignChars: /^\||\| *$/g, tableRowBlankLine: /\n[ \t]*$/, tableAlignRight: /^ *-+: *$/, tableAlignCenter: /^ *:-+: *$/, tableAlignLeft: /^ *:-+ *$/, startATag: /^<a /i, endATag: /^<\/a>/i, startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, startAngleBracket: /^</, endAngleBracket: />$/, pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, unicodeAlphaNumeric: /[\p{L}\p{N}]/u, escapeTest: /[&<>"']/, escapeReplace: /[&<>"']/g, escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, caret: /(^|[^\[])\^/g, percentDecode: /%25/g, findPipe: /\|/g, splitPipe: / \|/, slashPipe: /\\\|/g, carriageReturn: /\r\n|\r/g, spaceLine: /^ +$/gm, notSpaceStart: /^\S*/, endingNewline: /\n$/, listItemRegex: (l3) => new RegExp(`^( {0,3}${l3})((?:[ ][^\\n]*)?(?:\\n|$))`), nextBulletRegex: E((l3) => new RegExp(`^ {0,${l3}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`)), hrRegex: E((l3) => new RegExp(`^ {0,${l3}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`)), fencesBeginRegex: E((l3) => new RegExp(`^ {0,${l3}}(?:\`\`\`|~~~)`)), headingBeginRegex: E((l3) => new RegExp(`^ {0,${l3}}#`)), htmlBeginRegex: E((l3) => new RegExp(`^ {0,${l3}}<(?:[a-z].*>|!--)`, "i")), blockquoteBeginRegex: E((l3) => new RegExp(`^ {0,${l3}}>`)) };
1475
+ var Oe = /^(?:[ \t]*(?:\n|$))+/;
1476
+ var we = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/;
1477
+ var ye = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
1478
+ var B = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
1479
+ var Pe = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
1480
+ var j = / {0,3}(?:[*+-]|\d{1,9}[.)])/;
1481
+ var oe = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/;
1482
+ var ae = d(oe).replace(/bull/g, j).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}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex();
1483
+ var Se = d(oe).replace(/bull/g, j).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}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
1484
+ var F = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/;
1485
+ var $e = /^[^\n]+/;
1486
+ var U = /(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/;
1487
+ var Le = d(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", U).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
1488
+ var _e = d(/^(bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, j).getRegex();
1489
+ var H = "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";
1490
+ var K = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
1491
+ var ze = d("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\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", K).replace("tag", H).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
1492
+ var le = d(F).replace("hr", B).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", H).getRegex();
1493
+ var Me = d(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", le).getRegex();
1494
+ var W = { blockquote: Me, code: we, def: Le, fences: ye, heading: Pe, hr: B, html: ze, lheading: ae, list: _e, newline: Oe, paragraph: le, table: _, text: $e };
1495
+ var se = d("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", B).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3} )[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", H).getRegex();
1496
+ var Ee = { ...W, lheading: Se, table: se, paragraph: d(F).replace("hr", B).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", se).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", H).getRegex() };
1497
+ var Ie = { ...W, html: d(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", K).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: _, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: d(F).replace("hr", B).replace("heading", ` *#{1,6} *[^
1498
+ ]`).replace("lheading", ae).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() };
1499
+ var Ae = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
1500
+ var Ce = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
1501
+ var ue = /^( {2,}|\\)\n(?!\s*$)/;
1502
+ var Be = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
1503
+ var I = /[\p{P}\p{S}]/u;
1504
+ var Z = /[\s\p{P}\p{S}]/u;
1505
+ var X = /[^\s\p{P}\p{S}]/u;
1506
+ var De = d(/^((?![*_])punctSpace)/, "u").replace(/punctSpace/g, Z).getRegex();
1507
+ var pe = /(?!~)[\p{P}\p{S}]/u;
1508
+ var qe = /(?!~)[\s\p{P}\p{S}]/u;
1509
+ var ve = /(?:[^\s\p{P}\p{S}]|~)/u;
1510
+ var He = 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();
1511
+ var ce = /^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/;
1512
+ var Ze = d(ce, "u").replace(/punct/g, I).getRegex();
1513
+ var Ge = d(ce, "u").replace(/punct/g, pe).getRegex();
1514
+ var he = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)";
1515
+ var Ne = d(he, "gu").replace(/notPunctSpace/g, X).replace(/punctSpace/g, Z).replace(/punct/g, I).getRegex();
1516
+ var Qe = d(he, "gu").replace(/notPunctSpace/g, ve).replace(/punctSpace/g, qe).replace(/punct/g, pe).getRegex();
1517
+ var je = d("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, X).replace(/punctSpace/g, Z).replace(/punct/g, I).getRegex();
1518
+ var Fe = d(/^~~?(?:((?!~)punct)|[^\s~])/, "u").replace(/punct/g, I).getRegex();
1519
+ var Ue = "^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)";
1520
+ var Ke = d(Ue, "gu").replace(/notPunctSpace/g, X).replace(/punctSpace/g, Z).replace(/punct/g, I).getRegex();
1521
+ var We = d(/\\(punct)/, "gu").replace(/punct/g, I).getRegex();
1522
+ var Xe = 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();
1523
+ var Je = d(K).replace("(?:-->|$)", "-->").getRegex();
1524
+ var Ve = 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", Je).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
1525
+ var v = /(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/;
1526
+ var Ye = d(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label", v).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
1527
+ var ke = d(/^!?\[(label)\]\[(ref)\]/).replace("label", v).replace("ref", U).getRegex();
1528
+ var de = d(/^!?\[(ref)\](?:\[\])?/).replace("ref", U).getRegex();
1529
+ var et = d("reflink|nolink(?!\\()", "g").replace("reflink", ke).replace("nolink", de).getRegex();
1530
+ var ie = /[hH][tT][tT][pP][sS]?|[fF][tT][pP]/;
1531
+ var J = { _backpedal: _, anyPunctuation: We, autolink: Xe, blockSkip: He, br: ue, code: Ce, del: _, delLDelim: _, delRDelim: _, emStrongLDelim: Ze, emStrongRDelimAst: Ne, emStrongRDelimUnd: je, escape: Ae, link: Ye, nolink: de, punctuation: De, reflink: ke, reflinkSearch: et, tag: Ve, text: Be, url: _ };
1532
+ var tt = { ...J, link: d(/^!?\[(label)\]\((.*?)\)/).replace("label", v).getRegex(), reflink: d(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", v).getRegex() };
1533
+ var Q = { ...J, emStrongRDelimAst: Qe, emStrongLDelim: Ge, delLDelim: Fe, delRDelim: Ke, 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() };
1534
+ var nt = { ...Q, br: d(ue).replace("{2,}", "*").getRegex(), text: d(Q.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex() };
1535
+ var D = { normal: W, gfm: Ee, pedantic: Ie };
1536
+ var A = { normal: J, gfm: Q, breaks: nt, pedantic: tt };
1537
+ var rt = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" };
1538
+ var ge = (l3) => rt[l3];
1539
+ function O(l3, e) {
1540
+ if (e) {
1541
+ if (m.escapeTest.test(l3)) return l3.replace(m.escapeReplace, ge);
1542
+ } else if (m.escapeTestNoEncode.test(l3)) return l3.replace(m.escapeReplaceNoEncode, ge);
1543
+ return l3;
1544
+ }
1545
+ function V(l3) {
1546
+ try {
1547
+ l3 = encodeURI(l3).replace(m.percentDecode, "%");
1548
+ } catch {
1549
+ return null;
1550
+ }
1551
+ return l3;
1552
+ }
1553
+ function Y(l3, e) {
1554
+ let t = l3.replace(m.findPipe, (r, i, o) => {
1555
+ let u = false, a = i;
1556
+ for (; --a >= 0 && o[a] === "\\"; ) u = !u;
1557
+ return u ? "|" : " |";
1558
+ }), n = t.split(m.splitPipe), s = 0;
1559
+ if (n[0].trim() || n.shift(), n.length > 0 && !n.at(-1)?.trim() && n.pop(), e) if (n.length > e) n.splice(e);
1560
+ else for (; n.length < e; ) n.push("");
1561
+ for (; s < n.length; s++) n[s] = n[s].trim().replace(m.slashPipe, "|");
1562
+ return n;
1563
+ }
1564
+ function $(l3, e, t) {
1565
+ let n = l3.length;
1566
+ if (n === 0) return "";
1567
+ let s = 0;
1568
+ for (; s < n; ) {
1569
+ let r = l3.charAt(n - s - 1);
1570
+ if (r === e && !t) s++;
1571
+ else if (r !== e && t) s++;
1572
+ else break;
1573
+ }
1574
+ return l3.slice(0, n - s);
1575
+ }
1576
+ function ee(l3) {
1577
+ let e = l3.split(`
1578
+ `), t = e.length - 1;
1579
+ for (; t >= 0 && m.blankLine.test(e[t]); ) t--;
1580
+ return e.length - t <= 2 ? l3 : e.slice(0, t + 1).join(`
1581
+ `);
1582
+ }
1583
+ function fe(l3, e) {
1584
+ if (l3.indexOf(e[1]) === -1) return -1;
1585
+ let t = 0;
1586
+ for (let n = 0; n < l3.length; n++) if (l3[n] === "\\") n++;
1587
+ else if (l3[n] === e[0]) t++;
1588
+ else if (l3[n] === e[1] && (t--, t < 0)) return n;
1589
+ return t > 0 ? -2 : -1;
1590
+ }
1591
+ function me(l3, e = 0) {
1592
+ let t = e, n = "";
1593
+ for (let s of l3) if (s === " ") {
1594
+ let r = 4 - t % 4;
1595
+ n += " ".repeat(r), t += r;
1596
+ } else n += s, t++;
1597
+ return n;
1598
+ }
1599
+ function xe(l3, e, t, n, s) {
1600
+ let r = e.href, i = e.title || null, o = l3[1].replace(s.other.outputLinkReplace, "$1");
1601
+ n.state.inLink = true;
1602
+ let u = { type: l3[0].charAt(0) === "!" ? "image" : "link", raw: t, href: r, title: i, text: o, tokens: n.inlineTokens(o) };
1603
+ return n.state.inLink = false, u;
1604
+ }
1605
+ function st(l3, e, t) {
1606
+ let n = l3.match(t.other.indentCodeCompensation);
1607
+ if (n === null) return e;
1608
+ let s = n[1];
1609
+ return e.split(`
1610
+ `).map((r) => {
1611
+ let i = r.match(t.other.beginningSpace);
1612
+ if (i === null) return r;
1613
+ let [o] = i;
1614
+ return o.length >= s.length ? r.slice(s.length) : r;
1615
+ }).join(`
1616
+ `);
1617
+ }
1618
+ var w = class {
1619
+ options;
1620
+ rules;
1621
+ lexer;
1622
+ constructor(e) {
1623
+ this.options = e || T;
1624
+ }
1625
+ space(e) {
1626
+ let t = this.rules.block.newline.exec(e);
1627
+ if (t && t[0].length > 0) return { type: "space", raw: t[0] };
1628
+ }
1629
+ code(e) {
1630
+ let t = this.rules.block.code.exec(e);
1631
+ if (t) {
1632
+ let n = this.options.pedantic ? t[0] : ee(t[0]), s = n.replace(this.rules.other.codeRemoveIndent, "");
1633
+ return { type: "code", raw: n, codeBlockStyle: "indented", text: s };
1634
+ }
1635
+ }
1636
+ fences(e) {
1637
+ let t = this.rules.block.fences.exec(e);
1638
+ if (t) {
1639
+ let n = t[0], s = st(n, t[3] || "", this.rules);
1640
+ return { type: "code", raw: n, lang: t[2] ? t[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : t[2], text: s };
1641
+ }
1642
+ }
1643
+ heading(e) {
1644
+ let t = this.rules.block.heading.exec(e);
1645
+ if (t) {
1646
+ let n = t[2].trim();
1647
+ if (this.rules.other.endingHash.test(n)) {
1648
+ let s = $(n, "#");
1649
+ (this.options.pedantic || !s || this.rules.other.endingSpaceChar.test(s)) && (n = s.trim());
1650
+ }
1651
+ return { type: "heading", raw: $(t[0], `
1652
+ `), depth: t[1].length, text: n, tokens: this.lexer.inline(n) };
1653
+ }
1654
+ }
1655
+ hr(e) {
1656
+ let t = this.rules.block.hr.exec(e);
1657
+ if (t) return { type: "hr", raw: $(t[0], `
1658
+ `) };
1659
+ }
1660
+ blockquote(e) {
1661
+ let t = this.rules.block.blockquote.exec(e);
1662
+ if (t) {
1663
+ let n = $(t[0], `
1664
+ `).split(`
1665
+ `), s = "", r = "", i = [];
1666
+ for (; n.length > 0; ) {
1667
+ let o = false, u = [], a;
1668
+ for (a = 0; a < n.length; a++) if (this.rules.other.blockquoteStart.test(n[a])) u.push(n[a]), o = true;
1669
+ else if (!o) u.push(n[a]);
1670
+ else break;
1671
+ n = n.slice(a);
1672
+ let c = u.join(`
1673
+ `), p = c.replace(this.rules.other.blockquoteSetextReplace, `
1674
+ $1`).replace(this.rules.other.blockquoteSetextReplace2, "");
1675
+ s = s ? `${s}
1676
+ ${c}` : c, r = r ? `${r}
1677
+ ${p}` : p;
1678
+ let k = this.lexer.state.top;
1679
+ if (this.lexer.state.top = true, this.lexer.blockTokens(p, i, true), this.lexer.state.top = k, n.length === 0) break;
1680
+ let h = i.at(-1);
1681
+ if (h?.type === "code") break;
1682
+ if (h?.type === "blockquote") {
1683
+ let R = h, f = R.raw + `
1684
+ ` + n.join(`
1685
+ `), S = this.blockquote(f);
1686
+ i[i.length - 1] = S, s = s.substring(0, s.length - R.raw.length) + S.raw, r = r.substring(0, r.length - R.text.length) + S.text;
1687
+ break;
1688
+ } else if (h?.type === "list") {
1689
+ let R = h, f = R.raw + `
1690
+ ` + n.join(`
1691
+ `), S = this.list(f);
1692
+ i[i.length - 1] = S, s = s.substring(0, s.length - h.raw.length) + S.raw, r = r.substring(0, r.length - R.raw.length) + S.raw, n = f.substring(i.at(-1).raw.length).split(`
1693
+ `);
1694
+ continue;
1695
+ }
1696
+ }
1697
+ return { type: "blockquote", raw: s, tokens: i, text: r };
1698
+ }
1699
+ }
1700
+ list(e) {
1701
+ let t = this.rules.block.list.exec(e);
1702
+ if (t) {
1703
+ let n = t[1].trim(), s = n.length > 1, r = { type: "list", raw: "", ordered: s, start: s ? +n.slice(0, -1) : "", loose: false, items: [] };
1704
+ n = s ? `\\d{1,9}\\${n.slice(-1)}` : `\\${n}`, this.options.pedantic && (n = s ? n : "[*+-]");
1705
+ let i = this.rules.other.listItemRegex(n), o = false;
1706
+ for (; e; ) {
1707
+ let a = false, c = "", p = "";
1708
+ if (!(t = i.exec(e)) || this.rules.block.hr.test(e)) break;
1709
+ c = t[0], e = e.substring(c.length);
1710
+ let k = me(t[2].split(`
1711
+ `, 1)[0], t[1].length), h = e.split(`
1712
+ `, 1)[0], R = !k.trim(), f = 0;
1713
+ if (this.options.pedantic ? (f = 2, p = k.trimStart()) : R ? f = t[1].length + 1 : (f = k.search(this.rules.other.nonSpaceChar), f = f > 4 ? 1 : f, p = k.slice(f), f += t[1].length), R && this.rules.other.blankLine.test(h) && (c += h + `
1714
+ `, e = e.substring(h.length + 1), a = true), !a) {
1715
+ let S = this.rules.other.nextBulletRegex(f), te = this.rules.other.hrRegex(f), ne = this.rules.other.fencesBeginRegex(f), re = this.rules.other.headingBeginRegex(f), be = this.rules.other.htmlBeginRegex(f), Re = this.rules.other.blockquoteBeginRegex(f);
1716
+ for (; e; ) {
1717
+ let G = e.split(`
1718
+ `, 1)[0], C;
1719
+ if (h = G, this.options.pedantic ? (h = h.replace(this.rules.other.listReplaceNesting, " "), C = h) : C = h.replace(this.rules.other.tabCharGlobal, " "), ne.test(h) || re.test(h) || be.test(h) || Re.test(h) || S.test(h) || te.test(h)) break;
1720
+ if (C.search(this.rules.other.nonSpaceChar) >= f || !h.trim()) p += `
1721
+ ` + C.slice(f);
1722
+ else {
1723
+ if (R || k.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4 || ne.test(k) || re.test(k) || te.test(k)) break;
1724
+ p += `
1725
+ ` + h;
1726
+ }
1727
+ R = !h.trim(), c += G + `
1728
+ `, e = e.substring(G.length + 1), k = C.slice(f);
1729
+ }
1730
+ }
1731
+ r.loose || (o ? r.loose = true : this.rules.other.doubleBlankLine.test(c) && (o = true)), r.items.push({ type: "list_item", raw: c, task: !!this.options.gfm && this.rules.other.listIsTask.test(p), loose: false, text: p, tokens: [] }), r.raw += c;
1732
+ }
1733
+ let u = r.items.at(-1);
1734
+ if (u) u.raw = u.raw.trimEnd(), u.text = u.text.trimEnd();
1735
+ else return;
1736
+ r.raw = r.raw.trimEnd();
1737
+ for (let a of r.items) {
1738
+ this.lexer.state.top = false, a.tokens = this.lexer.blockTokens(a.text, []);
1739
+ let c = a.tokens[0];
1740
+ if (a.task && (c?.type === "text" || c?.type === "paragraph")) {
1741
+ a.text = a.text.replace(this.rules.other.listReplaceTask, ""), c.raw = c.raw.replace(this.rules.other.listReplaceTask, ""), c.text = c.text.replace(this.rules.other.listReplaceTask, "");
1742
+ for (let k = this.lexer.inlineQueue.length - 1; k >= 0; k--) if (this.rules.other.listIsTask.test(this.lexer.inlineQueue[k].src)) {
1743
+ this.lexer.inlineQueue[k].src = this.lexer.inlineQueue[k].src.replace(this.rules.other.listReplaceTask, "");
1744
+ break;
1745
+ }
1746
+ let p = this.rules.other.listTaskCheckbox.exec(a.raw);
1747
+ if (p) {
1748
+ let k = { type: "checkbox", raw: p[0] + " ", checked: p[0] !== "[ ]" };
1749
+ a.checked = k.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 = k.raw + a.tokens[0].raw, a.tokens[0].text = k.raw + a.tokens[0].text, a.tokens[0].tokens.unshift(k)) : a.tokens.unshift({ type: "paragraph", raw: k.raw, text: k.raw, tokens: [k] }) : a.tokens.unshift(k);
1750
+ }
1751
+ } else a.task && (a.task = false);
1752
+ if (!r.loose) {
1753
+ let p = a.tokens.filter((h) => h.type === "space"), k = p.length > 0 && p.some((h) => this.rules.other.anyLine.test(h.raw));
1754
+ r.loose = k;
1755
+ }
1756
+ }
1757
+ if (r.loose) for (let a of r.items) {
1758
+ a.loose = true;
1759
+ for (let c of a.tokens) c.type === "text" && (c.type = "paragraph");
1760
+ }
1761
+ return r;
1762
+ }
1763
+ }
1764
+ html(e) {
1765
+ let t = this.rules.block.html.exec(e);
1766
+ if (t) {
1767
+ let n = ee(t[0]);
1768
+ return { type: "html", block: true, raw: n, pre: t[1] === "pre" || t[1] === "script" || t[1] === "style", text: n };
1769
+ }
1770
+ }
1771
+ def(e) {
1772
+ let t = this.rules.block.def.exec(e);
1773
+ if (t) {
1774
+ let n = t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, " "), s = t[2] ? t[2].replace(this.rules.other.hrefBrackets, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "", r = t[3] ? t[3].substring(1, t[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : t[3];
1775
+ return { type: "def", tag: n, raw: $(t[0], `
1776
+ `), href: s, title: r };
1777
+ }
1778
+ }
1779
+ table(e) {
1780
+ let t = this.rules.block.table.exec(e);
1781
+ if (!t || !this.rules.other.tableDelimiter.test(t[2])) return;
1782
+ let n = Y(t[1]), s = t[2].replace(this.rules.other.tableAlignChars, "").split("|"), r = t[3]?.trim() ? t[3].replace(this.rules.other.tableRowBlankLine, "").split(`
1783
+ `) : [], i = { type: "table", raw: $(t[0], `
1784
+ `), header: [], align: [], rows: [] };
1785
+ if (n.length === s.length) {
1786
+ for (let o of s) this.rules.other.tableAlignRight.test(o) ? i.align.push("right") : this.rules.other.tableAlignCenter.test(o) ? i.align.push("center") : this.rules.other.tableAlignLeft.test(o) ? i.align.push("left") : i.align.push(null);
1787
+ for (let o = 0; o < n.length; o++) i.header.push({ text: n[o], tokens: this.lexer.inline(n[o]), header: true, align: i.align[o] });
1788
+ for (let o of r) i.rows.push(Y(o, i.header.length).map((u, a) => ({ text: u, tokens: this.lexer.inline(u), header: false, align: i.align[a] })));
1789
+ return i;
1790
+ }
1791
+ }
1792
+ lheading(e) {
1793
+ let t = this.rules.block.lheading.exec(e);
1794
+ if (t) {
1795
+ let n = t[1].trim();
1796
+ return { type: "heading", raw: $(t[0], `
1797
+ `), depth: t[2].charAt(0) === "=" ? 1 : 2, text: n, tokens: this.lexer.inline(n) };
1798
+ }
1799
+ }
1800
+ paragraph(e) {
1801
+ let t = this.rules.block.paragraph.exec(e);
1802
+ if (t) {
1803
+ let n = t[1].charAt(t[1].length - 1) === `
1804
+ ` ? t[1].slice(0, -1) : t[1];
1805
+ return { type: "paragraph", raw: t[0], text: n, tokens: this.lexer.inline(n) };
1806
+ }
1807
+ }
1808
+ text(e) {
1809
+ let t = this.rules.block.text.exec(e);
1810
+ if (t) return { type: "text", raw: t[0], text: t[0], tokens: this.lexer.inline(t[0]) };
1811
+ }
1812
+ escape(e) {
1813
+ let t = this.rules.inline.escape.exec(e);
1814
+ if (t) return { type: "escape", raw: t[0], text: t[1] };
1815
+ }
1816
+ tag(e) {
1817
+ let t = this.rules.inline.tag.exec(e);
1818
+ if (t) return !this.lexer.state.inLink && this.rules.other.startATag.test(t[0]) ? this.lexer.state.inLink = true : this.lexer.state.inLink && this.rules.other.endATag.test(t[0]) && (this.lexer.state.inLink = false), !this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(t[0]) ? this.lexer.state.inRawBlock = true : this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(t[0]) && (this.lexer.state.inRawBlock = false), { type: "html", raw: t[0], inLink: this.lexer.state.inLink, inRawBlock: this.lexer.state.inRawBlock, block: false, text: t[0] };
1819
+ }
1820
+ link(e) {
1821
+ let t = this.rules.inline.link.exec(e);
1822
+ if (t) {
1823
+ let n = t[2].trim();
1824
+ if (!this.options.pedantic && this.rules.other.startAngleBracket.test(n)) {
1825
+ if (!this.rules.other.endAngleBracket.test(n)) return;
1826
+ let i = $(n.slice(0, -1), "\\");
1827
+ if ((n.length - i.length) % 2 === 0) return;
1828
+ } else {
1829
+ let i = fe(t[2], "()");
1830
+ if (i === -2) return;
1831
+ if (i > -1) {
1832
+ let u = (t[0].indexOf("!") === 0 ? 5 : 4) + t[1].length + i;
1833
+ t[2] = t[2].substring(0, i), t[0] = t[0].substring(0, u).trim(), t[3] = "";
1834
+ }
1835
+ }
1836
+ let s = t[2], r = "";
1837
+ if (this.options.pedantic) {
1838
+ let i = this.rules.other.pedanticHrefTitle.exec(s);
1839
+ i && (s = i[1], r = i[3]);
1840
+ } else r = t[3] ? t[3].slice(1, -1) : "";
1841
+ return s = s.trim(), this.rules.other.startAngleBracket.test(s) && (this.options.pedantic && !this.rules.other.endAngleBracket.test(n) ? s = s.slice(1) : s = s.slice(1, -1)), xe(t, { href: s && s.replace(this.rules.inline.anyPunctuation, "$1"), title: r && r.replace(this.rules.inline.anyPunctuation, "$1") }, t[0], this.lexer, this.rules);
1842
+ }
1843
+ }
1844
+ reflink(e, t) {
1845
+ let n;
1846
+ if ((n = this.rules.inline.reflink.exec(e)) || (n = this.rules.inline.nolink.exec(e))) {
1847
+ let s = (n[2] || n[1]).replace(this.rules.other.multipleSpaceGlobal, " "), r = t[s.toLowerCase()];
1848
+ if (!r) {
1849
+ let i = n[0].charAt(0);
1850
+ return { type: "text", raw: i, text: i };
1851
+ }
1852
+ return xe(n, r, n[0], this.lexer, this.rules);
1853
+ }
1854
+ }
1855
+ emStrong(e, t, n = "") {
1856
+ let s = this.rules.inline.emStrongLDelim.exec(e);
1857
+ if (!s || !s[1] && !s[2] && !s[3] && !s[4] || s[4] && n.match(this.rules.other.unicodeAlphaNumeric)) return;
1858
+ if (!(s[1] || s[3] || "") || !n || this.rules.inline.punctuation.exec(n)) {
1859
+ let i = [...s[0]].length - 1, o, u, a = i, c = 0, p = s[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
1860
+ for (p.lastIndex = 0, t = t.slice(-1 * e.length + i); (s = p.exec(t)) !== null; ) {
1861
+ if (o = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !o) continue;
1862
+ if (u = [...o].length, s[3] || s[4]) {
1863
+ a += u;
1864
+ continue;
1865
+ } else if ((s[5] || s[6]) && i % 3 && !((i + u) % 3)) {
1866
+ c += u;
1867
+ continue;
1868
+ }
1869
+ if (a -= u, a > 0) continue;
1870
+ u = Math.min(u, u + a + c);
1871
+ let k = [...s[0]][0].length, h = e.slice(0, i + s.index + k + u);
1872
+ if (Math.min(i, u) % 2) {
1873
+ let f = h.slice(1, -1);
1874
+ return { type: "em", raw: h, text: f, tokens: this.lexer.inlineTokens(f) };
1875
+ }
1876
+ let R = h.slice(2, -2);
1877
+ return { type: "strong", raw: h, text: R, tokens: this.lexer.inlineTokens(R) };
1878
+ }
1879
+ }
1880
+ }
1881
+ codespan(e) {
1882
+ let t = this.rules.inline.code.exec(e);
1883
+ if (t) {
1884
+ let n = t[2].replace(this.rules.other.newLineCharGlobal, " "), s = this.rules.other.nonSpaceChar.test(n), r = this.rules.other.startingSpaceChar.test(n) && this.rules.other.endingSpaceChar.test(n);
1885
+ return s && r && (n = n.substring(1, n.length - 1)), { type: "codespan", raw: t[0], text: n };
1886
+ }
1887
+ }
1888
+ br(e) {
1889
+ let t = this.rules.inline.br.exec(e);
1890
+ if (t) return { type: "br", raw: t[0] };
1891
+ }
1892
+ del(e, t, n = "") {
1893
+ let s = this.rules.inline.delLDelim.exec(e);
1894
+ if (!s) return;
1895
+ if (!(s[1] || "") || !n || this.rules.inline.punctuation.exec(n)) {
1896
+ let i = [...s[0]].length - 1, o, u, a = i, c = this.rules.inline.delRDelim;
1897
+ for (c.lastIndex = 0, t = t.slice(-1 * e.length + i); (s = c.exec(t)) !== null; ) {
1898
+ if (o = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !o || (u = [...o].length, u !== i)) continue;
1899
+ if (s[3] || s[4]) {
1900
+ a += u;
1901
+ continue;
1902
+ }
1903
+ if (a -= u, a > 0) continue;
1904
+ u = Math.min(u, u + a);
1905
+ let p = [...s[0]][0].length, k = e.slice(0, i + s.index + p + u), h = k.slice(i, -i);
1906
+ return { type: "del", raw: k, text: h, tokens: this.lexer.inlineTokens(h) };
1907
+ }
1908
+ }
1909
+ }
1910
+ autolink(e) {
1911
+ let t = this.rules.inline.autolink.exec(e);
1912
+ if (t) {
1913
+ let n, s;
1914
+ return t[2] === "@" ? (n = t[1], s = "mailto:" + n) : (n = t[1], s = n), { type: "link", raw: t[0], text: n, href: s, tokens: [{ type: "text", raw: n, text: n }] };
1915
+ }
1916
+ }
1917
+ url(e) {
1918
+ let t;
1919
+ if (t = this.rules.inline.url.exec(e)) {
1920
+ let n, s;
1921
+ if (t[2] === "@") n = t[0], s = "mailto:" + n;
1922
+ else {
1923
+ let r;
1924
+ do
1925
+ r = t[0], t[0] = this.rules.inline._backpedal.exec(t[0])?.[0] ?? "";
1926
+ while (r !== t[0]);
1927
+ n = t[0], t[1] === "www." ? s = "http://" + t[0] : s = t[0];
1928
+ }
1929
+ return { type: "link", raw: t[0], text: n, href: s, tokens: [{ type: "text", raw: n, text: n }] };
1930
+ }
1931
+ }
1932
+ inlineText(e) {
1933
+ let t = this.rules.inline.text.exec(e);
1934
+ if (t) {
1935
+ let n = this.lexer.state.inRawBlock;
1936
+ return { type: "text", raw: t[0], text: t[0], escaped: n };
1937
+ }
1938
+ }
1939
+ };
1940
+ var x = class l {
1941
+ tokens;
1942
+ options;
1943
+ state;
1944
+ inlineQueue;
1945
+ tokenizer;
1946
+ constructor(e) {
1947
+ this.tokens = [], this.tokens.links = /* @__PURE__ */ Object.create(null), this.options = e || T, this.options.tokenizer = this.options.tokenizer || new w(), this.tokenizer = this.options.tokenizer, this.tokenizer.options = this.options, this.tokenizer.lexer = this, this.inlineQueue = [], this.state = { inLink: false, inRawBlock: false, top: true };
1948
+ let t = { other: m, block: D.normal, inline: A.normal };
1949
+ this.options.pedantic ? (t.block = D.pedantic, t.inline = A.pedantic) : this.options.gfm && (t.block = D.gfm, this.options.breaks ? t.inline = A.breaks : t.inline = A.gfm), this.tokenizer.rules = t;
1950
+ }
1951
+ static get rules() {
1952
+ return { block: D, inline: A };
1953
+ }
1954
+ static lex(e, t) {
1955
+ return new l(t).lex(e);
1956
+ }
1957
+ static lexInline(e, t) {
1958
+ return new l(t).inlineTokens(e);
1959
+ }
1960
+ lex(e) {
1961
+ e = e.replace(m.carriageReturn, `
1962
+ `), this.blockTokens(e, this.tokens);
1963
+ for (let t = 0; t < this.inlineQueue.length; t++) {
1964
+ let n = this.inlineQueue[t];
1965
+ this.inlineTokens(n.src, n.tokens);
1966
+ }
1967
+ return this.inlineQueue = [], this.tokens;
1968
+ }
1969
+ blockTokens(e, t = [], n = false) {
1970
+ this.tokenizer.lexer = this, this.options.pedantic && (e = e.replace(m.tabCharGlobal, " ").replace(m.spaceLine, ""));
1971
+ let s = 1 / 0;
1972
+ for (; e; ) {
1973
+ if (e.length < s) s = e.length;
1974
+ else {
1975
+ this.infiniteLoopError(e.charCodeAt(0));
1976
+ break;
1977
+ }
1978
+ let r;
1979
+ if (this.options.extensions?.block?.some((o) => (r = o.call({ lexer: this }, e, t)) ? (e = e.substring(r.raw.length), t.push(r), true) : false)) continue;
1980
+ if (r = this.tokenizer.space(e)) {
1981
+ e = e.substring(r.raw.length);
1982
+ let o = t.at(-1);
1983
+ r.raw.length === 1 && o !== void 0 ? o.raw += `
1984
+ ` : t.push(r);
1985
+ continue;
1986
+ }
1987
+ if (r = this.tokenizer.code(e)) {
1988
+ e = e.substring(r.raw.length);
1989
+ let o = t.at(-1);
1990
+ o?.type === "paragraph" || o?.type === "text" ? (o.raw += (o.raw.endsWith(`
1991
+ `) ? "" : `
1992
+ `) + r.raw, o.text += `
1993
+ ` + r.text, this.inlineQueue.at(-1).src = o.text) : t.push(r);
1994
+ continue;
1995
+ }
1996
+ if (r = this.tokenizer.fences(e)) {
1997
+ e = e.substring(r.raw.length), t.push(r);
1998
+ continue;
1999
+ }
2000
+ if (r = this.tokenizer.heading(e)) {
2001
+ e = e.substring(r.raw.length), t.push(r);
2002
+ continue;
2003
+ }
2004
+ if (r = this.tokenizer.hr(e)) {
2005
+ e = e.substring(r.raw.length), t.push(r);
2006
+ continue;
2007
+ }
2008
+ if (r = this.tokenizer.blockquote(e)) {
2009
+ e = e.substring(r.raw.length), t.push(r);
2010
+ continue;
2011
+ }
2012
+ if (r = this.tokenizer.list(e)) {
2013
+ e = e.substring(r.raw.length), t.push(r);
2014
+ continue;
2015
+ }
2016
+ if (r = this.tokenizer.html(e)) {
2017
+ e = e.substring(r.raw.length), t.push(r);
2018
+ continue;
2019
+ }
2020
+ if (r = this.tokenizer.def(e)) {
2021
+ e = e.substring(r.raw.length);
2022
+ let o = t.at(-1);
2023
+ o?.type === "paragraph" || o?.type === "text" ? (o.raw += (o.raw.endsWith(`
2024
+ `) ? "" : `
2025
+ `) + r.raw, o.text += `
2026
+ ` + r.raw, this.inlineQueue.at(-1).src = o.text) : this.tokens.links[r.tag] || (this.tokens.links[r.tag] = { href: r.href, title: r.title }, t.push(r));
2027
+ continue;
2028
+ }
2029
+ if (r = this.tokenizer.table(e)) {
2030
+ e = e.substring(r.raw.length), t.push(r);
2031
+ continue;
2032
+ }
2033
+ if (r = this.tokenizer.lheading(e)) {
2034
+ e = e.substring(r.raw.length), t.push(r);
2035
+ continue;
2036
+ }
2037
+ let i = e;
2038
+ if (this.options.extensions?.startBlock) {
2039
+ let o = 1 / 0, u = e.slice(1), a;
2040
+ this.options.extensions.startBlock.forEach((c) => {
2041
+ a = c.call({ lexer: this }, u), typeof a == "number" && a >= 0 && (o = Math.min(o, a));
2042
+ }), o < 1 / 0 && o >= 0 && (i = e.substring(0, o + 1));
2043
+ }
2044
+ if (this.state.top && (r = this.tokenizer.paragraph(i))) {
2045
+ let o = t.at(-1);
2046
+ n && o?.type === "paragraph" ? (o.raw += (o.raw.endsWith(`
2047
+ `) ? "" : `
2048
+ `) + r.raw, o.text += `
2049
+ ` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = o.text) : t.push(r), n = i.length !== e.length, e = e.substring(r.raw.length);
2050
+ continue;
2051
+ }
2052
+ if (r = this.tokenizer.text(e)) {
2053
+ e = e.substring(r.raw.length);
2054
+ let o = t.at(-1);
2055
+ o?.type === "text" ? (o.raw += (o.raw.endsWith(`
2056
+ `) ? "" : `
2057
+ `) + r.raw, o.text += `
2058
+ ` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = o.text) : t.push(r);
2059
+ continue;
2060
+ }
2061
+ if (e) {
2062
+ this.infiniteLoopError(e.charCodeAt(0));
2063
+ break;
2064
+ }
2065
+ }
2066
+ return this.state.top = true, t;
2067
+ }
2068
+ inline(e, t = []) {
2069
+ return this.inlineQueue.push({ src: e, tokens: t }), t;
2070
+ }
2071
+ inlineTokens(e, t = []) {
2072
+ this.tokenizer.lexer = this;
2073
+ let n = e, s = null;
2074
+ if (this.tokens.links) {
2075
+ let a = Object.keys(this.tokens.links);
2076
+ if (a.length > 0) for (; (s = this.tokenizer.rules.inline.reflinkSearch.exec(n)) !== null; ) a.includes(s[0].slice(s[0].lastIndexOf("[") + 1, -1)) && (n = n.slice(0, s.index) + "[" + "a".repeat(s[0].length - 2) + "]" + n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex));
2077
+ }
2078
+ for (; (s = this.tokenizer.rules.inline.anyPunctuation.exec(n)) !== null; ) n = n.slice(0, s.index) + "++" + n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
2079
+ let r;
2080
+ for (; (s = this.tokenizer.rules.inline.blockSkip.exec(n)) !== null; ) r = s[2] ? s[2].length : 0, n = n.slice(0, s.index + r) + "[" + "a".repeat(s[0].length - r - 2) + "]" + n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
2081
+ n = this.options.hooks?.emStrongMask?.call({ lexer: this }, n) ?? n;
2082
+ let i = false, o = "", u = 1 / 0;
2083
+ for (; e; ) {
2084
+ if (e.length < u) u = e.length;
2085
+ else {
2086
+ this.infiniteLoopError(e.charCodeAt(0));
2087
+ break;
2088
+ }
2089
+ i || (o = ""), i = false;
2090
+ let a;
2091
+ if (this.options.extensions?.inline?.some((p) => (a = p.call({ lexer: this }, e, t)) ? (e = e.substring(a.raw.length), t.push(a), true) : false)) continue;
2092
+ if (a = this.tokenizer.escape(e)) {
2093
+ e = e.substring(a.raw.length), t.push(a);
2094
+ continue;
2095
+ }
2096
+ if (a = this.tokenizer.tag(e)) {
2097
+ e = e.substring(a.raw.length), t.push(a);
2098
+ continue;
2099
+ }
2100
+ if (a = this.tokenizer.link(e)) {
2101
+ e = e.substring(a.raw.length), t.push(a);
2102
+ continue;
2103
+ }
2104
+ if (a = this.tokenizer.reflink(e, this.tokens.links)) {
2105
+ e = e.substring(a.raw.length);
2106
+ let p = t.at(-1);
2107
+ a.type === "text" && p?.type === "text" ? (p.raw += a.raw, p.text += a.text) : t.push(a);
2108
+ continue;
2109
+ }
2110
+ if (a = this.tokenizer.emStrong(e, n, o)) {
2111
+ e = e.substring(a.raw.length), t.push(a);
2112
+ continue;
2113
+ }
2114
+ if (a = this.tokenizer.codespan(e)) {
2115
+ e = e.substring(a.raw.length), t.push(a);
2116
+ continue;
2117
+ }
2118
+ if (a = this.tokenizer.br(e)) {
2119
+ e = e.substring(a.raw.length), t.push(a);
2120
+ continue;
2121
+ }
2122
+ if (a = this.tokenizer.del(e, n, o)) {
2123
+ e = e.substring(a.raw.length), t.push(a);
2124
+ continue;
2125
+ }
2126
+ if (a = this.tokenizer.autolink(e)) {
2127
+ e = e.substring(a.raw.length), t.push(a);
2128
+ continue;
2129
+ }
2130
+ if (!this.state.inLink && (a = this.tokenizer.url(e))) {
2131
+ e = e.substring(a.raw.length), t.push(a);
2132
+ continue;
2133
+ }
2134
+ let c = e;
2135
+ if (this.options.extensions?.startInline) {
2136
+ let p = 1 / 0, k = e.slice(1), h;
2137
+ this.options.extensions.startInline.forEach((R) => {
2138
+ h = R.call({ lexer: this }, k), typeof h == "number" && h >= 0 && (p = Math.min(p, h));
2139
+ }), p < 1 / 0 && p >= 0 && (c = e.substring(0, p + 1));
2140
+ }
2141
+ if (a = this.tokenizer.inlineText(c)) {
2142
+ e = e.substring(a.raw.length), a.raw.slice(-1) !== "_" && (o = a.raw.slice(-1)), i = true;
2143
+ let p = t.at(-1);
2144
+ p?.type === "text" ? (p.raw += a.raw, p.text += a.text) : t.push(a);
2145
+ continue;
2146
+ }
2147
+ if (e) {
2148
+ this.infiniteLoopError(e.charCodeAt(0));
2149
+ break;
2150
+ }
2151
+ }
2152
+ return t;
2153
+ }
2154
+ infiniteLoopError(e) {
2155
+ let t = "Infinite loop on byte: " + e;
2156
+ if (this.options.silent) console.error(t);
2157
+ else throw new Error(t);
2158
+ }
2159
+ };
2160
+ var y = class {
2161
+ options;
2162
+ parser;
2163
+ constructor(e) {
2164
+ this.options = e || T;
2165
+ }
2166
+ space(e) {
2167
+ return "";
2168
+ }
2169
+ code({ text: e, lang: t, escaped: n }) {
2170
+ let s = (t || "").match(m.notSpaceStart)?.[0], r = e.replace(m.endingNewline, "") + `
2171
+ `;
2172
+ return s ? '<pre><code class="language-' + O(s) + '">' + (n ? r : O(r, true)) + `</code></pre>
2173
+ ` : "<pre><code>" + (n ? r : O(r, true)) + `</code></pre>
2174
+ `;
2175
+ }
2176
+ blockquote({ tokens: e }) {
2177
+ return `<blockquote>
2178
+ ${this.parser.parse(e)}</blockquote>
2179
+ `;
2180
+ }
2181
+ html({ text: e }) {
2182
+ return e;
2183
+ }
2184
+ def(e) {
2185
+ return "";
2186
+ }
2187
+ heading({ tokens: e, depth: t }) {
2188
+ return `<h${t}>${this.parser.parseInline(e)}</h${t}>
2189
+ `;
2190
+ }
2191
+ hr(e) {
2192
+ return `<hr>
2193
+ `;
2194
+ }
2195
+ list(e) {
2196
+ let t = e.ordered, n = e.start, s = "";
2197
+ for (let o = 0; o < e.items.length; o++) {
2198
+ let u = e.items[o];
2199
+ s += this.listitem(u);
2200
+ }
2201
+ let r = t ? "ol" : "ul", i = t && n !== 1 ? ' start="' + n + '"' : "";
2202
+ return "<" + r + i + `>
2203
+ ` + s + "</" + r + `>
2204
+ `;
2205
+ }
2206
+ listitem(e) {
2207
+ return `<li>${this.parser.parse(e.tokens)}</li>
2208
+ `;
2209
+ }
2210
+ checkbox({ checked: e }) {
2211
+ return "<input " + (e ? 'checked="" ' : "") + 'disabled="" type="checkbox"> ';
2212
+ }
2213
+ paragraph({ tokens: e }) {
2214
+ return `<p>${this.parser.parseInline(e)}</p>
2215
+ `;
2216
+ }
2217
+ table(e) {
2218
+ let t = "", n = "";
2219
+ for (let r = 0; r < e.header.length; r++) n += this.tablecell(e.header[r]);
2220
+ t += this.tablerow({ text: n });
2221
+ let s = "";
2222
+ for (let r = 0; r < e.rows.length; r++) {
2223
+ let i = e.rows[r];
2224
+ n = "";
2225
+ for (let o = 0; o < i.length; o++) n += this.tablecell(i[o]);
2226
+ s += this.tablerow({ text: n });
2227
+ }
2228
+ return s && (s = `<tbody>${s}</tbody>`), `<table>
2229
+ <thead>
2230
+ ` + t + `</thead>
2231
+ ` + s + `</table>
2232
+ `;
2233
+ }
2234
+ tablerow({ text: e }) {
2235
+ return `<tr>
2236
+ ${e}</tr>
2237
+ `;
2238
+ }
2239
+ tablecell(e) {
2240
+ let t = this.parser.parseInline(e.tokens), n = e.header ? "th" : "td";
2241
+ return (e.align ? `<${n} align="${e.align}">` : `<${n}>`) + t + `</${n}>
2242
+ `;
2243
+ }
2244
+ strong({ tokens: e }) {
2245
+ return `<strong>${this.parser.parseInline(e)}</strong>`;
2246
+ }
2247
+ em({ tokens: e }) {
2248
+ return `<em>${this.parser.parseInline(e)}</em>`;
2249
+ }
2250
+ codespan({ text: e }) {
2251
+ return `<code>${O(e, true)}</code>`;
2252
+ }
2253
+ br(e) {
2254
+ return "<br>";
2255
+ }
2256
+ del({ tokens: e }) {
2257
+ return `<del>${this.parser.parseInline(e)}</del>`;
2258
+ }
2259
+ link({ href: e, title: t, tokens: n }) {
2260
+ let s = this.parser.parseInline(n), r = V(e);
2261
+ if (r === null) return s;
2262
+ e = r;
2263
+ let i = '<a href="' + e + '"';
2264
+ return t && (i += ' title="' + O(t) + '"'), i += ">" + s + "</a>", i;
2265
+ }
2266
+ image({ href: e, title: t, text: n, tokens: s }) {
2267
+ s && (n = this.parser.parseInline(s, this.parser.textRenderer));
2268
+ let r = V(e);
2269
+ if (r === null) return O(n);
2270
+ e = r;
2271
+ let i = `<img src="${e}" alt="${O(n)}"`;
2272
+ return t && (i += ` title="${O(t)}"`), i += ">", i;
2273
+ }
2274
+ text(e) {
2275
+ return "tokens" in e && e.tokens ? this.parser.parseInline(e.tokens) : "escaped" in e && e.escaped ? e.text : O(e.text);
2276
+ }
2277
+ };
2278
+ var L = class {
2279
+ strong({ text: e }) {
2280
+ return e;
2281
+ }
2282
+ em({ text: e }) {
2283
+ return e;
2284
+ }
2285
+ codespan({ text: e }) {
2286
+ return e;
2287
+ }
2288
+ del({ text: e }) {
2289
+ return e;
2290
+ }
2291
+ html({ text: e }) {
2292
+ return e;
2293
+ }
2294
+ text({ text: e }) {
2295
+ return e;
2296
+ }
2297
+ link({ text: e }) {
2298
+ return "" + e;
2299
+ }
2300
+ image({ text: e }) {
2301
+ return "" + e;
2302
+ }
2303
+ br() {
2304
+ return "";
2305
+ }
2306
+ checkbox({ raw: e }) {
2307
+ return e;
2308
+ }
2309
+ };
2310
+ var b = class l2 {
2311
+ options;
2312
+ renderer;
2313
+ textRenderer;
2314
+ constructor(e) {
2315
+ this.options = e || T, this.options.renderer = this.options.renderer || new y(), this.renderer = this.options.renderer, this.renderer.options = this.options, this.renderer.parser = this, this.textRenderer = new L();
2316
+ }
2317
+ static parse(e, t) {
2318
+ return new l2(t).parse(e);
2319
+ }
2320
+ static parseInline(e, t) {
2321
+ return new l2(t).parseInline(e);
2322
+ }
2323
+ parse(e) {
2324
+ this.renderer.parser = this;
2325
+ let t = "";
2326
+ for (let n = 0; n < e.length; n++) {
2327
+ let s = e[n];
2328
+ if (this.options.extensions?.renderers?.[s.type]) {
2329
+ let i = s, o = this.options.extensions.renderers[i.type].call({ parser: this }, i);
2330
+ if (o !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "html", "def", "paragraph", "text"].includes(i.type)) {
2331
+ t += o || "";
2332
+ continue;
2333
+ }
2334
+ }
2335
+ let r = s;
2336
+ switch (r.type) {
2337
+ case "space": {
2338
+ t += this.renderer.space(r);
2339
+ break;
2340
+ }
2341
+ case "hr": {
2342
+ t += this.renderer.hr(r);
2343
+ break;
2344
+ }
2345
+ case "heading": {
2346
+ t += this.renderer.heading(r);
2347
+ break;
2348
+ }
2349
+ case "code": {
2350
+ t += this.renderer.code(r);
2351
+ break;
2352
+ }
2353
+ case "table": {
2354
+ t += this.renderer.table(r);
2355
+ break;
2356
+ }
2357
+ case "blockquote": {
2358
+ t += this.renderer.blockquote(r);
2359
+ break;
2360
+ }
2361
+ case "list": {
2362
+ t += this.renderer.list(r);
2363
+ break;
2364
+ }
2365
+ case "checkbox": {
2366
+ t += this.renderer.checkbox(r);
2367
+ break;
2368
+ }
2369
+ case "html": {
2370
+ t += this.renderer.html(r);
2371
+ break;
2372
+ }
2373
+ case "def": {
2374
+ t += this.renderer.def(r);
2375
+ break;
2376
+ }
2377
+ case "paragraph": {
2378
+ t += this.renderer.paragraph(r);
2379
+ break;
2380
+ }
2381
+ case "text": {
2382
+ t += this.renderer.text(r);
2383
+ break;
2384
+ }
2385
+ default: {
2386
+ let i = 'Token with "' + r.type + '" type was not found.';
2387
+ if (this.options.silent) return console.error(i), "";
2388
+ throw new Error(i);
2389
+ }
2390
+ }
2391
+ }
2392
+ return t;
2393
+ }
2394
+ parseInline(e, t = this.renderer) {
2395
+ this.renderer.parser = this;
2396
+ let n = "";
2397
+ for (let s = 0; s < e.length; s++) {
2398
+ let r = e[s];
2399
+ if (this.options.extensions?.renderers?.[r.type]) {
2400
+ let o = this.options.extensions.renderers[r.type].call({ parser: this }, r);
2401
+ if (o !== false || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(r.type)) {
2402
+ n += o || "";
2403
+ continue;
2404
+ }
2405
+ }
2406
+ let i = r;
2407
+ switch (i.type) {
2408
+ case "escape": {
2409
+ n += t.text(i);
2410
+ break;
2411
+ }
2412
+ case "html": {
2413
+ n += t.html(i);
2414
+ break;
2415
+ }
2416
+ case "link": {
2417
+ n += t.link(i);
2418
+ break;
2419
+ }
2420
+ case "image": {
2421
+ n += t.image(i);
2422
+ break;
2423
+ }
2424
+ case "checkbox": {
2425
+ n += t.checkbox(i);
2426
+ break;
2427
+ }
2428
+ case "strong": {
2429
+ n += t.strong(i);
2430
+ break;
2431
+ }
2432
+ case "em": {
2433
+ n += t.em(i);
2434
+ break;
2435
+ }
2436
+ case "codespan": {
2437
+ n += t.codespan(i);
2438
+ break;
2439
+ }
2440
+ case "br": {
2441
+ n += t.br(i);
2442
+ break;
2443
+ }
2444
+ case "del": {
2445
+ n += t.del(i);
2446
+ break;
2447
+ }
2448
+ case "text": {
2449
+ n += t.text(i);
2450
+ break;
2451
+ }
2452
+ default: {
2453
+ let o = 'Token with "' + i.type + '" type was not found.';
2454
+ if (this.options.silent) return console.error(o), "";
2455
+ throw new Error(o);
2456
+ }
2457
+ }
2458
+ }
2459
+ return n;
2460
+ }
2461
+ };
2462
+ var P = class {
2463
+ options;
2464
+ block;
2465
+ constructor(e) {
2466
+ this.options = e || T;
2467
+ }
2468
+ static passThroughHooks = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens", "emStrongMask"]);
2469
+ static passThroughHooksRespectAsync = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens"]);
2470
+ preprocess(e) {
2471
+ return e;
2472
+ }
2473
+ postprocess(e) {
2474
+ return e;
2475
+ }
2476
+ processAllTokens(e) {
2477
+ return e;
2478
+ }
2479
+ emStrongMask(e) {
2480
+ return e;
2481
+ }
2482
+ provideLexer(e = this.block) {
2483
+ return e ? x.lex : x.lexInline;
2484
+ }
2485
+ provideParser(e = this.block) {
2486
+ return e ? b.parse : b.parseInline;
2487
+ }
2488
+ };
2489
+ var q = class {
2490
+ defaults = M();
2491
+ options = this.setOptions;
2492
+ parse = this.parseMarkdown(true);
2493
+ parseInline = this.parseMarkdown(false);
2494
+ Parser = b;
2495
+ Renderer = y;
2496
+ TextRenderer = L;
2497
+ Lexer = x;
2498
+ Tokenizer = w;
2499
+ Hooks = P;
2500
+ constructor(...e) {
2501
+ this.use(...e);
2502
+ }
2503
+ walkTokens(e, t) {
2504
+ let n = [];
2505
+ for (let s of e) switch (n = n.concat(t.call(this, s)), s.type) {
2506
+ case "table": {
2507
+ let r = s;
2508
+ for (let i of r.header) n = n.concat(this.walkTokens(i.tokens, t));
2509
+ for (let i of r.rows) for (let o of i) n = n.concat(this.walkTokens(o.tokens, t));
2510
+ break;
2511
+ }
2512
+ case "list": {
2513
+ let r = s;
2514
+ n = n.concat(this.walkTokens(r.items, t));
2515
+ break;
2516
+ }
2517
+ default: {
2518
+ let r = s;
2519
+ this.defaults.extensions?.childTokens?.[r.type] ? this.defaults.extensions.childTokens[r.type].forEach((i) => {
2520
+ let o = r[i].flat(1 / 0);
2521
+ n = n.concat(this.walkTokens(o, t));
2522
+ }) : r.tokens && (n = n.concat(this.walkTokens(r.tokens, t)));
2523
+ }
2524
+ }
2525
+ return n;
2526
+ }
2527
+ use(...e) {
2528
+ let t = this.defaults.extensions || { renderers: {}, childTokens: {} };
2529
+ return e.forEach((n) => {
2530
+ let s = { ...n };
2531
+ if (s.async = this.defaults.async || s.async || false, n.extensions && (n.extensions.forEach((r) => {
2532
+ if (!r.name) throw new Error("extension name required");
2533
+ if ("renderer" in r) {
2534
+ let i = t.renderers[r.name];
2535
+ i ? t.renderers[r.name] = function(...o) {
2536
+ let u = r.renderer.apply(this, o);
2537
+ return u === false && (u = i.apply(this, o)), u;
2538
+ } : t.renderers[r.name] = r.renderer;
2539
+ }
2540
+ if ("tokenizer" in r) {
2541
+ if (!r.level || r.level !== "block" && r.level !== "inline") throw new Error("extension level must be 'block' or 'inline'");
2542
+ let i = t[r.level];
2543
+ i ? i.unshift(r.tokenizer) : t[r.level] = [r.tokenizer], r.start && (r.level === "block" ? t.startBlock ? t.startBlock.push(r.start) : t.startBlock = [r.start] : r.level === "inline" && (t.startInline ? t.startInline.push(r.start) : t.startInline = [r.start]));
2544
+ }
2545
+ "childTokens" in r && r.childTokens && (t.childTokens[r.name] = r.childTokens);
2546
+ }), s.extensions = t), n.renderer) {
2547
+ let r = this.defaults.renderer || new y(this.defaults);
2548
+ for (let i in n.renderer) {
2549
+ if (!(i in r)) throw new Error(`renderer '${i}' does not exist`);
2550
+ if (["options", "parser"].includes(i)) continue;
2551
+ let o = i, u = n.renderer[o], a = r[o];
2552
+ r[o] = (...c) => {
2553
+ let p = u.apply(r, c);
2554
+ return p === false && (p = a.apply(r, c)), p || "";
2555
+ };
2556
+ }
2557
+ s.renderer = r;
2558
+ }
2559
+ if (n.tokenizer) {
2560
+ let r = this.defaults.tokenizer || new w(this.defaults);
2561
+ for (let i in n.tokenizer) {
2562
+ if (!(i in r)) throw new Error(`tokenizer '${i}' does not exist`);
2563
+ if (["options", "rules", "lexer"].includes(i)) continue;
2564
+ let o = i, u = n.tokenizer[o], a = r[o];
2565
+ r[o] = (...c) => {
2566
+ let p = u.apply(r, c);
2567
+ return p === false && (p = a.apply(r, c)), p;
2568
+ };
2569
+ }
2570
+ s.tokenizer = r;
2571
+ }
2572
+ if (n.hooks) {
2573
+ let r = this.defaults.hooks || new P();
2574
+ for (let i in n.hooks) {
2575
+ if (!(i in r)) throw new Error(`hook '${i}' does not exist`);
2576
+ if (["options", "block"].includes(i)) continue;
2577
+ let o = i, u = n.hooks[o], a = r[o];
2578
+ P.passThroughHooks.has(i) ? r[o] = (c) => {
2579
+ if (this.defaults.async && P.passThroughHooksRespectAsync.has(i)) return (async () => {
2580
+ let k = await u.call(r, c);
2581
+ return a.call(r, k);
2582
+ })();
2583
+ let p = u.call(r, c);
2584
+ return a.call(r, p);
2585
+ } : r[o] = (...c) => {
2586
+ if (this.defaults.async) return (async () => {
2587
+ let k = await u.apply(r, c);
2588
+ return k === false && (k = await a.apply(r, c)), k;
2589
+ })();
2590
+ let p = u.apply(r, c);
2591
+ return p === false && (p = a.apply(r, c)), p;
2592
+ };
2593
+ }
2594
+ s.hooks = r;
2595
+ }
2596
+ if (n.walkTokens) {
2597
+ let r = this.defaults.walkTokens, i = n.walkTokens;
2598
+ s.walkTokens = function(o) {
2599
+ let u = [];
2600
+ return u.push(i.call(this, o)), r && (u = u.concat(r.call(this, o))), u;
2601
+ };
2602
+ }
2603
+ this.defaults = { ...this.defaults, ...s };
2604
+ }), this;
2605
+ }
2606
+ setOptions(e) {
2607
+ return this.defaults = { ...this.defaults, ...e }, this;
2608
+ }
2609
+ lexer(e, t) {
2610
+ return x.lex(e, t ?? this.defaults);
2611
+ }
2612
+ parser(e, t) {
2613
+ return b.parse(e, t ?? this.defaults);
2614
+ }
2615
+ parseMarkdown(e) {
2616
+ return (n, s) => {
2617
+ let r = { ...s }, i = { ...this.defaults, ...r }, o = this.onError(!!i.silent, !!i.async);
2618
+ if (this.defaults.async === true && r.async === false) return o(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));
2619
+ if (typeof n > "u" || n === null) return o(new Error("marked(): input parameter is undefined or null"));
2620
+ if (typeof n != "string") return o(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(n) + ", string expected"));
2621
+ if (i.hooks && (i.hooks.options = i, i.hooks.block = e), i.async) return (async () => {
2622
+ let u = i.hooks ? await i.hooks.preprocess(n) : n, c = await (i.hooks ? await i.hooks.provideLexer(e) : e ? x.lex : x.lexInline)(u, i), p = i.hooks ? await i.hooks.processAllTokens(c) : c;
2623
+ i.walkTokens && await Promise.all(this.walkTokens(p, i.walkTokens));
2624
+ let h = await (i.hooks ? await i.hooks.provideParser(e) : e ? b.parse : b.parseInline)(p, i);
2625
+ return i.hooks ? await i.hooks.postprocess(h) : h;
2626
+ })().catch(o);
2627
+ try {
2628
+ i.hooks && (n = i.hooks.preprocess(n));
2629
+ let a = (i.hooks ? i.hooks.provideLexer(e) : e ? x.lex : x.lexInline)(n, i);
2630
+ i.hooks && (a = i.hooks.processAllTokens(a)), i.walkTokens && this.walkTokens(a, i.walkTokens);
2631
+ let p = (i.hooks ? i.hooks.provideParser(e) : e ? b.parse : b.parseInline)(a, i);
2632
+ return i.hooks && (p = i.hooks.postprocess(p)), p;
2633
+ } catch (u) {
2634
+ return o(u);
2635
+ }
2636
+ };
2637
+ }
2638
+ onError(e, t) {
2639
+ return (n) => {
2640
+ if (n.message += `
2641
+ Please report this to https://github.com/markedjs/marked.`, e) {
2642
+ let s = "<p>An error occurred:</p><pre>" + O(n.message + "", true) + "</pre>";
2643
+ return t ? Promise.resolve(s) : s;
2644
+ }
2645
+ if (t) return Promise.reject(n);
2646
+ throw n;
2647
+ };
2648
+ }
2649
+ };
2650
+ var z = new q();
2651
+ function g(l3, e) {
2652
+ return z.parse(l3, e);
2653
+ }
2654
+ g.options = g.setOptions = function(l3) {
2655
+ return z.setOptions(l3), g.defaults = z.defaults, N(g.defaults), g;
2656
+ };
2657
+ g.getDefaults = M;
2658
+ g.defaults = T;
2659
+ g.use = function(...l3) {
2660
+ return z.use(...l3), g.defaults = z.defaults, N(g.defaults), g;
2661
+ };
2662
+ g.walkTokens = function(l3, e) {
2663
+ return z.walkTokens(l3, e);
2664
+ };
2665
+ g.parseInline = z.parseInline;
2666
+ g.Parser = b;
2667
+ g.parser = b.parse;
2668
+ g.Renderer = y;
2669
+ g.TextRenderer = L;
2670
+ g.Lexer = x;
2671
+ g.lexer = x.lex;
2672
+ g.Tokenizer = w;
2673
+ g.Hooks = P;
2674
+ g.parse = g;
2675
+ var Ft = g.options;
2676
+ var Ut = g.setOptions;
2677
+ var Kt = g.use;
2678
+ var Wt = g.walkTokens;
2679
+ var Xt = g.parseInline;
2680
+ var Vt = b.parse;
2681
+ var Yt = x.lex;
2682
+
2683
+ // src/ui/render_markdown.ts
2684
+ g.setOptions({ gfm: true, breaks: true });
2685
+ var ALLOWED_TAGS = [
2686
+ "a",
2687
+ "p",
2688
+ "br",
2689
+ "strong",
2690
+ "em",
2691
+ "b",
2692
+ "i",
2693
+ "u",
2694
+ "s",
2695
+ "del",
2696
+ "code",
2697
+ "pre",
2698
+ "ul",
2699
+ "ol",
2700
+ "li",
2701
+ "blockquote",
2702
+ "h1",
2703
+ "h2",
2704
+ "h3",
2705
+ "h4",
2706
+ "h5",
2707
+ "h6",
2708
+ "hr",
2709
+ "span",
2710
+ "table",
2711
+ "thead",
2712
+ "tbody",
2713
+ "tr",
2714
+ "th",
2715
+ "td",
2716
+ "img"
2717
+ ];
2718
+ var ALLOWED_ATTR = ["href", "title", "class", "src", "alt", "width", "height"];
2719
+ function renderMarkdown(text2) {
2720
+ const rendered = g.parse(text2, { async: false });
2721
+ const clean = purify.sanitize(rendered, { ALLOWED_TAGS, ALLOWED_ATTR });
2722
+ const template = document.createElement("template");
2723
+ template.innerHTML = clean;
2724
+ for (const anchor of template.content.querySelectorAll("a[href]")) {
2725
+ anchor.setAttribute("target", "_blank");
2726
+ anchor.setAttribute("rel", "noopener noreferrer");
2727
+ }
2728
+ return template.innerHTML.trim();
2729
+ }
2730
+
2731
+ // src/ui/reveal_words.ts
2732
+ function collectTextNodes(root, out) {
2733
+ for (const child of Array.from(root.childNodes)) {
2734
+ if (child.nodeType === Node.TEXT_NODE) {
2735
+ out.push({ node: child, parent: root });
2736
+ } else {
2737
+ collectTextNodes(child, out);
2738
+ }
2739
+ }
2740
+ }
2741
+ function wrapWords(root) {
2742
+ const texts = [];
2743
+ collectTextNodes(root, texts);
2744
+ let index = 0;
2745
+ for (const { node, parent } of texts) {
2746
+ const fragment = document.createDocumentFragment();
2747
+ for (const part of node.data.split(/(\s+)/)) {
2748
+ if (part === "") {
2749
+ continue;
2750
+ }
2751
+ if (/\s/.test(part)) {
2752
+ fragment.appendChild(document.createTextNode(part));
2753
+ continue;
2754
+ }
2755
+ const span = document.createElement("span");
2756
+ span.className = "word";
2757
+ span.style.setProperty("--ag-ui-word-index", String(index));
2758
+ span.textContent = part;
2759
+ fragment.appendChild(span);
2760
+ index += 1;
2761
+ }
2762
+ parent.replaceChild(fragment, node);
2763
+ }
2764
+ }
2765
+
2766
+ // src/ui/skills_menu.ts
2767
+ var SkillsMenu = class {
2768
+ /** Chips row — append above the input. Hidden unless chips are enabled and present. */
2769
+ chips;
2770
+ /** The `/`-command dropdown — append in the input area. Hidden until opened. */
2771
+ palette;
2772
+ #onPick;
2773
+ #skills = [];
2774
+ #chipsEnabled = false;
2775
+ #slashEnabled = false;
2776
+ #filtered = [];
2777
+ #activeIndex = 0;
2778
+ constructor(onPick) {
2779
+ this.#onPick = onPick;
2780
+ this.chips = document.createElement("div");
2781
+ this.chips.className = "skill-chips";
2782
+ this.chips.hidden = true;
2783
+ this.palette = document.createElement("div");
2784
+ this.palette.className = "skill-palette";
2785
+ this.palette.setAttribute("role", "listbox");
2786
+ this.palette.hidden = true;
2787
+ }
2788
+ /** Replace the catalog (both surfaces re-derive from it). */
2789
+ setSkills(skills) {
2790
+ this.#skills = skills;
2791
+ this.#renderChips();
2792
+ }
2793
+ enableChips(enabled) {
2794
+ this.#chipsEnabled = enabled;
2795
+ this.#renderChips();
2796
+ }
2797
+ enableSlash(enabled) {
2798
+ this.#slashEnabled = enabled;
2799
+ }
2800
+ /** Whether the palette is currently open. */
2801
+ isOpen() {
2802
+ return !this.palette.hidden;
2803
+ }
2804
+ /**
2805
+ * React to an input value change: open + filter the palette when slash mode
2806
+ * is on and the value starts with `/`, otherwise close it.
2807
+ */
2808
+ onInput(value) {
2809
+ if (this.#slashEnabled && value.startsWith("/")) {
2810
+ this.#open(value.slice(1));
2811
+ } else {
2812
+ this.close();
2813
+ }
2814
+ }
2815
+ /**
2816
+ * Handle a keydown while the palette is open. Returns ``true`` when consumed
2817
+ * (the host should `preventDefault` and skip its own handling).
2818
+ */
2819
+ onKeydown(event) {
2820
+ if (!this.isOpen()) {
2821
+ return false;
2822
+ }
2823
+ if (event.key === "ArrowDown") {
2824
+ this.#move(1);
2825
+ return true;
2826
+ }
2827
+ if (event.key === "ArrowUp") {
2828
+ this.#move(-1);
2829
+ return true;
2830
+ }
2831
+ if (event.key === "Escape") {
2832
+ this.close();
2833
+ return true;
2834
+ }
2835
+ if (event.key === "Enter") {
2836
+ this.#filtered.slice(this.#activeIndex, this.#activeIndex + 1).forEach((skill) => {
2837
+ this.#pick(skill);
2838
+ });
2839
+ return true;
2840
+ }
2841
+ return false;
2842
+ }
2843
+ /** Close the palette. */
2844
+ close() {
2845
+ this.palette.hidden = true;
2846
+ this.palette.replaceChildren();
2847
+ }
2848
+ #open(query) {
2849
+ const needle = query.trim().toLowerCase();
2850
+ const matches = this.#skills.filter(
2851
+ (skill) => skill.name.toLowerCase().includes(needle) || skill.title.toLowerCase().includes(needle)
2852
+ );
2853
+ if (matches.length === 0) {
2854
+ this.close();
2855
+ return;
2856
+ }
2857
+ this.#filtered = matches;
2858
+ this.#activeIndex = 0;
2859
+ this.#renderPalette();
2860
+ this.palette.hidden = false;
2861
+ }
2862
+ #move(delta) {
2863
+ const count = this.#filtered.length;
2864
+ this.#activeIndex = (this.#activeIndex + delta + count) % count;
2865
+ this.#renderPalette();
2866
+ }
2867
+ #pick(skill) {
2868
+ this.close();
2869
+ this.#onPick(skill);
2870
+ }
2871
+ #renderChips() {
2872
+ this.chips.replaceChildren();
2873
+ const chipSkills = this.#chipsEnabled ? this.#skills.filter((skill) => skill.chip === true) : [];
2874
+ this.chips.hidden = chipSkills.length === 0;
2875
+ for (const skill of chipSkills) {
2876
+ const button = document.createElement("button");
2877
+ button.type = "button";
2878
+ button.className = "skill-chip";
2879
+ button.textContent = skill.title;
2880
+ button.addEventListener("click", () => this.#pick(skill));
2881
+ this.chips.appendChild(button);
2882
+ }
2883
+ }
2884
+ #renderPalette() {
2885
+ this.palette.replaceChildren();
2886
+ this.#filtered.forEach((skill, index) => {
2887
+ const item = document.createElement("button");
2888
+ item.type = "button";
2889
+ item.className = "skill-item";
2890
+ item.setAttribute("role", "option");
2891
+ item.setAttribute("aria-selected", index === this.#activeIndex ? "true" : "false");
2892
+ const title = document.createElement("span");
2893
+ title.className = "skill-item-title";
2894
+ title.textContent = skill.title;
2895
+ item.appendChild(title);
2896
+ if (skill.description !== void 0) {
2897
+ const desc = document.createElement("span");
2898
+ desc.className = "skill-item-desc";
2899
+ desc.textContent = skill.description;
2900
+ item.appendChild(desc);
2901
+ }
2902
+ item.addEventListener("click", () => this.#pick(skill));
2903
+ this.palette.appendChild(item);
2904
+ });
2905
+ }
2906
+ };
2907
+
2908
+ // src/ui/styles.ts
2909
+ var STYLES = `
2910
+ :host {
2911
+ /* Colors */
2912
+ --ag-ui-bg: #ffffff;
2913
+ --ag-ui-fg: #1a1a2e;
2914
+ --ag-ui-accent: #4f46e5;
2915
+ --ag-ui-user-bg: #4f46e5;
2916
+ --ag-ui-user-fg: #ffffff;
2917
+ --ag-ui-assistant-bg: #f1f1f6;
2918
+ --ag-ui-input-bg: var(--ag-ui-bg);
2919
+ --ag-ui-tool-bg: var(--ag-ui-assistant-bg);
2920
+ --ag-ui-tool-fg: var(--ag-ui-accent);
2921
+ --ag-ui-header-bg: var(--ag-ui-accent);
2922
+ --ag-ui-header-fg: #ffffff;
2923
+ --ag-ui-border: #e2e2ec;
2924
+ --ag-ui-radius: 12px;
2925
+
2926
+ /* Status accents for tool-call cards. */
2927
+ --ag-ui-success: #15803d;
2928
+ --ag-ui-danger: #b91c1c;
400
2929
  --ag-ui-muted: #6b7280;
401
2930
 
402
2931
  /* Surface \u2014 set --ag-ui-shadow: none for a flush, embedded panel. */
403
2932
  --ag-ui-shadow: 0 12px 32px rgba(20, 20, 50, 0.18);
404
2933
  --ag-ui-font: inherit;
405
2934
  --ag-ui-font-size: 14px;
2935
+ --ag-ui-code-font: ui-monospace, "SF Mono", Menlo, monospace;
2936
+
2937
+ /* Spacing \u2014 the density preset overrides these. */
2938
+ --ag-ui-space: 10px;
2939
+ --ag-ui-pad: 16px;
2940
+ --ag-ui-msg-pad: 8px 12px;
2941
+ --ag-ui-msg-radius: 14px;
406
2942
 
407
2943
  /* Layout \u2014 override from outside to dock the widget anywhere.
408
2944
  Set --ag-ui-position: static (and place this element in your own
@@ -428,6 +2964,91 @@ var STYLES = `
428
2964
  color: var(--ag-ui-fg);
429
2965
  }
430
2966
 
2967
+ /* \u2500\u2500 Themes \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
2968
+ Themes only re-set the colour variables; layout/spacing are unaffected.
2969
+ theme="auto" follows the OS via prefers-color-scheme. */
2970
+ :host([theme="dark"]) {
2971
+ --ag-ui-bg: #15151f;
2972
+ --ag-ui-fg: #e8e8f2;
2973
+ --ag-ui-assistant-bg: #25253a;
2974
+ --ag-ui-header-bg: #1f1f30;
2975
+ --ag-ui-header-fg: #e8e8f2;
2976
+ --ag-ui-border: #33334a;
2977
+ --ag-ui-muted: #9aa0b4;
2978
+ --ag-ui-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
2979
+ }
2980
+
2981
+ @media (prefers-color-scheme: dark) {
2982
+ :host([theme="auto"]) {
2983
+ --ag-ui-bg: #15151f;
2984
+ --ag-ui-fg: #e8e8f2;
2985
+ --ag-ui-assistant-bg: #25253a;
2986
+ --ag-ui-header-bg: #1f1f30;
2987
+ --ag-ui-header-fg: #e8e8f2;
2988
+ --ag-ui-border: #33334a;
2989
+ --ag-ui-muted: #9aa0b4;
2990
+ --ag-ui-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
2991
+ }
2992
+ }
2993
+
2994
+ /* A terminal-flavoured "code" theme: dark, monospace, green accent. */
2995
+ :host([theme="code"]) {
2996
+ --ag-ui-bg: #0d1117;
2997
+ --ag-ui-fg: #c9d1d9;
2998
+ --ag-ui-accent: #3fb950;
2999
+ --ag-ui-user-bg: #238636;
3000
+ --ag-ui-assistant-bg: #161b22;
3001
+ --ag-ui-header-bg: #010409;
3002
+ --ag-ui-header-fg: #c9d1d9;
3003
+ --ag-ui-border: #30363d;
3004
+ --ag-ui-muted: #8b949e;
3005
+ --ag-ui-font: var(--ag-ui-code-font);
3006
+ --ag-ui-shadow: 0 12px 32px rgba(0, 0, 0, 0.6);
3007
+ }
3008
+
3009
+ /* \u2500\u2500 Density \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 */
3010
+ :host([density="compact"]) {
3011
+ --ag-ui-font-size: 13px;
3012
+ --ag-ui-space: 6px;
3013
+ --ag-ui-pad: 10px;
3014
+ --ag-ui-msg-pad: 5px 9px;
3015
+ --ag-ui-msg-radius: 10px;
3016
+ }
3017
+
3018
+ /* \u2500\u2500 Placement presets \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 */
3019
+ :host([placement="bottom-left"]) {
3020
+ --ag-ui-inset: auto auto 24px 24px;
3021
+ }
3022
+
3023
+ :host([placement="side"]) {
3024
+ --ag-ui-inset: 0 0 0 auto;
3025
+ --ag-ui-width: 420px;
3026
+ --ag-ui-height: 100vh;
3027
+ --ag-ui-max-height: 100vh;
3028
+ --ag-ui-radius: 0;
3029
+ }
3030
+
3031
+ :host([placement="full"]) {
3032
+ --ag-ui-inset: 0;
3033
+ --ag-ui-width: 100vw;
3034
+ --ag-ui-height: 100vh;
3035
+ --ag-ui-max-width: 100vw;
3036
+ --ag-ui-max-height: 100vh;
3037
+ --ag-ui-radius: 0;
3038
+ }
3039
+
3040
+ /* Embedded: drop the floating chrome and the high z-index stacking context so
3041
+ the widget lives in the host's own layout (fixes overlay/z-index clashes). */
3042
+ :host([placement="embedded"]) {
3043
+ --ag-ui-position: static;
3044
+ --ag-ui-width: 100%;
3045
+ --ag-ui-height: 100%;
3046
+ --ag-ui-max-width: 100%;
3047
+ --ag-ui-max-height: 100%;
3048
+ --ag-ui-shadow: none;
3049
+ --ag-ui-z-index: auto;
3050
+ }
3051
+
431
3052
  .chat {
432
3053
  position: relative;
433
3054
  display: flex;
@@ -442,29 +3063,112 @@ var STYLES = `
442
3063
  }
443
3064
 
444
3065
  .header {
445
- padding: 12px 16px;
446
- font-weight: 600;
3066
+ display: flex;
3067
+ align-items: center;
3068
+ justify-content: space-between;
3069
+ gap: 8px;
3070
+ padding: 10px 14px;
447
3071
  border-bottom: 1px solid var(--ag-ui-border);
448
3072
  background: var(--ag-ui-header-bg);
449
3073
  color: var(--ag-ui-header-fg);
450
3074
  }
451
3075
 
3076
+ .header-title {
3077
+ font-weight: 600;
3078
+ overflow: hidden;
3079
+ text-overflow: ellipsis;
3080
+ white-space: nowrap;
3081
+ }
3082
+
3083
+ .header-controls {
3084
+ display: flex;
3085
+ gap: 2px;
3086
+ flex: none;
3087
+ }
3088
+
3089
+ .header-btn {
3090
+ border: none;
3091
+ background: transparent;
3092
+ color: inherit;
3093
+ font: inherit;
3094
+ line-height: 1;
3095
+ padding: 4px 7px;
3096
+ border-radius: 6px;
3097
+ cursor: pointer;
3098
+ opacity: 0.85;
3099
+ }
3100
+
3101
+ .header-btn:hover {
3102
+ opacity: 1;
3103
+ background: rgba(255, 255, 255, 0.18);
3104
+ }
3105
+
3106
+ /* Collapsed: keep just the header bar \u2014 hide the whole body, and let the host
3107
+ shrink to the header. (A host can also fully hide the element itself.) */
3108
+ :host([collapsed]) {
3109
+ height: auto;
3110
+ max-height: none;
3111
+ }
3112
+
3113
+ :host([collapsed]) .messages,
3114
+ :host([collapsed]) .input-row,
3115
+ :host([collapsed]) .skill-chips,
3116
+ :host([collapsed]) .skill-palette,
3117
+ :host([collapsed]) .skill-hint {
3118
+ display: none;
3119
+ }
3120
+
3121
+ /* Edge-docked placements pin top *and* bottom, which would otherwise keep the
3122
+ panel full-height when collapsed; unpin the bottom so it shrinks to the
3123
+ header. (Floating/bottom-left pin only the bottom, so they already shrink.) */
3124
+ :host([collapsed][placement="side"]),
3125
+ :host([collapsed][placement="full"]) {
3126
+ bottom: auto;
3127
+ }
3128
+
452
3129
  .messages {
453
3130
  flex: 1;
454
3131
  overflow-y: auto;
455
- padding: 16px;
3132
+ padding: var(--ag-ui-pad);
456
3133
  display: flex;
457
3134
  flex-direction: column;
458
- gap: 10px;
3135
+ gap: var(--ag-ui-space);
3136
+ }
3137
+
3138
+ .message {
3139
+ max-width: 80%;
3140
+ padding: var(--ag-ui-msg-pad);
3141
+ border-radius: var(--ag-ui-msg-radius);
3142
+ line-height: 1.4;
3143
+ white-space: pre-wrap;
3144
+ word-break: break-word;
3145
+ }
3146
+
3147
+ /* \u2500\u2500 Incoming-text animations (data-text-animation) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
3148
+ :host([data-text-animation="fade"]) .message--assistant {
3149
+ animation: ag-ui-msg-fade 0.25s ease both;
3150
+ }
3151
+
3152
+ @keyframes ag-ui-msg-fade {
3153
+ from { opacity: 0; transform: translateY(4px); }
3154
+ to { opacity: 1; transform: none; }
3155
+ }
3156
+
3157
+ .message--assistant .word {
3158
+ animation: ag-ui-word-in 0.3s ease both;
3159
+ animation-delay: calc(var(--ag-ui-word-index, 0) * 35ms);
3160
+ }
3161
+
3162
+ @keyframes ag-ui-word-in {
3163
+ from { opacity: 0; }
3164
+ to { opacity: 1; }
459
3165
  }
460
3166
 
461
- .message {
462
- max-width: 80%;
463
- padding: 8px 12px;
464
- border-radius: 14px;
465
- line-height: 1.4;
466
- white-space: pre-wrap;
467
- word-break: break-word;
3167
+ @media (prefers-reduced-motion: reduce) {
3168
+ :host([data-text-animation="fade"]) .message--assistant,
3169
+ .message--assistant .word {
3170
+ animation: none;
3171
+ }
468
3172
  }
469
3173
 
470
3174
  .message--user {
@@ -478,6 +3182,102 @@ var STYLES = `
478
3182
  align-self: flex-start;
479
3183
  background: var(--ag-ui-assistant-bg);
480
3184
  border-bottom-left-radius: 4px;
3185
+ /* Assistant bubbles hold rendered markdown/HTML, so collapse the source
3186
+ whitespace the renderer leaves between block tags. */
3187
+ white-space: normal;
3188
+ }
3189
+
3190
+ /* Rendered-markdown elements inside an assistant bubble. */
3191
+ .message--assistant > :first-child {
3192
+ margin-top: 0;
3193
+ }
3194
+
3195
+ .message--assistant > :last-child {
3196
+ margin-bottom: 0;
3197
+ }
3198
+
3199
+ .message--assistant p,
3200
+ .message--assistant ul,
3201
+ .message--assistant ol,
3202
+ .message--assistant blockquote,
3203
+ .message--assistant pre {
3204
+ margin: 0.5em 0;
3205
+ }
3206
+
3207
+ .message--assistant ul,
3208
+ .message--assistant ol {
3209
+ padding-left: 1.3em;
3210
+ }
3211
+
3212
+ .message--assistant a {
3213
+ color: var(--ag-ui-accent);
3214
+ text-decoration: underline;
3215
+ }
3216
+
3217
+ .message--assistant code {
3218
+ font-family: ui-monospace, "SF Mono", Menlo, monospace;
3219
+ font-size: 0.92em;
3220
+ background: rgba(127, 127, 127, 0.16);
3221
+ padding: 1px 4px;
3222
+ border-radius: 4px;
3223
+ }
3224
+
3225
+ .message--assistant pre {
3226
+ padding: 8px 10px;
3227
+ overflow: auto;
3228
+ background: var(--ag-ui-bg);
3229
+ border: 1px solid var(--ag-ui-border);
3230
+ border-radius: 6px;
3231
+ }
3232
+
3233
+ .message--assistant pre code {
3234
+ background: none;
3235
+ padding: 0;
3236
+ }
3237
+
3238
+ .message--assistant blockquote {
3239
+ padding-left: 10px;
3240
+ border-left: 3px solid var(--ag-ui-border);
3241
+ color: var(--ag-ui-muted);
3242
+ }
3243
+
3244
+ .pending {
3245
+ align-self: flex-start;
3246
+ display: inline-flex;
3247
+ gap: 4px;
3248
+ align-items: center;
3249
+ padding: 12px 14px;
3250
+ background: var(--ag-ui-assistant-bg);
3251
+ border-radius: 14px;
3252
+ border-bottom-left-radius: 4px;
3253
+ }
3254
+
3255
+ .pending-dot {
3256
+ width: 6px;
3257
+ height: 6px;
3258
+ border-radius: 50%;
3259
+ background: var(--ag-ui-muted);
3260
+ animation: ag-ui-pending 1.2s infinite ease-in-out both;
3261
+ }
3262
+
3263
+ .pending-dot:nth-child(2) {
3264
+ animation-delay: 0.16s;
3265
+ }
3266
+
3267
+ .pending-dot:nth-child(3) {
3268
+ animation-delay: 0.32s;
3269
+ }
3270
+
3271
+ @keyframes ag-ui-pending {
3272
+ 0%, 80%, 100% { opacity: 0.3; transform: translateY(0); }
3273
+ 40% { opacity: 1; transform: translateY(-3px); }
3274
+ }
3275
+
3276
+ @media (prefers-reduced-motion: reduce) {
3277
+ .pending-dot {
3278
+ animation: none;
3279
+ opacity: 0.6;
3280
+ }
481
3281
  }
482
3282
 
483
3283
  .tool-call {
@@ -602,38 +3402,30 @@ var STYLES = `
602
3402
  cursor: default;
603
3403
  }
604
3404
 
605
- .modal-overlay {
606
- position: absolute;
607
- inset: 0;
3405
+ /* Inline confirmation card \u2014 lives in the transcript, no focus-stealing overlay. */
3406
+ .confirm {
3407
+ align-self: stretch;
3408
+ box-sizing: border-box;
608
3409
  display: flex;
609
- align-items: center;
610
- justify-content: center;
611
- padding: 16px;
612
- background: rgba(20, 20, 50, 0.4);
613
- backdrop-filter: blur(2px);
614
- }
615
-
616
- .modal {
617
- width: 100%;
618
- max-width: 320px;
3410
+ flex-direction: column;
3411
+ gap: 8px;
3412
+ padding: 12px;
619
3413
  background: var(--ag-ui-bg);
620
- border-radius: 12px;
621
- box-shadow: 0 16px 40px rgba(20, 20, 50, 0.3);
622
- overflow: hidden;
3414
+ border: 1px solid var(--ag-ui-accent);
3415
+ border-radius: 10px;
623
3416
  }
624
3417
 
625
- .modal-title {
626
- padding: 12px 16px;
627
- font-weight: 600;
628
- border-bottom: 1px solid var(--ag-ui-border);
3418
+ .confirm[data-resolved] {
3419
+ opacity: 0.7;
3420
+ border-color: var(--ag-ui-border);
629
3421
  }
630
3422
 
631
- .modal-body {
632
- padding: 12px 16px 4px;
3423
+ .confirm-body {
3424
+ font-weight: 600;
633
3425
  }
634
3426
 
635
- .modal-args {
636
- margin: 0 16px 12px;
3427
+ .confirm-args {
3428
+ margin: 0;
637
3429
  padding: 8px 10px;
638
3430
  max-height: 140px;
639
3431
  overflow: auto;
@@ -645,14 +3437,13 @@ var STYLES = `
645
3437
  word-break: break-word;
646
3438
  }
647
3439
 
648
- .modal-actions {
3440
+ .confirm-actions {
649
3441
  display: flex;
650
3442
  gap: 8px;
651
- padding: 0 16px 16px;
652
3443
  justify-content: flex-end;
653
3444
  }
654
3445
 
655
- .modal-btn {
3446
+ .confirm-btn {
656
3447
  border: 1px solid var(--ag-ui-border);
657
3448
  border-radius: 8px;
658
3449
  padding: 8px 14px;
@@ -663,14 +3454,87 @@ var STYLES = `
663
3454
  color: var(--ag-ui-fg);
664
3455
  }
665
3456
 
666
- .modal-btn--confirm {
3457
+ .confirm-btn:disabled {
3458
+ cursor: default;
3459
+ opacity: 0.6;
3460
+ }
3461
+
3462
+ .confirm-btn--confirm {
667
3463
  border-color: var(--ag-ui-accent);
668
3464
  background: var(--ag-ui-accent);
669
3465
  color: #ffffff;
670
3466
  }
3467
+
3468
+ /* Skills \u2014 chips row + the /-command palette, above the input. */
3469
+ .skill-chips {
3470
+ display: flex;
3471
+ flex-wrap: wrap;
3472
+ gap: 6px;
3473
+ padding: 10px 12px;
3474
+ }
3475
+
3476
+ .skill-chip {
3477
+ border: 1px solid var(--ag-ui-border);
3478
+ border-radius: 999px;
3479
+ padding: 4px 12px;
3480
+ font: inherit;
3481
+ font-size: 0.9em;
3482
+ cursor: pointer;
3483
+ background: var(--ag-ui-assistant-bg);
3484
+ color: var(--ag-ui-fg);
3485
+ }
3486
+
3487
+ .skill-chip:hover {
3488
+ border-color: var(--ag-ui-accent);
3489
+ }
3490
+
3491
+ .skill-palette {
3492
+ margin: 8px 12px 0;
3493
+ display: flex;
3494
+ flex-direction: column;
3495
+ max-height: 220px;
3496
+ overflow: auto;
3497
+ background: var(--ag-ui-bg);
3498
+ border: 1px solid var(--ag-ui-border);
3499
+ border-radius: 8px;
3500
+ box-shadow: 0 8px 24px rgba(20, 20, 50, 0.16);
3501
+ }
3502
+
3503
+ .skill-item {
3504
+ display: flex;
3505
+ flex-direction: column;
3506
+ gap: 2px;
3507
+ align-items: flex-start;
3508
+ padding: 8px 12px;
3509
+ border: none;
3510
+ background: none;
3511
+ font: inherit;
3512
+ text-align: left;
3513
+ cursor: pointer;
3514
+ color: var(--ag-ui-fg);
3515
+ }
3516
+
3517
+ .skill-item[aria-selected="true"] {
3518
+ background: var(--ag-ui-assistant-bg);
3519
+ }
3520
+
3521
+ .skill-item-title {
3522
+ font-weight: 600;
3523
+ }
3524
+
3525
+ .skill-item-desc {
3526
+ font-size: 0.85em;
3527
+ color: var(--ag-ui-muted);
3528
+ }
3529
+
3530
+ .skill-hint {
3531
+ margin: 8px 12px 0;
3532
+ font-size: 0.85em;
3533
+ color: var(--ag-ui-danger);
3534
+ }
671
3535
  `;
672
3536
 
673
- // src/tool_call_card.ts
3537
+ // src/ui/tool_call_card.ts
674
3538
  var STATUS_LABEL = {
675
3539
  [TOOL_CALL_STATUS.PENDING]: "running\u2026",
676
3540
  [TOOL_CALL_STATUS.DONE]: "\u2713 done",
@@ -682,56 +3546,267 @@ var RESULT_LABEL = {
682
3546
  [TOOL_CALL_STATUS.ERROR]: "Error",
683
3547
  [TOOL_CALL_STATUS.DECLINED]: "Declined"
684
3548
  };
685
- var ToolCallCard = class {
686
- /** The card's root element; append this into the message list. */
687
- element;
688
- #status;
689
- constructor(name, args) {
690
- this.element = document.createElement("div");
691
- this.element.className = "tool-call";
692
- this.element.setAttribute("data-tool-name", name);
693
- this.element.setAttribute("data-status", TOOL_CALL_STATUS.PENDING);
694
- const head = document.createElement("div");
695
- head.className = "tool-call-head";
696
- const label = document.createElement("span");
697
- label.className = "tool-call-name";
698
- label.textContent = `\u{1F527} ${name}`;
699
- this.#status = document.createElement("span");
700
- this.#status.className = "tool-call-status";
701
- this.#status.textContent = STATUS_LABEL[TOOL_CALL_STATUS.PENDING];
702
- head.append(label, this.#status);
703
- const argsEl = document.createElement("pre");
704
- argsEl.className = "tool-call-args";
705
- argsEl.textContent = JSON.stringify(args, null, 2);
706
- this.element.append(head, argsEl);
3549
+ var ToolCallCard = class {
3550
+ /** The card's root element; append this into the message list. */
3551
+ element;
3552
+ #status;
3553
+ #mode;
3554
+ #args;
3555
+ constructor(name, args, mode = TOOL_DISPLAY.FULL, summary) {
3556
+ this.#mode = mode;
3557
+ this.#args = args;
3558
+ this.element = document.createElement("div");
3559
+ this.element.className = "tool-call";
3560
+ this.element.setAttribute("data-tool-name", name);
3561
+ this.element.setAttribute("data-status", TOOL_CALL_STATUS.PENDING);
3562
+ this.element.setAttribute("data-display", mode);
3563
+ const head = document.createElement("div");
3564
+ head.className = "tool-call-head";
3565
+ const label = document.createElement("span");
3566
+ label.className = "tool-call-name";
3567
+ label.textContent = `\u{1F527} ${summary ?? name}`;
3568
+ this.#status = document.createElement("span");
3569
+ this.#status.className = "tool-call-status";
3570
+ this.#status.textContent = STATUS_LABEL[TOOL_CALL_STATUS.PENDING];
3571
+ head.append(label, this.#status);
3572
+ this.element.append(head);
3573
+ if (mode === TOOL_DISPLAY.FULL) {
3574
+ const argsEl = document.createElement("pre");
3575
+ argsEl.className = "tool-call-args";
3576
+ argsEl.textContent = JSON.stringify(args, null, 2);
3577
+ this.element.append(argsEl);
3578
+ }
3579
+ }
3580
+ /**
3581
+ * Flip the status pill to ``status`` and, unless in `minimal` mode, append a
3582
+ * collapsed body behind a click-to-expand toggle: the result alone (`full`),
3583
+ * or the args + result together (`compact`).
3584
+ */
3585
+ settle(status, text2) {
3586
+ this.element.setAttribute("data-status", status);
3587
+ this.#status.textContent = STATUS_LABEL[status];
3588
+ if (this.#mode === TOOL_DISPLAY.MINIMAL) {
3589
+ return;
3590
+ }
3591
+ const toggle = document.createElement("button");
3592
+ toggle.type = "button";
3593
+ toggle.className = "tool-call-toggle";
3594
+ toggle.setAttribute("aria-expanded", "false");
3595
+ const output = document.createElement("pre");
3596
+ output.className = "tool-call-result";
3597
+ output.hidden = true;
3598
+ if (this.#mode === TOOL_DISPLAY.COMPACT) {
3599
+ toggle.textContent = "Details";
3600
+ output.textContent = `args: ${JSON.stringify(this.#args)}
3601
+
3602
+ ${text2}`;
3603
+ } else {
3604
+ toggle.textContent = RESULT_LABEL[status];
3605
+ output.textContent = text2;
3606
+ }
3607
+ toggle.addEventListener("click", () => {
3608
+ const expand = output.hidden;
3609
+ output.hidden = !expand;
3610
+ toggle.setAttribute("aria-expanded", String(expand));
3611
+ });
3612
+ this.element.append(toggle, output);
3613
+ }
3614
+ };
3615
+
3616
+ // src/core/agui_client.ts
3617
+ import { randomUUID } from "@ag-ui/client";
3618
+ var AgUiClient = class {
3619
+ #agent;
3620
+ #handlers;
3621
+ #getTools;
3622
+ #getContext;
3623
+ #executeTool;
3624
+ #onPersist;
3625
+ constructor(config) {
3626
+ this.#agent = config.agent;
3627
+ this.#handlers = config.handlers;
3628
+ this.#getTools = config.getTools ?? (() => []);
3629
+ this.#getContext = config.getContext ?? (() => []);
3630
+ this.#executeTool = config.executeTool ?? null;
3631
+ this.#onPersist = config.onPersist ?? (() => {
3632
+ });
3633
+ }
3634
+ /** Whether a run is currently in flight. */
3635
+ get running() {
3636
+ return this.#agent.isRunning;
3637
+ }
3638
+ /** The current conversation history (for persistence / rehydration). */
3639
+ get messages() {
3640
+ return this.#agent.messages;
3641
+ }
3642
+ /**
3643
+ * Append a user message and run the agent to completion.
3644
+ *
3645
+ * When the agent calls frontend tools, this executes them and re-runs the
3646
+ * agent with the results, looping until the agent stops calling frontend
3647
+ * tools (bounded by {@link MAX_TOOL_ROUNDS}).
3648
+ */
3649
+ async send(content) {
3650
+ this.#agent.addMessage({ id: randomUUID(), role: "user", content });
3651
+ this.#onPersist(this.#agent.messages);
3652
+ await this.#run();
3653
+ }
3654
+ /**
3655
+ * Resume the run loop after a navigating tool's result was supplied
3656
+ * post-reload (via {@link addToolResult}). Unlike {@link send}, adds no user
3657
+ * message — it simply continues the conversation already in history.
3658
+ */
3659
+ async resume() {
3660
+ await this.#run();
3661
+ }
3662
+ /** Append a frontend tool result to history (used by the resume path). */
3663
+ addToolResult(toolCallId, content) {
3664
+ this.#agent.addMessage({ id: randomUUID(), role: "tool", content, toolCallId });
3665
+ this.#onPersist(this.#agent.messages);
3666
+ }
3667
+ async #run() {
3668
+ try {
3669
+ await this.#runLoop();
3670
+ } catch (error) {
3671
+ this.#handlers.onError(error instanceof Error ? error.message : String(error));
3672
+ }
3673
+ }
3674
+ async #runLoop() {
3675
+ for (let round = 0; round < MAX_TOOL_ROUNDS; round += 1) {
3676
+ const pending = [];
3677
+ await this.#agent.runAgent(
3678
+ { tools: this.#getTools(), context: this.#getContext() },
3679
+ this.#buildSubscriber(pending)
3680
+ );
3681
+ this.#onPersist(this.#agent.messages);
3682
+ if (this.#executeTool === null || pending.length === 0) {
3683
+ return;
3684
+ }
3685
+ let executed = false;
3686
+ for (const call of pending) {
3687
+ const result = await this.#executeTool(call);
3688
+ if (result === null) {
3689
+ continue;
3690
+ }
3691
+ if (result.halt === true) {
3692
+ return;
3693
+ }
3694
+ this.#agent.addMessage({
3695
+ id: randomUUID(),
3696
+ role: "tool",
3697
+ content: result.content,
3698
+ toolCallId: call.id
3699
+ });
3700
+ this.#onPersist(this.#agent.messages);
3701
+ executed = true;
3702
+ }
3703
+ if (!executed) {
3704
+ return;
3705
+ }
3706
+ }
3707
+ }
3708
+ #buildSubscriber(pending) {
3709
+ const h = this.#handlers;
3710
+ return {
3711
+ onRunInitialized() {
3712
+ h.onRunStart();
3713
+ },
3714
+ onTextMessageContentEvent({ textMessageBuffer }) {
3715
+ h.onTextDelta(textMessageBuffer);
3716
+ },
3717
+ onTextMessageEndEvent({ textMessageBuffer }) {
3718
+ h.onTextEnd(textMessageBuffer);
3719
+ },
3720
+ onToolCallEndEvent({ event, toolCallName, toolCallArgs }) {
3721
+ const call = {
3722
+ id: event.toolCallId,
3723
+ name: toolCallName,
3724
+ args: toolCallArgs
3725
+ };
3726
+ pending.push(call);
3727
+ h.onToolCall(call);
3728
+ },
3729
+ onRunErrorEvent({ event }) {
3730
+ h.onError(event.message);
3731
+ },
3732
+ onRunFinalized() {
3733
+ h.onRunEnd();
3734
+ }
3735
+ };
3736
+ }
3737
+ };
3738
+
3739
+ // src/core/conversation_store.ts
3740
+ import { randomUUID as randomUUID2 } from "@ag-ui/client";
3741
+ var THREAD_KEY = "ag-ui-chat:thread";
3742
+ var MESSAGES_PREFIX = "ag-ui-chat:messages:";
3743
+ var CHECKPOINT_PREFIX = "ag-ui-chat:checkpoint:";
3744
+ var SessionStorageStore = class {
3745
+ threadId() {
3746
+ const existing = sessionStorage.getItem(THREAD_KEY);
3747
+ if (existing !== null) {
3748
+ return existing;
3749
+ }
3750
+ const id = randomUUID2();
3751
+ sessionStorage.setItem(THREAD_KEY, id);
3752
+ return id;
707
3753
  }
708
- /**
709
- * Flip the status pill to ``status`` and append a collapsed body holding
710
- * ``text`` (the JSON result, an error message, a decline notice, or a
711
- * server-executed note) behind a click-to-expand toggle.
712
- */
713
- settle(status, text) {
714
- this.element.setAttribute("data-status", status);
715
- this.#status.textContent = STATUS_LABEL[status];
716
- const toggle = document.createElement("button");
717
- toggle.type = "button";
718
- toggle.className = "tool-call-toggle";
719
- toggle.setAttribute("aria-expanded", "false");
720
- toggle.textContent = RESULT_LABEL[status];
721
- const output = document.createElement("pre");
722
- output.className = "tool-call-result";
723
- output.textContent = text;
724
- output.hidden = true;
725
- toggle.addEventListener("click", () => {
726
- const expand = output.hidden;
727
- output.hidden = !expand;
728
- toggle.setAttribute("aria-expanded", String(expand));
729
- });
730
- this.element.append(toggle, output);
3754
+ loadMessages(threadId) {
3755
+ return Promise.resolve(this.#readJson(MESSAGES_PREFIX + threadId));
3756
+ }
3757
+ saveMessages(threadId, messages) {
3758
+ sessionStorage.setItem(MESSAGES_PREFIX + threadId, JSON.stringify(messages));
3759
+ }
3760
+ loadCheckpoint(threadId) {
3761
+ return this.#readJson(CHECKPOINT_PREFIX + threadId);
3762
+ }
3763
+ saveCheckpoint(threadId, checkpoint) {
3764
+ const key = CHECKPOINT_PREFIX + threadId;
3765
+ if (checkpoint === null) {
3766
+ sessionStorage.removeItem(key);
3767
+ return;
3768
+ }
3769
+ sessionStorage.setItem(key, JSON.stringify(checkpoint));
3770
+ }
3771
+ clear(threadId) {
3772
+ sessionStorage.removeItem(MESSAGES_PREFIX + threadId);
3773
+ sessionStorage.removeItem(CHECKPOINT_PREFIX + threadId);
3774
+ sessionStorage.removeItem(THREAD_KEY);
3775
+ }
3776
+ /** Parse a stored JSON value, returning `null` when absent or corrupt. */
3777
+ #readJson(key) {
3778
+ const raw = sessionStorage.getItem(key);
3779
+ if (raw === null) {
3780
+ return null;
3781
+ }
3782
+ try {
3783
+ return JSON.parse(raw);
3784
+ } catch {
3785
+ return null;
3786
+ }
731
3787
  }
732
3788
  };
733
3789
 
734
- // src/ag_ui_chat.ts
3790
+ // src/core/create_http_agent.ts
3791
+ import { HttpAgent } from "@ag-ui/client";
3792
+ function createHttpAgent(options) {
3793
+ return new HttpAgent({
3794
+ url: options.endpoint,
3795
+ headers: options.headers ?? {},
3796
+ // HttpAgent invokes its configured fetch as a method (`this.fetch(...)`),
3797
+ // which would rebind the global `fetch` to the agent instance and trigger
3798
+ // "Illegal invocation" in browsers. Wrap it so `fetch` is always called as
3799
+ // a free function with the correct receiver.
3800
+ fetch: (url, init) => fetch(url, init),
3801
+ // Spread conditionally: under `exactOptionalPropertyTypes` an explicit
3802
+ // `undefined` is not assignable to these optional config fields.
3803
+ ...options.threadId !== void 0 ? { threadId: options.threadId } : {},
3804
+ ...options.initialMessages !== void 0 ? { initialMessages: [...options.initialMessages] } : {}
3805
+ });
3806
+ }
3807
+
3808
+ // src/core/ag_ui_chat.ts
3809
+ var COLLAPSED_KEY = "ag-ui-chat:collapsed";
735
3810
  var AgUiChat = class extends HTMLElement {
736
3811
  /** Agent factory; override to inject a custom or fake agent (tests). */
737
3812
  agentFactory = createHttpAgent;
@@ -739,6 +3814,14 @@ var AgUiChat = class extends HTMLElement {
739
3814
  headers = {};
740
3815
  /** When true, destructive tools execute without a confirmation modal. */
741
3816
  autoConfirm = false;
3817
+ /**
3818
+ * Optional per-call confirmation predicate. When set, it is authoritative:
3819
+ * given a tool name + args it decides whether *this* call needs confirmation
3820
+ * (so one tool can be instant for some args and confirmed for others — what a
3821
+ * static `x-destructive` flag can't express). When unset, the `x-destructive`
3822
+ * schema flag is used. `autoConfirm` short-circuits both.
3823
+ */
3824
+ confirmPredicate = null;
742
3825
  /**
743
3826
  * Per-run frontend tool catalog provider. Defaults to the built-in
744
3827
  * `route.*` tools (when a {@link routeMap} is set) plus the tools registered
@@ -746,7 +3829,7 @@ var AgUiChat = class extends HTMLElement {
746
3829
  * fully custom catalog.
747
3830
  */
748
3831
  getTools = () => [
749
- ...this.#routeTools().map((t) => ({
3832
+ ...this.#builtinTools().map((t) => ({
750
3833
  name: t.name,
751
3834
  description: t.description,
752
3835
  parameters: t.parameters
@@ -788,6 +3871,12 @@ var AgUiChat = class extends HTMLElement {
788
3871
  navigated: true,
789
3872
  url: window.location.href
790
3873
  });
3874
+ /**
3875
+ * Named values used to fill a skill prompt's `{placeholder}`s before send
3876
+ * (e.g. `{ model: "Order", selected_ids: "1,2" }`). A host (the admin) sets
3877
+ * this from the current page; a missing placeholder blocks the send.
3878
+ */
3879
+ skillContext = () => ({});
791
3880
  #toolRegistry = new ClientToolRegistry();
792
3881
  /** Tool-call cards awaiting execution, keyed by call id. */
793
3882
  #toolCards = /* @__PURE__ */ new Map();
@@ -796,10 +3885,18 @@ var AgUiChat = class extends HTMLElement {
796
3885
  #messages;
797
3886
  #input;
798
3887
  #send;
3888
+ #title;
3889
+ #skillsMenu;
3890
+ #skillHint;
799
3891
  #client = null;
800
3892
  #streamingBubble = null;
3893
+ #pending = null;
801
3894
  #threadId = "";
802
3895
  #initialMessages = [];
3896
+ // Skill catalog by source; merged backend → embed → client (later wins).
3897
+ #backendSkills = [];
3898
+ #embedSkills = [];
3899
+ #clientSkills = [];
803
3900
  constructor() {
804
3901
  super();
805
3902
  this.#root = this.attachShadow({ mode: "open" });
@@ -807,6 +3904,16 @@ var AgUiChat = class extends HTMLElement {
807
3904
  this.#messages = document.createElement("div");
808
3905
  this.#input = document.createElement("textarea");
809
3906
  this.#send = document.createElement("button");
3907
+ this.#title = document.createElement("span");
3908
+ this.#skillHint = document.createElement("div");
3909
+ this.#skillsMenu = new SkillsMenu((skill) => this.#applySkill(skill));
3910
+ }
3911
+ /** Attributes whose late changes must reflect in already-rendered chrome. */
3912
+ static get observedAttributes() {
3913
+ return ["title-text"];
3914
+ }
3915
+ attributeChangedCallback(_name, _previous, value) {
3916
+ this.#title.textContent = value ?? "Assistant";
810
3917
  }
811
3918
  /** Declare a frontend tool the agent may call. */
812
3919
  registerTool(tool) {
@@ -828,11 +3935,34 @@ var AgUiChat = class extends HTMLElement {
828
3935
  () => this.navigate
829
3936
  );
830
3937
  }
831
- /** Resolve a tool by name: built-in route tools first, then the registry. */
3938
+ /**
3939
+ * The built-in `read_page` tool, present only when a {@link getPageMap}
3940
+ * provider is set. A *pull* the agent can call mid-turn to see the page after
3941
+ * it has acted (the auto-injected context is a send-time snapshot).
3942
+ */
3943
+ #pageTools() {
3944
+ const getPageMap = this.getPageMap;
3945
+ if (getPageMap === null) {
3946
+ return [];
3947
+ }
3948
+ return [
3949
+ {
3950
+ name: "read_page",
3951
+ description: "Read the current page's structure (fields, buttons, route). Call after acting to observe the result within the same turn.",
3952
+ parameters: { type: "object", properties: {}, required: [] },
3953
+ handler: () => getPageMap()
3954
+ }
3955
+ ];
3956
+ }
3957
+ /** All built-in (route + page) frontend tools. */
3958
+ #builtinTools() {
3959
+ return [...this.#routeTools(), ...this.#pageTools()];
3960
+ }
3961
+ /** Resolve a tool by name: built-in tools first, then the registry. */
832
3962
  #resolveTool(name) {
833
- const route = this.#routeTools().find((t) => t.name === name);
834
- if (route !== void 0) {
835
- return route;
3963
+ const builtin = this.#builtinTools().find((t) => t.name === name);
3964
+ if (builtin !== void 0) {
3965
+ return builtin;
836
3966
  }
837
3967
  return this.#toolRegistry.has(name) ? this.#toolRegistry.get(name) : null;
838
3968
  }
@@ -840,11 +3970,148 @@ var AgUiChat = class extends HTMLElement {
840
3970
  get endpoint() {
841
3971
  return this.getAttribute("endpoint") ?? "";
842
3972
  }
3973
+ // Reflecting setter so frameworks (e.g. React 19) that assign matching
3974
+ // props as element *properties* don't hit a read-only property. Read at
3975
+ // use-time, so a runtime change applies to the next run.
3976
+ set endpoint(value) {
3977
+ this.setAttribute("endpoint", value);
3978
+ }
3979
+ /**
3980
+ * How much detail tool-call cards show, from the `data-tool-display`
3981
+ * attribute (`minimal` / `compact` / `full`). Defaults to `full`.
3982
+ */
3983
+ get toolDisplay() {
3984
+ const attr = this.getAttribute("data-tool-display");
3985
+ if (attr === TOOL_DISPLAY.MINIMAL || attr === TOOL_DISPLAY.COMPACT) {
3986
+ return attr;
3987
+ }
3988
+ return TOOL_DISPLAY.FULL;
3989
+ }
3990
+ set toolDisplay(value) {
3991
+ this.setAttribute("data-tool-display", value);
3992
+ }
843
3993
  connectedCallback() {
844
3994
  this.#render();
3995
+ if (sessionStorage.getItem(COLLAPSED_KEY) === "1") {
3996
+ this.setAttribute("collapsed", "");
3997
+ }
3998
+ this.#initSkills();
845
3999
  this.#threadId = this.conversationStore.threadId();
846
4000
  void this.#rehydrate();
847
4001
  }
4002
+ /**
4003
+ * Replace the host-supplied (client) skill catalog. Merged after the embedded
4004
+ * and fetched skills (so a client skill overrides a same-named server one).
4005
+ */
4006
+ setSkills(skills) {
4007
+ this.#clientSkills = skills;
4008
+ this.#recomputeSkills();
4009
+ }
4010
+ /** Wire the skill surfaces: opt-in flags, embedded catalog, optional fetch. */
4011
+ #initSkills() {
4012
+ this.#skillsMenu.enableChips(this.getAttribute("data-prompt-chips") === "true");
4013
+ this.#skillsMenu.enableSlash(this.getAttribute("data-slash-commands") === "true");
4014
+ this.#embedSkills = this.#readEmbeddedSkills();
4015
+ this.#recomputeSkills();
4016
+ void this.#fetchSkills();
4017
+ }
4018
+ /** Parse the inline `data-skills` JSON catalog (empty when absent/malformed). */
4019
+ #readEmbeddedSkills() {
4020
+ const raw = this.getAttribute("data-skills");
4021
+ if (raw === null) {
4022
+ return [];
4023
+ }
4024
+ try {
4025
+ return parseSkills(JSON.parse(raw));
4026
+ } catch {
4027
+ return [];
4028
+ }
4029
+ }
4030
+ /** Fetch the backend skills catalog from `data-skills-url`, if set. */
4031
+ async #fetchSkills() {
4032
+ const url = this.getAttribute("data-skills-url");
4033
+ if (url === null) {
4034
+ return;
4035
+ }
4036
+ try {
4037
+ const response = await fetch(url, { headers: this.headers });
4038
+ this.#backendSkills = parseSkills(await response.json());
4039
+ this.#recomputeSkills();
4040
+ } catch {
4041
+ }
4042
+ }
4043
+ /** Merge the three sources (backend → embed → client; later wins by name). */
4044
+ #recomputeSkills() {
4045
+ const merged = /* @__PURE__ */ new Map();
4046
+ for (const skill of [...this.#backendSkills, ...this.#embedSkills, ...this.#clientSkills]) {
4047
+ merged.set(skill.name, skill);
4048
+ }
4049
+ this.#skillsMenu.setSkills([...merged.values()]);
4050
+ }
4051
+ /** Pre-fill (or send) a picked skill's prompt, filling its placeholders. */
4052
+ #applySkill(skill) {
4053
+ const { text: text2, missing } = fillTemplate(skill.prompt, this.skillContext());
4054
+ if (missing.length > 0) {
4055
+ this.#skillHint.textContent = `\u201C${skill.title}\u201D needs: ${missing.join(", ")}`;
4056
+ this.#skillHint.hidden = false;
4057
+ return;
4058
+ }
4059
+ this.#skillHint.hidden = true;
4060
+ this.#input.value = text2;
4061
+ if (skill.sendImmediately === true) {
4062
+ void this.#submit();
4063
+ } else {
4064
+ this.#input.focus();
4065
+ }
4066
+ }
4067
+ /** Whether the widget is collapsed (reflected as the `collapsed` attribute). */
4068
+ get collapsed() {
4069
+ return this.hasAttribute("collapsed");
4070
+ }
4071
+ // Property setter (framework interop) — delegates to setCollapsed so a
4072
+ // `collapsed` prop assignment persists + emits the toggle event.
4073
+ set collapsed(value) {
4074
+ this.setCollapsed(value);
4075
+ }
4076
+ /**
4077
+ * Set the collapsed state: reflect the `collapsed` attribute, persist it
4078
+ * per-tab, and emit a {@link TOGGLE_EVENT} so a host can mirror the state in
4079
+ * its own chrome.
4080
+ */
4081
+ setCollapsed(collapsed) {
4082
+ if (collapsed) {
4083
+ this.setAttribute("collapsed", "");
4084
+ } else {
4085
+ this.removeAttribute("collapsed");
4086
+ }
4087
+ sessionStorage.setItem(COLLAPSED_KEY, collapsed ? "1" : "0");
4088
+ this.dispatchEvent(
4089
+ new CustomEvent(TOGGLE_EVENT, {
4090
+ detail: { collapsed },
4091
+ bubbles: true,
4092
+ composed: true
4093
+ })
4094
+ );
4095
+ }
4096
+ /** Flip the collapsed state. Bound to the built-in header toggle. */
4097
+ toggleCollapsed() {
4098
+ this.setCollapsed(!this.collapsed);
4099
+ }
4100
+ /**
4101
+ * Start a fresh conversation: forget the persisted history, drop the
4102
+ * in-memory run state, clear the transcript, and mint a new thread id.
4103
+ */
4104
+ newChat() {
4105
+ this.conversationStore.clear(this.#threadId);
4106
+ this.#client = null;
4107
+ this.#streamingBubble = null;
4108
+ this.#hidePending();
4109
+ this.#toolCards.clear();
4110
+ this.#initialMessages = [];
4111
+ this.#messages.replaceChildren();
4112
+ this.#threadId = this.conversationStore.threadId();
4113
+ this.#send.disabled = false;
4114
+ }
848
4115
  /**
849
4116
  * Restore the conversation from the store on mount, then — if a navigating
850
4117
  * tool reloaded the page mid-run — resume the loop by supplying that tool's
@@ -871,7 +4138,16 @@ var AgUiChat = class extends HTMLElement {
871
4138
  if (message.role === MESSAGE_ROLE.USER) {
872
4139
  this.appendMessage(MESSAGE_ROLE.USER, message.content);
873
4140
  } else if (message.role === MESSAGE_ROLE.ASSISTANT) {
874
- this.appendMessage(MESSAGE_ROLE.ASSISTANT, message.content);
4141
+ this.#revealWords(this.appendMessage(MESSAGE_ROLE.ASSISTANT, message.content));
4142
+ }
4143
+ }
4144
+ /**
4145
+ * Word-by-word reveal for the `word` text-animation mode, applied to a
4146
+ * completed assistant bubble. `fade` is pure CSS (no JS); `none` is a no-op.
4147
+ */
4148
+ #revealWords(bubble) {
4149
+ if (this.getAttribute("data-text-animation") === "word") {
4150
+ wrapWords(bubble);
875
4151
  }
876
4152
  }
877
4153
  /** Complete the checkpointed navigating tool call and continue the run. */
@@ -881,11 +4157,21 @@ var AgUiChat = class extends HTMLElement {
881
4157
  client.addToolResult(checkpoint.toolCallId, JSON.stringify(this.navigationResult(checkpoint)));
882
4158
  await client.resume();
883
4159
  }
884
- /** Append a message bubble and return it. */
4160
+ /**
4161
+ * Append a message bubble and return it.
4162
+ *
4163
+ * Assistant content is rendered as sanitised markdown/HTML; user content
4164
+ * stays literal text (no need to parse what the user typed, and it avoids
4165
+ * rendering user-authored markup).
4166
+ */
885
4167
  appendMessage(role, content) {
886
4168
  const bubble = document.createElement("div");
887
4169
  bubble.className = `message message--${role}`;
888
- bubble.textContent = content;
4170
+ if (role === MESSAGE_ROLE.ASSISTANT) {
4171
+ bubble.innerHTML = renderMarkdown(content);
4172
+ } else {
4173
+ bubble.textContent = content;
4174
+ }
889
4175
  this.#messages.appendChild(bubble);
890
4176
  this.#messages.scrollTop = this.#messages.scrollHeight;
891
4177
  return bubble;
@@ -896,25 +4182,68 @@ var AgUiChat = class extends HTMLElement {
896
4182
  this.#chat.className = "chat";
897
4183
  const header = document.createElement("div");
898
4184
  header.className = "header";
899
- header.textContent = this.getAttribute("title-text") ?? "Assistant";
4185
+ const title = this.#title;
4186
+ title.className = "header-title";
4187
+ title.textContent = this.getAttribute("title-text") ?? "Assistant";
4188
+ const controls = document.createElement("div");
4189
+ controls.className = "header-controls";
4190
+ const newChat = document.createElement("button");
4191
+ newChat.type = "button";
4192
+ newChat.className = "header-btn header-btn--new";
4193
+ newChat.title = "New chat";
4194
+ newChat.setAttribute("aria-label", "New chat");
4195
+ newChat.textContent = "\u271A";
4196
+ newChat.addEventListener("click", () => this.newChat());
4197
+ const collapse = document.createElement("button");
4198
+ collapse.type = "button";
4199
+ collapse.className = "header-btn header-btn--collapse";
4200
+ collapse.title = "Collapse";
4201
+ collapse.setAttribute("aria-label", "Collapse");
4202
+ collapse.textContent = "\u2014";
4203
+ collapse.addEventListener("click", () => this.toggleCollapsed());
4204
+ controls.append(newChat, collapse);
4205
+ header.append(title, controls);
900
4206
  this.#messages.className = "messages";
4207
+ this.#messages.setAttribute("role", "log");
4208
+ this.#messages.setAttribute("aria-live", "polite");
4209
+ this.#messages.setAttribute("aria-label", "Conversation");
901
4210
  const inputRow = document.createElement("div");
902
4211
  inputRow.className = "input-row";
903
4212
  this.#input.className = "input";
4213
+ this.#input.setAttribute("aria-label", "Message");
904
4214
  this.#input.rows = 2;
905
4215
  this.#input.placeholder = "Ask anything\u2026";
906
4216
  this.#input.addEventListener("keydown", (event) => this.#onKeydown(event));
4217
+ this.#input.addEventListener("input", () => this.#onInput());
907
4218
  this.#send.className = "send";
908
4219
  this.#send.type = "button";
909
4220
  this.#send.textContent = "Send";
910
4221
  this.#send.addEventListener("click", () => {
911
4222
  void this.#submit();
912
4223
  });
4224
+ this.#skillHint.className = "skill-hint";
4225
+ this.#skillHint.hidden = true;
913
4226
  inputRow.append(this.#input, this.#send);
914
- this.#chat.append(header, this.#messages, inputRow);
4227
+ this.#chat.append(
4228
+ header,
4229
+ this.#messages,
4230
+ this.#skillsMenu.palette,
4231
+ this.#skillsMenu.chips,
4232
+ this.#skillHint,
4233
+ inputRow
4234
+ );
915
4235
  this.#root.append(style, this.#chat);
916
4236
  }
4237
+ /** Forward input changes to the skills palette and clear any stale hint. */
4238
+ #onInput() {
4239
+ this.#skillsMenu.onInput(this.#input.value);
4240
+ this.#skillHint.hidden = true;
4241
+ }
917
4242
  #onKeydown(event) {
4243
+ if (this.#skillsMenu.onKeydown(event)) {
4244
+ event.preventDefault();
4245
+ return;
4246
+ }
918
4247
  if (event.key === "Enter" && !event.shiftKey) {
919
4248
  event.preventDefault();
920
4249
  void this.#submit();
@@ -961,22 +4290,38 @@ var AgUiChat = class extends HTMLElement {
961
4290
  }
962
4291
  return this.#client;
963
4292
  }
4293
+ /** Whether ``call`` should be gated behind the confirmation card. */
4294
+ async #needsConfirmation(call, tool) {
4295
+ if (this.autoConfirm) {
4296
+ return false;
4297
+ }
4298
+ if (this.confirmPredicate !== null) {
4299
+ return await this.confirmPredicate(call.name, call.args) === true;
4300
+ }
4301
+ return isDestructive(tool.parameters);
4302
+ }
964
4303
  async #executeTool(call) {
965
4304
  const card = this.#cardFor(call);
966
4305
  this.#toolCards.delete(call.id);
967
4306
  const tool = this.#resolveTool(call.name);
968
4307
  if (tool === null) {
969
4308
  card.settle(TOOL_CALL_STATUS.DONE, "Executed on the server.");
4309
+ this.#showPending();
970
4310
  return null;
971
4311
  }
972
- if (isDestructive(tool.parameters) && !this.autoConfirm) {
973
- const accepted = await requestConfirmation(this.#chat, {
974
- toolName: call.name,
975
- args: call.args
976
- });
4312
+ if (await this.#needsConfirmation(call, tool)) {
4313
+ const request = { toolName: call.name, args: call.args };
4314
+ const confirmText = tool.parameters[X_CONFIRM_KEY];
4315
+ if (typeof confirmText === "string") {
4316
+ request.message = confirmText;
4317
+ }
4318
+ const decision = requestConfirmation(this.#messages, request);
4319
+ this.#messages.scrollTop = this.#messages.scrollHeight;
4320
+ const accepted = await decision;
977
4321
  if (!accepted) {
978
4322
  const message = "User declined the action.";
979
4323
  card.settle(TOOL_CALL_STATUS.DECLINED, message);
4324
+ this.#showPending();
980
4325
  return { content: message };
981
4326
  }
982
4327
  }
@@ -992,6 +4337,7 @@ var AgUiChat = class extends HTMLElement {
992
4337
  }
993
4338
  const content = JSON.stringify(result ?? null);
994
4339
  card.settle(TOOL_CALL_STATUS.DONE, content);
4340
+ this.#showPending();
995
4341
  return { content };
996
4342
  } catch (error) {
997
4343
  if (navigates) {
@@ -999,6 +4345,7 @@ var AgUiChat = class extends HTMLElement {
999
4345
  }
1000
4346
  const message = error instanceof Error ? error.message : String(error);
1001
4347
  card.settle(TOOL_CALL_STATUS.ERROR, message);
4348
+ this.#showPending();
1002
4349
  return { content: `Error: ${message}`, error: message };
1003
4350
  }
1004
4351
  }
@@ -1006,34 +4353,67 @@ var AgUiChat = class extends HTMLElement {
1006
4353
  return {
1007
4354
  onRunStart: () => {
1008
4355
  this.#send.disabled = true;
4356
+ this.#showPending();
1009
4357
  },
1010
4358
  onTextDelta: (buffer) => {
4359
+ this.#hidePending();
1011
4360
  this.#streamInto(buffer);
1012
4361
  },
1013
4362
  onTextEnd: (buffer) => {
1014
- this.#streamInto(buffer);
4363
+ this.#revealWords(this.#streamInto(buffer));
1015
4364
  this.#streamingBubble = null;
1016
4365
  },
1017
4366
  onToolCall: (call) => {
4367
+ this.#hidePending();
1018
4368
  this.#cardFor(call);
1019
4369
  },
1020
4370
  onRunEnd: () => {
4371
+ this.#hidePending();
1021
4372
  this.#send.disabled = false;
1022
4373
  this.#streamingBubble = null;
1023
4374
  },
1024
4375
  onError: (message) => {
1025
- this.appendMessage(MESSAGE_ROLE.ASSISTANT, `\u26A0\uFE0F ${message}`);
4376
+ this.#hidePending();
4377
+ this.#revealWords(this.appendMessage(MESSAGE_ROLE.ASSISTANT, `\u26A0\uFE0F ${message}`));
1026
4378
  this.#send.disabled = false;
1027
4379
  this.#streamingBubble = null;
1028
4380
  }
1029
4381
  };
1030
4382
  }
4383
+ /**
4384
+ * Show a "thinking" indicator while the agent is being awaited — both the
4385
+ * silent stretch before the first token and the gap after a tool result
4386
+ * while the next round is requested. Idempotent.
4387
+ */
4388
+ #showPending() {
4389
+ if (this.#pending !== null) {
4390
+ return;
4391
+ }
4392
+ const pending = document.createElement("div");
4393
+ pending.className = "pending";
4394
+ pending.setAttribute("role", "status");
4395
+ pending.setAttribute("aria-label", "Assistant is thinking\u2026");
4396
+ for (let i = 0; i < 3; i += 1) {
4397
+ const dot = document.createElement("span");
4398
+ dot.className = "pending-dot";
4399
+ pending.appendChild(dot);
4400
+ }
4401
+ this.#pending = pending;
4402
+ this.#messages.appendChild(pending);
4403
+ this.#messages.scrollTop = this.#messages.scrollHeight;
4404
+ }
4405
+ /** Remove the pending indicator if shown. */
4406
+ #hidePending() {
4407
+ this.#pending?.remove();
4408
+ this.#pending = null;
4409
+ }
1031
4410
  #streamInto(buffer) {
1032
4411
  if (this.#streamingBubble === null) {
1033
4412
  this.#streamingBubble = this.appendMessage(MESSAGE_ROLE.ASSISTANT, "");
1034
4413
  }
1035
- this.#streamingBubble.textContent = buffer;
4414
+ this.#streamingBubble.innerHTML = renderMarkdown(buffer);
1036
4415
  this.#messages.scrollTop = this.#messages.scrollHeight;
4416
+ return this.#streamingBubble;
1037
4417
  }
1038
4418
  /**
1039
4419
  * The card for ``call``, creating and appending it on first sight.
@@ -1046,7 +4426,13 @@ var AgUiChat = class extends HTMLElement {
1046
4426
  if (existing !== void 0) {
1047
4427
  return existing;
1048
4428
  }
1049
- const card = new ToolCallCard(call.name, call.args);
4429
+ const summary = this.#resolveTool(call.name)?.parameters[X_SUMMARY_KEY];
4430
+ const card = new ToolCallCard(
4431
+ call.name,
4432
+ call.args,
4433
+ this.toolDisplay,
4434
+ typeof summary === "string" ? summary : void 0
4435
+ );
1050
4436
  this.#toolCards.set(call.id, card);
1051
4437
  this.#messages.appendChild(card.element);
1052
4438
  this.#messages.scrollTop = this.#messages.scrollHeight;
@@ -1054,7 +4440,36 @@ var AgUiChat = class extends HTMLElement {
1054
4440
  }
1055
4441
  };
1056
4442
 
1057
- // src/animations.ts
4443
+ // src/core/define_ag_ui_chat.ts
4444
+ function defineAgUiChat() {
4445
+ if (customElements.get(ELEMENT_TAG) === void 0) {
4446
+ customElements.define(ELEMENT_TAG, AgUiChat);
4447
+ }
4448
+ }
4449
+
4450
+ // src/dom/native_setter.ts
4451
+ function prototypeSetter(proto, prop) {
4452
+ const setter = Object.getOwnPropertyDescriptor(proto, prop).set;
4453
+ return setter;
4454
+ }
4455
+ var setInputValue = prototypeSetter(HTMLInputElement.prototype, "value");
4456
+ var setTextareaValue = prototypeSetter(HTMLTextAreaElement.prototype, "value");
4457
+ var setSelectValue = prototypeSetter(HTMLSelectElement.prototype, "value");
4458
+ var setInputChecked = prototypeSetter(HTMLInputElement.prototype, "checked");
4459
+ function setNativeValue(el, value) {
4460
+ if (el instanceof HTMLTextAreaElement) {
4461
+ setTextareaValue.call(el, value);
4462
+ } else if (el instanceof HTMLSelectElement) {
4463
+ setSelectValue.call(el, value);
4464
+ } else {
4465
+ setInputValue.call(el, value);
4466
+ }
4467
+ }
4468
+ function setNativeChecked(el, checked) {
4469
+ setInputChecked.call(el, checked);
4470
+ }
4471
+
4472
+ // src/dom/animations.ts
1058
4473
  var ACCENT = "#4f46e5";
1059
4474
  function delay(ms) {
1060
4475
  return new Promise((resolve) => {
@@ -1063,10 +4478,10 @@ function delay(ms) {
1063
4478
  }
1064
4479
  async function typeInto(el, value, options = {}) {
1065
4480
  const charDelayMs = options.charDelayMs ?? 35;
1066
- el.value = "";
4481
+ setNativeValue(el, "");
1067
4482
  el.dispatchEvent(new Event("input", { bubbles: true }));
1068
4483
  for (const char of value) {
1069
- el.value += char;
4484
+ setNativeValue(el, el.value + char);
1070
4485
  el.dispatchEvent(new Event("input", { bubbles: true }));
1071
4486
  if (charDelayMs > 0) {
1072
4487
  await delay(charDelayMs);
@@ -1096,15 +4511,67 @@ async function focusWithFlash(el, options = {}) {
1096
4511
  await delay(flashMs);
1097
4512
  el.style.boxShadow = previousShadow;
1098
4513
  }
1099
-
1100
- // src/define_ag_ui_chat.ts
1101
- function defineAgUiChat() {
1102
- if (customElements.get(ELEMENT_TAG) === void 0) {
1103
- customElements.define(ELEMENT_TAG, AgUiChat);
4514
+ var RING = "0 0 0 3px rgba(79, 70, 229, 0.4)";
4515
+ function prefersReducedMotion() {
4516
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
4517
+ }
4518
+ function motionDelay(ms) {
4519
+ if (ms <= 0 || prefersReducedMotion()) {
4520
+ return Promise.resolve();
4521
+ }
4522
+ return delay(ms);
4523
+ }
4524
+ async function pressThenClick(el, options = {}) {
4525
+ const pressMs = options.pressMs ?? 140;
4526
+ const previousTransform = el.style.transform;
4527
+ const previousTransition = el.style.transition;
4528
+ const previousShadow = el.style.boxShadow;
4529
+ el.style.transition = "transform 80ms ease";
4530
+ el.style.transform = "scale(0.96)";
4531
+ el.style.boxShadow = RING;
4532
+ await motionDelay(pressMs);
4533
+ el.style.transform = previousTransform;
4534
+ el.style.transition = previousTransition;
4535
+ el.style.boxShadow = previousShadow;
4536
+ el.click();
4537
+ }
4538
+ function findOption(el, value) {
4539
+ for (const option of Array.from(el.options)) {
4540
+ if (option.value === value || option.text === value) {
4541
+ return option;
4542
+ }
4543
+ }
4544
+ return null;
4545
+ }
4546
+ async function selectOption(el, value, options = {}) {
4547
+ const option = findOption(el, value);
4548
+ if (option === null) {
4549
+ throw new Error(`no <option> matching "${value}"`);
1104
4550
  }
4551
+ const highlightMs = options.highlightMs ?? 220;
4552
+ const previousOutline = el.style.outline;
4553
+ const previousOffset = el.style.outlineOffset;
4554
+ el.style.outline = `2px solid ${ACCENT}`;
4555
+ el.style.outlineOffset = "2px";
4556
+ await motionDelay(highlightMs);
4557
+ setNativeValue(el, option.value);
4558
+ el.dispatchEvent(new Event("input", { bubbles: true }));
4559
+ el.dispatchEvent(new Event("change", { bubbles: true }));
4560
+ el.style.outline = previousOutline;
4561
+ el.style.outlineOffset = previousOffset;
4562
+ }
4563
+ async function toggleControl(el, checked, options = {}) {
4564
+ const flashMs = options.flashMs ?? 200;
4565
+ const previousShadow = el.style.boxShadow;
4566
+ el.style.boxShadow = RING;
4567
+ await motionDelay(flashMs);
4568
+ setNativeChecked(el, checked);
4569
+ el.dispatchEvent(new Event("input", { bubbles: true }));
4570
+ el.dispatchEvent(new Event("change", { bubbles: true }));
4571
+ el.style.boxShadow = previousShadow;
1105
4572
  }
1106
4573
 
1107
- // src/dom_driver.ts
4574
+ // src/dom/dom_driver.ts
1108
4575
  async function fillField(el, value, options = {}) {
1109
4576
  scrollIntoCenterView(el);
1110
4577
  await focusWithFlash(el, { flashMs: options.flashMs ?? 0 });
@@ -1114,18 +4581,30 @@ async function clickElement(el, options = {}) {
1114
4581
  scrollIntoCenterView(el);
1115
4582
  await highlightThenClick(el, options);
1116
4583
  }
4584
+ async function pressButton(el, options = {}) {
4585
+ scrollIntoCenterView(el);
4586
+ await pressThenClick(el, options);
4587
+ }
4588
+ async function selectControl(el, value, options = {}) {
4589
+ scrollIntoCenterView(el);
4590
+ await selectOption(el, value, options);
4591
+ }
4592
+ async function toggleCheckbox(el, checked, options = {}) {
4593
+ scrollIntoCenterView(el);
4594
+ await toggleControl(el, checked, options);
4595
+ }
1117
4596
  function setControlValue(el, value) {
1118
4597
  if (el instanceof HTMLInputElement && el.type === "checkbox") {
1119
- el.checked = Boolean(value);
4598
+ setNativeChecked(el, Boolean(value));
1120
4599
  } else {
1121
- el.value = String(value);
4600
+ setNativeValue(el, String(value));
1122
4601
  }
1123
4602
  el.dispatchEvent(new Event("input", { bubbles: true }));
1124
4603
  el.dispatchEvent(new Event("change", { bubbles: true }));
1125
4604
  }
1126
4605
 
1127
4606
  // src/version.ts
1128
- var VERSION = "0.1.1";
4607
+ var VERSION = "0.2.0";
1129
4608
  export {
1130
4609
  AgUiChat,
1131
4610
  AgUiClient,
@@ -1135,11 +4614,15 @@ export {
1135
4614
  MESSAGE_ROLE,
1136
4615
  SUBMIT_EVENT,
1137
4616
  SessionStorageStore,
4617
+ TOGGLE_EVENT,
1138
4618
  TOOL_CALL_STATUS,
4619
+ TOOL_DISPLAY,
1139
4620
  ToolCallCard,
1140
4621
  VERSION,
4622
+ X_CONFIRM_KEY,
1141
4623
  X_DESTRUCTIVE_KEY,
1142
4624
  X_NAVIGATES_KEY,
4625
+ X_SUMMARY_KEY,
1143
4626
  clickElement,
1144
4627
  createHttpAgent,
1145
4628
  createPageMapContext,
@@ -1151,9 +4634,24 @@ export {
1151
4634
  highlightThenClick,
1152
4635
  isDestructive,
1153
4636
  isNavigates,
4637
+ prefersReducedMotion,
4638
+ pressButton,
4639
+ pressThenClick,
4640
+ renderMarkdown,
1154
4641
  requestConfirmation,
1155
4642
  scrollIntoCenterView,
4643
+ selectControl,
4644
+ selectOption,
1156
4645
  setControlValue,
4646
+ setNativeChecked,
4647
+ setNativeValue,
4648
+ toggleCheckbox,
4649
+ toggleControl,
1157
4650
  typeInto
1158
4651
  };
4652
+ /*! Bundled license information:
4653
+
4654
+ dompurify/dist/purify.es.mjs:
4655
+ (*! @license DOMPurify 3.4.7 | (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.7/LICENSE *)
4656
+ */
1159
4657
  //# sourceMappingURL=index.js.map