@artooi/ag-ui-web-component 0.1.0 → 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.
- package/CHANGELOG.md +102 -2
- package/README.md +235 -47
- package/dist/ag-ui-web-component.bundle.js +451 -46
- package/dist/ag-ui-web-component.bundle.js.map +4 -4
- package/dist/constants.d.ts +34 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/{ag_ui_chat.d.ts → core/ag_ui_chat.d.ts} +63 -6
- package/dist/core/ag_ui_chat.d.ts.map +1 -0
- package/dist/core/agui_client.d.ts.map +1 -0
- package/dist/core/conversation_store.d.ts.map +1 -0
- package/dist/core/create_http_agent.d.ts.map +1 -0
- package/dist/core/define_ag_ui_chat.d.ts.map +1 -0
- package/dist/dom/animations.d.ts +71 -0
- package/dist/dom/animations.d.ts.map +1 -0
- package/dist/{dom_driver.d.ts → dom/dom_driver.d.ts} +7 -1
- package/dist/dom/dom_driver.d.ts.map +1 -0
- package/dist/dom/native_setter.d.ts +5 -0
- package/dist/dom/native_setter.d.ts.map +1 -0
- package/dist/index.d.ts +19 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3886 -388
- package/dist/index.js.map +4 -4
- package/dist/skills/fill_template.d.ts +17 -0
- package/dist/skills/fill_template.d.ts.map +1 -0
- package/dist/skills/parse_skills.d.ts +8 -0
- package/dist/skills/parse_skills.d.ts.map +1 -0
- package/dist/skills/skill.d.ts +24 -0
- package/dist/skills/skill.d.ts.map +1 -0
- package/dist/{client_tool_registry.d.ts → tools/client_tool_registry.d.ts} +6 -1
- package/dist/tools/client_tool_registry.d.ts.map +1 -0
- package/dist/tools/is_destructive.d.ts.map +1 -0
- package/dist/tools/is_navigates.d.ts.map +1 -0
- package/dist/tools/page_map.d.ts.map +1 -0
- package/dist/tools/route_map.d.ts +40 -0
- package/dist/tools/route_map.d.ts.map +1 -0
- package/dist/tools/state_hook.d.ts.map +1 -0
- package/dist/ui/confirmation_card.d.ts +22 -0
- package/dist/ui/confirmation_card.d.ts.map +1 -0
- package/dist/ui/render_markdown.d.ts +13 -0
- package/dist/ui/render_markdown.d.ts.map +1 -0
- package/dist/ui/reveal_words.d.ts +8 -0
- package/dist/ui/reveal_words.d.ts.map +1 -0
- package/dist/ui/skills_menu.d.ts +35 -0
- package/dist/ui/skills_menu.d.ts.map +1 -0
- package/dist/ui/styles.d.ts +2 -0
- package/dist/ui/styles.d.ts.map +1 -0
- package/dist/ui/tool_call_card.d.ts +35 -0
- package/dist/ui/tool_call_card.d.ts.map +1 -0
- package/package.json +5 -3
- package/src/constants.ts +38 -0
- package/src/core/ag_ui_chat.ts +786 -0
- package/src/{agui_client.ts → core/agui_client.ts} +1 -1
- package/src/{define_ag_ui_chat.ts → core/define_ag_ui_chat.ts} +1 -1
- package/src/dom/animations.ts +201 -0
- package/src/{dom_driver.ts → dom/dom_driver.ts} +35 -2
- package/src/dom/native_setter.ts +42 -0
- package/src/index.ts +61 -32
- package/src/skills/fill_template.ts +32 -0
- package/src/skills/parse_skills.ts +26 -0
- package/src/skills/skill.ts +23 -0
- package/src/{client_tool_registry.ts → tools/client_tool_registry.ts} +6 -4
- package/src/{is_destructive.ts → tools/is_destructive.ts} +1 -1
- package/src/{is_navigates.ts → tools/is_navigates.ts} +1 -1
- package/src/tools/route_map.ts +140 -0
- package/src/{state_hook.ts → tools/state_hook.ts} +1 -1
- package/src/ui/confirmation_card.ts +71 -0
- package/src/ui/render_markdown.ts +68 -0
- package/src/ui/reveal_words.ts +41 -0
- package/src/ui/skills_menu.ts +171 -0
- package/src/ui/styles.ts +631 -0
- package/src/{tool_call_card.ts → ui/tool_call_card.ts} +50 -19
- package/src/version.ts +1 -1
- package/dist/ag_ui_chat.d.ts.map +0 -1
- package/dist/agui_client.d.ts.map +0 -1
- package/dist/animations.d.ts +0 -33
- package/dist/animations.d.ts.map +0 -1
- package/dist/client_tool_registry.d.ts.map +0 -1
- package/dist/confirmation_modal.d.ts +0 -14
- package/dist/confirmation_modal.d.ts.map +0 -1
- package/dist/conversation_store.d.ts.map +0 -1
- package/dist/create_http_agent.d.ts.map +0 -1
- package/dist/define_ag_ui_chat.d.ts.map +0 -1
- package/dist/dom_driver.d.ts.map +0 -1
- package/dist/is_destructive.d.ts.map +0 -1
- package/dist/is_navigates.d.ts.map +0 -1
- package/dist/page_map.d.ts.map +0 -1
- package/dist/route_map.d.ts +0 -27
- package/dist/route_map.d.ts.map +0 -1
- package/dist/state_hook.d.ts.map +0 -1
- package/dist/styles.d.ts +0 -2
- package/dist/styles.d.ts.map +0 -1
- package/dist/tool_call_card.d.ts +0 -29
- package/dist/tool_call_card.d.ts.map +0 -1
- package/src/ag_ui_chat.ts +0 -411
- package/src/animations.ts +0 -86
- package/src/confirmation_modal.ts +0 -69
- package/src/route_map.ts +0 -83
- package/src/styles.ts +0 -296
- /package/dist/{agui_client.d.ts → core/agui_client.d.ts} +0 -0
- /package/dist/{conversation_store.d.ts → core/conversation_store.d.ts} +0 -0
- /package/dist/{create_http_agent.d.ts → core/create_http_agent.d.ts} +0 -0
- /package/dist/{define_ag_ui_chat.d.ts → core/define_ag_ui_chat.d.ts} +0 -0
- /package/dist/{is_destructive.d.ts → tools/is_destructive.d.ts} +0 -0
- /package/dist/{is_navigates.d.ts → tools/is_navigates.d.ts} +0 -0
- /package/dist/{page_map.d.ts → tools/page_map.d.ts} +0 -0
- /package/dist/{state_hook.d.ts → tools/state_hook.d.ts} +0 -0
- /package/src/{conversation_store.ts → core/conversation_store.ts} +0 -0
- /package/src/{create_http_agent.ts → core/create_http_agent.ts} +0 -0
- /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/
|
|
22
|
-
var
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
/**
|
|
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/
|
|
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
|
-
|
|
308
|
-
|
|
309
|
-
|
|
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
|
|
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/
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
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
|
-
|
|
398
|
-
|
|
399
|
-
|
|
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 = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" };
|
|
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
|
-
|
|
446
|
-
|
|
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:
|
|
3132
|
+
padding: var(--ag-ui-pad);
|
|
456
3133
|
display: flex;
|
|
457
3134
|
flex-direction: column;
|
|
458
|
-
gap:
|
|
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
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
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
|
-
|
|
606
|
-
|
|
607
|
-
|
|
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
|
-
|
|
610
|
-
|
|
611
|
-
padding:
|
|
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
|
|
621
|
-
|
|
622
|
-
overflow: hidden;
|
|
3414
|
+
border: 1px solid var(--ag-ui-accent);
|
|
3415
|
+
border-radius: 10px;
|
|
623
3416
|
}
|
|
624
3417
|
|
|
625
|
-
.
|
|
626
|
-
|
|
627
|
-
|
|
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
|
-
.
|
|
632
|
-
|
|
3423
|
+
.confirm-body {
|
|
3424
|
+
font-weight: 600;
|
|
633
3425
|
}
|
|
634
3426
|
|
|
635
|
-
.
|
|
636
|
-
margin: 0
|
|
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
|
-
.
|
|
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
|
-
.
|
|
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
|
-
.
|
|
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
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
this
|
|
693
|
-
this
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
this.
|
|
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
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
this.#
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
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/
|
|
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.#
|
|
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
|
-
/**
|
|
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
|
|
834
|
-
if (
|
|
835
|
-
return
|
|
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
|
-
/**
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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 (
|
|
973
|
-
const
|
|
974
|
-
|
|
975
|
-
|
|
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
|
|
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.
|
|
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
|
|
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/
|
|
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
|
|
4481
|
+
setNativeValue(el, "");
|
|
1067
4482
|
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
1068
4483
|
for (const char of value) {
|
|
1069
|
-
el.value
|
|
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
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
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
|
|
4598
|
+
setNativeChecked(el, Boolean(value));
|
|
1120
4599
|
} else {
|
|
1121
|
-
el
|
|
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.
|
|
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
|