@oyehello/chat 0.1.1 → 0.3.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/README.md +18 -2
- package/dist/index.cjs +858 -121
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -3
- package/dist/index.d.ts +48 -3
- package/dist/index.global.js +3797 -182
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +854 -121
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
package/dist/index.global.js
CHANGED
|
@@ -139,18 +139,18 @@ var OyehelloChat = (function (exports) {
|
|
|
139
139
|
const emitMessages = () => emit({ type: "messages", messages: messages.slice() });
|
|
140
140
|
const onEvent = (ev) => {
|
|
141
141
|
if (ev.type === "token") {
|
|
142
|
-
let
|
|
143
|
-
if (!
|
|
144
|
-
|
|
145
|
-
messages.push(
|
|
146
|
-
streamingId =
|
|
142
|
+
let m2 = streamingId ? messages.find((x2) => x2.id === streamingId) : void 0;
|
|
143
|
+
if (!m2) {
|
|
144
|
+
m2 = { id: uid("m"), role: "assistant", text: "", streaming: true };
|
|
145
|
+
messages.push(m2);
|
|
146
|
+
streamingId = m2.id;
|
|
147
147
|
}
|
|
148
|
-
|
|
148
|
+
m2.text += ev.text;
|
|
149
149
|
emitMessages();
|
|
150
150
|
} else if (ev.type === "message") {
|
|
151
151
|
if (seenTurnIds.has(ev.turnId)) {
|
|
152
152
|
if (streamingId) {
|
|
153
|
-
const idx = messages.findIndex((
|
|
153
|
+
const idx = messages.findIndex((x2) => x2.id === streamingId);
|
|
154
154
|
if (idx !== -1) messages.splice(idx, 1);
|
|
155
155
|
streamingId = null;
|
|
156
156
|
emitMessages();
|
|
@@ -158,20 +158,20 @@ var OyehelloChat = (function (exports) {
|
|
|
158
158
|
return;
|
|
159
159
|
}
|
|
160
160
|
seenTurnIds.add(ev.turnId);
|
|
161
|
-
const
|
|
162
|
-
if (
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
161
|
+
const m2 = streamingId ? messages.find((x2) => x2.id === streamingId) : void 0;
|
|
162
|
+
if (m2) {
|
|
163
|
+
m2.text = ev.text || m2.text;
|
|
164
|
+
m2.streaming = false;
|
|
165
|
+
m2.turnId = ev.turnId;
|
|
166
166
|
} else {
|
|
167
167
|
messages.push({ id: uid("m"), role: "assistant", text: ev.text, streaming: false, turnId: ev.turnId });
|
|
168
168
|
}
|
|
169
169
|
streamingId = null;
|
|
170
170
|
emitMessages();
|
|
171
171
|
} else if (ev.type === "citations") {
|
|
172
|
-
const
|
|
173
|
-
if (
|
|
174
|
-
|
|
172
|
+
const m2 = messages.find((x2) => x2.turnId === ev.turnId);
|
|
173
|
+
if (m2) {
|
|
174
|
+
m2.sources = ev.sources;
|
|
175
175
|
emitMessages();
|
|
176
176
|
}
|
|
177
177
|
} else if (ev.type === "error") {
|
|
@@ -196,9 +196,9 @@ var OyehelloChat = (function (exports) {
|
|
|
196
196
|
})();
|
|
197
197
|
} else if (ev.type === "attachment") {
|
|
198
198
|
const items = ev.items;
|
|
199
|
-
const alreadyRendered = messages.some((
|
|
199
|
+
const alreadyRendered = messages.some((m2) => m2.attachments?.some((a) => items.some((i) => i.storageRef === a.storageRef)));
|
|
200
200
|
if (alreadyRendered) return;
|
|
201
|
-
const target = [...messages].reverse().find((
|
|
201
|
+
const target = [...messages].reverse().find((m2) => m2.role === "user" && !m2.attachments);
|
|
202
202
|
if (target) target.attachments = items;
|
|
203
203
|
else messages.push({ id: uid("u"), role: "user", text: "", streaming: false, attachments: items });
|
|
204
204
|
emitMessages();
|
|
@@ -282,7 +282,10 @@ var OyehelloChat = (function (exports) {
|
|
|
282
282
|
return getAttachmentUrl({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, storageRef, fetchImpl });
|
|
283
283
|
},
|
|
284
284
|
async start() {
|
|
285
|
-
if (state
|
|
285
|
+
if (state === "opening" || state === "ready") return;
|
|
286
|
+
closed = false;
|
|
287
|
+
clearReconnect();
|
|
288
|
+
reconnectAttempts = 0;
|
|
286
289
|
setState("opening");
|
|
287
290
|
try {
|
|
288
291
|
await open();
|
|
@@ -291,95 +294,3398 @@ var OyehelloChat = (function (exports) {
|
|
|
291
294
|
setState("error");
|
|
292
295
|
emit({ type: "error", error: err });
|
|
293
296
|
}
|
|
294
|
-
},
|
|
295
|
-
async sendMessage(
|
|
296
|
-
if (!session) {
|
|
297
|
-
emit({ type: "error", error: new Error("call start() before sendMessage") });
|
|
298
|
-
return;
|
|
297
|
+
},
|
|
298
|
+
async sendMessage(text2, files) {
|
|
299
|
+
if (!session) {
|
|
300
|
+
emit({ type: "error", error: new Error("call start() before sendMessage") });
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const fileList = files ?? [];
|
|
304
|
+
if (fileList.length > maxAttachments) {
|
|
305
|
+
emit({ type: "error", error: new Error(`too many attachments: max ${maxAttachments} per message`) });
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
const oversized = fileList.find((f2) => f2.size > maxAttachmentBytes);
|
|
309
|
+
if (oversized) {
|
|
310
|
+
emit({ type: "error", error: new Error(`attachment too large: ${oversized.name} exceeds ${maxAttachmentBytes} bytes`) });
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
let attachments = [];
|
|
314
|
+
if (fileList.length > 0) {
|
|
315
|
+
try {
|
|
316
|
+
attachments = await uploadFiles(fileList);
|
|
317
|
+
} catch (err) {
|
|
318
|
+
emit({ type: "error", error: err });
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
messages.push({ id: uid("u"), role: "user", text: text2, streaming: false, attachments: attachments.length > 0 ? attachments : void 0 });
|
|
323
|
+
emitMessages();
|
|
324
|
+
try {
|
|
325
|
+
await postMessage({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, text: text2, attachments, fetchImpl });
|
|
326
|
+
} catch (err) {
|
|
327
|
+
if (err instanceof ChatApiError && err.code === "session_expired") {
|
|
328
|
+
try {
|
|
329
|
+
await open();
|
|
330
|
+
const freshAttachments = fileList.length ? await uploadFiles(fileList) : [];
|
|
331
|
+
await postMessage({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, text: text2, attachments: freshAttachments, fetchImpl });
|
|
332
|
+
} catch (retryErr) {
|
|
333
|
+
emit({ type: "error", error: retryErr });
|
|
334
|
+
}
|
|
335
|
+
} else {
|
|
336
|
+
emit({ type: "error", error: err });
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
async end() {
|
|
341
|
+
closed = true;
|
|
342
|
+
clearReconnect();
|
|
343
|
+
if (session) await endSession({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, fetchImpl });
|
|
344
|
+
es?.close();
|
|
345
|
+
es = null;
|
|
346
|
+
setState("ended");
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// ../../node_modules/marked/lib/marked.esm.js
|
|
352
|
+
function A() {
|
|
353
|
+
return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
|
|
354
|
+
}
|
|
355
|
+
var T = A();
|
|
356
|
+
function j(u3) {
|
|
357
|
+
T = u3;
|
|
358
|
+
}
|
|
359
|
+
var E = { exec: () => null };
|
|
360
|
+
function I(u3) {
|
|
361
|
+
let e = [];
|
|
362
|
+
return (t) => {
|
|
363
|
+
let n = Math.max(0, Math.min(3, t - 1)), s = e[n];
|
|
364
|
+
return s || (s = u3(n), e[n] = s), s;
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
function k(u3, e = "") {
|
|
368
|
+
let t = typeof u3 == "string" ? u3 : u3.source, n = { replace: (s, r) => {
|
|
369
|
+
let o = typeof r == "string" ? r : r.source;
|
|
370
|
+
return o = o.replace(m.caret, "$1"), t = t.replace(s, o), n;
|
|
371
|
+
}, getRegex: () => new RegExp(t, e) };
|
|
372
|
+
return n;
|
|
373
|
+
}
|
|
374
|
+
var Te = ((u3 = "") => {
|
|
375
|
+
try {
|
|
376
|
+
return !!new RegExp("(?<=1)(?<!1)" + u3);
|
|
377
|
+
} catch {
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
})();
|
|
381
|
+
var m = { codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm, outputLinkReplace: /\\([\[\]])/g, indentCodeCompensation: /^(\s+)(?:```)/, beginningSpace: /^\s+/, endingHash: /#$/, startingSpaceChar: /^ /, endingSpaceChar: / $/, endingSpaceTabChar: /[ \t]$/, 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: (u3) => new RegExp(`^( {0,3}${u3})((?:[ ][^\\n]*)?(?:\\n|$))`), nextBulletRegex: I((u3) => new RegExp(`^ {0,${u3}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`)), hrRegex: I((u3) => new RegExp(`^ {0,${u3}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`)), fencesBeginRegex: I((u3) => new RegExp(`^ {0,${u3}}(?:\`\`\`|~~~)`)), headingBeginRegex: I((u3) => new RegExp(`^ {0,${u3}}#`)), htmlBeginRegex: I((u3) => new RegExp(`^ {0,${u3}}<(?:[a-z].*>|!--)`, "i")), blockquoteBeginRegex: I((u3) => new RegExp(`^ {0,${u3}}>`)) };
|
|
382
|
+
var Oe = /^(?:[ \t]*(?:\n|$))+/;
|
|
383
|
+
var we = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/;
|
|
384
|
+
var ye = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
|
|
385
|
+
var q = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
|
|
386
|
+
var Pe = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
|
|
387
|
+
var U = / {0,3}(?:[*+-]|\d{1,9}[.)])/;
|
|
388
|
+
var oe = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/;
|
|
389
|
+
var ae = k(oe).replace(/bull/g, U).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}(?:\s|$)/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex();
|
|
390
|
+
var Se = k(oe).replace(/bull/g, U).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}(?:\s|$)/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
|
|
391
|
+
var K = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table|[ \t]+\n)[^\n]+)*)/;
|
|
392
|
+
var _e = /^[^\n]+/;
|
|
393
|
+
var W = /(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/;
|
|
394
|
+
var $e = k(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", W).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
|
|
395
|
+
var Le = k(/^(bull)([ \t][^\n]*?)?(?:\n|$)/).replace(/bull/g, U).getRegex();
|
|
396
|
+
var Q = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
|
|
397
|
+
var X = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
|
|
398
|
+
var ze = k("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n*|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>[^\\n]*\\n*|$)|<![A-Z][\\s\\S]*?(?:>[^\\n]*\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>[^\\n]*\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][a-z0-9-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][a-z0-9-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))", "i").replace("comment", X).replace("tag", Q).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
|
|
399
|
+
var le = (u3) => k(K).replace("hr", q).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list", u3).replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", Q).getRegex();
|
|
400
|
+
var Ee = le(/ {0,3}(?:[*+-]|1[.)])[ \t]+[^ \t\n]/);
|
|
401
|
+
var Me = le(/ {0,3}(?:[*+-]|\d{1,9}[.)])(?:[ \t]|\n|$)/);
|
|
402
|
+
var Ae = k(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", Me).getRegex();
|
|
403
|
+
var J = { blockquote: Ae, code: we, def: $e, fences: ye, heading: Pe, hr: q, html: ze, lheading: ae, list: Le, newline: Oe, paragraph: Ee, table: E, text: _e };
|
|
404
|
+
var se = k("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", q).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3} )[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", Q).getRegex();
|
|
405
|
+
var Ie = { ...J, lheading: Se, table: se, paragraph: k(K).replace("hr", q).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", se).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", Q).getRegex() };
|
|
406
|
+
var Ce = { ...J, html: k(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", X).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, heading: /^(#{1,6})(.*)(?:\n+|$)/, fences: E, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: k(K).replace("hr", q).replace("heading", ` *#{1,6} *[^
|
|
407
|
+
]`).replace("lheading", ae).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() };
|
|
408
|
+
var Be = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
|
|
409
|
+
var De = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
|
|
410
|
+
var ue = /^( {2,}|\\)\n(?!\s*$)/;
|
|
411
|
+
var qe = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
|
|
412
|
+
var _ = /[\p{P}\p{S}]/u;
|
|
413
|
+
var C = /[\s\p{P}\p{S}]/u;
|
|
414
|
+
var v = /[^\s\p{P}\p{S}]/u;
|
|
415
|
+
var ve = k(/^((?![*_])punctSpace)/, "u").replace(/punctSpace/g, C).getRegex();
|
|
416
|
+
var He = /[\p{Pi}\p{Ps}"']/u;
|
|
417
|
+
var pe = /(?!~)[\p{P}\p{S}]/u;
|
|
418
|
+
var Ze = /(?!~)[\s\p{P}\p{S}]/u;
|
|
419
|
+
var Ge = /(?:[^\s\p{P}\p{S}]|~)/u;
|
|
420
|
+
var Qe = k(/link|precode-code|html/, "g").replace("link", /\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-", Te ? "(?<!`)()" : "(^^|[^`])").replace("code", /(?<b>`+)[^`]+\k<b>(?!`)/).replace("html", /<(?! )[^<>]*?>/).getRegex();
|
|
421
|
+
var ce = /^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/;
|
|
422
|
+
var Ne = k(ce, "u").replace(/punct/g, _).getRegex();
|
|
423
|
+
var je = k(ce, "u").replace(/punct/g, pe).getRegex();
|
|
424
|
+
var Fe = /^(?:\*+(?:((?!\*)(?!openQuote)punct)|([^\s*]))?)|^_+(?:((?!_)(?!openQuote)punct)|([^\s_]))?/;
|
|
425
|
+
var Ue = k(Fe, "u").replace(/openQuote/g, He).replace(/punct/g, _).getRegex();
|
|
426
|
+
var he = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)";
|
|
427
|
+
var Ke = k(he, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, C).replace(/punct/g, _).getRegex();
|
|
428
|
+
var We = k(he, "gu").replace(/notPunctSpace/g, Ge).replace(/punctSpace/g, Ze).replace(/punct/g, pe).getRegex();
|
|
429
|
+
var Xe = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)[\\s](\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|(?:(?!\\*)punct|notPunctSpace)(\\*+)(?!\\*)(?=notPunctSpace)";
|
|
430
|
+
var Je = k(Xe, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, C).replace(/punct/g, _).getRegex();
|
|
431
|
+
var Ve = k("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, C).replace(/punct/g, _).getRegex();
|
|
432
|
+
var Ye = "^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)[\\s](_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)|(?:(?!_)punct|notPunctSpace)(_+)(?!_)(?=notPunctSpace)";
|
|
433
|
+
var et = k(Ye, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, C).replace(/punct/g, _).getRegex();
|
|
434
|
+
var tt = k(/^~~?(?:((?!~)punct)|[^\s~])/, "u").replace(/punct/g, _).getRegex();
|
|
435
|
+
var nt = "^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)";
|
|
436
|
+
var rt = k(nt, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, C).replace(/punct/g, _).getRegex();
|
|
437
|
+
var st = k(/\\(punct)/, "gu").replace(/punct/g, _).getRegex();
|
|
438
|
+
var it = k(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
|
|
439
|
+
var ot = k(X).replace("(?:-->|$)", "-->").getRegex();
|
|
440
|
+
var at = k("^comment|^</[a-zA-Z][a-zA-Z0-9-]*\\s*>|^<[a-zA-Z][a-zA-Z0-9-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment", ot).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
|
|
441
|
+
var lt = /\[(?:\\[\s\S]|[^\[\]\\])*\]/;
|
|
442
|
+
var G = k(/(?:\[(?:brackets|\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/).replace("brackets", lt).getRegex();
|
|
443
|
+
var ut = k(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label", G).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]+|(?=\))/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
|
|
444
|
+
var ke = k(/^!?\[(label)\]\[(ref)\]/).replace("label", G).replace("ref", W).getRegex();
|
|
445
|
+
var de = k(/^!?\[(ref)\](?:\[\])?/).replace("ref", W).getRegex();
|
|
446
|
+
var pt = k("reflink|nolink(?!\\()", "g").replace("reflink", ke).replace("nolink", de).getRegex();
|
|
447
|
+
var ie = /[hH][tT][tT][pP][sS]?|[fF][tT][pP]/;
|
|
448
|
+
var V = { _backpedal: E, anyPunctuation: st, autolink: it, blockSkip: Qe, br: ue, code: De, del: E, delLDelim: E, delRDelim: E, emStrongLDelim: Ne, emStrongRDelimAst: Ke, emStrongRDelimUnd: Ve, escape: Be, link: ut, nolink: de, punctuation: ve, reflink: ke, reflinkSearch: pt, tag: at, text: qe, url: E };
|
|
449
|
+
var ct = { ...V, emStrongLDelim: Ue, emStrongRDelimAst: Je, emStrongRDelimUnd: et, link: k(/^!?\[(label)\]\((.*?)\)/).replace("label", G).getRegex(), reflink: k(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", G).getRegex() };
|
|
450
|
+
var F = { ...V, emStrongRDelimAst: We, emStrongLDelim: je, delLDelim: tt, delRDelim: rt, url: k(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol", ie).replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![\w-])/).getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, text: k(/^(`+|~+|[^`~])(?:(?=[`~])|(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol", ie).getRegex() };
|
|
451
|
+
var ht = { ...F, br: k(ue).replace("{2,}", "*").getRegex(), text: k(F.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex() };
|
|
452
|
+
var H = { normal: J, gfm: Ie, pedantic: Ce };
|
|
453
|
+
var B = { normal: V, gfm: F, breaks: ht, pedantic: ct };
|
|
454
|
+
var kt = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" };
|
|
455
|
+
var ge = (u3) => kt[u3];
|
|
456
|
+
function R(u3, e) {
|
|
457
|
+
if (e) {
|
|
458
|
+
if (m.escapeTest.test(u3)) return u3.replace(m.escapeReplace, ge);
|
|
459
|
+
} else if (m.escapeTestNoEncode.test(u3)) return u3.replace(m.escapeReplaceNoEncode, ge);
|
|
460
|
+
return u3;
|
|
461
|
+
}
|
|
462
|
+
function Y(u3) {
|
|
463
|
+
try {
|
|
464
|
+
u3 = encodeURI(u3).replace(m.percentDecode, "%");
|
|
465
|
+
} catch {
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
468
|
+
return u3;
|
|
469
|
+
}
|
|
470
|
+
function ee(u3, e) {
|
|
471
|
+
let t = u3.replace(m.findPipe, (r, o, i) => {
|
|
472
|
+
let l = false, a = o;
|
|
473
|
+
for (; --a >= 0 && i[a] === "\\"; ) l = !l;
|
|
474
|
+
return l ? "|" : " |";
|
|
475
|
+
}), n = t.split(m.splitPipe), s = 0;
|
|
476
|
+
if (n[0].trim() || n.shift(), n.length > 0 && !n.at(-1)?.trim() && n.pop(), e) if (n.length > e) n.splice(e);
|
|
477
|
+
else for (; n.length < e; ) n.push("");
|
|
478
|
+
for (; s < n.length; s++) n[s] = n[s].trim().replace(m.slashPipe, "|");
|
|
479
|
+
return n;
|
|
480
|
+
}
|
|
481
|
+
function $(u3, e, t) {
|
|
482
|
+
let n = u3.length;
|
|
483
|
+
if (n === 0) return "";
|
|
484
|
+
let s = 0;
|
|
485
|
+
for (; s < n; ) {
|
|
486
|
+
let r = u3.charAt(n - s - 1);
|
|
487
|
+
if (r === e && true) s++;
|
|
488
|
+
else break;
|
|
489
|
+
}
|
|
490
|
+
return u3.slice(0, n - s);
|
|
491
|
+
}
|
|
492
|
+
function te(u3) {
|
|
493
|
+
let e = u3.split(`
|
|
494
|
+
`), t = e.length - 1;
|
|
495
|
+
for (; t >= 0 && m.blankLine.test(e[t]); ) t--;
|
|
496
|
+
return e.length - t <= 2 ? u3 : e.slice(0, t + 1).join(`
|
|
497
|
+
`);
|
|
498
|
+
}
|
|
499
|
+
function fe(u3, e) {
|
|
500
|
+
if (u3.indexOf(e[1]) === -1) return -1;
|
|
501
|
+
let t = 0;
|
|
502
|
+
for (let n = 0; n < u3.length; n++) if (u3[n] === "\\") n++;
|
|
503
|
+
else if (u3[n] === e[0]) t++;
|
|
504
|
+
else if (u3[n] === e[1] && (t--, t < 0)) return n;
|
|
505
|
+
return t > 0 ? -2 : -1;
|
|
506
|
+
}
|
|
507
|
+
function me(u3, e = 0) {
|
|
508
|
+
let t = e, n = "";
|
|
509
|
+
for (let s of u3) if (s === " ") {
|
|
510
|
+
let r = 4 - t % 4;
|
|
511
|
+
n += " ".repeat(r), t += r;
|
|
512
|
+
} else n += s, t++;
|
|
513
|
+
return n;
|
|
514
|
+
}
|
|
515
|
+
function xe(u3, e, t, n, s) {
|
|
516
|
+
let r = e.href, o = e.title || null, i = u3[1].replace(s.other.outputLinkReplace, "$1"), l = u3[0].charAt(0) === "!";
|
|
517
|
+
n.state.inLink = true;
|
|
518
|
+
let a = n.state.linkEmitted, p = n.state.inRawBlock;
|
|
519
|
+
n.state.linkEmitted = false;
|
|
520
|
+
let c = n.inlineTokens(i), h = n.state.linkEmitted;
|
|
521
|
+
if (n.state.linkEmitted = a, n.state.inLink = false, !l) {
|
|
522
|
+
if (h) {
|
|
523
|
+
n.state.inRawBlock = p;
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
n.state.linkEmitted = true;
|
|
527
|
+
}
|
|
528
|
+
return { type: l ? "image" : "link", raw: t, href: r, title: o, text: i, tokens: c };
|
|
529
|
+
}
|
|
530
|
+
function dt(u3, e, t) {
|
|
531
|
+
let n = u3.match(t.other.indentCodeCompensation);
|
|
532
|
+
if (n === null) return e;
|
|
533
|
+
let s = n[1];
|
|
534
|
+
return e.split(`
|
|
535
|
+
`).map((r) => {
|
|
536
|
+
let o = r.match(t.other.beginningSpace);
|
|
537
|
+
if (o === null) return r;
|
|
538
|
+
let [i] = o;
|
|
539
|
+
return r.slice(Math.min(i.length, s.length));
|
|
540
|
+
}).join(`
|
|
541
|
+
`);
|
|
542
|
+
}
|
|
543
|
+
var y = class {
|
|
544
|
+
options;
|
|
545
|
+
rules;
|
|
546
|
+
lexer;
|
|
547
|
+
constructor(e) {
|
|
548
|
+
this.options = e || T;
|
|
549
|
+
}
|
|
550
|
+
space(e) {
|
|
551
|
+
let t = this.rules.block.newline.exec(e);
|
|
552
|
+
if (t && t[0].length > 0) return { type: "space", raw: t[0] };
|
|
553
|
+
}
|
|
554
|
+
code(e) {
|
|
555
|
+
let t = this.rules.block.code.exec(e);
|
|
556
|
+
if (t) {
|
|
557
|
+
let n = this.options.pedantic ? t[0] : te(t[0]), s = n.replace(this.rules.other.codeRemoveIndent, "");
|
|
558
|
+
return { type: "code", raw: n, codeBlockStyle: "indented", text: s };
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
fences(e) {
|
|
562
|
+
let t = this.rules.block.fences.exec(e);
|
|
563
|
+
if (t) {
|
|
564
|
+
let n = t[0], s = dt(n, t[3] || "", this.rules);
|
|
565
|
+
return { type: "code", raw: n, lang: t[2] ? t[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : t[2], text: s };
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
heading(e) {
|
|
569
|
+
let t = this.rules.block.heading.exec(e);
|
|
570
|
+
if (t) {
|
|
571
|
+
let n = t[2].trim();
|
|
572
|
+
if (this.rules.other.endingHash.test(n)) {
|
|
573
|
+
let s = $(n, "#");
|
|
574
|
+
(this.options.pedantic || !s || this.rules.other.endingSpaceTabChar.test(s)) && (n = s.trim());
|
|
575
|
+
}
|
|
576
|
+
return { type: "heading", raw: $(t[0], `
|
|
577
|
+
`), depth: t[1].length, text: n, tokens: this.lexer.inline(n) };
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
hr(e) {
|
|
581
|
+
let t = this.rules.block.hr.exec(e);
|
|
582
|
+
if (t) return { type: "hr", raw: $(t[0], `
|
|
583
|
+
`) };
|
|
584
|
+
}
|
|
585
|
+
blockquote(e) {
|
|
586
|
+
let t = this.rules.block.blockquote.exec(e);
|
|
587
|
+
if (t) {
|
|
588
|
+
let n = $(t[0], `
|
|
589
|
+
`).split(`
|
|
590
|
+
`), s = "", r = "", o = [];
|
|
591
|
+
for (; n.length > 0; ) {
|
|
592
|
+
let i = false, l = [], a;
|
|
593
|
+
for (a = 0; a < n.length; a++) if (this.rules.other.blockquoteStart.test(n[a])) l.push(n[a]), i = true;
|
|
594
|
+
else if (!i) l.push(n[a]);
|
|
595
|
+
else break;
|
|
596
|
+
n = n.slice(a);
|
|
597
|
+
let p = l.join(`
|
|
598
|
+
`), c = p.replace(this.rules.other.blockquoteSetextReplace, `
|
|
599
|
+
$1`).replace(this.rules.other.blockquoteSetextReplace2, "");
|
|
600
|
+
s = s ? `${s}
|
|
601
|
+
${p}` : p, r = r ? `${r}
|
|
602
|
+
${c}` : c;
|
|
603
|
+
let h = this.lexer.state.top;
|
|
604
|
+
if (this.lexer.state.top = true, this.lexer.blockTokens(c, o, true), this.lexer.state.top = h, n.length === 0) break;
|
|
605
|
+
let d = o.at(-1);
|
|
606
|
+
if (d?.type === "code") break;
|
|
607
|
+
if (d?.type === "blockquote") {
|
|
608
|
+
let O = d, g = n.join(`
|
|
609
|
+
`), w = O.raw + `
|
|
610
|
+
` + g.replace(this.rules.other.blockquoteSetextReplace2, ""), z = this.blockquote(w);
|
|
611
|
+
o[o.length - 1] = z, s = `${s}
|
|
612
|
+
${g}`, r = r.substring(0, r.length - O.text.length) + z.text;
|
|
613
|
+
break;
|
|
614
|
+
} else if (d?.type === "list") {
|
|
615
|
+
let O = d, g = O.raw + `
|
|
616
|
+
` + n.join(`
|
|
617
|
+
`), w = this.list(g);
|
|
618
|
+
o[o.length - 1] = w, s = s.substring(0, s.length - d.raw.length) + w.raw, r = r.substring(0, r.length - O.raw.length) + w.raw, n = g.substring(o.at(-1).raw.length).split(`
|
|
619
|
+
`);
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
return { type: "blockquote", raw: s, tokens: o, text: r };
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
list(e) {
|
|
627
|
+
let t = this.rules.block.list.exec(e);
|
|
628
|
+
if (t) {
|
|
629
|
+
let n = t[1].trim(), s = n.length > 1, r = { type: "list", raw: "", ordered: s, start: s ? +n.slice(0, -1) : "", loose: false, items: [] };
|
|
630
|
+
n = s ? `\\d{1,9}\\${n.slice(-1)}` : `\\${n}`, this.options.pedantic && (n = s ? n : "[*+-]");
|
|
631
|
+
let o = this.rules.other.listItemRegex(n), i = false;
|
|
632
|
+
for (; e; ) {
|
|
633
|
+
let a = false, p = "", c = "";
|
|
634
|
+
if (!(t = o.exec(e)) || this.rules.block.hr.test(e)) break;
|
|
635
|
+
p = t[0], e = e.substring(p.length);
|
|
636
|
+
let h = me(t[2].split(`
|
|
637
|
+
`, 1)[0], t[1].length), d = e.split(`
|
|
638
|
+
`, 1)[0], O = !h.trim(), g = 0;
|
|
639
|
+
if (this.options.pedantic ? (g = 2, c = h.trimStart()) : O ? g = t[1].length + 1 : (g = h.search(this.rules.other.nonSpaceChar), g = g > 4 ? 1 : g, c = h.slice(g), g += t[1].length), O && this.rules.other.blankLine.test(d) && (p += d + `
|
|
640
|
+
`, e = e.substring(d.length + 1), a = true), !a) {
|
|
641
|
+
let w = this.rules.other.nextBulletRegex(g), z = this.rules.other.hrRegex(g), ne = this.rules.other.fencesBeginRegex(g), re = this.rules.other.headingBeginRegex(g), be = this.rules.other.htmlBeginRegex(g), Re = this.rules.other.blockquoteBeginRegex(g);
|
|
642
|
+
for (; e; ) {
|
|
643
|
+
let N = e.split(`
|
|
644
|
+
`, 1)[0], D;
|
|
645
|
+
if (d = N, this.options.pedantic ? (d = d.replace(this.rules.other.listReplaceNesting, " "), D = d) : D = d.replace(this.rules.other.tabCharGlobal, " "), ne.test(d) || re.test(d) || be.test(d) || Re.test(d) || w.test(d) || z.test(d)) break;
|
|
646
|
+
if (D.search(this.rules.other.nonSpaceChar) >= g || !d.trim()) c += `
|
|
647
|
+
` + D.slice(g);
|
|
648
|
+
else {
|
|
649
|
+
if (O || h.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4 || ne.test(h) || re.test(h) || z.test(h)) break;
|
|
650
|
+
c += `
|
|
651
|
+
` + d;
|
|
652
|
+
}
|
|
653
|
+
O = !d.trim(), p += N + `
|
|
654
|
+
`, e = e.substring(N.length + 1), h = D.slice(g);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
r.loose || (i ? r.loose = true : this.rules.other.doubleBlankLine.test(p) && (i = true)), r.items.push({ type: "list_item", raw: p, task: !!this.options.gfm && this.rules.other.listIsTask.test(c), loose: false, text: c, tokens: [] }), r.raw += p;
|
|
658
|
+
}
|
|
659
|
+
let l = r.items.at(-1);
|
|
660
|
+
if (l) l.raw = l.raw.trimEnd(), l.text = l.text.trimEnd();
|
|
661
|
+
else return;
|
|
662
|
+
r.raw = r.raw.trimEnd();
|
|
663
|
+
for (let a of r.items) if (this.lexer.state.top = false, a.tokens = this.lexer.blockTokens(a.text, []), !r.loose) {
|
|
664
|
+
let p = a.tokens.filter((h) => h.type === "space"), c = p.length > 0 && p.some((h) => this.rules.other.anyLine.test(h.raw));
|
|
665
|
+
r.loose = c;
|
|
666
|
+
}
|
|
667
|
+
for (let a of r.items) {
|
|
668
|
+
let p = a.tokens[0];
|
|
669
|
+
if (a.task && (p?.type === "text" || p?.type === "paragraph")) {
|
|
670
|
+
a.text = a.text.replace(this.rules.other.listReplaceTask, ""), p.raw = p.raw.replace(this.rules.other.listReplaceTask, ""), p.text = p.text.replace(this.rules.other.listReplaceTask, "");
|
|
671
|
+
for (let h = this.lexer.inlineQueue.length - 1; h >= 0; h--) if (this.rules.other.listIsTask.test(this.lexer.inlineQueue[h].src)) {
|
|
672
|
+
this.lexer.inlineQueue[h].src = this.lexer.inlineQueue[h].src.replace(this.rules.other.listReplaceTask, "");
|
|
673
|
+
break;
|
|
674
|
+
}
|
|
675
|
+
let c = this.rules.other.listTaskCheckbox.exec(a.raw);
|
|
676
|
+
if (c) {
|
|
677
|
+
let h = { type: "checkbox", raw: c[0] + " ", checked: c[0] !== "[ ]" };
|
|
678
|
+
a.checked = h.checked, r.loose ? a.tokens[0] && ["paragraph", "text"].includes(a.tokens[0].type) && "tokens" in a.tokens[0] && a.tokens[0].tokens ? (a.tokens[0].raw = h.raw + a.tokens[0].raw, a.tokens[0].text = h.raw + a.tokens[0].text, a.tokens[0].tokens.unshift(h)) : a.tokens.unshift({ type: "paragraph", raw: h.raw, text: h.raw, tokens: [h] }) : a.tokens.unshift(h);
|
|
679
|
+
}
|
|
680
|
+
} else a.task && (a.task = false);
|
|
681
|
+
}
|
|
682
|
+
if (r.loose) for (let a of r.items) {
|
|
683
|
+
a.loose = true;
|
|
684
|
+
for (let p of a.tokens) p.type === "text" && (p.type = "paragraph");
|
|
685
|
+
}
|
|
686
|
+
return r;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
html(e) {
|
|
690
|
+
let t = this.rules.block.html.exec(e);
|
|
691
|
+
if (t) {
|
|
692
|
+
let n = te(t[0]);
|
|
693
|
+
return { type: "html", block: true, raw: n, pre: t[1] === "pre" || t[1] === "script" || t[1] === "style", text: n };
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
def(e) {
|
|
697
|
+
let t = this.rules.block.def.exec(e);
|
|
698
|
+
if (t) {
|
|
699
|
+
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];
|
|
700
|
+
return { type: "def", tag: n, raw: $(t[0], `
|
|
701
|
+
`), href: s, title: r };
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
table(e) {
|
|
705
|
+
let t = this.rules.block.table.exec(e);
|
|
706
|
+
if (!t || !this.rules.other.tableDelimiter.test(t[2])) return;
|
|
707
|
+
let n = ee(t[1]), s = t[2].replace(this.rules.other.tableAlignChars, "").split("|"), r = t[3]?.trim() ? t[3].replace(this.rules.other.tableRowBlankLine, "").split(`
|
|
708
|
+
`) : [], o = { type: "table", raw: $(t[0], `
|
|
709
|
+
`), header: [], align: [], rows: [] };
|
|
710
|
+
if (n.length === s.length) {
|
|
711
|
+
for (let i of s) this.rules.other.tableAlignRight.test(i) ? o.align.push("right") : this.rules.other.tableAlignCenter.test(i) ? o.align.push("center") : this.rules.other.tableAlignLeft.test(i) ? o.align.push("left") : o.align.push(null);
|
|
712
|
+
for (let i = 0; i < n.length; i++) o.header.push({ text: n[i], tokens: this.lexer.inline(n[i]), header: true, align: o.align[i] });
|
|
713
|
+
for (let i of r) o.rows.push(ee(i, o.header.length).map((l, a) => ({ text: l, tokens: this.lexer.inline(l), header: false, align: o.align[a] })));
|
|
714
|
+
return o;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
lheading(e) {
|
|
718
|
+
let t = this.rules.block.lheading.exec(e);
|
|
719
|
+
if (t) {
|
|
720
|
+
let n = t[1].trim();
|
|
721
|
+
return { type: "heading", raw: $(t[0], `
|
|
722
|
+
`), depth: t[2].charAt(0) === "=" ? 1 : 2, text: n, tokens: this.lexer.inline(n) };
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
paragraph(e) {
|
|
726
|
+
let t = this.rules.block.paragraph.exec(e);
|
|
727
|
+
if (t) {
|
|
728
|
+
let n = t[1].charAt(t[1].length - 1) === `
|
|
729
|
+
` ? t[1].slice(0, -1) : t[1];
|
|
730
|
+
return { type: "paragraph", raw: t[0], text: n, tokens: this.lexer.inline(n) };
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
text(e) {
|
|
734
|
+
let t = this.rules.block.text.exec(e);
|
|
735
|
+
if (t) return { type: "text", raw: t[0], text: t[0], tokens: this.lexer.inline(t[0]) };
|
|
736
|
+
}
|
|
737
|
+
escape(e) {
|
|
738
|
+
let t = this.rules.inline.escape.exec(e);
|
|
739
|
+
if (t) return { type: "escape", raw: t[0], text: t[1] };
|
|
740
|
+
}
|
|
741
|
+
tag(e) {
|
|
742
|
+
let t = this.rules.inline.tag.exec(e);
|
|
743
|
+
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] };
|
|
744
|
+
}
|
|
745
|
+
link(e) {
|
|
746
|
+
let t = this.rules.inline.link.exec(e);
|
|
747
|
+
if (t) {
|
|
748
|
+
let n = t[2].trim();
|
|
749
|
+
if (!this.options.pedantic && this.rules.other.startAngleBracket.test(n)) {
|
|
750
|
+
if (!this.rules.other.endAngleBracket.test(n)) return;
|
|
751
|
+
let o = $(n.slice(0, -1), "\\");
|
|
752
|
+
if ((n.length - o.length) % 2 === 0) return;
|
|
753
|
+
} else {
|
|
754
|
+
let o = fe(t[2], "()");
|
|
755
|
+
if (o === -2) return;
|
|
756
|
+
if (o > -1) {
|
|
757
|
+
let l = (t[0].indexOf("!") === 0 ? 5 : 4) + t[1].length + o;
|
|
758
|
+
t[2] = t[2].substring(0, o), t[0] = t[0].substring(0, l).trim(), t[3] = "";
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
let s = t[2], r = "";
|
|
762
|
+
if (this.options.pedantic) {
|
|
763
|
+
let o = this.rules.other.pedanticHrefTitle.exec(s);
|
|
764
|
+
o && (s = o[1], r = o[3]);
|
|
765
|
+
} else r = t[3] ? t[3].slice(1, -1) : "";
|
|
766
|
+
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);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
reflink(e, t) {
|
|
770
|
+
let n;
|
|
771
|
+
if ((n = this.rules.inline.reflink.exec(e)) || (n = this.rules.inline.nolink.exec(e))) {
|
|
772
|
+
let s = (n[2] || n[1]).replace(this.rules.other.multipleSpaceGlobal, " "), r = t[s.toLowerCase()];
|
|
773
|
+
if (!r) {
|
|
774
|
+
let o = n[0].charAt(0);
|
|
775
|
+
return { type: "text", raw: o, text: o };
|
|
776
|
+
}
|
|
777
|
+
return xe(n, r, n[0], this.lexer, this.rules);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
emStrong(e, t, n = "") {
|
|
781
|
+
let s = this.rules.inline.emStrongLDelim.exec(e);
|
|
782
|
+
if (!s || !s[1] && !s[2] && !s[3] && !s[4] || s[4] && n.match(this.rules.other.unicodeAlphaNumeric)) return;
|
|
783
|
+
if (!(s[1] || s[3] || "") || !n || this.rules.inline.punctuation.exec(n)) {
|
|
784
|
+
let o = [...s[0]].length - 1, i, l, a = o, p = 0, c = s[0][0], h = n === c, d = c === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
|
|
785
|
+
for (d.lastIndex = 0, t = t.slice(-1 * e.length + o); (s = d.exec(t)) !== null; ) {
|
|
786
|
+
if (i = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !i) continue;
|
|
787
|
+
if (l = [...i].length, s[3] || s[4]) {
|
|
788
|
+
a += l;
|
|
789
|
+
continue;
|
|
790
|
+
} else if (s[5] || s[6]) {
|
|
791
|
+
if (o % 3 && !((o + l) % 3)) {
|
|
792
|
+
p += l;
|
|
793
|
+
continue;
|
|
794
|
+
}
|
|
795
|
+
if (h) break;
|
|
796
|
+
}
|
|
797
|
+
if (a -= l, a > 0) continue;
|
|
798
|
+
l = Math.min(l, l + a + p);
|
|
799
|
+
let O = [...s[0]][0].length, g = e.slice(0, o + s.index + O + l);
|
|
800
|
+
if (Math.min(o, l) % 2) {
|
|
801
|
+
let z = g.slice(1, -1);
|
|
802
|
+
return { type: "em", raw: g, text: z, tokens: this.lexer.inlineTokens(z) };
|
|
803
|
+
}
|
|
804
|
+
let w = g.slice(2, -2);
|
|
805
|
+
return { type: "strong", raw: g, text: w, tokens: this.lexer.inlineTokens(w) };
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
codespan(e) {
|
|
810
|
+
let t = this.rules.inline.code.exec(e);
|
|
811
|
+
if (t) {
|
|
812
|
+
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);
|
|
813
|
+
return s && r && (n = n.substring(1, n.length - 1)), { type: "codespan", raw: t[0], text: n };
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
br(e) {
|
|
817
|
+
let t = this.rules.inline.br.exec(e);
|
|
818
|
+
if (t) return { type: "br", raw: t[0] };
|
|
819
|
+
}
|
|
820
|
+
del(e, t, n = "") {
|
|
821
|
+
let s = this.rules.inline.delLDelim.exec(e);
|
|
822
|
+
if (!s) return;
|
|
823
|
+
if (!(s[1] || "") || !n || this.rules.inline.punctuation.exec(n)) {
|
|
824
|
+
let o = [...s[0]].length - 1, i, l, a = o, p = this.rules.inline.delRDelim;
|
|
825
|
+
for (p.lastIndex = 0, t = t.slice(-1 * e.length + o); (s = p.exec(t)) !== null; ) {
|
|
826
|
+
if (i = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !i || (l = [...i].length, l !== o)) continue;
|
|
827
|
+
if (s[3] || s[4]) {
|
|
828
|
+
a += l;
|
|
829
|
+
continue;
|
|
830
|
+
}
|
|
831
|
+
if (a -= l, a > 0) continue;
|
|
832
|
+
l = Math.min(l, l + a);
|
|
833
|
+
let c = [...s[0]][0].length, h = e.slice(0, o + s.index + c + l), d = h.slice(o, -o);
|
|
834
|
+
return { type: "del", raw: h, text: d, tokens: this.lexer.inlineTokens(d) };
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
autolink(e) {
|
|
839
|
+
let t = this.rules.inline.autolink.exec(e);
|
|
840
|
+
if (t) {
|
|
841
|
+
let n, s;
|
|
842
|
+
return t[2] === "@" ? (n = t[1], s = "mailto:" + n) : (n = t[1], s = n), { type: "link", raw: t[0], text: n, href: s, autolink: true, tokens: [{ type: "text", raw: n, text: n }] };
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
url(e) {
|
|
846
|
+
let t;
|
|
847
|
+
if (t = this.rules.inline.url.exec(e)) {
|
|
848
|
+
let n, s;
|
|
849
|
+
if (t[2] === "@") n = t[0], s = "mailto:" + n;
|
|
850
|
+
else {
|
|
851
|
+
let r;
|
|
852
|
+
do
|
|
853
|
+
r = t[0], t[0] = this.rules.inline._backpedal.exec(t[0])?.[0] ?? "";
|
|
854
|
+
while (r !== t[0]);
|
|
855
|
+
n = t[0], t[1] === "www." ? s = "http://" + t[0] : s = t[0];
|
|
856
|
+
}
|
|
857
|
+
return { type: "link", raw: t[0], text: n, href: s, autolink: true, tokens: [{ type: "text", raw: n, text: n }] };
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
inlineText(e) {
|
|
861
|
+
let t = this.rules.inline.text.exec(e);
|
|
862
|
+
if (t) {
|
|
863
|
+
let n = this.lexer.state.inRawBlock;
|
|
864
|
+
return { type: "text", raw: t[0], text: t[0], escaped: n };
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
};
|
|
868
|
+
var x = class u {
|
|
869
|
+
tokens;
|
|
870
|
+
options;
|
|
871
|
+
state;
|
|
872
|
+
inlineQueue;
|
|
873
|
+
tokenizer;
|
|
874
|
+
constructor(e) {
|
|
875
|
+
this.tokens = [], this.tokens.links = /* @__PURE__ */ Object.create(null), this.options = e || T, this.options.tokenizer = this.options.tokenizer || new y(), this.tokenizer = this.options.tokenizer, this.tokenizer.options = this.options, this.tokenizer.lexer = this, this.inlineQueue = [], this.state = { inLink: false, inRawBlock: false, linkEmitted: false, top: true };
|
|
876
|
+
let t = { other: m, block: H.normal, inline: B.normal };
|
|
877
|
+
this.options.pedantic ? (t.block = H.pedantic, t.inline = B.pedantic) : this.options.gfm && (t.block = H.gfm, this.options.breaks ? t.inline = B.breaks : t.inline = B.gfm), this.tokenizer.rules = t;
|
|
878
|
+
}
|
|
879
|
+
static get rules() {
|
|
880
|
+
return { block: H, inline: B };
|
|
881
|
+
}
|
|
882
|
+
static lex(e, t) {
|
|
883
|
+
return new u(t).lex(e);
|
|
884
|
+
}
|
|
885
|
+
static lexInline(e, t) {
|
|
886
|
+
return new u(t).inlineTokens(e);
|
|
887
|
+
}
|
|
888
|
+
lex(e) {
|
|
889
|
+
e = e.replace(m.carriageReturn, `
|
|
890
|
+
`), this.blockTokens(e, this.tokens);
|
|
891
|
+
for (let t = 0; t < this.inlineQueue.length; t++) {
|
|
892
|
+
let n = this.inlineQueue[t];
|
|
893
|
+
this.inlineTokens(n.src, n.tokens);
|
|
894
|
+
}
|
|
895
|
+
return this.inlineQueue = [], this.tokens;
|
|
896
|
+
}
|
|
897
|
+
blockTokens(e, t = [], n = false) {
|
|
898
|
+
this.tokenizer.lexer = this, this.options.pedantic && (e = e.replace(m.tabCharGlobal, " ").replace(m.spaceLine, ""));
|
|
899
|
+
let s = 1 / 0;
|
|
900
|
+
for (; e; ) {
|
|
901
|
+
if (e.length < s) s = e.length;
|
|
902
|
+
else {
|
|
903
|
+
this.infiniteLoopError(e.charCodeAt(0));
|
|
904
|
+
break;
|
|
905
|
+
}
|
|
906
|
+
let r;
|
|
907
|
+
if (this.options.extensions?.block?.some((i) => (r = i.call({ lexer: this }, e, t)) ? (e = e.substring(r.raw.length), t.push(r), true) : false)) continue;
|
|
908
|
+
if (r = this.tokenizer.space(e)) {
|
|
909
|
+
e = e.substring(r.raw.length);
|
|
910
|
+
let i = t.at(-1);
|
|
911
|
+
r.raw.length === 1 && i !== void 0 ? i.raw += `
|
|
912
|
+
` : t.push(r);
|
|
913
|
+
continue;
|
|
914
|
+
}
|
|
915
|
+
if (r = this.tokenizer.code(e)) {
|
|
916
|
+
e = e.substring(r.raw.length);
|
|
917
|
+
let i = t.at(-1);
|
|
918
|
+
i?.type === "paragraph" || i?.type === "text" ? (i.raw += (i.raw.endsWith(`
|
|
919
|
+
`) ? "" : `
|
|
920
|
+
`) + r.raw, i.text += `
|
|
921
|
+
` + r.text, this.inlineQueue.at(-1).src = i.text) : t.push(r);
|
|
922
|
+
continue;
|
|
923
|
+
}
|
|
924
|
+
if (r = this.tokenizer.fences(e)) {
|
|
925
|
+
e = e.substring(r.raw.length), t.push(r);
|
|
926
|
+
continue;
|
|
927
|
+
}
|
|
928
|
+
if (r = this.tokenizer.heading(e)) {
|
|
929
|
+
e = e.substring(r.raw.length), t.push(r);
|
|
930
|
+
continue;
|
|
931
|
+
}
|
|
932
|
+
if (r = this.tokenizer.hr(e)) {
|
|
933
|
+
e = e.substring(r.raw.length), t.push(r);
|
|
934
|
+
continue;
|
|
935
|
+
}
|
|
936
|
+
if (r = this.tokenizer.blockquote(e)) {
|
|
937
|
+
e = e.substring(r.raw.length), t.push(r);
|
|
938
|
+
continue;
|
|
939
|
+
}
|
|
940
|
+
if (r = this.tokenizer.list(e)) {
|
|
941
|
+
e = e.substring(r.raw.length), t.push(r);
|
|
942
|
+
continue;
|
|
943
|
+
}
|
|
944
|
+
if (r = this.tokenizer.html(e)) {
|
|
945
|
+
e = e.substring(r.raw.length), t.push(r);
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
if (r = this.tokenizer.def(e)) {
|
|
949
|
+
e = e.substring(r.raw.length);
|
|
950
|
+
let i = t.at(-1);
|
|
951
|
+
i?.type === "paragraph" || i?.type === "text" ? (i.raw += (i.raw.endsWith(`
|
|
952
|
+
`) ? "" : `
|
|
953
|
+
`) + r.raw, i.text += `
|
|
954
|
+
` + r.raw, this.inlineQueue.at(-1).src = i.text) : this.tokens.links[r.tag] || (this.tokens.links[r.tag] = { href: r.href, title: r.title }, t.push(r));
|
|
955
|
+
continue;
|
|
956
|
+
}
|
|
957
|
+
if (r = this.tokenizer.table(e)) {
|
|
958
|
+
e = e.substring(r.raw.length), t.push(r);
|
|
959
|
+
continue;
|
|
960
|
+
}
|
|
961
|
+
if (r = this.tokenizer.lheading(e)) {
|
|
962
|
+
e = e.substring(r.raw.length), t.push(r);
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
965
|
+
let o = e;
|
|
966
|
+
if (this.options.extensions?.startBlock) {
|
|
967
|
+
let i = 1 / 0, l = e.slice(1), a;
|
|
968
|
+
this.options.extensions.startBlock.forEach((p) => {
|
|
969
|
+
a = p.call({ lexer: this }, l), typeof a == "number" && a >= 0 && (i = Math.min(i, a));
|
|
970
|
+
}), i < 1 / 0 && i >= 0 && (o = e.substring(0, i + 1));
|
|
971
|
+
}
|
|
972
|
+
if (this.state.top && (r = this.tokenizer.paragraph(o))) {
|
|
973
|
+
let i = t.at(-1);
|
|
974
|
+
n && i?.type === "paragraph" ? (i.raw += (i.raw.endsWith(`
|
|
975
|
+
`) ? "" : `
|
|
976
|
+
`) + r.raw, i.text += `
|
|
977
|
+
` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = i.text) : t.push(r), n = o.length !== e.length, e = e.substring(r.raw.length);
|
|
978
|
+
continue;
|
|
979
|
+
}
|
|
980
|
+
if (r = this.tokenizer.text(e)) {
|
|
981
|
+
e = e.substring(r.raw.length);
|
|
982
|
+
let i = t.at(-1);
|
|
983
|
+
i?.type === "text" ? (i.raw += (i.raw.endsWith(`
|
|
984
|
+
`) ? "" : `
|
|
985
|
+
`) + r.raw, i.text += `
|
|
986
|
+
` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = i.text) : t.push(r);
|
|
987
|
+
continue;
|
|
988
|
+
}
|
|
989
|
+
if (e) {
|
|
990
|
+
this.infiniteLoopError(e.charCodeAt(0));
|
|
991
|
+
break;
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
return this.state.top = true, t;
|
|
995
|
+
}
|
|
996
|
+
inline(e, t = []) {
|
|
997
|
+
return this.inlineQueue.push({ src: e, tokens: t }), t;
|
|
998
|
+
}
|
|
999
|
+
linkInText(e) {
|
|
1000
|
+
if (!e.includes("[")) return false;
|
|
1001
|
+
let t = this.tokenizer.rules.inline.link;
|
|
1002
|
+
for (let n of e.matchAll(this.tokenizer.rules.inline.blockSkip)) if (t.test(n[0]) && e.charAt(n.index - 1) !== "!") return true;
|
|
1003
|
+
for (let n of e.matchAll(this.tokenizer.rules.inline.reflinkSearch)) {
|
|
1004
|
+
let s = n[0], r = s.lastIndexOf("[");
|
|
1005
|
+
if (!(s.charAt(0) === "!" || !Object.hasOwn(this.tokens.links, s.slice(r + 1, -1))) && !(r > 1 && this.linkInText(s.slice(1, r - 1)))) return true;
|
|
1006
|
+
}
|
|
1007
|
+
return false;
|
|
1008
|
+
}
|
|
1009
|
+
inlineTokens(e, t = []) {
|
|
1010
|
+
this.tokenizer.lexer = this;
|
|
1011
|
+
let n = e;
|
|
1012
|
+
if (this.tokens.links && e.includes("[")) {
|
|
1013
|
+
let i = this.tokenizer.rules.inline.reflinkSearch, l = (a) => {
|
|
1014
|
+
let p = a.lastIndexOf("[");
|
|
1015
|
+
if (!Object.hasOwn(this.tokens.links, a.slice(p + 1, -1))) return a;
|
|
1016
|
+
if (p > 1 && a.charAt(0) !== "!") {
|
|
1017
|
+
let c = a.slice(1, p - 1);
|
|
1018
|
+
if (this.linkInText(c)) return "[" + c.replace(i, l) + "][" + "a".repeat(a.length - p - 2) + "]";
|
|
1019
|
+
}
|
|
1020
|
+
return "[" + "a".repeat(a.length - 2) + "]";
|
|
1021
|
+
};
|
|
1022
|
+
n = n.replace(i, l);
|
|
1023
|
+
}
|
|
1024
|
+
n = n.replace(this.tokenizer.rules.inline.anyPunctuation, (i) => "+".repeat(i.length)), n = n.replace(this.tokenizer.rules.inline.blockSkip, (i, l, a) => {
|
|
1025
|
+
let p = a ? a.length : 0;
|
|
1026
|
+
return i.slice(0, p) + "[" + "a".repeat(i.length - p - 2) + "]";
|
|
1027
|
+
}), n = this.options.hooks?.emStrongMask?.call({ lexer: this }, n) ?? n;
|
|
1028
|
+
let s = false, r = "", o = 1 / 0;
|
|
1029
|
+
for (; e; ) {
|
|
1030
|
+
if (e.length < o) o = e.length;
|
|
1031
|
+
else {
|
|
1032
|
+
this.infiniteLoopError(e.charCodeAt(0));
|
|
1033
|
+
break;
|
|
1034
|
+
}
|
|
1035
|
+
s || (r = ""), s = false;
|
|
1036
|
+
let i;
|
|
1037
|
+
if (this.options.extensions?.inline?.some((a) => (i = a.call({ lexer: this }, e, t)) ? (e = e.substring(i.raw.length), t.push(i), true) : false)) continue;
|
|
1038
|
+
if (i = this.tokenizer.escape(e)) {
|
|
1039
|
+
e = e.substring(i.raw.length), t.push(i);
|
|
1040
|
+
continue;
|
|
1041
|
+
}
|
|
1042
|
+
if (i = this.tokenizer.tag(e)) {
|
|
1043
|
+
e = e.substring(i.raw.length), t.push(i);
|
|
1044
|
+
continue;
|
|
1045
|
+
}
|
|
1046
|
+
if (i = this.tokenizer.link(e)) {
|
|
1047
|
+
e = e.substring(i.raw.length), t.push(i);
|
|
1048
|
+
continue;
|
|
1049
|
+
}
|
|
1050
|
+
if (i = this.tokenizer.reflink(e, this.tokens.links)) {
|
|
1051
|
+
e = e.substring(i.raw.length);
|
|
1052
|
+
let a = t.at(-1);
|
|
1053
|
+
i.type === "text" && a?.type === "text" ? (a.raw += i.raw, a.text += i.text) : t.push(i);
|
|
1054
|
+
continue;
|
|
1055
|
+
}
|
|
1056
|
+
if (i = this.tokenizer.emStrong(e, n, r)) {
|
|
1057
|
+
e = e.substring(i.raw.length), t.push(i);
|
|
1058
|
+
continue;
|
|
1059
|
+
}
|
|
1060
|
+
if (i = this.tokenizer.codespan(e)) {
|
|
1061
|
+
e = e.substring(i.raw.length), t.push(i);
|
|
1062
|
+
continue;
|
|
1063
|
+
}
|
|
1064
|
+
if (i = this.tokenizer.br(e)) {
|
|
1065
|
+
e = e.substring(i.raw.length), t.push(i);
|
|
1066
|
+
continue;
|
|
1067
|
+
}
|
|
1068
|
+
if (i = this.tokenizer.del(e, n, r)) {
|
|
1069
|
+
e = e.substring(i.raw.length), t.push(i);
|
|
1070
|
+
continue;
|
|
1071
|
+
}
|
|
1072
|
+
if (i = this.tokenizer.autolink(e)) {
|
|
1073
|
+
e = e.substring(i.raw.length), t.push(i);
|
|
1074
|
+
continue;
|
|
1075
|
+
}
|
|
1076
|
+
if (!this.state.inLink && (i = this.tokenizer.url(e))) {
|
|
1077
|
+
e = e.substring(i.raw.length), t.push(i);
|
|
1078
|
+
continue;
|
|
1079
|
+
}
|
|
1080
|
+
let l = e;
|
|
1081
|
+
if (this.options.extensions?.startInline) {
|
|
1082
|
+
let a = 1 / 0, p = e.slice(1), c;
|
|
1083
|
+
this.options.extensions.startInline.forEach((h) => {
|
|
1084
|
+
c = h.call({ lexer: this }, p), typeof c == "number" && c >= 0 && (a = Math.min(a, c));
|
|
1085
|
+
}), a < 1 / 0 && a >= 0 && (l = e.substring(0, a + 1));
|
|
1086
|
+
}
|
|
1087
|
+
if (i = this.tokenizer.inlineText(l)) {
|
|
1088
|
+
e = e.substring(i.raw.length), i.raw.slice(-1) !== "_" && (r = i.raw.slice(-1)), s = true;
|
|
1089
|
+
let a = t.at(-1);
|
|
1090
|
+
a?.type === "text" ? (a.raw += i.raw, a.text += i.text) : t.push(i);
|
|
1091
|
+
continue;
|
|
1092
|
+
}
|
|
1093
|
+
if (e) {
|
|
1094
|
+
this.infiniteLoopError(e.charCodeAt(0));
|
|
1095
|
+
break;
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
return t;
|
|
1099
|
+
}
|
|
1100
|
+
infiniteLoopError(e) {
|
|
1101
|
+
let t = "Infinite loop on byte: " + e;
|
|
1102
|
+
if (this.options.silent) console.error(t);
|
|
1103
|
+
else throw new Error(t);
|
|
1104
|
+
}
|
|
1105
|
+
};
|
|
1106
|
+
var P = class {
|
|
1107
|
+
options;
|
|
1108
|
+
parser;
|
|
1109
|
+
constructor(e) {
|
|
1110
|
+
this.options = e || T;
|
|
1111
|
+
}
|
|
1112
|
+
space(e) {
|
|
1113
|
+
return "";
|
|
1114
|
+
}
|
|
1115
|
+
code({ text: e, lang: t, escaped: n }) {
|
|
1116
|
+
let s = (t || "").match(m.notSpaceStart)?.[0], r = e ? e.replace(m.endingNewline, "") + `
|
|
1117
|
+
` : "";
|
|
1118
|
+
return s ? '<pre><code class="language-' + R(s) + '">' + (n ? r : R(r, true)) + `</code></pre>
|
|
1119
|
+
` : "<pre><code>" + (n ? r : R(r, true)) + `</code></pre>
|
|
1120
|
+
`;
|
|
1121
|
+
}
|
|
1122
|
+
blockquote({ tokens: e }) {
|
|
1123
|
+
return `<blockquote>
|
|
1124
|
+
${this.parser.parse(e)}</blockquote>
|
|
1125
|
+
`;
|
|
1126
|
+
}
|
|
1127
|
+
html({ text: e }) {
|
|
1128
|
+
return e;
|
|
1129
|
+
}
|
|
1130
|
+
def(e) {
|
|
1131
|
+
return "";
|
|
1132
|
+
}
|
|
1133
|
+
heading({ tokens: e, depth: t }) {
|
|
1134
|
+
return `<h${t}>${this.parser.parseInline(e)}</h${t}>
|
|
1135
|
+
`;
|
|
1136
|
+
}
|
|
1137
|
+
hr(e) {
|
|
1138
|
+
return `<hr>
|
|
1139
|
+
`;
|
|
1140
|
+
}
|
|
1141
|
+
list(e) {
|
|
1142
|
+
let t = e.ordered, n = e.start, s = "";
|
|
1143
|
+
for (let i = 0; i < e.items.length; i++) {
|
|
1144
|
+
let l = e.items[i];
|
|
1145
|
+
s += this.listitem(l);
|
|
1146
|
+
}
|
|
1147
|
+
let r = t ? "ol" : "ul", o = t && n !== 1 ? ' start="' + n + '"' : "";
|
|
1148
|
+
return "<" + r + o + `>
|
|
1149
|
+
` + s + "</" + r + `>
|
|
1150
|
+
`;
|
|
1151
|
+
}
|
|
1152
|
+
listitem(e) {
|
|
1153
|
+
return `<li>${this.parser.parse(e.tokens)}</li>
|
|
1154
|
+
`;
|
|
1155
|
+
}
|
|
1156
|
+
checkbox({ checked: e }) {
|
|
1157
|
+
return "<input " + (e ? 'checked="" ' : "") + 'disabled="" type="checkbox"> ';
|
|
1158
|
+
}
|
|
1159
|
+
paragraph({ tokens: e }) {
|
|
1160
|
+
return `<p>${this.parser.parseInline(e)}</p>
|
|
1161
|
+
`;
|
|
1162
|
+
}
|
|
1163
|
+
table(e) {
|
|
1164
|
+
let t = "", n = "";
|
|
1165
|
+
for (let r = 0; r < e.header.length; r++) n += this.tablecell(e.header[r]);
|
|
1166
|
+
t += this.tablerow({ text: n });
|
|
1167
|
+
let s = "";
|
|
1168
|
+
for (let r = 0; r < e.rows.length; r++) {
|
|
1169
|
+
let o = e.rows[r];
|
|
1170
|
+
n = "";
|
|
1171
|
+
for (let i = 0; i < o.length; i++) n += this.tablecell(o[i]);
|
|
1172
|
+
s += this.tablerow({ text: n });
|
|
1173
|
+
}
|
|
1174
|
+
return s && (s = `<tbody>${s}</tbody>`), `<table>
|
|
1175
|
+
<thead>
|
|
1176
|
+
` + t + `</thead>
|
|
1177
|
+
` + s + `</table>
|
|
1178
|
+
`;
|
|
1179
|
+
}
|
|
1180
|
+
tablerow({ text: e }) {
|
|
1181
|
+
return `<tr>
|
|
1182
|
+
${e}</tr>
|
|
1183
|
+
`;
|
|
1184
|
+
}
|
|
1185
|
+
tablecell(e) {
|
|
1186
|
+
let t = this.parser.parseInline(e.tokens), n = e.header ? "th" : "td";
|
|
1187
|
+
return (e.align ? `<${n} align="${e.align}">` : `<${n}>`) + t + `</${n}>
|
|
1188
|
+
`;
|
|
1189
|
+
}
|
|
1190
|
+
strong({ tokens: e }) {
|
|
1191
|
+
return `<strong>${this.parser.parseInline(e)}</strong>`;
|
|
1192
|
+
}
|
|
1193
|
+
em({ tokens: e }) {
|
|
1194
|
+
return `<em>${this.parser.parseInline(e)}</em>`;
|
|
1195
|
+
}
|
|
1196
|
+
codespan({ text: e }) {
|
|
1197
|
+
return `<code>${R(e, true)}</code>`;
|
|
1198
|
+
}
|
|
1199
|
+
br(e) {
|
|
1200
|
+
return "<br>";
|
|
1201
|
+
}
|
|
1202
|
+
del({ tokens: e }) {
|
|
1203
|
+
return `<del>${this.parser.parseInline(e)}</del>`;
|
|
1204
|
+
}
|
|
1205
|
+
link({ href: e, title: t, text: n, tokens: s, autolink: r }) {
|
|
1206
|
+
let o = r ? R(n, true) : this.parser.parseInline(s), i = Y(e);
|
|
1207
|
+
if (i === null) return o;
|
|
1208
|
+
e = R(i, r);
|
|
1209
|
+
let l = '<a href="' + e + '"';
|
|
1210
|
+
return t && (l += ' title="' + R(t) + '"'), l += ">" + o + "</a>", l;
|
|
1211
|
+
}
|
|
1212
|
+
image({ href: e, title: t, text: n, tokens: s }) {
|
|
1213
|
+
s && (n = this.parser.parseInline(s, this.parser.textRenderer));
|
|
1214
|
+
let r = Y(e);
|
|
1215
|
+
if (r === null) return R(n);
|
|
1216
|
+
e = r;
|
|
1217
|
+
let o = `<img src="${R(e)}" alt="${R(n)}"`;
|
|
1218
|
+
return t && (o += ` title="${R(t)}"`), o += ">", o;
|
|
1219
|
+
}
|
|
1220
|
+
text(e) {
|
|
1221
|
+
return "tokens" in e && e.tokens ? this.parser.parseInline(e.tokens) : "escaped" in e && e.escaped ? e.text : R(e.text);
|
|
1222
|
+
}
|
|
1223
|
+
};
|
|
1224
|
+
var L = class {
|
|
1225
|
+
strong({ text: e }) {
|
|
1226
|
+
return e;
|
|
1227
|
+
}
|
|
1228
|
+
em({ text: e }) {
|
|
1229
|
+
return e;
|
|
1230
|
+
}
|
|
1231
|
+
codespan({ text: e }) {
|
|
1232
|
+
return e;
|
|
1233
|
+
}
|
|
1234
|
+
del({ text: e }) {
|
|
1235
|
+
return e;
|
|
1236
|
+
}
|
|
1237
|
+
html({ text: e }) {
|
|
1238
|
+
return e;
|
|
1239
|
+
}
|
|
1240
|
+
text({ text: e }) {
|
|
1241
|
+
return e;
|
|
1242
|
+
}
|
|
1243
|
+
link({ text: e }) {
|
|
1244
|
+
return "" + e;
|
|
1245
|
+
}
|
|
1246
|
+
image({ text: e }) {
|
|
1247
|
+
return "" + e;
|
|
1248
|
+
}
|
|
1249
|
+
br() {
|
|
1250
|
+
return "";
|
|
1251
|
+
}
|
|
1252
|
+
checkbox({ raw: e }) {
|
|
1253
|
+
return e;
|
|
1254
|
+
}
|
|
1255
|
+
};
|
|
1256
|
+
var b = class u2 {
|
|
1257
|
+
options;
|
|
1258
|
+
renderer;
|
|
1259
|
+
textRenderer;
|
|
1260
|
+
constructor(e) {
|
|
1261
|
+
this.options = e || T, this.options.renderer = this.options.renderer || new P(), this.renderer = this.options.renderer, this.renderer.options = this.options, this.renderer.parser = this, this.textRenderer = new L();
|
|
1262
|
+
}
|
|
1263
|
+
static parse(e, t) {
|
|
1264
|
+
return new u2(t).parse(e);
|
|
1265
|
+
}
|
|
1266
|
+
static parseInline(e, t) {
|
|
1267
|
+
return new u2(t).parseInline(e);
|
|
1268
|
+
}
|
|
1269
|
+
parse(e) {
|
|
1270
|
+
this.renderer.parser = this;
|
|
1271
|
+
let t = "";
|
|
1272
|
+
for (let n = 0; n < e.length; n++) {
|
|
1273
|
+
let s = e[n];
|
|
1274
|
+
if (this.options.extensions?.renderers?.[s.type]) {
|
|
1275
|
+
let o = s, i = this.options.extensions.renderers[o.type].call({ parser: this }, o);
|
|
1276
|
+
if (i !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "checkbox", "html", "def", "paragraph", "text"].includes(o.type)) {
|
|
1277
|
+
t += i || "";
|
|
1278
|
+
continue;
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
let r = s;
|
|
1282
|
+
switch (r.type) {
|
|
1283
|
+
case "space": {
|
|
1284
|
+
t += this.renderer.space(r);
|
|
1285
|
+
break;
|
|
1286
|
+
}
|
|
1287
|
+
case "hr": {
|
|
1288
|
+
t += this.renderer.hr(r);
|
|
1289
|
+
break;
|
|
1290
|
+
}
|
|
1291
|
+
case "heading": {
|
|
1292
|
+
t += this.renderer.heading(r);
|
|
1293
|
+
break;
|
|
1294
|
+
}
|
|
1295
|
+
case "code": {
|
|
1296
|
+
t += this.renderer.code(r);
|
|
1297
|
+
break;
|
|
1298
|
+
}
|
|
1299
|
+
case "table": {
|
|
1300
|
+
t += this.renderer.table(r);
|
|
1301
|
+
break;
|
|
1302
|
+
}
|
|
1303
|
+
case "blockquote": {
|
|
1304
|
+
t += this.renderer.blockquote(r);
|
|
1305
|
+
break;
|
|
1306
|
+
}
|
|
1307
|
+
case "list": {
|
|
1308
|
+
t += this.renderer.list(r);
|
|
1309
|
+
break;
|
|
1310
|
+
}
|
|
1311
|
+
case "checkbox": {
|
|
1312
|
+
t += this.renderer.checkbox(r);
|
|
1313
|
+
break;
|
|
1314
|
+
}
|
|
1315
|
+
case "html": {
|
|
1316
|
+
t += this.renderer.html(r);
|
|
1317
|
+
break;
|
|
1318
|
+
}
|
|
1319
|
+
case "def": {
|
|
1320
|
+
t += this.renderer.def(r);
|
|
1321
|
+
break;
|
|
1322
|
+
}
|
|
1323
|
+
case "paragraph": {
|
|
1324
|
+
t += this.renderer.paragraph(r);
|
|
1325
|
+
break;
|
|
1326
|
+
}
|
|
1327
|
+
case "text": {
|
|
1328
|
+
t += this.renderer.text(r);
|
|
1329
|
+
break;
|
|
1330
|
+
}
|
|
1331
|
+
default: {
|
|
1332
|
+
let o = 'Token with "' + r.type + '" type was not found.';
|
|
1333
|
+
if (this.options.silent) return console.error(o), "";
|
|
1334
|
+
throw new Error(o);
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
return t;
|
|
1339
|
+
}
|
|
1340
|
+
parseInline(e, t = this.renderer) {
|
|
1341
|
+
this.renderer.parser = this;
|
|
1342
|
+
let n = "";
|
|
1343
|
+
for (let s = 0; s < e.length; s++) {
|
|
1344
|
+
let r = e[s];
|
|
1345
|
+
if (this.options.extensions?.renderers?.[r.type]) {
|
|
1346
|
+
let i = this.options.extensions.renderers[r.type].call({ parser: this }, r);
|
|
1347
|
+
if (i !== false || !["escape", "html", "link", "image", "checkbox", "strong", "em", "codespan", "br", "del", "text"].includes(r.type)) {
|
|
1348
|
+
n += i || "";
|
|
1349
|
+
continue;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
let o = r;
|
|
1353
|
+
switch (o.type) {
|
|
1354
|
+
case "escape": {
|
|
1355
|
+
n += t.text(o);
|
|
1356
|
+
break;
|
|
1357
|
+
}
|
|
1358
|
+
case "html": {
|
|
1359
|
+
n += t.html(o);
|
|
1360
|
+
break;
|
|
1361
|
+
}
|
|
1362
|
+
case "link": {
|
|
1363
|
+
n += t.link(o);
|
|
1364
|
+
break;
|
|
1365
|
+
}
|
|
1366
|
+
case "image": {
|
|
1367
|
+
n += t.image(o);
|
|
1368
|
+
break;
|
|
1369
|
+
}
|
|
1370
|
+
case "checkbox": {
|
|
1371
|
+
n += t.checkbox(o);
|
|
1372
|
+
break;
|
|
1373
|
+
}
|
|
1374
|
+
case "strong": {
|
|
1375
|
+
n += t.strong(o);
|
|
1376
|
+
break;
|
|
1377
|
+
}
|
|
1378
|
+
case "em": {
|
|
1379
|
+
n += t.em(o);
|
|
1380
|
+
break;
|
|
1381
|
+
}
|
|
1382
|
+
case "codespan": {
|
|
1383
|
+
n += t.codespan(o);
|
|
1384
|
+
break;
|
|
1385
|
+
}
|
|
1386
|
+
case "br": {
|
|
1387
|
+
n += t.br(o);
|
|
1388
|
+
break;
|
|
1389
|
+
}
|
|
1390
|
+
case "del": {
|
|
1391
|
+
n += t.del(o);
|
|
1392
|
+
break;
|
|
1393
|
+
}
|
|
1394
|
+
case "text": {
|
|
1395
|
+
n += t.text(o);
|
|
1396
|
+
break;
|
|
1397
|
+
}
|
|
1398
|
+
default: {
|
|
1399
|
+
let i = 'Token with "' + o.type + '" type was not found.';
|
|
1400
|
+
if (this.options.silent) return console.error(i), "";
|
|
1401
|
+
throw new Error(i);
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
return n;
|
|
1406
|
+
}
|
|
1407
|
+
};
|
|
1408
|
+
var S = class {
|
|
1409
|
+
options;
|
|
1410
|
+
block;
|
|
1411
|
+
constructor(e) {
|
|
1412
|
+
this.options = e || T;
|
|
1413
|
+
}
|
|
1414
|
+
static passThroughHooks = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens", "emStrongMask"]);
|
|
1415
|
+
static passThroughHooksRespectAsync = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens"]);
|
|
1416
|
+
preprocess(e) {
|
|
1417
|
+
return e;
|
|
1418
|
+
}
|
|
1419
|
+
postprocess(e) {
|
|
1420
|
+
return e;
|
|
1421
|
+
}
|
|
1422
|
+
processAllTokens(e) {
|
|
1423
|
+
return e;
|
|
1424
|
+
}
|
|
1425
|
+
emStrongMask(e) {
|
|
1426
|
+
return e;
|
|
1427
|
+
}
|
|
1428
|
+
provideLexer(e = this.block) {
|
|
1429
|
+
return e ? x.lex : x.lexInline;
|
|
1430
|
+
}
|
|
1431
|
+
provideParser(e = this.block) {
|
|
1432
|
+
return e ? b.parse : b.parseInline;
|
|
1433
|
+
}
|
|
1434
|
+
};
|
|
1435
|
+
var Z = class {
|
|
1436
|
+
defaults = A();
|
|
1437
|
+
options = this.setOptions;
|
|
1438
|
+
parse = this.parseMarkdown(true);
|
|
1439
|
+
parseInline = this.parseMarkdown(false);
|
|
1440
|
+
Parser = b;
|
|
1441
|
+
Renderer = P;
|
|
1442
|
+
TextRenderer = L;
|
|
1443
|
+
Lexer = x;
|
|
1444
|
+
Tokenizer = y;
|
|
1445
|
+
Hooks = S;
|
|
1446
|
+
constructor(...e) {
|
|
1447
|
+
this.use(...e);
|
|
1448
|
+
}
|
|
1449
|
+
walkTokens(e, t) {
|
|
1450
|
+
let n = [];
|
|
1451
|
+
for (let s of e) switch (n = n.concat(t.call(this, s)), s.type) {
|
|
1452
|
+
case "table": {
|
|
1453
|
+
let r = s;
|
|
1454
|
+
for (let o of r.header) n = n.concat(this.walkTokens(o.tokens, t));
|
|
1455
|
+
for (let o of r.rows) for (let i of o) n = n.concat(this.walkTokens(i.tokens, t));
|
|
1456
|
+
break;
|
|
1457
|
+
}
|
|
1458
|
+
case "list": {
|
|
1459
|
+
let r = s;
|
|
1460
|
+
n = n.concat(this.walkTokens(r.items, t));
|
|
1461
|
+
break;
|
|
1462
|
+
}
|
|
1463
|
+
default: {
|
|
1464
|
+
let r = s;
|
|
1465
|
+
this.defaults.extensions?.childTokens?.[r.type] ? this.defaults.extensions.childTokens[r.type].forEach((o) => {
|
|
1466
|
+
let i = r[o].flat(1 / 0);
|
|
1467
|
+
n = n.concat(this.walkTokens(i, t));
|
|
1468
|
+
}) : r.tokens && (n = n.concat(this.walkTokens(r.tokens, t)));
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
return n;
|
|
1472
|
+
}
|
|
1473
|
+
use(...e) {
|
|
1474
|
+
let t = this.defaults.extensions || { renderers: {}, childTokens: {} };
|
|
1475
|
+
return e.forEach((n) => {
|
|
1476
|
+
let s = { ...n };
|
|
1477
|
+
if (s.async = this.defaults.async || s.async || false, n.extensions && (n.extensions.forEach((r) => {
|
|
1478
|
+
if (!r.name) throw new Error("extension name required");
|
|
1479
|
+
if ("renderer" in r) {
|
|
1480
|
+
let o = t.renderers[r.name];
|
|
1481
|
+
o ? t.renderers[r.name] = function(...i) {
|
|
1482
|
+
let l = r.renderer.apply(this, i);
|
|
1483
|
+
return l === false && (l = o.apply(this, i)), l;
|
|
1484
|
+
} : t.renderers[r.name] = r.renderer;
|
|
1485
|
+
}
|
|
1486
|
+
if ("tokenizer" in r) {
|
|
1487
|
+
if (!r.level || r.level !== "block" && r.level !== "inline") throw new Error("extension level must be 'block' or 'inline'");
|
|
1488
|
+
let o = t[r.level];
|
|
1489
|
+
o ? o.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]));
|
|
1490
|
+
}
|
|
1491
|
+
"childTokens" in r && r.childTokens && (t.childTokens[r.name] = r.childTokens);
|
|
1492
|
+
}), s.extensions = t), n.renderer) {
|
|
1493
|
+
let r = this.defaults.renderer || new P(this.defaults);
|
|
1494
|
+
for (let o in n.renderer) {
|
|
1495
|
+
if (!(o in r)) throw new Error(`renderer '${o}' does not exist`);
|
|
1496
|
+
if (["options", "parser"].includes(o)) continue;
|
|
1497
|
+
let i = o, l = n.renderer[i], a = r[i];
|
|
1498
|
+
r[i] = (...p) => {
|
|
1499
|
+
let c = l.apply(r, p);
|
|
1500
|
+
return c === false && (c = a.apply(r, p)), c || "";
|
|
1501
|
+
};
|
|
1502
|
+
}
|
|
1503
|
+
s.renderer = r;
|
|
1504
|
+
}
|
|
1505
|
+
if (n.tokenizer) {
|
|
1506
|
+
let r = this.defaults.tokenizer || new y(this.defaults);
|
|
1507
|
+
for (let o in n.tokenizer) {
|
|
1508
|
+
if (!(o in r)) throw new Error(`tokenizer '${o}' does not exist`);
|
|
1509
|
+
if (["options", "rules", "lexer"].includes(o)) continue;
|
|
1510
|
+
let i = o, l = n.tokenizer[i], a = r[i];
|
|
1511
|
+
r[i] = (...p) => {
|
|
1512
|
+
let c = l.apply(r, p);
|
|
1513
|
+
return c === false && (c = a.apply(r, p)), c;
|
|
1514
|
+
};
|
|
1515
|
+
}
|
|
1516
|
+
s.tokenizer = r;
|
|
1517
|
+
}
|
|
1518
|
+
if (n.hooks) {
|
|
1519
|
+
let r = this.defaults.hooks || new S();
|
|
1520
|
+
for (let o in n.hooks) {
|
|
1521
|
+
if (!(o in r)) throw new Error(`hook '${o}' does not exist`);
|
|
1522
|
+
if (["options", "block"].includes(o)) continue;
|
|
1523
|
+
let i = o, l = n.hooks[i], a = r[i];
|
|
1524
|
+
S.passThroughHooks.has(o) ? r[i] = (p) => {
|
|
1525
|
+
if (this.defaults.async && S.passThroughHooksRespectAsync.has(o)) return (async () => {
|
|
1526
|
+
let h = await l.call(r, p);
|
|
1527
|
+
return a.call(r, h);
|
|
1528
|
+
})();
|
|
1529
|
+
let c = l.call(r, p);
|
|
1530
|
+
return a.call(r, c);
|
|
1531
|
+
} : r[i] = (...p) => {
|
|
1532
|
+
if (this.defaults.async) return (async () => {
|
|
1533
|
+
let h = await l.apply(r, p);
|
|
1534
|
+
return h === false && (h = await a.apply(r, p)), h;
|
|
1535
|
+
})();
|
|
1536
|
+
let c = l.apply(r, p);
|
|
1537
|
+
return c === false && (c = a.apply(r, p)), c;
|
|
1538
|
+
};
|
|
1539
|
+
}
|
|
1540
|
+
s.hooks = r;
|
|
1541
|
+
}
|
|
1542
|
+
if (n.walkTokens) {
|
|
1543
|
+
let r = this.defaults.walkTokens, o = n.walkTokens;
|
|
1544
|
+
s.walkTokens = function(i) {
|
|
1545
|
+
let l = [];
|
|
1546
|
+
return l.push(o.call(this, i)), r && (l = l.concat(r.call(this, i))), l;
|
|
1547
|
+
};
|
|
1548
|
+
}
|
|
1549
|
+
this.defaults = { ...this.defaults, ...s };
|
|
1550
|
+
}), this;
|
|
1551
|
+
}
|
|
1552
|
+
setOptions(e) {
|
|
1553
|
+
return this.defaults = { ...this.defaults, ...e }, this;
|
|
1554
|
+
}
|
|
1555
|
+
lexer(e, t) {
|
|
1556
|
+
return x.lex(e, t ?? this.defaults);
|
|
1557
|
+
}
|
|
1558
|
+
parser(e, t) {
|
|
1559
|
+
return b.parse(e, t ?? this.defaults);
|
|
1560
|
+
}
|
|
1561
|
+
parseMarkdown(e) {
|
|
1562
|
+
return (n, s) => {
|
|
1563
|
+
let r = { ...s }, o = { ...this.defaults, ...r }, i = this.onError(!!o.silent, !!o.async);
|
|
1564
|
+
if (this.defaults.async === true && r.async === false) return i(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."));
|
|
1565
|
+
if (typeof n > "u" || n === null) return i(new Error("marked(): input parameter is undefined or null"));
|
|
1566
|
+
if (typeof n != "string") return i(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(n) + ", string expected"));
|
|
1567
|
+
if (o.hooks && (o.hooks.options = o, o.hooks.block = e), o.async) return (async () => {
|
|
1568
|
+
let l = o.hooks ? await o.hooks.preprocess(n) : n, p = await (o.hooks ? await o.hooks.provideLexer(e) : e ? x.lex : x.lexInline)(l, o), c = o.hooks ? await o.hooks.processAllTokens(p) : p;
|
|
1569
|
+
o.walkTokens && await Promise.all(this.walkTokens(c, o.walkTokens));
|
|
1570
|
+
let d = await (o.hooks ? await o.hooks.provideParser(e) : e ? b.parse : b.parseInline)(c, o);
|
|
1571
|
+
return o.hooks ? await o.hooks.postprocess(d) : d;
|
|
1572
|
+
})().catch(i);
|
|
1573
|
+
try {
|
|
1574
|
+
o.hooks && (n = o.hooks.preprocess(n));
|
|
1575
|
+
let a = (o.hooks ? o.hooks.provideLexer(e) : e ? x.lex : x.lexInline)(n, o);
|
|
1576
|
+
o.hooks && (a = o.hooks.processAllTokens(a)), o.walkTokens && this.walkTokens(a, o.walkTokens);
|
|
1577
|
+
let c = (o.hooks ? o.hooks.provideParser(e) : e ? b.parse : b.parseInline)(a, o);
|
|
1578
|
+
return o.hooks && (c = o.hooks.postprocess(c)), c;
|
|
1579
|
+
} catch (l) {
|
|
1580
|
+
return i(l);
|
|
1581
|
+
}
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1584
|
+
onError(e, t) {
|
|
1585
|
+
return (n) => {
|
|
1586
|
+
if (n.message += `
|
|
1587
|
+
Please report this to https://github.com/markedjs/marked.`, e) {
|
|
1588
|
+
let s = "<p>An error occurred:</p><pre>" + R(n.message + "", true) + "</pre>";
|
|
1589
|
+
return t ? Promise.resolve(s) : s;
|
|
1590
|
+
}
|
|
1591
|
+
if (t) return Promise.reject(n);
|
|
1592
|
+
throw n;
|
|
1593
|
+
};
|
|
1594
|
+
}
|
|
1595
|
+
};
|
|
1596
|
+
var M = new Z();
|
|
1597
|
+
function f(u3, e) {
|
|
1598
|
+
return M.parse(u3, e);
|
|
1599
|
+
}
|
|
1600
|
+
f.options = f.setOptions = function(u3) {
|
|
1601
|
+
return M.setOptions(u3), f.defaults = M.defaults, j(f.defaults), f;
|
|
1602
|
+
};
|
|
1603
|
+
f.getDefaults = A;
|
|
1604
|
+
f.defaults = T;
|
|
1605
|
+
function gt(...u3) {
|
|
1606
|
+
return M.use(...u3), f.defaults = M.defaults, j(f.defaults), f;
|
|
1607
|
+
}
|
|
1608
|
+
f.use = gt;
|
|
1609
|
+
f.walkTokens = function(u3, e) {
|
|
1610
|
+
return M.walkTokens(u3, e);
|
|
1611
|
+
};
|
|
1612
|
+
f.parseInline = M.parseInline;
|
|
1613
|
+
f.Parser = b;
|
|
1614
|
+
f.parser = b.parse;
|
|
1615
|
+
f.Renderer = P;
|
|
1616
|
+
f.TextRenderer = L;
|
|
1617
|
+
f.Lexer = x;
|
|
1618
|
+
f.lexer = x.lex;
|
|
1619
|
+
f.Tokenizer = y;
|
|
1620
|
+
f.Hooks = S;
|
|
1621
|
+
f.parse = f;
|
|
1622
|
+
f.options;
|
|
1623
|
+
f.setOptions;
|
|
1624
|
+
f.walkTokens;
|
|
1625
|
+
f.parseInline;
|
|
1626
|
+
b.parse;
|
|
1627
|
+
x.lex;
|
|
1628
|
+
|
|
1629
|
+
// ../../node_modules/dompurify/dist/purify.es.mjs
|
|
1630
|
+
function _arrayLikeToArray(r, a) {
|
|
1631
|
+
(null == a || a > r.length) && (a = r.length);
|
|
1632
|
+
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
|
|
1633
|
+
return n;
|
|
1634
|
+
}
|
|
1635
|
+
function _arrayWithHoles(r) {
|
|
1636
|
+
if (Array.isArray(r)) return r;
|
|
1637
|
+
}
|
|
1638
|
+
function _iterableToArrayLimit(r, l) {
|
|
1639
|
+
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
|
|
1640
|
+
if (null != t) {
|
|
1641
|
+
var e, n, i, u3, a = [], f2 = true, o = false;
|
|
1642
|
+
try {
|
|
1643
|
+
if (i = (t = t.call(r)).next, 0 === l) ;
|
|
1644
|
+
else for (; !(f2 = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f2 = true) ;
|
|
1645
|
+
} catch (r2) {
|
|
1646
|
+
o = true, n = r2;
|
|
1647
|
+
} finally {
|
|
1648
|
+
try {
|
|
1649
|
+
if (!f2 && null != t.return && (u3 = t.return(), Object(u3) !== u3)) return;
|
|
1650
|
+
} finally {
|
|
1651
|
+
if (o) throw n;
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
return a;
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
function _nonIterableRest() {
|
|
1658
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
1659
|
+
}
|
|
1660
|
+
function _slicedToArray(r, e) {
|
|
1661
|
+
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
|
|
1662
|
+
}
|
|
1663
|
+
function _unsupportedIterableToArray(r, a) {
|
|
1664
|
+
if (r) {
|
|
1665
|
+
if ("string" == typeof r) return _arrayLikeToArray(r, a);
|
|
1666
|
+
var t = {}.toString.call(r).slice(8, -1);
|
|
1667
|
+
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;
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
var entries = Object.entries;
|
|
1671
|
+
var setPrototypeOf = Object.setPrototypeOf;
|
|
1672
|
+
var isFrozen = Object.isFrozen;
|
|
1673
|
+
var getPrototypeOf = Object.getPrototypeOf;
|
|
1674
|
+
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
1675
|
+
var freeze = Object.freeze;
|
|
1676
|
+
var seal = Object.seal;
|
|
1677
|
+
var create = Object.create;
|
|
1678
|
+
var _ref = typeof Reflect !== "undefined" && Reflect;
|
|
1679
|
+
var apply = _ref.apply;
|
|
1680
|
+
var construct = _ref.construct;
|
|
1681
|
+
if (!freeze) {
|
|
1682
|
+
freeze = function freeze2(x2) {
|
|
1683
|
+
return x2;
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
if (!seal) {
|
|
1687
|
+
seal = function seal2(x2) {
|
|
1688
|
+
return x2;
|
|
1689
|
+
};
|
|
1690
|
+
}
|
|
1691
|
+
if (!apply) {
|
|
1692
|
+
apply = function apply2(func, thisArg) {
|
|
1693
|
+
for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
|
|
1694
|
+
args[_key - 2] = arguments[_key];
|
|
1695
|
+
}
|
|
1696
|
+
return func.apply(thisArg, args);
|
|
1697
|
+
};
|
|
1698
|
+
}
|
|
1699
|
+
if (!construct) {
|
|
1700
|
+
construct = function construct2(Func) {
|
|
1701
|
+
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
|
|
1702
|
+
args[_key2 - 1] = arguments[_key2];
|
|
1703
|
+
}
|
|
1704
|
+
return new Func(...args);
|
|
1705
|
+
};
|
|
1706
|
+
}
|
|
1707
|
+
var arrayForEach = unapply(Array.prototype.forEach);
|
|
1708
|
+
var arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);
|
|
1709
|
+
var arrayPop = unapply(Array.prototype.pop);
|
|
1710
|
+
var arrayPush = unapply(Array.prototype.push);
|
|
1711
|
+
var arraySplice = unapply(Array.prototype.splice);
|
|
1712
|
+
var arrayIsArray = Array.isArray;
|
|
1713
|
+
var stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
1714
|
+
var stringToString = unapply(String.prototype.toString);
|
|
1715
|
+
var stringMatch = unapply(String.prototype.match);
|
|
1716
|
+
var stringReplace = unapply(String.prototype.replace);
|
|
1717
|
+
var stringIndexOf = unapply(String.prototype.indexOf);
|
|
1718
|
+
var stringTrim = unapply(String.prototype.trim);
|
|
1719
|
+
var numberToString = unapply(Number.prototype.toString);
|
|
1720
|
+
var booleanToString = unapply(Boolean.prototype.toString);
|
|
1721
|
+
var bigintToString = typeof BigInt === "undefined" ? null : unapply(BigInt.prototype.toString);
|
|
1722
|
+
var symbolToString = typeof Symbol === "undefined" ? null : unapply(Symbol.prototype.toString);
|
|
1723
|
+
var objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
|
|
1724
|
+
var objectToString = unapply(Object.prototype.toString);
|
|
1725
|
+
var regExpTest = unapply(RegExp.prototype.test);
|
|
1726
|
+
var typeErrorCreate = unconstruct(TypeError);
|
|
1727
|
+
function unapply(func) {
|
|
1728
|
+
return function(thisArg) {
|
|
1729
|
+
if (thisArg instanceof RegExp) {
|
|
1730
|
+
thisArg.lastIndex = 0;
|
|
1731
|
+
}
|
|
1732
|
+
for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
|
|
1733
|
+
args[_key3 - 1] = arguments[_key3];
|
|
1734
|
+
}
|
|
1735
|
+
return apply(func, thisArg, args);
|
|
1736
|
+
};
|
|
1737
|
+
}
|
|
1738
|
+
function unconstruct(Func) {
|
|
1739
|
+
return function() {
|
|
1740
|
+
for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
|
|
1741
|
+
args[_key4] = arguments[_key4];
|
|
1742
|
+
}
|
|
1743
|
+
return construct(Func, args);
|
|
1744
|
+
};
|
|
1745
|
+
}
|
|
1746
|
+
function addToSet(set, array) {
|
|
1747
|
+
let transformCaseFunc = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : stringToLowerCase;
|
|
1748
|
+
if (setPrototypeOf) {
|
|
1749
|
+
setPrototypeOf(set, null);
|
|
1750
|
+
}
|
|
1751
|
+
if (!arrayIsArray(array)) {
|
|
1752
|
+
return set;
|
|
1753
|
+
}
|
|
1754
|
+
let l = array.length;
|
|
1755
|
+
while (l--) {
|
|
1756
|
+
let element = array[l];
|
|
1757
|
+
if (typeof element === "string") {
|
|
1758
|
+
const lcElement = transformCaseFunc(element);
|
|
1759
|
+
if (lcElement !== element) {
|
|
1760
|
+
if (!isFrozen(array)) {
|
|
1761
|
+
array[l] = lcElement;
|
|
1762
|
+
}
|
|
1763
|
+
element = lcElement;
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
set[element] = true;
|
|
1767
|
+
}
|
|
1768
|
+
return set;
|
|
1769
|
+
}
|
|
1770
|
+
function cleanArray(array) {
|
|
1771
|
+
for (let index = 0; index < array.length; index++) {
|
|
1772
|
+
const isPropertyExist = objectHasOwnProperty(array, index);
|
|
1773
|
+
if (!isPropertyExist) {
|
|
1774
|
+
array[index] = null;
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
return array;
|
|
1778
|
+
}
|
|
1779
|
+
function clone(object) {
|
|
1780
|
+
const newObject = create(null);
|
|
1781
|
+
for (const _ref2 of entries(object)) {
|
|
1782
|
+
var _ref3 = _slicedToArray(_ref2, 2);
|
|
1783
|
+
const property = _ref3[0];
|
|
1784
|
+
const value = _ref3[1];
|
|
1785
|
+
const isPropertyExist = objectHasOwnProperty(object, property);
|
|
1786
|
+
if (isPropertyExist) {
|
|
1787
|
+
if (arrayIsArray(value)) {
|
|
1788
|
+
newObject[property] = cleanArray(value);
|
|
1789
|
+
} else if (value && typeof value === "object" && value.constructor === Object) {
|
|
1790
|
+
newObject[property] = clone(value);
|
|
1791
|
+
} else {
|
|
1792
|
+
newObject[property] = value;
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
return newObject;
|
|
1797
|
+
}
|
|
1798
|
+
function stringifyValue(value) {
|
|
1799
|
+
switch (typeof value) {
|
|
1800
|
+
case "string": {
|
|
1801
|
+
return value;
|
|
1802
|
+
}
|
|
1803
|
+
case "number": {
|
|
1804
|
+
return numberToString(value);
|
|
1805
|
+
}
|
|
1806
|
+
case "boolean": {
|
|
1807
|
+
return booleanToString(value);
|
|
1808
|
+
}
|
|
1809
|
+
case "bigint": {
|
|
1810
|
+
return bigintToString ? bigintToString(value) : "0";
|
|
1811
|
+
}
|
|
1812
|
+
case "symbol": {
|
|
1813
|
+
return symbolToString ? symbolToString(value) : "Symbol()";
|
|
1814
|
+
}
|
|
1815
|
+
case "undefined": {
|
|
1816
|
+
return objectToString(value);
|
|
1817
|
+
}
|
|
1818
|
+
case "function":
|
|
1819
|
+
case "object": {
|
|
1820
|
+
if (value === null) {
|
|
1821
|
+
return objectToString(value);
|
|
1822
|
+
}
|
|
1823
|
+
const valueAsRecord = value;
|
|
1824
|
+
const valueToString = lookupGetter(valueAsRecord, "toString");
|
|
1825
|
+
if (typeof valueToString === "function") {
|
|
1826
|
+
const stringified = valueToString(valueAsRecord);
|
|
1827
|
+
return typeof stringified === "string" ? stringified : objectToString(stringified);
|
|
1828
|
+
}
|
|
1829
|
+
return objectToString(value);
|
|
1830
|
+
}
|
|
1831
|
+
default: {
|
|
1832
|
+
return objectToString(value);
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
function lookupGetter(object, prop) {
|
|
1837
|
+
while (object !== null) {
|
|
1838
|
+
const desc = getOwnPropertyDescriptor(object, prop);
|
|
1839
|
+
if (desc) {
|
|
1840
|
+
if (desc.get) {
|
|
1841
|
+
return unapply(desc.get);
|
|
1842
|
+
}
|
|
1843
|
+
if (typeof desc.value === "function") {
|
|
1844
|
+
return unapply(desc.value);
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
object = getPrototypeOf(object);
|
|
1848
|
+
}
|
|
1849
|
+
function fallbackValue() {
|
|
1850
|
+
return null;
|
|
1851
|
+
}
|
|
1852
|
+
return fallbackValue;
|
|
1853
|
+
}
|
|
1854
|
+
function isRegex(value) {
|
|
1855
|
+
try {
|
|
1856
|
+
regExpTest(value, "");
|
|
1857
|
+
return true;
|
|
1858
|
+
} catch (_unused) {
|
|
1859
|
+
return false;
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
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"]);
|
|
1863
|
+
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"]);
|
|
1864
|
+
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"]);
|
|
1865
|
+
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"]);
|
|
1866
|
+
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"]);
|
|
1867
|
+
var mathMlDisallowed = freeze(["maction", "maligngroup", "malignmark", "mlongdiv", "mscarries", "mscarry", "msgroup", "mstack", "msline", "msrow", "semantics", "annotation", "annotation-xml", "mprescripts", "none"]);
|
|
1868
|
+
var text = freeze(["#text"]);
|
|
1869
|
+
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"]);
|
|
1870
|
+
var svg = freeze(["accent-height", "accumulate", "additive", "alignment-baseline", "amplitude", "ascent", "attributename", "attributetype", "azimuth", "basefrequency", "baseline-shift", "begin", "bias", "by", "class", "clip", "clippathunits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "cx", "cy", "d", "dx", "dy", "diffuseconstant", "direction", "display", "divisor", "dominant-baseline", "dur", "edgemode", "elevation", "end", "exponent", "fill", "fill-opacity", "fill-rule", "filter", "filterunits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "fx", "fy", "g1", "g2", "glyph-name", "glyphref", "gradientunits", "gradienttransform", "height", "href", "id", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kerning", "keypoints", "keysplines", "keytimes", "lang", "lengthadjust", "letter-spacing", "kernelmatrix", "kernelunitlength", "lighting-color", "local", "marker-end", "marker-mid", "marker-start", "markerheight", "markerunits", "markerwidth", "maskcontentunits", "maskunits", "max", "mask", "mask-type", "media", "method", "mode", "min", "name", "numoctaves", "offset", "operator", "opacity", "order", "orient", "orientation", "origin", "overflow", "paint-order", "path", "pathlength", "patterncontentunits", "patterntransform", "patternunits", "pointer-events", "points", "preservealpha", "preserveaspectratio", "primitiveunits", "r", "rx", "ry", "radius", "refx", "refy", "repeatcount", "repeatdur", "restart", "result", "rotate", "scale", "seed", "shape-rendering", "slope", "specularconstant", "specularexponent", "spreadmethod", "startoffset", "stddeviation", "stitchtiles", "stop-color", "stop-opacity", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke", "stroke-width", "style", "surfacescale", "systemlanguage", "tabindex", "tablevalues", "targetx", "targety", "transform", "transform-origin", "text-anchor", "text-decoration", "text-orientation", "text-rendering", "textlength", "type", "u1", "u2", "unicode", "values", "vector-effect", "viewbox", "visibility", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "width", "word-spacing", "wrap", "writing-mode", "xchannelselector", "ychannelselector", "x", "x1", "x2", "xmlns", "y", "y1", "y2", "z", "zoomandpan"]);
|
|
1871
|
+
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"]);
|
|
1872
|
+
var xml = freeze(["xlink:href", "xml:id", "xlink:title", "xml:space", "xmlns:xlink"]);
|
|
1873
|
+
var MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g);
|
|
1874
|
+
var ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g);
|
|
1875
|
+
var TMPLIT_EXPR = seal(/\${[\w\W]*/g);
|
|
1876
|
+
var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/);
|
|
1877
|
+
var ARIA_ATTR = seal(/^aria-[\-\w]+$/);
|
|
1878
|
+
var IS_ALLOWED_URI = seal(
|
|
1879
|
+
/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i
|
|
1880
|
+
// eslint-disable-line no-useless-escape
|
|
1881
|
+
);
|
|
1882
|
+
var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
|
|
1883
|
+
var ATTR_WHITESPACE = seal(
|
|
1884
|
+
/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g
|
|
1885
|
+
// eslint-disable-line no-control-regex
|
|
1886
|
+
);
|
|
1887
|
+
var DOCTYPE_NAME = seal(/^html$/i);
|
|
1888
|
+
var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
|
|
1889
|
+
var ELEMENT_MARKUP_PROBE = seal(/<[/\w!]/g);
|
|
1890
|
+
var COMMENT_MARKUP_PROBE = seal(/<[/\w]/g);
|
|
1891
|
+
var FALLBACK_TAG_CLOSE = seal(/<\/no(script|embed|frames)/i);
|
|
1892
|
+
var SELF_CLOSING_TAG = seal(/\/>/i);
|
|
1893
|
+
var NODE_TYPE = {
|
|
1894
|
+
element: 1,
|
|
1895
|
+
attribute: 2,
|
|
1896
|
+
text: 3,
|
|
1897
|
+
cdataSection: 4,
|
|
1898
|
+
entityReference: 5,
|
|
1899
|
+
// Deprecated
|
|
1900
|
+
entityNode: 6,
|
|
1901
|
+
// Deprecated
|
|
1902
|
+
processingInstruction: 7,
|
|
1903
|
+
comment: 8,
|
|
1904
|
+
document: 9,
|
|
1905
|
+
documentType: 10,
|
|
1906
|
+
documentFragment: 11,
|
|
1907
|
+
notation: 12
|
|
1908
|
+
// Deprecated
|
|
1909
|
+
};
|
|
1910
|
+
var LITERAL_TEXT_ELEMENT_NAMES = ["style", "script", "xmp", "iframe", "noembed", "noframes", "plaintext", "noscript"];
|
|
1911
|
+
var LITERAL_TEXT_ELEMENTS = freeze(addToSet({}, LITERAL_TEXT_ELEMENT_NAMES));
|
|
1912
|
+
var LITERAL_TEXT_CLOSE = (function() {
|
|
1913
|
+
const map = {};
|
|
1914
|
+
arrayForEach(LITERAL_TEXT_ELEMENT_NAMES, (name) => {
|
|
1915
|
+
map[name] = seal(new RegExp("</" + name + "(?=[\\t\\n\\f\\r />])", "i"));
|
|
1916
|
+
});
|
|
1917
|
+
return freeze(map);
|
|
1918
|
+
})();
|
|
1919
|
+
var getGlobal = function getGlobal2() {
|
|
1920
|
+
return typeof window === "undefined" ? null : window;
|
|
1921
|
+
};
|
|
1922
|
+
var _createTrustedTypesPolicy = function _createTrustedTypesPolicy2(trustedTypes, purifyHostElement) {
|
|
1923
|
+
if (typeof trustedTypes !== "object" || typeof trustedTypes.createPolicy !== "function") {
|
|
1924
|
+
return null;
|
|
1925
|
+
}
|
|
1926
|
+
let suffix = null;
|
|
1927
|
+
const ATTR_NAME = "data-tt-policy-suffix";
|
|
1928
|
+
if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {
|
|
1929
|
+
suffix = purifyHostElement.getAttribute(ATTR_NAME);
|
|
1930
|
+
}
|
|
1931
|
+
const policyName = "dompurify" + (suffix ? "#" + suffix : "");
|
|
1932
|
+
try {
|
|
1933
|
+
return trustedTypes.createPolicy(policyName, {
|
|
1934
|
+
createHTML(html2) {
|
|
1935
|
+
return html2;
|
|
1936
|
+
},
|
|
1937
|
+
createScriptURL(scriptUrl) {
|
|
1938
|
+
return scriptUrl;
|
|
1939
|
+
}
|
|
1940
|
+
});
|
|
1941
|
+
} catch (_2) {
|
|
1942
|
+
console.warn("TrustedTypes policy " + policyName + " could not be created.");
|
|
1943
|
+
return null;
|
|
1944
|
+
}
|
|
1945
|
+
};
|
|
1946
|
+
var _createHooksMap = function _createHooksMap2() {
|
|
1947
|
+
return {
|
|
1948
|
+
afterSanitizeAttributes: [],
|
|
1949
|
+
afterSanitizeElements: [],
|
|
1950
|
+
afterSanitizeShadowDOM: [],
|
|
1951
|
+
beforeSanitizeAttributes: [],
|
|
1952
|
+
beforeSanitizeElements: [],
|
|
1953
|
+
beforeSanitizeShadowDOM: [],
|
|
1954
|
+
uponSanitizeAttribute: [],
|
|
1955
|
+
uponSanitizeElement: [],
|
|
1956
|
+
uponSanitizeShadowNode: []
|
|
1957
|
+
};
|
|
1958
|
+
};
|
|
1959
|
+
var _resolveSetOption = function _resolveSetOption2(cfg, key, fallback, options) {
|
|
1960
|
+
return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback;
|
|
1961
|
+
};
|
|
1962
|
+
var _resolveObjectOption = function _resolveObjectOption2(cfg, key, makeFallback) {
|
|
1963
|
+
const value = objectHasOwnProperty(cfg, key) ? cfg[key] : void 0;
|
|
1964
|
+
return value && typeof value === "object" ? clone(value) : makeFallback();
|
|
1965
|
+
};
|
|
1966
|
+
function createDOMPurify() {
|
|
1967
|
+
let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal();
|
|
1968
|
+
const DOMPurify = (root) => createDOMPurify(root);
|
|
1969
|
+
DOMPurify.version = "3.4.15";
|
|
1970
|
+
DOMPurify.removed = [];
|
|
1971
|
+
if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) {
|
|
1972
|
+
DOMPurify.isSupported = false;
|
|
1973
|
+
return DOMPurify;
|
|
1974
|
+
}
|
|
1975
|
+
let document = window2.document;
|
|
1976
|
+
const originalDocument = document;
|
|
1977
|
+
const currentScript = originalDocument.currentScript;
|
|
1978
|
+
window2.DocumentFragment;
|
|
1979
|
+
const HTMLTemplateElement = window2.HTMLTemplateElement, Node = window2.Node, Element = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap;
|
|
1980
|
+
_window$NamedNodeMap === void 0 ? window2.NamedNodeMap || window2.MozNamedAttrMap : _window$NamedNodeMap;
|
|
1981
|
+
window2.HTMLFormElement;
|
|
1982
|
+
const DOMParser = window2.DOMParser, trustedTypes = window2.trustedTypes;
|
|
1983
|
+
const ElementPrototype = Element.prototype;
|
|
1984
|
+
const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
|
|
1985
|
+
const remove = lookupGetter(ElementPrototype, "remove");
|
|
1986
|
+
const removeAttributeNode = lookupGetter(ElementPrototype, "removeAttributeNode");
|
|
1987
|
+
const getNextSibling = lookupGetter(ElementPrototype, "nextSibling");
|
|
1988
|
+
const getChildNodes = lookupGetter(ElementPrototype, "childNodes");
|
|
1989
|
+
const getParentNode = lookupGetter(ElementPrototype, "parentNode");
|
|
1990
|
+
const getShadowRoot = lookupGetter(ElementPrototype, "shadowRoot");
|
|
1991
|
+
const getAttributes = lookupGetter(ElementPrototype, "attributes");
|
|
1992
|
+
const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeType") : null;
|
|
1993
|
+
const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeName") : null;
|
|
1994
|
+
const getOwnerDocument = Node && Node.prototype ? lookupGetter(Node.prototype, "ownerDocument") : null;
|
|
1995
|
+
const _readNodeType = function _readNodeType2(node) {
|
|
1996
|
+
return getNodeType ? getNodeType(node) : node.nodeType;
|
|
1997
|
+
};
|
|
1998
|
+
const _readNodeName = function _readNodeName2(node) {
|
|
1999
|
+
return getNodeName ? getNodeName(node) : node.nodeName;
|
|
2000
|
+
};
|
|
2001
|
+
if (typeof HTMLTemplateElement === "function") {
|
|
2002
|
+
const template = document.createElement("template");
|
|
2003
|
+
if (template.content && template.content.ownerDocument) {
|
|
2004
|
+
document = template.content.ownerDocument;
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
let trustedTypesPolicy;
|
|
2008
|
+
let emptyHTML = "";
|
|
2009
|
+
let defaultTrustedTypesPolicy;
|
|
2010
|
+
let defaultTrustedTypesPolicyResolved = false;
|
|
2011
|
+
let IN_TRUSTED_TYPES_POLICY = 0;
|
|
2012
|
+
const _assertNotInTrustedTypesPolicy = function _assertNotInTrustedTypesPolicy2() {
|
|
2013
|
+
if (IN_TRUSTED_TYPES_POLICY > 0) {
|
|
2014
|
+
throw typeErrorCreate('A configured TRUSTED_TYPES_POLICY callback (createHTML or createScriptURL) must not call DOMPurify.sanitize, as that causes infinite recursion. Do not pass a policy whose callbacks wrap DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted Types" section of the README.');
|
|
2015
|
+
}
|
|
2016
|
+
};
|
|
2017
|
+
const _createTrustedHTML = function _createTrustedHTML2(html2) {
|
|
2018
|
+
_assertNotInTrustedTypesPolicy();
|
|
2019
|
+
IN_TRUSTED_TYPES_POLICY++;
|
|
2020
|
+
try {
|
|
2021
|
+
return trustedTypesPolicy.createHTML(html2);
|
|
2022
|
+
} finally {
|
|
2023
|
+
IN_TRUSTED_TYPES_POLICY--;
|
|
2024
|
+
}
|
|
2025
|
+
};
|
|
2026
|
+
const _createTrustedScriptURL = function _createTrustedScriptURL2(scriptUrl) {
|
|
2027
|
+
_assertNotInTrustedTypesPolicy();
|
|
2028
|
+
IN_TRUSTED_TYPES_POLICY++;
|
|
2029
|
+
try {
|
|
2030
|
+
return trustedTypesPolicy.createScriptURL(scriptUrl);
|
|
2031
|
+
} finally {
|
|
2032
|
+
IN_TRUSTED_TYPES_POLICY--;
|
|
2033
|
+
}
|
|
2034
|
+
};
|
|
2035
|
+
const _getDefaultTrustedTypesPolicy = function _getDefaultTrustedTypesPolicy2() {
|
|
2036
|
+
if (!defaultTrustedTypesPolicyResolved) {
|
|
2037
|
+
defaultTrustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
|
|
2038
|
+
defaultTrustedTypesPolicyResolved = true;
|
|
2039
|
+
}
|
|
2040
|
+
return defaultTrustedTypesPolicy;
|
|
2041
|
+
};
|
|
2042
|
+
const _document = document, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName;
|
|
2043
|
+
const importNode = originalDocument.importNode;
|
|
2044
|
+
let hooks = _createHooksMap();
|
|
2045
|
+
DOMPurify.isSupported = typeof entries === "function" && typeof getParentNode === "function" && implementation && implementation.createHTMLDocument !== void 0;
|
|
2046
|
+
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;
|
|
2047
|
+
let IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
|
|
2048
|
+
let ALLOWED_TAGS2 = null;
|
|
2049
|
+
const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);
|
|
2050
|
+
let ALLOWED_ATTR2 = null;
|
|
2051
|
+
const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);
|
|
2052
|
+
let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {
|
|
2053
|
+
tagNameCheck: {
|
|
2054
|
+
writable: true,
|
|
2055
|
+
configurable: false,
|
|
2056
|
+
enumerable: true,
|
|
2057
|
+
value: null
|
|
2058
|
+
},
|
|
2059
|
+
attributeNameCheck: {
|
|
2060
|
+
writable: true,
|
|
2061
|
+
configurable: false,
|
|
2062
|
+
enumerable: true,
|
|
2063
|
+
value: null
|
|
2064
|
+
},
|
|
2065
|
+
allowCustomizedBuiltInElements: {
|
|
2066
|
+
writable: true,
|
|
2067
|
+
configurable: false,
|
|
2068
|
+
enumerable: true,
|
|
2069
|
+
value: false
|
|
2070
|
+
}
|
|
2071
|
+
}));
|
|
2072
|
+
let FORBID_TAGS = null;
|
|
2073
|
+
let FORBID_ATTR = null;
|
|
2074
|
+
const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {
|
|
2075
|
+
tagCheck: {
|
|
2076
|
+
writable: true,
|
|
2077
|
+
configurable: false,
|
|
2078
|
+
enumerable: true,
|
|
2079
|
+
value: null
|
|
2080
|
+
},
|
|
2081
|
+
attributeCheck: {
|
|
2082
|
+
writable: true,
|
|
2083
|
+
configurable: false,
|
|
2084
|
+
enumerable: true,
|
|
2085
|
+
value: null
|
|
2086
|
+
}
|
|
2087
|
+
}));
|
|
2088
|
+
let ALLOW_ARIA_ATTR = true;
|
|
2089
|
+
let ALLOW_DATA_ATTR = true;
|
|
2090
|
+
let ALLOW_UNKNOWN_PROTOCOLS = false;
|
|
2091
|
+
let ALLOW_SELF_CLOSE_IN_ATTR = true;
|
|
2092
|
+
let SAFE_FOR_TEMPLATES = false;
|
|
2093
|
+
let SAFE_FOR_XML = true;
|
|
2094
|
+
let WHOLE_DOCUMENT = false;
|
|
2095
|
+
let SET_CONFIG = false;
|
|
2096
|
+
let SET_CONFIG_ALLOWED_TAGS = null;
|
|
2097
|
+
let SET_CONFIG_ALLOWED_ATTR = null;
|
|
2098
|
+
let FORCE_BODY = false;
|
|
2099
|
+
let RETURN_DOM = false;
|
|
2100
|
+
let RETURN_DOM_FRAGMENT = false;
|
|
2101
|
+
let RETURN_TRUSTED_TYPE = false;
|
|
2102
|
+
let SANITIZE_DOM = true;
|
|
2103
|
+
let SANITIZE_NAMED_PROPS = false;
|
|
2104
|
+
const SANITIZE_NAMED_PROPS_PREFIX = "user-content-";
|
|
2105
|
+
let KEEP_CONTENT = true;
|
|
2106
|
+
let IN_PLACE = false;
|
|
2107
|
+
let USE_PROFILES = {};
|
|
2108
|
+
let FORBID_CONTENTS = null;
|
|
2109
|
+
const DEFAULT_FORBID_CONTENTS = addToSet({}, [
|
|
2110
|
+
"annotation-xml",
|
|
2111
|
+
"audio",
|
|
2112
|
+
"colgroup",
|
|
2113
|
+
"desc",
|
|
2114
|
+
"foreignobject",
|
|
2115
|
+
"head",
|
|
2116
|
+
"iframe",
|
|
2117
|
+
"math",
|
|
2118
|
+
"mi",
|
|
2119
|
+
"mn",
|
|
2120
|
+
"mo",
|
|
2121
|
+
"ms",
|
|
2122
|
+
"mtext",
|
|
2123
|
+
"noembed",
|
|
2124
|
+
"noframes",
|
|
2125
|
+
"noscript",
|
|
2126
|
+
"plaintext",
|
|
2127
|
+
"script",
|
|
2128
|
+
// <selectedcontent> mirrors the selected <option>'s subtree, cloned by
|
|
2129
|
+
// the UA (customizable <select>) — including any on* handlers — and the
|
|
2130
|
+
// engine re-mirrors synchronously whenever a removal changes which
|
|
2131
|
+
// option/selectedcontent is current, even inside DOMPurify's inert
|
|
2132
|
+
// DOMParser document. Hoisting its children on removal re-inserts a fresh
|
|
2133
|
+
// mirror target ahead of the walk, which the engine refills, looping
|
|
2134
|
+
// forever (DoS) and amplifying output. Dropping its content on removal
|
|
2135
|
+
// (rather than hoisting) breaks that cascade; the content is a duplicate
|
|
2136
|
+
// of the option, which is sanitized on its own. See campaign-3 F1/F6.
|
|
2137
|
+
"selectedcontent",
|
|
2138
|
+
"style",
|
|
2139
|
+
"svg",
|
|
2140
|
+
"template",
|
|
2141
|
+
"thead",
|
|
2142
|
+
"title",
|
|
2143
|
+
"video",
|
|
2144
|
+
"xmp"
|
|
2145
|
+
]);
|
|
2146
|
+
let DATA_URI_TAGS = null;
|
|
2147
|
+
const DEFAULT_DATA_URI_TAGS = addToSet({}, ["audio", "video", "img", "source", "image", "track"]);
|
|
2148
|
+
let URI_SAFE_ATTRIBUTES = null;
|
|
2149
|
+
const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ["alt", "class", "for", "id", "label", "name", "pattern", "placeholder", "role", "summary", "title", "value", "style", "xmlns"]);
|
|
2150
|
+
const MATHML_NAMESPACE = "http://www.w3.org/1998/Math/MathML";
|
|
2151
|
+
const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
2152
|
+
const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
|
2153
|
+
let NAMESPACE = HTML_NAMESPACE;
|
|
2154
|
+
let IS_EMPTY_INPUT = false;
|
|
2155
|
+
let ALLOWED_NAMESPACES = null;
|
|
2156
|
+
const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
|
|
2157
|
+
const DEFAULT_MATHML_TEXT_INTEGRATION_POINTS = freeze(["mi", "mo", "mn", "ms", "mtext"]);
|
|
2158
|
+
let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS);
|
|
2159
|
+
const DEFAULT_HTML_INTEGRATION_POINTS = freeze(["annotation-xml"]);
|
|
2160
|
+
let HTML_INTEGRATION_POINTS = addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS);
|
|
2161
|
+
const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ["title", "style", "font", "a", "script"]);
|
|
2162
|
+
let PARSER_MEDIA_TYPE = null;
|
|
2163
|
+
const SUPPORTED_PARSER_MEDIA_TYPES = ["application/xhtml+xml", "text/html"];
|
|
2164
|
+
const DEFAULT_PARSER_MEDIA_TYPE = "text/html";
|
|
2165
|
+
let transformCaseFunc = null;
|
|
2166
|
+
let CONFIG = null;
|
|
2167
|
+
const formElement = document.createElement("form");
|
|
2168
|
+
const isRegexOrFunction = function isRegexOrFunction2(testValue) {
|
|
2169
|
+
return testValue instanceof RegExp || testValue instanceof Function;
|
|
2170
|
+
};
|
|
2171
|
+
const _parseConfig = function _parseConfig2() {
|
|
2172
|
+
let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
|
2173
|
+
if (CONFIG && CONFIG === cfg) {
|
|
2174
|
+
return;
|
|
2175
|
+
}
|
|
2176
|
+
if (!cfg || typeof cfg !== "object") {
|
|
2177
|
+
cfg = {};
|
|
2178
|
+
}
|
|
2179
|
+
cfg = clone(cfg);
|
|
2180
|
+
PARSER_MEDIA_TYPE = // eslint-disable-next-line unicorn/prefer-includes
|
|
2181
|
+
SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;
|
|
2182
|
+
transformCaseFunc = PARSER_MEDIA_TYPE === "application/xhtml+xml" ? stringToString : stringToLowerCase;
|
|
2183
|
+
ALLOWED_TAGS2 = _resolveSetOption(cfg, "ALLOWED_TAGS", DEFAULT_ALLOWED_TAGS, {
|
|
2184
|
+
transform: transformCaseFunc
|
|
2185
|
+
});
|
|
2186
|
+
ALLOWED_ATTR2 = _resolveSetOption(cfg, "ALLOWED_ATTR", DEFAULT_ALLOWED_ATTR, {
|
|
2187
|
+
transform: transformCaseFunc
|
|
2188
|
+
});
|
|
2189
|
+
ALLOWED_NAMESPACES = _resolveSetOption(cfg, "ALLOWED_NAMESPACES", DEFAULT_ALLOWED_NAMESPACES, {
|
|
2190
|
+
transform: stringToString
|
|
2191
|
+
});
|
|
2192
|
+
URI_SAFE_ATTRIBUTES = _resolveSetOption(cfg, "ADD_URI_SAFE_ATTR", DEFAULT_URI_SAFE_ATTRIBUTES, {
|
|
2193
|
+
transform: transformCaseFunc,
|
|
2194
|
+
base: DEFAULT_URI_SAFE_ATTRIBUTES
|
|
2195
|
+
});
|
|
2196
|
+
DATA_URI_TAGS = _resolveSetOption(cfg, "ADD_DATA_URI_TAGS", DEFAULT_DATA_URI_TAGS, {
|
|
2197
|
+
transform: transformCaseFunc,
|
|
2198
|
+
base: DEFAULT_DATA_URI_TAGS
|
|
2199
|
+
});
|
|
2200
|
+
FORBID_CONTENTS = _resolveSetOption(cfg, "FORBID_CONTENTS", DEFAULT_FORBID_CONTENTS, {
|
|
2201
|
+
transform: transformCaseFunc
|
|
2202
|
+
});
|
|
2203
|
+
FORBID_TAGS = _resolveSetOption(cfg, "FORBID_TAGS", clone({}), {
|
|
2204
|
+
transform: transformCaseFunc
|
|
2205
|
+
});
|
|
2206
|
+
FORBID_ATTR = _resolveSetOption(cfg, "FORBID_ATTR", clone({}), {
|
|
2207
|
+
transform: transformCaseFunc
|
|
2208
|
+
});
|
|
2209
|
+
USE_PROFILES = objectHasOwnProperty(cfg, "USE_PROFILES") ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === "object" ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false;
|
|
2210
|
+
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
|
|
2211
|
+
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
|
|
2212
|
+
ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false;
|
|
2213
|
+
ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false;
|
|
2214
|
+
SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false;
|
|
2215
|
+
SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false;
|
|
2216
|
+
WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false;
|
|
2217
|
+
RETURN_DOM = cfg.RETURN_DOM || false;
|
|
2218
|
+
RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false;
|
|
2219
|
+
RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
|
|
2220
|
+
FORCE_BODY = cfg.FORCE_BODY || false;
|
|
2221
|
+
SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
|
|
2222
|
+
SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false;
|
|
2223
|
+
KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
|
|
2224
|
+
IN_PLACE = cfg.IN_PLACE || false;
|
|
2225
|
+
IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI;
|
|
2226
|
+
NAMESPACE = typeof cfg.NAMESPACE === "string" ? cfg.NAMESPACE : HTML_NAMESPACE;
|
|
2227
|
+
MATHML_TEXT_INTEGRATION_POINTS = _resolveObjectOption(
|
|
2228
|
+
cfg,
|
|
2229
|
+
"MATHML_TEXT_INTEGRATION_POINTS",
|
|
2230
|
+
() => addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS)
|
|
2231
|
+
// Default built-in map
|
|
2232
|
+
);
|
|
2233
|
+
HTML_INTEGRATION_POINTS = _resolveObjectOption(
|
|
2234
|
+
cfg,
|
|
2235
|
+
"HTML_INTEGRATION_POINTS",
|
|
2236
|
+
() => addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS)
|
|
2237
|
+
// Default built-in map
|
|
2238
|
+
);
|
|
2239
|
+
const customElementHandling = _resolveObjectOption(cfg, "CUSTOM_ELEMENT_HANDLING", () => create(null));
|
|
2240
|
+
CUSTOM_ELEMENT_HANDLING = create(null);
|
|
2241
|
+
if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) {
|
|
2242
|
+
CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck;
|
|
2243
|
+
}
|
|
2244
|
+
if (objectHasOwnProperty(customElementHandling, "attributeNameCheck") && isRegexOrFunction(customElementHandling.attributeNameCheck)) {
|
|
2245
|
+
CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck;
|
|
2246
|
+
}
|
|
2247
|
+
if (objectHasOwnProperty(customElementHandling, "allowCustomizedBuiltInElements") && typeof customElementHandling.allowCustomizedBuiltInElements === "boolean") {
|
|
2248
|
+
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements;
|
|
2249
|
+
}
|
|
2250
|
+
seal(CUSTOM_ELEMENT_HANDLING);
|
|
2251
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
2252
|
+
ALLOW_DATA_ATTR = false;
|
|
2253
|
+
}
|
|
2254
|
+
if (RETURN_DOM_FRAGMENT) {
|
|
2255
|
+
RETURN_DOM = true;
|
|
2256
|
+
}
|
|
2257
|
+
if (USE_PROFILES) {
|
|
2258
|
+
ALLOWED_TAGS2 = addToSet({}, text);
|
|
2259
|
+
ALLOWED_ATTR2 = create(null);
|
|
2260
|
+
if (USE_PROFILES.html === true) {
|
|
2261
|
+
addToSet(ALLOWED_TAGS2, html$1);
|
|
2262
|
+
addToSet(ALLOWED_ATTR2, html);
|
|
2263
|
+
}
|
|
2264
|
+
if (USE_PROFILES.svg === true) {
|
|
2265
|
+
addToSet(ALLOWED_TAGS2, svg$1);
|
|
2266
|
+
addToSet(ALLOWED_ATTR2, svg);
|
|
2267
|
+
addToSet(ALLOWED_ATTR2, xml);
|
|
2268
|
+
}
|
|
2269
|
+
if (USE_PROFILES.svgFilters === true) {
|
|
2270
|
+
addToSet(ALLOWED_TAGS2, svgFilters);
|
|
2271
|
+
addToSet(ALLOWED_ATTR2, svg);
|
|
2272
|
+
addToSet(ALLOWED_ATTR2, xml);
|
|
2273
|
+
}
|
|
2274
|
+
if (USE_PROFILES.mathMl === true) {
|
|
2275
|
+
addToSet(ALLOWED_TAGS2, mathMl$1);
|
|
2276
|
+
addToSet(ALLOWED_ATTR2, mathMl);
|
|
2277
|
+
addToSet(ALLOWED_ATTR2, xml);
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
EXTRA_ELEMENT_HANDLING.tagCheck = null;
|
|
2281
|
+
EXTRA_ELEMENT_HANDLING.attributeCheck = null;
|
|
2282
|
+
if (objectHasOwnProperty(cfg, "ADD_TAGS")) {
|
|
2283
|
+
if (typeof cfg.ADD_TAGS === "function") {
|
|
2284
|
+
EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
|
|
2285
|
+
} else if (arrayIsArray(cfg.ADD_TAGS)) {
|
|
2286
|
+
if (ALLOWED_TAGS2 === DEFAULT_ALLOWED_TAGS) {
|
|
2287
|
+
ALLOWED_TAGS2 = clone(ALLOWED_TAGS2);
|
|
2288
|
+
}
|
|
2289
|
+
addToSet(ALLOWED_TAGS2, cfg.ADD_TAGS, transformCaseFunc);
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
if (objectHasOwnProperty(cfg, "ADD_ATTR")) {
|
|
2293
|
+
if (typeof cfg.ADD_ATTR === "function") {
|
|
2294
|
+
EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
|
|
2295
|
+
} else if (arrayIsArray(cfg.ADD_ATTR)) {
|
|
2296
|
+
if (ALLOWED_ATTR2 === DEFAULT_ALLOWED_ATTR) {
|
|
2297
|
+
ALLOWED_ATTR2 = clone(ALLOWED_ATTR2);
|
|
2298
|
+
}
|
|
2299
|
+
addToSet(ALLOWED_ATTR2, cfg.ADD_ATTR, transformCaseFunc);
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
if (objectHasOwnProperty(cfg, "ADD_FORBID_CONTENTS") && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
|
|
2303
|
+
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
2304
|
+
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
2305
|
+
}
|
|
2306
|
+
addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
|
|
2307
|
+
}
|
|
2308
|
+
if (KEEP_CONTENT) {
|
|
2309
|
+
ALLOWED_TAGS2["#text"] = true;
|
|
2310
|
+
}
|
|
2311
|
+
if (WHOLE_DOCUMENT) {
|
|
2312
|
+
addToSet(ALLOWED_TAGS2, ["html", "head", "body"]);
|
|
2313
|
+
}
|
|
2314
|
+
if (ALLOWED_TAGS2.table) {
|
|
2315
|
+
addToSet(ALLOWED_TAGS2, ["tbody"]);
|
|
2316
|
+
delete FORBID_TAGS.tbody;
|
|
2317
|
+
}
|
|
2318
|
+
if (cfg.TRUSTED_TYPES_POLICY) {
|
|
2319
|
+
if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== "function") {
|
|
2320
|
+
throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');
|
|
2321
|
+
}
|
|
2322
|
+
if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== "function") {
|
|
2323
|
+
throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
|
|
2324
|
+
}
|
|
2325
|
+
const previousTrustedTypesPolicy = trustedTypesPolicy;
|
|
2326
|
+
trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
|
|
2327
|
+
try {
|
|
2328
|
+
emptyHTML = _createTrustedHTML("");
|
|
2329
|
+
} catch (error) {
|
|
2330
|
+
trustedTypesPolicy = previousTrustedTypesPolicy;
|
|
2331
|
+
throw error;
|
|
2332
|
+
}
|
|
2333
|
+
} else if (cfg.TRUSTED_TYPES_POLICY === null) {
|
|
2334
|
+
trustedTypesPolicy = void 0;
|
|
2335
|
+
emptyHTML = "";
|
|
2336
|
+
} else {
|
|
2337
|
+
if (trustedTypesPolicy === void 0) {
|
|
2338
|
+
trustedTypesPolicy = _getDefaultTrustedTypesPolicy();
|
|
2339
|
+
}
|
|
2340
|
+
if (trustedTypesPolicy && typeof emptyHTML === "string") {
|
|
2341
|
+
emptyHTML = _createTrustedHTML("");
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
if (freeze) {
|
|
2345
|
+
freeze(cfg);
|
|
2346
|
+
}
|
|
2347
|
+
CONFIG = cfg;
|
|
2348
|
+
};
|
|
2349
|
+
const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);
|
|
2350
|
+
const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);
|
|
2351
|
+
const _checkSvgNamespace = function _checkSvgNamespace2(tagName, parent, parentTagName) {
|
|
2352
|
+
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
2353
|
+
return tagName === "svg";
|
|
2354
|
+
}
|
|
2355
|
+
if (parent.namespaceURI === MATHML_NAMESPACE) {
|
|
2356
|
+
return tagName === "svg" && (parentTagName === "annotation-xml" || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
|
|
2357
|
+
}
|
|
2358
|
+
return Boolean(ALL_SVG_TAGS[tagName]);
|
|
2359
|
+
};
|
|
2360
|
+
const _checkMathMlNamespace = function _checkMathMlNamespace2(tagName, parent, parentTagName) {
|
|
2361
|
+
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
2362
|
+
return tagName === "math";
|
|
2363
|
+
}
|
|
2364
|
+
if (parent.namespaceURI === SVG_NAMESPACE) {
|
|
2365
|
+
return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName];
|
|
2366
|
+
}
|
|
2367
|
+
return Boolean(ALL_MATHML_TAGS[tagName]);
|
|
2368
|
+
};
|
|
2369
|
+
const _checkHtmlNamespace = function _checkHtmlNamespace2(tagName, parent, parentTagName) {
|
|
2370
|
+
if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
|
|
2371
|
+
return false;
|
|
2372
|
+
}
|
|
2373
|
+
if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
|
|
2374
|
+
return false;
|
|
2375
|
+
}
|
|
2376
|
+
return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
|
|
2377
|
+
};
|
|
2378
|
+
const _checkValidNamespace = function _checkValidNamespace2(element) {
|
|
2379
|
+
let parent = getParentNode(element);
|
|
2380
|
+
if (!parent || !parent.tagName) {
|
|
2381
|
+
parent = {
|
|
2382
|
+
namespaceURI: NAMESPACE,
|
|
2383
|
+
tagName: "template"
|
|
2384
|
+
};
|
|
2385
|
+
}
|
|
2386
|
+
const tagName = stringToLowerCase(element.tagName);
|
|
2387
|
+
const parentTagName = stringToLowerCase(parent.tagName);
|
|
2388
|
+
if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
|
|
2389
|
+
return false;
|
|
2390
|
+
}
|
|
2391
|
+
if (element.namespaceURI === SVG_NAMESPACE) {
|
|
2392
|
+
return _checkSvgNamespace(tagName, parent, parentTagName);
|
|
2393
|
+
}
|
|
2394
|
+
if (element.namespaceURI === MATHML_NAMESPACE) {
|
|
2395
|
+
return _checkMathMlNamespace(tagName, parent, parentTagName);
|
|
2396
|
+
}
|
|
2397
|
+
if (element.namespaceURI === HTML_NAMESPACE) {
|
|
2398
|
+
return _checkHtmlNamespace(tagName, parent, parentTagName);
|
|
2399
|
+
}
|
|
2400
|
+
if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && ALLOWED_NAMESPACES[element.namespaceURI]) {
|
|
2401
|
+
return true;
|
|
2402
|
+
}
|
|
2403
|
+
return false;
|
|
2404
|
+
};
|
|
2405
|
+
const _forceRemove = function _forceRemove2(node) {
|
|
2406
|
+
arrayPush(DOMPurify.removed, {
|
|
2407
|
+
element: node
|
|
2408
|
+
});
|
|
2409
|
+
try {
|
|
2410
|
+
getParentNode(node).removeChild(node);
|
|
2411
|
+
} catch (_2) {
|
|
2412
|
+
remove(node);
|
|
2413
|
+
if (!getParentNode(node)) {
|
|
2414
|
+
throw typeErrorCreate("a node selected for removal could not be detached from its tree and cannot be safely returned; refusing to sanitize in place");
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
};
|
|
2418
|
+
const _stripAttributeNode = function _stripAttributeNode2(element, attribute, name) {
|
|
2419
|
+
try {
|
|
2420
|
+
removeAttributeNode(element, attribute);
|
|
2421
|
+
} catch (_2) {
|
|
2422
|
+
try {
|
|
2423
|
+
element.removeAttribute(name);
|
|
2424
|
+
} catch (_3) {
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
};
|
|
2428
|
+
const _neutralizeRoot = function _neutralizeRoot2(root) {
|
|
2429
|
+
_neutralizeSubtree(root);
|
|
2430
|
+
const childNodes = getChildNodes(root);
|
|
2431
|
+
if (childNodes) {
|
|
2432
|
+
const snapshot = [];
|
|
2433
|
+
arrayForEach(childNodes, (child) => {
|
|
2434
|
+
arrayPush(snapshot, child);
|
|
2435
|
+
});
|
|
2436
|
+
arrayForEach(snapshot, (child) => {
|
|
2437
|
+
try {
|
|
2438
|
+
remove(child);
|
|
2439
|
+
} catch (_2) {
|
|
2440
|
+
}
|
|
2441
|
+
});
|
|
2442
|
+
}
|
|
2443
|
+
const attributes = getAttributes(root);
|
|
2444
|
+
if (attributes) {
|
|
2445
|
+
for (let i = attributes.length - 1; i >= 0; --i) {
|
|
2446
|
+
const attribute = attributes[i];
|
|
2447
|
+
const name = attribute && attribute.name;
|
|
2448
|
+
if (typeof name === "string") {
|
|
2449
|
+
_stripAttributeNode(root, attribute, name);
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
};
|
|
2454
|
+
const _removeAttribute = function _removeAttribute2(name, element, attr) {
|
|
2455
|
+
if (!attr) {
|
|
2456
|
+
try {
|
|
2457
|
+
attr = element.getAttributeNode(name);
|
|
2458
|
+
} catch (_2) {
|
|
2459
|
+
attr = null;
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
arrayPush(DOMPurify.removed, {
|
|
2463
|
+
attribute: attr || null,
|
|
2464
|
+
from: element
|
|
2465
|
+
});
|
|
2466
|
+
try {
|
|
2467
|
+
if (attr) {
|
|
2468
|
+
removeAttributeNode(element, attr);
|
|
2469
|
+
} else {
|
|
2470
|
+
element.removeAttribute(name);
|
|
2471
|
+
}
|
|
2472
|
+
} catch (_2) {
|
|
2473
|
+
try {
|
|
2474
|
+
element.removeAttribute(name);
|
|
2475
|
+
} catch (_3) {
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
if (name === "is") {
|
|
2479
|
+
if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
|
|
2480
|
+
try {
|
|
2481
|
+
_forceRemove(element);
|
|
2482
|
+
} catch (_2) {
|
|
2483
|
+
}
|
|
2484
|
+
} else {
|
|
2485
|
+
try {
|
|
2486
|
+
element.setAttribute(name, "");
|
|
2487
|
+
} catch (_2) {
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
};
|
|
2492
|
+
const _stripDisallowedAttributes = function _stripDisallowedAttributes2(element) {
|
|
2493
|
+
const attributes = getAttributes(element);
|
|
2494
|
+
if (!attributes) {
|
|
2495
|
+
return;
|
|
2496
|
+
}
|
|
2497
|
+
for (let i = attributes.length - 1; i >= 0; --i) {
|
|
2498
|
+
const attribute = attributes[i];
|
|
2499
|
+
const name = attribute && attribute.name;
|
|
2500
|
+
if (typeof name !== "string" || ALLOWED_ATTR2[transformCaseFunc(name)]) {
|
|
2501
|
+
continue;
|
|
2502
|
+
}
|
|
2503
|
+
_stripAttributeNode(element, attribute, name);
|
|
2504
|
+
}
|
|
2505
|
+
};
|
|
2506
|
+
const _neutralizeSubtree = function _neutralizeSubtree2(root) {
|
|
2507
|
+
const stack = [root];
|
|
2508
|
+
while (stack.length > 0) {
|
|
2509
|
+
const node = stack.pop();
|
|
2510
|
+
const nodeType = _readNodeType(node);
|
|
2511
|
+
if (nodeType === NODE_TYPE.element) {
|
|
2512
|
+
_stripDisallowedAttributes(node);
|
|
2513
|
+
}
|
|
2514
|
+
const childNodes = getChildNodes(node);
|
|
2515
|
+
if (childNodes) {
|
|
2516
|
+
for (let i = childNodes.length - 1; i >= 0; --i) {
|
|
2517
|
+
stack.push(childNodes[i]);
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
};
|
|
2522
|
+
const _isPatchLinkageAttribute = function _isPatchLinkageAttribute2(lcName, lcTag) {
|
|
2523
|
+
if (!SAFE_FOR_XML) {
|
|
2524
|
+
return false;
|
|
2525
|
+
}
|
|
2526
|
+
if (lcName === "patchsrc") {
|
|
2527
|
+
return true;
|
|
2528
|
+
}
|
|
2529
|
+
return lcName === "for" && lcTag !== "label" && lcTag !== "output";
|
|
2530
|
+
};
|
|
2531
|
+
const _neutralizePatchLinkage = function _neutralizePatchLinkage2(root) {
|
|
2532
|
+
if (!SAFE_FOR_XML) {
|
|
2533
|
+
return;
|
|
2534
|
+
}
|
|
2535
|
+
const stack = [root];
|
|
2536
|
+
while (stack.length > 0) {
|
|
2537
|
+
const node = stack.pop();
|
|
2538
|
+
const nodeType = _readNodeType(node);
|
|
2539
|
+
if (nodeType === NODE_TYPE.processingInstruction || nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, node.data)) {
|
|
2540
|
+
try {
|
|
2541
|
+
remove(node);
|
|
2542
|
+
} catch (_2) {
|
|
2543
|
+
}
|
|
2544
|
+
continue;
|
|
2545
|
+
}
|
|
2546
|
+
if (nodeType === NODE_TYPE.element) {
|
|
2547
|
+
const element = node;
|
|
2548
|
+
const lcTag = transformCaseFunc(_readNodeName(node));
|
|
2549
|
+
try {
|
|
2550
|
+
if (element.hasAttribute && element.hasAttribute("patchsrc")) {
|
|
2551
|
+
element.removeAttribute("patchsrc");
|
|
2552
|
+
}
|
|
2553
|
+
if (element.hasAttribute && element.hasAttribute("for") && _isPatchLinkageAttribute("for", lcTag)) {
|
|
2554
|
+
element.removeAttribute("for");
|
|
2555
|
+
}
|
|
2556
|
+
} catch (_2) {
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
const childNodes = getChildNodes(node);
|
|
2560
|
+
if (childNodes) {
|
|
2561
|
+
for (let i = childNodes.length - 1; i >= 0; --i) {
|
|
2562
|
+
stack.push(childNodes[i]);
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
};
|
|
2567
|
+
const _initDocument = function _initDocument2(dirty) {
|
|
2568
|
+
let doc = null;
|
|
2569
|
+
let leadingWhitespace = null;
|
|
2570
|
+
if (FORCE_BODY) {
|
|
2571
|
+
dirty = "<remove></remove>" + dirty;
|
|
2572
|
+
} else {
|
|
2573
|
+
const matches = stringMatch(dirty, /^[\r\n\t ]+/);
|
|
2574
|
+
leadingWhitespace = matches && matches[0];
|
|
2575
|
+
}
|
|
2576
|
+
if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && NAMESPACE === HTML_NAMESPACE) {
|
|
2577
|
+
dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + "</body></html>";
|
|
2578
|
+
}
|
|
2579
|
+
const dirtyPayload = trustedTypesPolicy ? _createTrustedHTML(dirty) : dirty;
|
|
2580
|
+
if (NAMESPACE === HTML_NAMESPACE) {
|
|
2581
|
+
try {
|
|
2582
|
+
doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
|
|
2583
|
+
} catch (_2) {
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
if (!doc || !doc.documentElement) {
|
|
2587
|
+
doc = implementation.createDocument(NAMESPACE, "template", null);
|
|
2588
|
+
try {
|
|
2589
|
+
doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
|
|
2590
|
+
} catch (_2) {
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
const body = doc.body || doc.documentElement;
|
|
2594
|
+
if (dirty && leadingWhitespace) {
|
|
2595
|
+
body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
|
|
2596
|
+
}
|
|
2597
|
+
if (NAMESPACE === HTML_NAMESPACE) {
|
|
2598
|
+
return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? "html" : "body")[0];
|
|
2599
|
+
}
|
|
2600
|
+
return WHOLE_DOCUMENT ? doc.documentElement : body;
|
|
2601
|
+
};
|
|
2602
|
+
const _createNodeIterator = function _createNodeIterator2(root) {
|
|
2603
|
+
const doc = getOwnerDocument ? getOwnerDocument(root) : root.ownerDocument;
|
|
2604
|
+
return createNodeIterator.call(
|
|
2605
|
+
doc || root,
|
|
2606
|
+
root,
|
|
2607
|
+
// eslint-disable-next-line no-bitwise
|
|
2608
|
+
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION,
|
|
2609
|
+
null
|
|
2610
|
+
);
|
|
2611
|
+
};
|
|
2612
|
+
const _stripTemplateExpressions = function _stripTemplateExpressions2(value) {
|
|
2613
|
+
value = stringReplace(value, MUSTACHE_EXPR$1, " ");
|
|
2614
|
+
value = stringReplace(value, ERB_EXPR$1, " ");
|
|
2615
|
+
value = stringReplace(value, TMPLIT_EXPR$1, " ");
|
|
2616
|
+
return value;
|
|
2617
|
+
};
|
|
2618
|
+
const _scrubTemplateExpressions2 = function _scrubTemplateExpressions(node) {
|
|
2619
|
+
var _node$querySelectorAl;
|
|
2620
|
+
node.normalize();
|
|
2621
|
+
const doc = getOwnerDocument ? getOwnerDocument(node) : node.ownerDocument;
|
|
2622
|
+
const walker = createNodeIterator.call(
|
|
2623
|
+
doc || node,
|
|
2624
|
+
node,
|
|
2625
|
+
// eslint-disable-next-line no-bitwise
|
|
2626
|
+
NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_CDATA_SECTION | NodeFilter.SHOW_PROCESSING_INSTRUCTION,
|
|
2627
|
+
null
|
|
2628
|
+
);
|
|
2629
|
+
let currentNode = walker.nextNode();
|
|
2630
|
+
while (currentNode) {
|
|
2631
|
+
currentNode.data = _stripTemplateExpressions(currentNode.data);
|
|
2632
|
+
currentNode = walker.nextNode();
|
|
2633
|
+
}
|
|
2634
|
+
const templates = (_node$querySelectorAl = node.querySelectorAll) === null || _node$querySelectorAl === void 0 ? void 0 : _node$querySelectorAl.call(node, "template");
|
|
2635
|
+
if (templates) {
|
|
2636
|
+
arrayForEach(templates, (tmpl) => {
|
|
2637
|
+
if (_isDocumentFragment(tmpl.content)) {
|
|
2638
|
+
_scrubTemplateExpressions2(tmpl.content);
|
|
2639
|
+
}
|
|
2640
|
+
});
|
|
2641
|
+
}
|
|
2642
|
+
};
|
|
2643
|
+
const _isClobbered = function _isClobbered2(element) {
|
|
2644
|
+
const realTagName = getNodeName ? getNodeName(element) : null;
|
|
2645
|
+
if (typeof realTagName !== "string") {
|
|
2646
|
+
return false;
|
|
2647
|
+
}
|
|
2648
|
+
if (transformCaseFunc(realTagName) !== "form") {
|
|
2649
|
+
return false;
|
|
2650
|
+
}
|
|
2651
|
+
return typeof element.nodeName !== "string" || typeof element.textContent !== "string" || typeof element.removeChild !== "function" || // Realm-safe NamedNodeMap detection: equality against the cached
|
|
2652
|
+
// prototype getter. Clobbered .attributes (e.g. <input name="attributes">)
|
|
2653
|
+
// makes the direct read diverge from the cached read; a clean form
|
|
2654
|
+
// (same-realm OR foreign-realm) has both reads pointing at the same
|
|
2655
|
+
// canonical NamedNodeMap.
|
|
2656
|
+
element.attributes !== getAttributes(element) || typeof element.removeAttribute !== "function" || // A form descendant named "removeAttributeNode" or "getAttributeNode"
|
|
2657
|
+
// shadows these Attr-node methods via [LegacyOverrideBuiltIns].
|
|
2658
|
+
// _removeAttribute() / _stripAttributeNode() reach for
|
|
2659
|
+
// element.removeAttributeNode(attr) first; when it is shadowed the call
|
|
2660
|
+
// throws and the name-based fallback element.removeAttribute(name)
|
|
2661
|
+
// ASCII-lowercases its lookup key in an HTML document, silently missing
|
|
2662
|
+
// a case-preserved event-handler attribute (e.g. an ONANIMATIONSTART
|
|
2663
|
+
// that reached the sanitizer through an XML/XHTML parse). Flag the form
|
|
2664
|
+
// so it is removed wholesale, exactly as for the other shadowed methods.
|
|
2665
|
+
typeof element.removeAttributeNode !== "function" || typeof element.getAttributeNode !== "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
|
|
2666
|
+
// returns the integer 1 for any Element regardless of realm; direct
|
|
2667
|
+
// read on a clobbered form (e.g. <input name="nodeType">) returns
|
|
2668
|
+
// the named child element. Cheap addition — nodeType is read from
|
|
2669
|
+
// an internal slot, no serialization cost — and removes a residual
|
|
2670
|
+
// clobbering surface used by several mXSS / PI / comment branches
|
|
2671
|
+
// in _sanitizeElements that compare currentNode.nodeType directly.
|
|
2672
|
+
element.nodeType !== getNodeType(element) || // HTMLFormElement has [LegacyOverrideBuiltIns]: a descendant named
|
|
2673
|
+
// "childNodes" shadows the prototype getter. Direct reads of
|
|
2674
|
+
// form.childNodes from a clobbered form return the named child
|
|
2675
|
+
// instead of the real NodeList, so any walk that reads it directly
|
|
2676
|
+
// skips the form's real children. Compare the direct read to the
|
|
2677
|
+
// cached Node.prototype getter — when the form's named-property
|
|
2678
|
+
// getter intercepts the read, the two values differ and we flag
|
|
2679
|
+
// the form. This catches every clobbering child type (input,
|
|
2680
|
+
// select, etc.) regardless of whether the named child happens to
|
|
2681
|
+
// carry a numeric .length, which a typeof-based probe would miss
|
|
2682
|
+
// (e.g. HTMLSelectElement.length is a defined unsigned-long).
|
|
2683
|
+
element.childNodes !== getChildNodes(element);
|
|
2684
|
+
};
|
|
2685
|
+
const _isDocumentFragment = function _isDocumentFragment2(value) {
|
|
2686
|
+
if (!getNodeType || typeof value !== "object" || value === null) {
|
|
2687
|
+
return false;
|
|
2688
|
+
}
|
|
2689
|
+
try {
|
|
2690
|
+
return getNodeType(value) === NODE_TYPE.documentFragment;
|
|
2691
|
+
} catch (_2) {
|
|
2692
|
+
return false;
|
|
2693
|
+
}
|
|
2694
|
+
};
|
|
2695
|
+
const _isNode = function _isNode2(value) {
|
|
2696
|
+
if (!getNodeType || typeof value !== "object" || value === null) {
|
|
2697
|
+
return false;
|
|
2698
|
+
}
|
|
2699
|
+
try {
|
|
2700
|
+
return typeof getNodeType(value) === "number";
|
|
2701
|
+
} catch (_2) {
|
|
2702
|
+
return false;
|
|
2703
|
+
}
|
|
2704
|
+
};
|
|
2705
|
+
function _executeHooks(hooks2, currentNode, data) {
|
|
2706
|
+
if (hooks2.length === 0) {
|
|
2707
|
+
return;
|
|
2708
|
+
}
|
|
2709
|
+
arrayForEach(hooks2, (hook) => {
|
|
2710
|
+
hook.call(DOMPurify, currentNode, data, CONFIG);
|
|
2711
|
+
});
|
|
2712
|
+
}
|
|
2713
|
+
const _isUnsafeNode = function _isUnsafeNode2(currentNode, tagName) {
|
|
2714
|
+
if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.textContent) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.innerHTML)) {
|
|
2715
|
+
return true;
|
|
2716
|
+
}
|
|
2717
|
+
if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && LITERAL_TEXT_ELEMENTS[tagName] && (_isNode(currentNode.firstElementChild) || typeof currentNode.textContent === "string" && regExpTest(LITERAL_TEXT_CLOSE[tagName], currentNode.textContent))) {
|
|
2718
|
+
return true;
|
|
2719
|
+
}
|
|
2720
|
+
if (currentNode.nodeType === NODE_TYPE.processingInstruction) {
|
|
2721
|
+
return true;
|
|
2722
|
+
}
|
|
2723
|
+
if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, currentNode.data)) {
|
|
2724
|
+
return true;
|
|
2725
|
+
}
|
|
2726
|
+
return false;
|
|
2727
|
+
};
|
|
2728
|
+
const _matchesNameCheck = function _matchesNameCheck2(check, name) {
|
|
2729
|
+
if (check instanceof RegExp) {
|
|
2730
|
+
return regExpTest(check, name);
|
|
2731
|
+
}
|
|
2732
|
+
if (check instanceof Function) {
|
|
2733
|
+
for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
|
|
2734
|
+
args[_key - 2] = arguments[_key];
|
|
2735
|
+
}
|
|
2736
|
+
return Boolean(check(name, ...args));
|
|
2737
|
+
}
|
|
2738
|
+
return false;
|
|
2739
|
+
};
|
|
2740
|
+
const _sanitizeDisallowedNode = function _sanitizeDisallowedNode2(currentNode, tagName, root) {
|
|
2741
|
+
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
|
|
2742
|
+
return false;
|
|
2743
|
+
}
|
|
2744
|
+
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
2745
|
+
const parentNode = getParentNode(currentNode);
|
|
2746
|
+
const childNodes = getChildNodes(currentNode);
|
|
2747
|
+
if (childNodes && parentNode) {
|
|
2748
|
+
const childCount = childNodes.length;
|
|
2749
|
+
for (let i = childCount - 1; i >= 0; --i) {
|
|
2750
|
+
const hoisted = currentNode === root ? cloneNode(childNodes[i], true) : childNodes[i];
|
|
2751
|
+
parentNode.insertBefore(hoisted, getNextSibling(currentNode));
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
_forceRemove(currentNode);
|
|
2756
|
+
return true;
|
|
2757
|
+
};
|
|
2758
|
+
const _forkSharedAllowlist = function _forkSharedAllowlist2(hookList, set, defaultSet, setConfigSet) {
|
|
2759
|
+
if (hookList.length === 0) {
|
|
2760
|
+
return set;
|
|
2761
|
+
}
|
|
2762
|
+
return set === defaultSet || set === setConfigSet ? clone(set) : set;
|
|
2763
|
+
};
|
|
2764
|
+
const _handleHookDetachedNode = function _handleHookDetachedNode2(currentNode, root) {
|
|
2765
|
+
if (currentNode === root || getParentNode(currentNode) !== null) {
|
|
2766
|
+
return false;
|
|
2767
|
+
}
|
|
2768
|
+
if (IN_PLACE) {
|
|
2769
|
+
_neutralizeSubtree(currentNode);
|
|
2770
|
+
}
|
|
2771
|
+
return true;
|
|
2772
|
+
};
|
|
2773
|
+
const _sanitizeElements = function _sanitizeElements2(currentNode, root) {
|
|
2774
|
+
_executeHooks(hooks.beforeSanitizeElements, currentNode, null);
|
|
2775
|
+
if (_handleHookDetachedNode(currentNode, root)) {
|
|
2776
|
+
return true;
|
|
2777
|
+
}
|
|
2778
|
+
if (_isClobbered(currentNode)) {
|
|
2779
|
+
_forceRemove(currentNode);
|
|
2780
|
+
return true;
|
|
2781
|
+
}
|
|
2782
|
+
const tagName = transformCaseFunc(_readNodeName(currentNode));
|
|
2783
|
+
ALLOWED_TAGS2 = _forkSharedAllowlist(hooks.uponSanitizeElement, ALLOWED_TAGS2, DEFAULT_ALLOWED_TAGS, SET_CONFIG_ALLOWED_TAGS);
|
|
2784
|
+
_executeHooks(hooks.uponSanitizeElement, currentNode, {
|
|
2785
|
+
tagName,
|
|
2786
|
+
allowedTags: ALLOWED_TAGS2
|
|
2787
|
+
});
|
|
2788
|
+
if (_handleHookDetachedNode(currentNode, root)) {
|
|
2789
|
+
return true;
|
|
2790
|
+
}
|
|
2791
|
+
if (_isUnsafeNode(currentNode, tagName)) {
|
|
2792
|
+
_forceRemove(currentNode);
|
|
2793
|
+
return true;
|
|
2794
|
+
}
|
|
2795
|
+
if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS2[tagName]) {
|
|
2796
|
+
const removed = _sanitizeDisallowedNode(currentNode, tagName, root);
|
|
2797
|
+
if (removed === false) {
|
|
2798
|
+
_executeHooks(hooks.afterSanitizeElements, currentNode, null);
|
|
2799
|
+
}
|
|
2800
|
+
return removed;
|
|
2801
|
+
}
|
|
2802
|
+
const nt2 = _readNodeType(currentNode);
|
|
2803
|
+
if (nt2 === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
|
|
2804
|
+
_forceRemove(currentNode);
|
|
2805
|
+
return true;
|
|
2806
|
+
}
|
|
2807
|
+
if ((tagName === "noscript" || tagName === "noembed" || tagName === "noframes") && regExpTest(FALLBACK_TAG_CLOSE, currentNode.innerHTML)) {
|
|
2808
|
+
_forceRemove(currentNode);
|
|
2809
|
+
return true;
|
|
2810
|
+
}
|
|
2811
|
+
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
|
|
2812
|
+
const content = _stripTemplateExpressions(currentNode.textContent);
|
|
2813
|
+
if (currentNode.textContent !== content) {
|
|
2814
|
+
arrayPush(DOMPurify.removed, {
|
|
2815
|
+
element: currentNode.cloneNode()
|
|
2816
|
+
});
|
|
2817
|
+
currentNode.textContent = content;
|
|
299
2818
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
2819
|
+
}
|
|
2820
|
+
_executeHooks(hooks.afterSanitizeElements, currentNode, null);
|
|
2821
|
+
return false;
|
|
2822
|
+
};
|
|
2823
|
+
const _isValidAttribute = function _isValidAttribute2(lcTag, lcName, value) {
|
|
2824
|
+
if (FORBID_ATTR[lcName]) {
|
|
2825
|
+
return false;
|
|
2826
|
+
}
|
|
2827
|
+
if (_isPatchLinkageAttribute(lcName, lcTag)) {
|
|
2828
|
+
return false;
|
|
2829
|
+
}
|
|
2830
|
+
if (SANITIZE_DOM && (lcName === "id" || lcName === "name") && (value in document || value in formElement)) {
|
|
2831
|
+
return false;
|
|
2832
|
+
}
|
|
2833
|
+
const nameIsPermitted = ALLOWED_ATTR2[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
|
|
2834
|
+
if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName)) {
|
|
2835
|
+
return true;
|
|
2836
|
+
}
|
|
2837
|
+
if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) {
|
|
2838
|
+
return true;
|
|
2839
|
+
}
|
|
2840
|
+
if (!nameIsPermitted) {
|
|
2841
|
+
return (
|
|
2842
|
+
// Condition a) covers a basically valid custom element tag name whose
|
|
2843
|
+
// tag passes the configured tagNameCheck and whose attribute name
|
|
2844
|
+
// passes the configured attributeNameCheck ...
|
|
2845
|
+
_isBasicCustomElement(lcTag) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName, lcTag) || // Condition b) covers an `is` attribute whose value passes the
|
|
2846
|
+
// configured tagNameCheck while customized built-in elements are
|
|
2847
|
+
// allowed.
|
|
2848
|
+
lcName === "is" && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value)
|
|
2849
|
+
);
|
|
2850
|
+
}
|
|
2851
|
+
if (URI_SAFE_ATTRIBUTES[lcName]) {
|
|
2852
|
+
return true;
|
|
2853
|
+
}
|
|
2854
|
+
if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) {
|
|
2855
|
+
return true;
|
|
2856
|
+
}
|
|
2857
|
+
if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]) {
|
|
2858
|
+
return true;
|
|
2859
|
+
}
|
|
2860
|
+
if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) {
|
|
2861
|
+
return true;
|
|
2862
|
+
}
|
|
2863
|
+
return !value;
|
|
2864
|
+
};
|
|
2865
|
+
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"]);
|
|
2866
|
+
const _isBasicCustomElement = function _isBasicCustomElement2(tagName) {
|
|
2867
|
+
return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName);
|
|
2868
|
+
};
|
|
2869
|
+
const _applyTrustedTypesToAttribute = function _applyTrustedTypesToAttribute2(lcTag, lcName, namespaceURI, value) {
|
|
2870
|
+
if (trustedTypesPolicy && typeof trustedTypes === "object" && typeof trustedTypes.getAttributeType === "function" && !namespaceURI) {
|
|
2871
|
+
switch (trustedTypes.getAttributeType(lcTag, lcName)) {
|
|
2872
|
+
case "TrustedHTML": {
|
|
2873
|
+
return _createTrustedHTML(value);
|
|
2874
|
+
}
|
|
2875
|
+
case "TrustedScriptURL": {
|
|
2876
|
+
return _createTrustedScriptURL(value);
|
|
2877
|
+
}
|
|
304
2878
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
2879
|
+
}
|
|
2880
|
+
return value;
|
|
2881
|
+
};
|
|
2882
|
+
const _setAttributeValue = function _setAttributeValue2(currentNode, name, namespaceURI, value) {
|
|
2883
|
+
try {
|
|
2884
|
+
if (namespaceURI) {
|
|
2885
|
+
currentNode.setAttributeNS(namespaceURI, name, value);
|
|
2886
|
+
} else {
|
|
2887
|
+
currentNode.setAttribute(name, value);
|
|
309
2888
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
2889
|
+
if (_isClobbered(currentNode)) {
|
|
2890
|
+
_forceRemove(currentNode);
|
|
2891
|
+
return false;
|
|
2892
|
+
}
|
|
2893
|
+
return true;
|
|
2894
|
+
} catch (_2) {
|
|
2895
|
+
_removeAttribute(name, currentNode);
|
|
2896
|
+
return false;
|
|
2897
|
+
}
|
|
2898
|
+
};
|
|
2899
|
+
const _sanitizeAttributes = function _sanitizeAttributes2(currentNode) {
|
|
2900
|
+
_executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
|
|
2901
|
+
const attributes = currentNode.attributes;
|
|
2902
|
+
if (!attributes || _isClobbered(currentNode)) {
|
|
2903
|
+
return;
|
|
2904
|
+
}
|
|
2905
|
+
ALLOWED_ATTR2 = _forkSharedAllowlist(hooks.uponSanitizeAttribute, ALLOWED_ATTR2, DEFAULT_ALLOWED_ATTR, SET_CONFIG_ALLOWED_ATTR);
|
|
2906
|
+
const hookEvent = {
|
|
2907
|
+
attrName: "",
|
|
2908
|
+
attrValue: "",
|
|
2909
|
+
keepAttr: true,
|
|
2910
|
+
allowedAttributes: ALLOWED_ATTR2,
|
|
2911
|
+
forceKeepAttr: void 0
|
|
2912
|
+
};
|
|
2913
|
+
let l = attributes.length;
|
|
2914
|
+
const lcTag = transformCaseFunc(currentNode.nodeName);
|
|
2915
|
+
while (l--) {
|
|
2916
|
+
const attr = attributes[l];
|
|
2917
|
+
const name = attr.name, namespaceURI = attr.namespaceURI, attrValue = attr.value;
|
|
2918
|
+
const lcName = transformCaseFunc(name);
|
|
2919
|
+
const initValue = attrValue;
|
|
2920
|
+
let value = name === "value" ? initValue : stringTrim(initValue);
|
|
2921
|
+
let recreatedNamedProp = false;
|
|
2922
|
+
hookEvent.attrName = lcName;
|
|
2923
|
+
hookEvent.attrValue = value;
|
|
2924
|
+
hookEvent.keepAttr = true;
|
|
2925
|
+
hookEvent.forceKeepAttr = void 0;
|
|
2926
|
+
_executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
|
|
2927
|
+
value = hookEvent.attrValue;
|
|
2928
|
+
if (SANITIZE_NAMED_PROPS && (lcName === "id" || lcName === "name") && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
|
|
2929
|
+
_removeAttribute(name, currentNode, attr);
|
|
2930
|
+
value = SANITIZE_NAMED_PROPS_PREFIX + value;
|
|
2931
|
+
recreatedNamedProp = true;
|
|
2932
|
+
}
|
|
2933
|
+
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
|
|
2934
|
+
_removeAttribute(name, currentNode, attr);
|
|
2935
|
+
continue;
|
|
2936
|
+
}
|
|
2937
|
+
if (lcName === "attributename" && stringMatch(value, "href")) {
|
|
2938
|
+
_removeAttribute(name, currentNode, attr);
|
|
2939
|
+
continue;
|
|
2940
|
+
}
|
|
2941
|
+
if (hookEvent.forceKeepAttr) {
|
|
2942
|
+
continue;
|
|
2943
|
+
}
|
|
2944
|
+
if (!hookEvent.keepAttr) {
|
|
2945
|
+
_removeAttribute(name, currentNode, attr);
|
|
2946
|
+
continue;
|
|
2947
|
+
}
|
|
2948
|
+
if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(SELF_CLOSING_TAG, value)) {
|
|
2949
|
+
_removeAttribute(name, currentNode, attr);
|
|
2950
|
+
continue;
|
|
2951
|
+
}
|
|
2952
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
2953
|
+
value = _stripTemplateExpressions(value);
|
|
2954
|
+
}
|
|
2955
|
+
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
2956
|
+
_removeAttribute(name, currentNode, attr);
|
|
2957
|
+
continue;
|
|
2958
|
+
}
|
|
2959
|
+
value = _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value);
|
|
2960
|
+
if (value !== initValue) {
|
|
2961
|
+
const cleanWrite = _setAttributeValue(currentNode, name, namespaceURI, value);
|
|
2962
|
+
if (cleanWrite && recreatedNamedProp) {
|
|
2963
|
+
arrayPop(DOMPurify.removed);
|
|
317
2964
|
}
|
|
318
2965
|
}
|
|
319
|
-
|
|
320
|
-
|
|
2966
|
+
}
|
|
2967
|
+
_executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
|
|
2968
|
+
};
|
|
2969
|
+
const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {
|
|
2970
|
+
let shadowNode = null;
|
|
2971
|
+
const shadowIterator = _createNodeIterator(fragment);
|
|
2972
|
+
_executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);
|
|
2973
|
+
while (shadowNode = shadowIterator.nextNode()) {
|
|
2974
|
+
_executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
|
|
2975
|
+
_sanitizeElements(shadowNode, fragment);
|
|
2976
|
+
_sanitizeAttributes(shadowNode);
|
|
2977
|
+
if (_isDocumentFragment(shadowNode.content)) {
|
|
2978
|
+
_sanitizeShadowDOM2(shadowNode.content);
|
|
2979
|
+
}
|
|
2980
|
+
if (_readNodeType(shadowNode) === NODE_TYPE.element) {
|
|
2981
|
+
const innerSr = getShadowRoot(shadowNode);
|
|
2982
|
+
if (_isDocumentFragment(innerSr)) {
|
|
2983
|
+
_sanitizeAttachedShadowRoots(innerSr);
|
|
2984
|
+
_sanitizeShadowDOM2(innerSr);
|
|
2985
|
+
}
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
_executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
|
|
2989
|
+
};
|
|
2990
|
+
const _sanitizeAttachedShadowRoots = function _sanitizeAttachedShadowRoots2(root) {
|
|
2991
|
+
const stack = [{
|
|
2992
|
+
node: root,
|
|
2993
|
+
shadow: null
|
|
2994
|
+
}];
|
|
2995
|
+
while (stack.length > 0) {
|
|
2996
|
+
const item = stack.pop();
|
|
2997
|
+
if (item.shadow) {
|
|
2998
|
+
_sanitizeShadowDOM2(item.shadow);
|
|
2999
|
+
continue;
|
|
3000
|
+
}
|
|
3001
|
+
const node = item.node;
|
|
3002
|
+
const nodeType = _readNodeType(node);
|
|
3003
|
+
const isElement = nodeType === NODE_TYPE.element;
|
|
3004
|
+
const childNodes = getChildNodes(node);
|
|
3005
|
+
if (childNodes) {
|
|
3006
|
+
for (let i = childNodes.length - 1; i >= 0; --i) {
|
|
3007
|
+
stack.push({
|
|
3008
|
+
node: childNodes[i],
|
|
3009
|
+
shadow: null
|
|
3010
|
+
});
|
|
3011
|
+
}
|
|
3012
|
+
}
|
|
3013
|
+
if (isElement) {
|
|
3014
|
+
const rootName = getNodeName ? getNodeName(node) : null;
|
|
3015
|
+
if (typeof rootName === "string" && transformCaseFunc(rootName) === "template") {
|
|
3016
|
+
const content = node.content;
|
|
3017
|
+
if (_isDocumentFragment(content)) {
|
|
3018
|
+
stack.push({
|
|
3019
|
+
node: content,
|
|
3020
|
+
shadow: null
|
|
3021
|
+
});
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
if (isElement) {
|
|
3026
|
+
const sr = getShadowRoot(node);
|
|
3027
|
+
if (_isDocumentFragment(sr)) {
|
|
3028
|
+
stack.push({
|
|
3029
|
+
node: null,
|
|
3030
|
+
shadow: sr
|
|
3031
|
+
}, {
|
|
3032
|
+
node: sr,
|
|
3033
|
+
shadow: null
|
|
3034
|
+
});
|
|
3035
|
+
}
|
|
3036
|
+
}
|
|
3037
|
+
}
|
|
3038
|
+
};
|
|
3039
|
+
DOMPurify.sanitize = function(dirty) {
|
|
3040
|
+
let cfg = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
3041
|
+
let body = null;
|
|
3042
|
+
let importedNode = null;
|
|
3043
|
+
let currentNode = null;
|
|
3044
|
+
let returnNode = null;
|
|
3045
|
+
IS_EMPTY_INPUT = !dirty;
|
|
3046
|
+
if (IS_EMPTY_INPUT) {
|
|
3047
|
+
dirty = "<!-->";
|
|
3048
|
+
}
|
|
3049
|
+
if (typeof dirty !== "string" && !_isNode(dirty)) {
|
|
3050
|
+
dirty = stringifyValue(dirty);
|
|
3051
|
+
if (typeof dirty !== "string") {
|
|
3052
|
+
throw typeErrorCreate("dirty is not a string, aborting");
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
if (!DOMPurify.isSupported) {
|
|
3056
|
+
return dirty;
|
|
3057
|
+
}
|
|
3058
|
+
if (SET_CONFIG) {
|
|
3059
|
+
ALLOWED_TAGS2 = SET_CONFIG_ALLOWED_TAGS;
|
|
3060
|
+
ALLOWED_ATTR2 = SET_CONFIG_ALLOWED_ATTR;
|
|
3061
|
+
} else {
|
|
3062
|
+
_parseConfig(cfg);
|
|
3063
|
+
}
|
|
3064
|
+
if (hooks.uponSanitizeElement.length > 0 || hooks.uponSanitizeAttribute.length > 0) {
|
|
3065
|
+
ALLOWED_TAGS2 = clone(ALLOWED_TAGS2);
|
|
3066
|
+
}
|
|
3067
|
+
if (hooks.uponSanitizeAttribute.length > 0) {
|
|
3068
|
+
ALLOWED_ATTR2 = clone(ALLOWED_ATTR2);
|
|
3069
|
+
}
|
|
3070
|
+
DOMPurify.removed = [];
|
|
3071
|
+
const inPlace = IN_PLACE && typeof dirty !== "string" && _isNode(dirty);
|
|
3072
|
+
if (inPlace) {
|
|
3073
|
+
_neutralizePatchLinkage(dirty);
|
|
3074
|
+
const nn = _readNodeName(dirty);
|
|
3075
|
+
if (typeof nn === "string") {
|
|
3076
|
+
const tagName = transformCaseFunc(nn);
|
|
3077
|
+
if (!ALLOWED_TAGS2[tagName] || FORBID_TAGS[tagName]) {
|
|
3078
|
+
_neutralizeRoot(dirty);
|
|
3079
|
+
throw typeErrorCreate("root node is forbidden and cannot be sanitized in-place");
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
if (_isClobbered(dirty)) {
|
|
3083
|
+
_neutralizeRoot(dirty);
|
|
3084
|
+
throw typeErrorCreate("root node is clobbered and cannot be sanitized in-place");
|
|
3085
|
+
}
|
|
321
3086
|
try {
|
|
322
|
-
|
|
323
|
-
} catch (
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
3087
|
+
_sanitizeAttachedShadowRoots(dirty);
|
|
3088
|
+
} catch (error) {
|
|
3089
|
+
_neutralizeRoot(dirty);
|
|
3090
|
+
throw error;
|
|
3091
|
+
}
|
|
3092
|
+
} else if (_isNode(dirty)) {
|
|
3093
|
+
body = _initDocument("<!---->");
|
|
3094
|
+
importedNode = body.ownerDocument.importNode(dirty, true);
|
|
3095
|
+
if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === "BODY") {
|
|
3096
|
+
body = importedNode;
|
|
3097
|
+
} else if (importedNode.nodeName === "HTML") {
|
|
3098
|
+
body = importedNode;
|
|
3099
|
+
} else {
|
|
3100
|
+
body.appendChild(importedNode);
|
|
3101
|
+
}
|
|
3102
|
+
_sanitizeAttachedShadowRoots(body);
|
|
3103
|
+
} else {
|
|
3104
|
+
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && // eslint-disable-next-line unicorn/prefer-includes
|
|
3105
|
+
dirty.indexOf("<") === -1) {
|
|
3106
|
+
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(dirty) : dirty;
|
|
3107
|
+
}
|
|
3108
|
+
body = _initDocument(dirty);
|
|
3109
|
+
if (!body) {
|
|
3110
|
+
return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : "";
|
|
3111
|
+
}
|
|
3112
|
+
}
|
|
3113
|
+
if (body && FORCE_BODY) {
|
|
3114
|
+
_forceRemove(body.firstChild);
|
|
3115
|
+
}
|
|
3116
|
+
const walkRoot = inPlace ? dirty : body;
|
|
3117
|
+
try {
|
|
3118
|
+
const nodeIterator = _createNodeIterator(walkRoot);
|
|
3119
|
+
while (currentNode = nodeIterator.nextNode()) {
|
|
3120
|
+
_sanitizeElements(currentNode, walkRoot);
|
|
3121
|
+
_sanitizeAttributes(currentNode);
|
|
3122
|
+
if (_isDocumentFragment(currentNode.content)) {
|
|
3123
|
+
_sanitizeShadowDOM2(currentNode.content);
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
} catch (error) {
|
|
3127
|
+
if (inPlace) {
|
|
3128
|
+
_neutralizeRoot(dirty);
|
|
3129
|
+
arrayForEach(DOMPurify.removed, (entry) => {
|
|
3130
|
+
if (entry.element) {
|
|
3131
|
+
_neutralizeSubtree(entry.element);
|
|
331
3132
|
}
|
|
332
|
-
}
|
|
333
|
-
|
|
3133
|
+
});
|
|
3134
|
+
}
|
|
3135
|
+
throw error;
|
|
3136
|
+
}
|
|
3137
|
+
if (inPlace) {
|
|
3138
|
+
arrayForEach(DOMPurify.removed, (entry) => {
|
|
3139
|
+
if (entry.element) {
|
|
3140
|
+
_neutralizeSubtree(entry.element);
|
|
334
3141
|
}
|
|
3142
|
+
});
|
|
3143
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
3144
|
+
_scrubTemplateExpressions2(dirty);
|
|
335
3145
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
3146
|
+
return dirty;
|
|
3147
|
+
}
|
|
3148
|
+
if (RETURN_DOM) {
|
|
3149
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
3150
|
+
_scrubTemplateExpressions2(body);
|
|
3151
|
+
}
|
|
3152
|
+
if (RETURN_DOM_FRAGMENT) {
|
|
3153
|
+
returnNode = createDocumentFragment.call(body.ownerDocument);
|
|
3154
|
+
while (body.firstChild) {
|
|
3155
|
+
returnNode.appendChild(body.firstChild);
|
|
3156
|
+
}
|
|
3157
|
+
} else {
|
|
3158
|
+
returnNode = body;
|
|
3159
|
+
}
|
|
3160
|
+
if (ALLOWED_ATTR2.shadowroot || ALLOWED_ATTR2.shadowrootmode) {
|
|
3161
|
+
returnNode = importNode.call(originalDocument, returnNode, true);
|
|
3162
|
+
}
|
|
3163
|
+
return returnNode;
|
|
3164
|
+
}
|
|
3165
|
+
let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
|
|
3166
|
+
if (WHOLE_DOCUMENT && ALLOWED_TAGS2["!doctype"] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
|
|
3167
|
+
serializedHTML = "<!DOCTYPE " + body.ownerDocument.doctype.name + ">\n" + serializedHTML;
|
|
3168
|
+
}
|
|
3169
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
3170
|
+
serializedHTML = _stripTemplateExpressions(serializedHTML);
|
|
3171
|
+
}
|
|
3172
|
+
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(serializedHTML) : serializedHTML;
|
|
3173
|
+
};
|
|
3174
|
+
DOMPurify.setConfig = function() {
|
|
3175
|
+
let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
|
3176
|
+
_parseConfig(cfg);
|
|
3177
|
+
SET_CONFIG = true;
|
|
3178
|
+
SET_CONFIG_ALLOWED_TAGS = ALLOWED_TAGS2;
|
|
3179
|
+
SET_CONFIG_ALLOWED_ATTR = ALLOWED_ATTR2;
|
|
3180
|
+
};
|
|
3181
|
+
DOMPurify.clearConfig = function() {
|
|
3182
|
+
CONFIG = null;
|
|
3183
|
+
SET_CONFIG = false;
|
|
3184
|
+
SET_CONFIG_ALLOWED_TAGS = null;
|
|
3185
|
+
SET_CONFIG_ALLOWED_ATTR = null;
|
|
3186
|
+
trustedTypesPolicy = defaultTrustedTypesPolicy;
|
|
3187
|
+
emptyHTML = "";
|
|
3188
|
+
};
|
|
3189
|
+
DOMPurify.isValidAttribute = function(tag, attr, value) {
|
|
3190
|
+
if (!CONFIG) {
|
|
3191
|
+
_parseConfig({});
|
|
3192
|
+
}
|
|
3193
|
+
const lcTag = transformCaseFunc(tag);
|
|
3194
|
+
const lcName = transformCaseFunc(attr);
|
|
3195
|
+
return _isValidAttribute(lcTag, lcName, value);
|
|
3196
|
+
};
|
|
3197
|
+
DOMPurify.addHook = function(entryPoint, hookFunction) {
|
|
3198
|
+
if (typeof hookFunction !== "function") {
|
|
3199
|
+
return;
|
|
3200
|
+
}
|
|
3201
|
+
if (!objectHasOwnProperty(hooks, entryPoint)) {
|
|
3202
|
+
return;
|
|
3203
|
+
}
|
|
3204
|
+
arrayPush(hooks[entryPoint], hookFunction);
|
|
3205
|
+
};
|
|
3206
|
+
DOMPurify.removeHook = function(entryPoint, hookFunction) {
|
|
3207
|
+
if (!objectHasOwnProperty(hooks, entryPoint)) {
|
|
3208
|
+
return void 0;
|
|
3209
|
+
}
|
|
3210
|
+
if (hookFunction !== void 0) {
|
|
3211
|
+
const index = arrayLastIndexOf(hooks[entryPoint], hookFunction);
|
|
3212
|
+
return index === -1 ? void 0 : arraySplice(hooks[entryPoint], index, 1)[0];
|
|
3213
|
+
}
|
|
3214
|
+
return arrayPop(hooks[entryPoint]);
|
|
3215
|
+
};
|
|
3216
|
+
DOMPurify.removeHooks = function(entryPoint) {
|
|
3217
|
+
if (!objectHasOwnProperty(hooks, entryPoint)) {
|
|
3218
|
+
return;
|
|
344
3219
|
}
|
|
3220
|
+
hooks[entryPoint] = [];
|
|
345
3221
|
};
|
|
3222
|
+
DOMPurify.removeAllHooks = function() {
|
|
3223
|
+
hooks = _createHooksMap();
|
|
3224
|
+
};
|
|
3225
|
+
return DOMPurify;
|
|
3226
|
+
}
|
|
3227
|
+
var purify = createDOMPurify();
|
|
3228
|
+
|
|
3229
|
+
// src/markdown.ts
|
|
3230
|
+
f.setOptions({ gfm: true, breaks: true });
|
|
3231
|
+
var hookInstalled = false;
|
|
3232
|
+
function installLinkHook() {
|
|
3233
|
+
if (hookInstalled) return;
|
|
3234
|
+
purify.addHook("afterSanitizeAttributes", (node) => {
|
|
3235
|
+
if (node.nodeName === "A") {
|
|
3236
|
+
node.setAttribute("target", "_blank");
|
|
3237
|
+
node.setAttribute("rel", "noopener noreferrer nofollow");
|
|
3238
|
+
}
|
|
3239
|
+
});
|
|
3240
|
+
hookInstalled = true;
|
|
3241
|
+
}
|
|
3242
|
+
var ALLOWED_TAGS = [
|
|
3243
|
+
"p",
|
|
3244
|
+
"br",
|
|
3245
|
+
"strong",
|
|
3246
|
+
"em",
|
|
3247
|
+
"b",
|
|
3248
|
+
"i",
|
|
3249
|
+
"del",
|
|
3250
|
+
"s",
|
|
3251
|
+
"code",
|
|
3252
|
+
"pre",
|
|
3253
|
+
"blockquote",
|
|
3254
|
+
"ul",
|
|
3255
|
+
"ol",
|
|
3256
|
+
"li",
|
|
3257
|
+
"a",
|
|
3258
|
+
"h1",
|
|
3259
|
+
"h2",
|
|
3260
|
+
"h3",
|
|
3261
|
+
"h4",
|
|
3262
|
+
"h5",
|
|
3263
|
+
"h6",
|
|
3264
|
+
"hr",
|
|
3265
|
+
"table",
|
|
3266
|
+
"thead",
|
|
3267
|
+
"tbody",
|
|
3268
|
+
"tr",
|
|
3269
|
+
"th",
|
|
3270
|
+
"td",
|
|
3271
|
+
"span"
|
|
3272
|
+
];
|
|
3273
|
+
var ALLOWED_ATTR = ["href", "target", "rel", "class"];
|
|
3274
|
+
function renderMarkdown(text2) {
|
|
3275
|
+
installLinkHook();
|
|
3276
|
+
const raw = f.parse(text2, { async: false });
|
|
3277
|
+
return purify.sanitize(raw, {
|
|
3278
|
+
ALLOWED_TAGS,
|
|
3279
|
+
ALLOWED_ATTR,
|
|
3280
|
+
ALLOW_DATA_ATTR: false,
|
|
3281
|
+
ALLOWED_URI_REGEXP: /^(?:https?:|mailto:)/i
|
|
3282
|
+
});
|
|
3283
|
+
}
|
|
3284
|
+
|
|
3285
|
+
// src/styles.ts
|
|
3286
|
+
var STYLES = `
|
|
3287
|
+
:host {
|
|
3288
|
+
/* accent (consumer-overridable via --oc-accent) + its derivations */
|
|
3289
|
+
--oc-ac: var(--oc-accent, #096DD9);
|
|
3290
|
+
--oc-btn-rim: color-mix(in oklab, var(--oc-ac) 70%, black);
|
|
3291
|
+
--oc-btn-edge: 0 6px 16px -10px color-mix(in oklab, var(--oc-ac) 55%, transparent);
|
|
3292
|
+
--oc-danger: #D92D20;
|
|
3293
|
+
--oc-ease: cubic-bezier(0.16,1,0.3,1);
|
|
3294
|
+
--oc-bounce: cubic-bezier(0.18,0.89,0.32,1.13);
|
|
3295
|
+
--oc-mono: 'Geist Mono', ui-monospace, monospace;
|
|
3296
|
+
--oc-r-full: 999px;
|
|
3297
|
+
|
|
3298
|
+
/* light palette (base) */
|
|
3299
|
+
--oc-bg: #FFFFFF; --oc-bg-sunk: #F6F8FB;
|
|
3300
|
+
--oc-fg: #0A0D12; --oc-fg-muted: rgba(10,13,18,0.66); --oc-fg-dim: rgba(10,13,18,0.44);
|
|
3301
|
+
--oc-border: rgba(9,13,20,0.10);
|
|
3302
|
+
--oc-accent-text: color-mix(in oklab, var(--oc-ac) 88%, black);
|
|
3303
|
+
--oc-tint-1: rgba(9,13,20,0.025); --oc-tint-2: rgba(9,13,20,0.04); --oc-tint-3: rgba(9,13,20,0.055);
|
|
3304
|
+
--oc-field-bg: #FFFFFF; --oc-field-border: rgba(9,13,20,0.22);
|
|
3305
|
+
--oc-glass-border: rgba(9,13,20,0.12);
|
|
3306
|
+
|
|
3307
|
+
position: fixed; right: 24px; bottom: 24px; z-index: 2147483000;
|
|
3308
|
+
font-family: 'Geist', system-ui, -apple-system, 'Helvetica Neue', sans-serif;
|
|
3309
|
+
-webkit-font-smoothing: antialiased;
|
|
3310
|
+
}
|
|
3311
|
+
@media (prefers-color-scheme: dark) {
|
|
3312
|
+
:host(:not([theme="light"])) {
|
|
3313
|
+
--oc-bg: #000000; --oc-bg-sunk: #000000;
|
|
3314
|
+
--oc-fg: #FFFFFF; --oc-fg-muted: rgba(255,255,255,0.68); --oc-fg-dim: rgba(255,255,255,0.42);
|
|
3315
|
+
--oc-border: rgba(255,255,255,0.09);
|
|
3316
|
+
--oc-accent-text: color-mix(in oklab, var(--oc-ac) 62%, white);
|
|
3317
|
+
--oc-tint-1: rgba(255,255,255,0.03); --oc-tint-2: rgba(255,255,255,0.05); --oc-tint-3: rgba(255,255,255,0.07);
|
|
3318
|
+
--oc-field-bg: rgba(255,255,255,0.045); --oc-field-border: rgba(255,255,255,0.20);
|
|
3319
|
+
--oc-glass-border: rgba(255,255,255,0.12);
|
|
3320
|
+
}
|
|
3321
|
+
}
|
|
3322
|
+
:host([theme="dark"]) {
|
|
3323
|
+
--oc-bg: #000000; --oc-bg-sunk: #000000;
|
|
3324
|
+
--oc-fg: #FFFFFF; --oc-fg-muted: rgba(255,255,255,0.68); --oc-fg-dim: rgba(255,255,255,0.42);
|
|
3325
|
+
--oc-border: rgba(255,255,255,0.09);
|
|
3326
|
+
--oc-accent-text: color-mix(in oklab, var(--oc-ac) 62%, white);
|
|
3327
|
+
--oc-tint-1: rgba(255,255,255,0.03); --oc-tint-2: rgba(255,255,255,0.05); --oc-tint-3: rgba(255,255,255,0.07);
|
|
3328
|
+
--oc-field-bg: rgba(255,255,255,0.045); --oc-field-border: rgba(255,255,255,0.20);
|
|
3329
|
+
--oc-glass-border: rgba(255,255,255,0.12);
|
|
3330
|
+
}
|
|
3331
|
+
* { box-sizing: border-box; }
|
|
3332
|
+
button { font-family: inherit; }
|
|
3333
|
+
|
|
3334
|
+
.oc { display: flex; flex-direction: column; align-items: flex-end; gap: 14px; }
|
|
3335
|
+
|
|
3336
|
+
/* \u2500\u2500 Launcher \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
3337
|
+
.launcher {
|
|
3338
|
+
position: relative; flex: none; width: 46px; height: 46px; border-radius: var(--oc-r-full);
|
|
3339
|
+
border: 1px solid var(--oc-btn-rim); background: var(--oc-ac);
|
|
3340
|
+
box-shadow: 0 8px 22px -8px color-mix(in oklab, var(--oc-ac) 70%, transparent), 0 18px 48px -18px rgba(0,0,0,0.6);
|
|
3341
|
+
color: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer;
|
|
3342
|
+
transition: transform .26s var(--oc-bounce), filter .2s var(--oc-ease); align-self: flex-end;
|
|
3343
|
+
}
|
|
3344
|
+
.launcher:hover { transform: scale(1.06); }
|
|
3345
|
+
.launcher:active { transform: scale(0.93); }
|
|
3346
|
+
.ring { pointer-events: none; position: absolute; inset: -1px; border-radius: var(--oc-r-full); border: 2px solid var(--oc-ac); opacity: 0; }
|
|
3347
|
+
.oc.ring:not(.open) .ring { animation: w-ring 2.4s ease-out 1.1s 3; }
|
|
3348
|
+
.ic-chat, .ic-close { position: absolute; display: flex; align-items: center; justify-content: center; transition: all .3s var(--oc-bounce); }
|
|
3349
|
+
.ic-chat { width: 28px; height: 28px; opacity: 1; transform: rotate(0) scale(1); }
|
|
3350
|
+
.ic-close { opacity: 0; transform: rotate(90deg) scale(0.6); }
|
|
3351
|
+
.oc.open .ic-chat { opacity: 0; transform: rotate(-90deg) scale(0.6); }
|
|
3352
|
+
.oc.open .ic-close { opacity: 1; transform: rotate(0) scale(1); }
|
|
3353
|
+
.badge {
|
|
3354
|
+
position: absolute; top: -2px; right: -2px; min-width: 17px; height: 17px; padding: 0 5px;
|
|
3355
|
+
border-radius: var(--oc-r-full); border: 2px solid var(--oc-bg-sunk); background: var(--oc-danger);
|
|
3356
|
+
color: #fff; font-family: var(--oc-mono); font-size: 10px; font-weight: 700;
|
|
3357
|
+
display: flex; align-items: center; justify-content: center; opacity: 0; transform: scale(0.4);
|
|
3358
|
+
transition: all .26s var(--oc-bounce);
|
|
3359
|
+
}
|
|
3360
|
+
.oc.unread:not(.open) .badge { opacity: 1; transform: scale(1); }
|
|
3361
|
+
|
|
3362
|
+
/* \u2500\u2500 Teaser \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
3363
|
+
.teaser {
|
|
3364
|
+
position: absolute; right: 0; bottom: 60px; display: none; align-items: center; gap: 11px;
|
|
3365
|
+
opacity: 0; transform: translateY(8px) scale(0.94); pointer-events: none;
|
|
3366
|
+
transition: opacity .3s var(--oc-ease), transform .38s var(--oc-bounce);
|
|
3367
|
+
}
|
|
3368
|
+
.oc.has-teaser .teaser { display: flex; }
|
|
3369
|
+
.oc.teaser:not(.open) .teaser { opacity: 1; transform: none; pointer-events: auto; }
|
|
3370
|
+
.teaser-btn {
|
|
3371
|
+
max-width: 250px; display: flex; align-items: center; gap: 10px; padding: 11px 15px;
|
|
3372
|
+
border-radius: 16px 16px 5px 16px; border: 1px solid var(--oc-glass-border); background: var(--oc-bg);
|
|
3373
|
+
box-shadow: 0 10px 30px -14px rgba(0,0,0,0.5); color: var(--oc-fg); font-size: 13.5px; line-height: 1.45;
|
|
3374
|
+
text-align: left; cursor: pointer; transition: transform .2s var(--oc-ease);
|
|
3375
|
+
}
|
|
3376
|
+
.teaser-btn:hover { transform: translateY(-1px); }
|
|
3377
|
+
.teaser-btn .logo { flex: none; width: 24px; height: 24px; border-radius: 6px; overflow: hidden; color: var(--oc-ac); }
|
|
3378
|
+
.teaser-x {
|
|
3379
|
+
flex: none; width: 22px; height: 22px; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border);
|
|
3380
|
+
background: var(--oc-bg); color: var(--oc-fg-dim); display: flex; align-items: center; justify-content: center; cursor: pointer;
|
|
3381
|
+
}
|
|
3382
|
+
.teaser-x:hover { color: var(--oc-fg); }
|
|
3383
|
+
|
|
3384
|
+
/* \u2500\u2500 Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
3385
|
+
.panel {
|
|
3386
|
+
position: relative; width: min(384px, calc(100vw - 40px)); height: min(560px, calc(100vh - 108px));
|
|
3387
|
+
display: flex; flex-direction: column; border-radius: 20px; border: 1px solid var(--oc-glass-border);
|
|
3388
|
+
background: var(--oc-bg); box-shadow: 0 12px 28px -12px rgba(0,0,0,0.28), 0 40px 90px -30px rgba(0,0,0,0.55);
|
|
3389
|
+
overflow: hidden; transform-origin: bottom right;
|
|
3390
|
+
opacity: 0; transform: translateY(16px) scale(0.94); pointer-events: none; visibility: hidden;
|
|
3391
|
+
transition: opacity .24s var(--oc-ease), transform .34s var(--oc-bounce), visibility .34s, width .3s var(--oc-ease), height .3s var(--oc-ease);
|
|
3392
|
+
}
|
|
3393
|
+
.oc.open .panel { opacity: 1; transform: none; pointer-events: auto; visibility: visible; }
|
|
3394
|
+
.oc.max .panel { width: min(720px, calc(100vw - 40px)); height: calc(100vh - 108px); }
|
|
3395
|
+
|
|
3396
|
+
.hd { position: relative; flex: none; display: flex; align-items: center; gap: 12px; padding: 13px 14px 12px; background: var(--oc-ac); color: #fff; overflow: hidden; }
|
|
3397
|
+
.hd-grid { pointer-events: none; position: absolute; inset: 0; background-image: linear-gradient(90deg, rgba(255,255,255,0.11) 1px, transparent 1px), linear-gradient(180deg, rgba(255,255,255,0.11) 1px, transparent 1px); background-size: 26px 26px; }
|
|
3398
|
+
.hd .logo { position: relative; flex: none; width: 32px; height: 32px; border-radius: 7px; overflow: hidden; color: rgba(255,255,255,0.22); }
|
|
3399
|
+
.hd-txt { position: relative; flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
|
|
3400
|
+
.hd-title { font-size: 14.5px; font-weight: 600; letter-spacing: -0.015em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
3401
|
+
.hd-status { display: flex; align-items: center; gap: 6px; font-size: 11.5px; opacity: 0.9; }
|
|
3402
|
+
.hd-status .dot { width: 6px; height: 6px; border-radius: var(--oc-r-full); background: #7BE3A6; flex: none; }
|
|
3403
|
+
.hd-status .t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
3404
|
+
.hd-btn { position: relative; flex: none; width: 28px; height: 28px; border-radius: 8px; border: none; background: rgba(255,255,255,0.16); color: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background .18s var(--oc-ease); }
|
|
3405
|
+
.hd-btn:hover { background: rgba(255,255,255,0.28); }
|
|
3406
|
+
.hd-btn .i { position: absolute; display: flex; transition: opacity .2s var(--oc-ease); }
|
|
3407
|
+
.i-expand { opacity: 1; } .i-shrink { opacity: 0; }
|
|
3408
|
+
.oc.max .i-expand { opacity: 0; } .oc.max .i-shrink { opacity: 1; }
|
|
3409
|
+
|
|
3410
|
+
.err { flex: none; display: flex; align-items: center; gap: 8px; padding: 8px 16px; font-size: 12px; color: #fff; background: var(--oc-danger); }
|
|
3411
|
+
.err .retry { padding: 3px 10px; font-size: 11px; background: rgba(255,255,255,0.2); color: #fff; border: none; border-radius: 6px; cursor: pointer; }
|
|
3412
|
+
|
|
3413
|
+
/* \u2500\u2500 Message list \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 */
|
|
3414
|
+
.body { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 16px; padding: 16px 16px 26px; background: var(--oc-bg); scroll-behavior: smooth; }
|
|
3415
|
+
.turn { display: flex; flex-direction: column; gap: 6px; animation: w-in .42s var(--oc-ease) both; }
|
|
3416
|
+
.turn.bot { align-items: flex-start; } .turn.user { align-items: flex-end; }
|
|
3417
|
+
.b { font-size: 13.5px; line-height: 1.55; text-wrap: pretty; word-break: break-word; }
|
|
3418
|
+
.turn.bot .b { max-width: 86%; padding: 13px 15px; border-radius: 20px; background: var(--oc-tint-2); color: var(--oc-fg); }
|
|
3419
|
+
.turn.user .b { max-width: 82%; padding: 11px 15px; border-radius: var(--oc-r-full); background: var(--oc-ac); color: #fff; }
|
|
3420
|
+
.turn.human .b { max-width: 86%; padding: 13px 15px; border-radius: 20px; background: color-mix(in oklab, var(--oc-ac) 16%, transparent); color: var(--oc-fg); }
|
|
3421
|
+
.src { display: inline-flex; align-items: center; gap: 7px; padding: 5px 10px 5px 8px; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border); background: var(--oc-tint-1); max-width: 100%; }
|
|
3422
|
+
.src .t { min-width: 0; font-size: 11.5px; color: var(--oc-fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3423
|
+
.byline { display: flex; align-items: center; gap: 6px; padding: 0 4px; font-size: 11.5px; color: var(--oc-fg-dim); }
|
|
3424
|
+
.human-label { font-size: 11px; font-weight: 600; opacity: .7; margin-bottom: 2px; }
|
|
3425
|
+
|
|
3426
|
+
/* markdown inside a bot bubble */
|
|
3427
|
+
.md > :first-child { margin-top: 0; } .md > :last-child { margin-bottom: 0; }
|
|
3428
|
+
.md p { margin: 0 0 8px; } .md ul, .md ol { margin: 0 0 8px; padding-left: 20px; } .md li { margin: 2px 0; }
|
|
3429
|
+
.md a { color: var(--oc-accent-text); text-decoration: underline; text-underline-offset: 2px; }
|
|
3430
|
+
.md code { font-family: var(--oc-mono); font-size: 12.5px; background: var(--oc-tint-3); padding: 1px 5px; border-radius: 5px; }
|
|
3431
|
+
.md pre { background: color-mix(in oklab, var(--oc-fg) 10%, transparent); padding: 10px 12px; border-radius: 8px; overflow-x: auto; margin: 0 0 8px; }
|
|
3432
|
+
.md pre code { background: none; padding: 0; }
|
|
3433
|
+
.md blockquote { margin: 0 0 8px; padding-left: 10px; border-left: 3px solid var(--oc-border); color: var(--oc-fg-muted); }
|
|
3434
|
+
.md h1, .md h2, .md h3, .md h4 { margin: 8px 0 6px; font-size: 15px; }
|
|
3435
|
+
.md table { border-collapse: collapse; font-size: 13px; margin: 0 0 8px; display: block; overflow-x: auto; }
|
|
3436
|
+
.md th, .md td { border: 1px solid var(--oc-border); padding: 4px 8px; }
|
|
3437
|
+
.att-thumb { display: block; max-width: 180px; max-height: 180px; border-radius: 8px; margin-bottom: 6px; }
|
|
3438
|
+
.att-chip { display: inline-block; font-size: 12px; background: var(--oc-tint-3); border-radius: 6px; padding: 2px 8px; margin: 0 0 6px; }
|
|
3439
|
+
.turn.user .att-chip { background: rgba(255,255,255,0.25); }
|
|
3440
|
+
|
|
3441
|
+
.typing { align-self: flex-start; display: flex; align-items: center; gap: 5px; padding: 13px 16px; border-radius: 20px; background: var(--oc-tint-2); animation: w-in .3s var(--oc-ease) both; }
|
|
3442
|
+
.typing span { width: 6px; height: 6px; border-radius: var(--oc-r-full); background: var(--oc-fg-muted); animation: w-dot 1.2s ease-in-out infinite; }
|
|
3443
|
+
.typing span:nth-child(2) { animation-delay: .15s; } .typing span:nth-child(3) { animation-delay: .3s; }
|
|
3444
|
+
|
|
3445
|
+
.chips { display: flex; flex-wrap: wrap; gap: 7px; padding-top: 2px; animation: w-in .42s var(--oc-ease) both; animation-delay: .3s; }
|
|
3446
|
+
.chip { padding: 8px 13px; border-radius: var(--oc-r-full); border: 1px solid color-mix(in oklab, var(--oc-ac) 34%, transparent); background: color-mix(in oklab, var(--oc-ac) 10%, transparent); color: var(--oc-accent-text); font-size: 12px; font-weight: 500; cursor: pointer; white-space: nowrap; transition: all .18s var(--oc-ease); }
|
|
3447
|
+
.chip:hover { background: color-mix(in oklab, var(--oc-ac) 18%, transparent); }
|
|
3448
|
+
|
|
3449
|
+
/* \u2500\u2500 Jump to latest \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 */
|
|
3450
|
+
.jump-wrap { position: relative; flex: none; height: 0; z-index: 2; display: flex; justify-content: center; }
|
|
3451
|
+
.jump { position: absolute; bottom: 8px; width: 34px; height: 34px; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border); background: var(--oc-bg); box-shadow: 0 8px 20px -10px rgba(0,0,0,0.5); color: var(--oc-fg-muted); display: flex; align-items: center; justify-content: center; cursor: pointer; opacity: 0; transform: translateY(6px) scale(0.8); pointer-events: none; transition: all .22s var(--oc-ease); }
|
|
3452
|
+
.oc.away .jump { opacity: 1; transform: none; pointer-events: auto; }
|
|
3453
|
+
.jump:hover { color: var(--oc-fg); border-color: var(--oc-fg-dim); }
|
|
3454
|
+
|
|
3455
|
+
/* \u2500\u2500 Composer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
3456
|
+
.composer { flex: none; display: flex; flex-direction: column; gap: 9px; padding: 12px 14px 13px; background: var(--oc-bg); }
|
|
3457
|
+
.field { display: flex; flex-direction: column; gap: 11px; padding: 13px 14px 11px; border-radius: 18px; border: 1px solid var(--oc-field-border); background: var(--oc-field-bg); transition: border-color .18s var(--oc-ease); }
|
|
3458
|
+
.oc.focus .field { border-color: var(--oc-ac); }
|
|
3459
|
+
.input { width: 100%; border: none; background: transparent; color: var(--oc-fg); font-size: 13.5px; line-height: 1.4; outline: none; padding: 0; resize: none; max-height: 108px; font-family: inherit; }
|
|
3460
|
+
.input::placeholder { color: var(--oc-fg-dim); }
|
|
3461
|
+
.acts { display: flex; align-items: center; gap: 16px; }
|
|
3462
|
+
.act { flex: none; display: flex; border: none; background: transparent; padding: 4px; margin: -4px; color: var(--oc-fg-dim); cursor: pointer; transition: color .18s var(--oc-ease); }
|
|
3463
|
+
.act:hover { color: var(--oc-fg-muted); }
|
|
3464
|
+
.oc.emoji .act.emoji-btn { color: var(--oc-accent-text); }
|
|
3465
|
+
.send { flex: none; margin-left: auto; width: 34px; height: 34px; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border); background: var(--oc-tint-3); color: var(--oc-fg-dim); box-shadow: none; display: flex; align-items: center; justify-content: center; cursor: default; transition: all .22s var(--oc-ease); }
|
|
3466
|
+
.oc.ready .send { border-color: var(--oc-btn-rim); background: var(--oc-ac); color: #fff; box-shadow: var(--oc-btn-edge); cursor: pointer; }
|
|
3467
|
+
.oc.ready .send:hover { filter: brightness(1.1); }
|
|
3468
|
+
.send:active { transform: scale(0.92); }
|
|
3469
|
+
|
|
3470
|
+
.foot { position: relative; display: none; text-align: center; font-size: 11.5px; line-height: 1.5; color: var(--oc-fg-dim); }
|
|
3471
|
+
.oc.has-privacy .foot { display: block; }
|
|
3472
|
+
.foot .priv { color: var(--oc-fg-muted); text-decoration: underline; text-underline-offset: 2px; cursor: default; }
|
|
3473
|
+
.foot .tip { position: absolute; left: 0; right: 0; bottom: 16px; padding-bottom: 8px; z-index: 7; display: flex; justify-content: flex-end; pointer-events: none; opacity: 0; transition: opacity .18s var(--oc-ease); }
|
|
3474
|
+
.oc.max .foot .tip { right: 188px; }
|
|
3475
|
+
.foot:hover .tip { opacity: 1; }
|
|
3476
|
+
.foot .tip-card { max-width: 100%; width: 262px; padding: 13px 15px; border-radius: 14px; border: 1px solid var(--oc-border); background: var(--oc-bg); box-shadow: 0 8px 22px -12px rgba(0,0,0,0.32); text-align: left; font-size: 11.5px; line-height: 1.55; color: var(--oc-fg-muted); text-wrap: pretty; transform: translateY(6px); transition: transform .24s var(--oc-bounce); }
|
|
3477
|
+
.foot:hover .tip-card { transform: none; }
|
|
3478
|
+
.foot .tip-card a { color: var(--oc-fg); text-decoration: underline; text-underline-offset: 2px; }
|
|
3479
|
+
|
|
3480
|
+
/* \u2500\u2500 Emoji picker \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 */
|
|
3481
|
+
.emoji-scrim { position: absolute; inset: 0; z-index: 3; display: none; }
|
|
3482
|
+
.oc.emoji .emoji-scrim { display: block; }
|
|
3483
|
+
.emoji-panel { position: absolute; left: 10px; right: 10px; bottom: 96px; z-index: 4; max-height: min(340px, 58%); display: flex; flex-direction: column; border-radius: 18px; border: 1px solid var(--oc-border); background: var(--oc-bg); box-shadow: 0 18px 46px -18px rgba(0,0,0,0.6); overflow: hidden; opacity: 0; transform: translateY(10px) scale(0.96); transform-origin: bottom center; pointer-events: none; visibility: hidden; transition: opacity .18s var(--oc-ease), transform .26s var(--oc-bounce), visibility .26s; }
|
|
3484
|
+
.oc.emoji .emoji-panel { opacity: 1; transform: none; pointer-events: auto; visibility: visible; }
|
|
3485
|
+
.emoji-search { flex: none; display: flex; align-items: center; gap: 11px; padding: 13px 16px; border-bottom: 1px solid var(--oc-border); color: var(--oc-fg-dim); }
|
|
3486
|
+
.emoji-search input { flex: 1 1 auto; min-width: 0; border: none; background: transparent; color: var(--oc-fg); font-size: 14.5px; outline: none; font-family: inherit; }
|
|
3487
|
+
.emoji-search input::placeholder { color: var(--oc-fg-dim); }
|
|
3488
|
+
.emoji-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; padding: 12px 14px 16px; }
|
|
3489
|
+
.emoji-grp { display: flex; flex-direction: column; gap: 6px; }
|
|
3490
|
+
.emoji-grp + .emoji-grp { padding-top: 8px; }
|
|
3491
|
+
.emoji-grp-name { font-family: var(--oc-mono); font-size: 9.5px; font-weight: 600; letter-spacing: 0.15em; text-transform: uppercase; color: var(--oc-fg-dim); }
|
|
3492
|
+
.emoji-grid { display: grid; grid-template-columns: repeat(7, minmax(0,1fr)); gap: 2px; }
|
|
3493
|
+
.emoji-grid button { display: flex; align-items: center; justify-content: center; height: 34px; border-radius: 8px; border: none; background: transparent; font-size: 20px; line-height: 1; cursor: pointer; transition: background .14s var(--oc-ease); }
|
|
3494
|
+
.emoji-grid button:hover { background: var(--oc-tint-3); }
|
|
3495
|
+
.emoji-empty { display: none; flex-direction: column; align-items: center; gap: 5px; padding: 26px 10px; text-align: center; }
|
|
3496
|
+
.emoji-empty .h { font-size: 14px; color: var(--oc-fg); } .emoji-empty .s { font-size: 12.5px; color: var(--oc-fg-dim); }
|
|
3497
|
+
|
|
3498
|
+
@media (max-width: 480px) {
|
|
3499
|
+
:host { right: 0; bottom: 0; }
|
|
3500
|
+
.oc { padding: 0 16px 16px; }
|
|
3501
|
+
.panel { position: fixed; inset: 0; width: 100vw; height: 100dvh; border-radius: 0; }
|
|
3502
|
+
.oc.max .panel { width: 100vw; height: 100dvh; }
|
|
3503
|
+
}
|
|
3504
|
+
@media (prefers-reduced-motion: reduce) {
|
|
3505
|
+
.launcher, .panel, .teaser, .turn, .jump, .emoji-panel { transition: none; animation: none; }
|
|
3506
|
+
.ring { animation: none; } .body { scroll-behavior: auto; }
|
|
3507
|
+
}
|
|
3508
|
+
|
|
3509
|
+
@keyframes w-in { from { opacity: 0; transform: translateY(10px) scale(0.97); } to { opacity: 1; transform: none; } }
|
|
3510
|
+
@keyframes w-dot { 0%,60%,100% { transform: translateY(0); opacity: .45; } 30% { transform: translateY(-4px); opacity: 1; } }
|
|
3511
|
+
@keyframes w-ring { 0% { transform: scale(1); opacity: .5; } 70%,100% { transform: scale(1.7); opacity: 0; } }
|
|
3512
|
+
`;
|
|
3513
|
+
|
|
3514
|
+
// src/icons.ts
|
|
3515
|
+
var logoMark = (rectFill) => `<svg viewBox="0 0 1032 1024" fill="none" style="display:block;width:100%;height:100%"><rect x="4" width="1024" height="1024" rx="150" fill="${rectFill}"></rect><path d="M430.924 831.644C270.203 859.983 138.14 760.606 111.329 608.551C84.5174 456.497 174.627 317.945 335.348 289.605C496.068 261.266 628.131 360.643 654.943 512.698C681.754 664.752 591.644 803.304 430.924 831.644ZM406.613 693.77C488.549 679.323 518.727 615.513 505.252 539.092C491.777 462.671 441.594 413.031 359.658 427.478C277.722 441.926 247.544 505.736 261.02 582.157C274.495 658.578 324.677 708.218 406.613 693.77ZM870.337 558.389L744.281 580.616C727.055 482.923 674.565 369.515 652.06 241.884L841.143 208.543C863.509 335.387 853.111 460.696 870.337 558.389ZM910.583 740.568L768.771 765.573L745.016 630.852L886.828 605.846L910.583 740.568Z" fill="#fff"></path></svg>`;
|
|
3516
|
+
var stroke = (w, path, size = 24) => `<svg width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="${w}" stroke-linecap="round" stroke-linejoin="round" style="display:block;flex:none">${path}</svg>`;
|
|
3517
|
+
var ICON = {
|
|
3518
|
+
close: (size = 19) => stroke(2.4, '<path d="M18 6 6 18M6 6l12 12"/>', size),
|
|
3519
|
+
minus: stroke(2, '<path d="M6 12h12"/>', 15),
|
|
3520
|
+
expand: stroke(2, '<path d="M15 4h5v5M20 4l-6.5 6.5M9 20H4v-5M4 20l6.5-6.5"/>', 15),
|
|
3521
|
+
shrink: stroke(2, '<path d="M20 9h-5V4M15 9l5.5-5.5M4 15h5v5M9 15l-5.5 5.5"/>', 15),
|
|
3522
|
+
chevronDown: stroke(2.1, '<path d="m6 9 6 6 6-6"/>', 16),
|
|
3523
|
+
send: stroke(2.2, '<path d="M12 19V5M6 11l6-6 6 6"/>', 16),
|
|
3524
|
+
paperclip: stroke(1.7, '<path d="M21 11.5 12.5 20a5.5 5.5 0 0 1-7.8-7.8l8.5-8.5a3.7 3.7 0 0 1 5.2 5.2l-8.5 8.5a1.8 1.8 0 0 1-2.6-2.6l7.9-7.8"/>', 17),
|
|
3525
|
+
emoji: stroke(1.7, '<circle cx="12" cy="12" r="9"/><path d="M8.5 14.5a4.5 4.5 0 0 0 7 0M9 9.5h.01M15 9.5h.01"/>', 17),
|
|
3526
|
+
mic: stroke(1.7, '<rect x="9" y="3" width="6" height="11" rx="3"/><path d="M5 11a7 7 0 0 0 14 0M12 18v3"/>', 17),
|
|
3527
|
+
search: stroke(1.9, '<circle cx="11" cy="11" r="7.5"/><path d="m21 21-4.3-4.3"/>', 17),
|
|
3528
|
+
clear: stroke(2.2, '<path d="M18 6 6 18M6 6l12 12"/>', 15),
|
|
3529
|
+
// Two-page "source" glyph for citation chips.
|
|
3530
|
+
book: `<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" style="display:block;flex:none;color:var(--oc-accent-text)"><path d="M3 5.5A2.5 2.5 0 0 1 5.5 3H11v18H5.5A2.5 2.5 0 0 1 3 18.5Z"/><path d="M21 5.5A2.5 2.5 0 0 0 18.5 3H13v18h5.5a2.5 2.5 0 0 0 2.5-2.5Z"/></svg>`,
|
|
3531
|
+
teaserDismiss: stroke(2.4, '<path d="M18 6 6 18M6 6l12 12"/>', 12)
|
|
3532
|
+
};
|
|
3533
|
+
|
|
3534
|
+
// src/emoji.ts
|
|
3535
|
+
var CATS = [
|
|
3536
|
+
{ name: "Frequently used", items: [
|
|
3537
|
+
["\u{1F44D}", "thumbs up"],
|
|
3538
|
+
["\u{1F64F}", "thanks"],
|
|
3539
|
+
["\u{1F44B}", "wave"],
|
|
3540
|
+
["\u2705", "done"],
|
|
3541
|
+
["\u{1F4DE}", "call"],
|
|
3542
|
+
["\u{1F60A}", "smile"],
|
|
3543
|
+
["\u2764\uFE0F", "heart"]
|
|
3544
|
+
] },
|
|
3545
|
+
{ name: "Smileys and emotion", items: [
|
|
3546
|
+
["\u{1F600}", "grinning"],
|
|
3547
|
+
["\u{1F603}", "smiley"],
|
|
3548
|
+
["\u{1F604}", "grin"],
|
|
3549
|
+
["\u{1F601}", "beaming"],
|
|
3550
|
+
["\u{1F606}", "squinting"],
|
|
3551
|
+
["\u{1F605}", "relief"],
|
|
3552
|
+
["\u{1F923}", "rolling"],
|
|
3553
|
+
["\u{1F602}", "tears of joy"],
|
|
3554
|
+
["\u{1F642}", "slightly smiling"],
|
|
3555
|
+
["\u{1F643}", "upside down"],
|
|
3556
|
+
["\u{1F609}", "wink"],
|
|
3557
|
+
["\u{1F607}", "halo"],
|
|
3558
|
+
["\u{1F970}", "smiling hearts"],
|
|
3559
|
+
["\u{1F60D}", "heart eyes"],
|
|
3560
|
+
["\u{1F618}", "kiss"],
|
|
3561
|
+
["\u{1F60B}", "yum"],
|
|
3562
|
+
["\u{1F914}", "thinking"],
|
|
3563
|
+
["\u{1F928}", "raised brow"],
|
|
3564
|
+
["\u{1F610}", "neutral"],
|
|
3565
|
+
["\u{1F644}", "eye roll"],
|
|
3566
|
+
["\u{1F62C}", "grimace"],
|
|
3567
|
+
["\u{1F625}", "sad"],
|
|
3568
|
+
["\u{1F622}", "crying"],
|
|
3569
|
+
["\u{1F62D}", "sobbing"],
|
|
3570
|
+
["\u{1F620}", "angry"],
|
|
3571
|
+
["\u{1F633}", "flushed"],
|
|
3572
|
+
["\u{1F929}", "star struck"],
|
|
3573
|
+
["\u{1F634}", "sleeping"]
|
|
3574
|
+
] },
|
|
3575
|
+
{ name: "Gestures", items: [
|
|
3576
|
+
["\u{1F44E}", "thumbs down"],
|
|
3577
|
+
["\u{1F44F}", "clap"],
|
|
3578
|
+
["\u{1F64C}", "raised hands"],
|
|
3579
|
+
["\u{1F91D}", "handshake"],
|
|
3580
|
+
["\u{1F44C}", "ok hand"],
|
|
3581
|
+
["\u270C\uFE0F", "victory"],
|
|
3582
|
+
["\u{1F4AA}", "strong"],
|
|
3583
|
+
["\u{1F440}", "eyes"],
|
|
3584
|
+
["\u{1F9E0}", "brain"],
|
|
3585
|
+
["\u{1F91F}", "love you"],
|
|
3586
|
+
["\u261D\uFE0F", "point up"],
|
|
3587
|
+
["\u{1F447}", "point down"],
|
|
3588
|
+
["\u{1F91A}", "raised back"],
|
|
3589
|
+
["\u{1F91E}", "fingers crossed"]
|
|
3590
|
+
] },
|
|
3591
|
+
{ name: "Work and travel", items: [
|
|
3592
|
+
["\u{1F4C5}", "calendar"],
|
|
3593
|
+
["\u{1F4C4}", "document"],
|
|
3594
|
+
["\u{1F4B0}", "money"],
|
|
3595
|
+
["\u{1F4CA}", "chart"],
|
|
3596
|
+
["\u{1F4E6}", "package"],
|
|
3597
|
+
["\u{1F3E5}", "hospital"],
|
|
3598
|
+
["\u{1F3E6}", "bank"],
|
|
3599
|
+
["\u{1F69A}", "truck"],
|
|
3600
|
+
["\u2708\uFE0F", "plane"],
|
|
3601
|
+
["\u{1F4F1}", "phone"],
|
|
3602
|
+
["\u{1F4BB}", "laptop"],
|
|
3603
|
+
["\u{1F50D}", "search"],
|
|
3604
|
+
["\u{1F4CC}", "pin"],
|
|
3605
|
+
["\u{1F514}", "bell"]
|
|
3606
|
+
] },
|
|
3607
|
+
{ name: "Symbols", items: [
|
|
3608
|
+
["\u{1F525}", "fire"],
|
|
3609
|
+
["\u2728", "sparkles"],
|
|
3610
|
+
["\u{1F389}", "celebrate"],
|
|
3611
|
+
["\u{1F4AF}", "hundred"],
|
|
3612
|
+
["\u26A0\uFE0F", "warning"],
|
|
3613
|
+
["\u274C", "cross"],
|
|
3614
|
+
["\u2B50", "star"],
|
|
3615
|
+
["\u{1F680}", "launch"],
|
|
3616
|
+
["\u{1F49A}", "green heart"],
|
|
3617
|
+
["\u{1F499}", "blue heart"],
|
|
3618
|
+
["\u{1F552}", "clock"],
|
|
3619
|
+
["\u{1F4A1}", "idea"],
|
|
3620
|
+
["\u{1F512}", "lock"],
|
|
3621
|
+
["\u{1F3AF}", "target"]
|
|
3622
|
+
] }
|
|
3623
|
+
];
|
|
3624
|
+
var toGroup = (name, items) => ({
|
|
3625
|
+
name,
|
|
3626
|
+
items: items.map(([ch, kw]) => ({ ch, name: kw }))
|
|
3627
|
+
});
|
|
3628
|
+
function emojiGroups(query) {
|
|
3629
|
+
const q2 = query.trim().toLowerCase();
|
|
3630
|
+
if (!q2) return CATS.map((c) => toGroup(c.name, c.items));
|
|
3631
|
+
const hits = [];
|
|
3632
|
+
for (const c of CATS) for (const e of c.items) {
|
|
3633
|
+
if (e[1].indexOf(q2) >= 0 && !hits.some((h) => h[0] === e[0])) hits.push(e);
|
|
3634
|
+
}
|
|
3635
|
+
if (!hits.length) return [];
|
|
3636
|
+
return [toGroup(`${hits.length} result${hits.length === 1 ? "" : "s"}`, hits)];
|
|
346
3637
|
}
|
|
347
3638
|
|
|
348
3639
|
// src/element.ts
|
|
349
|
-
var
|
|
3640
|
+
var DEFAULT_STATUS = "Replies in a few seconds";
|
|
3641
|
+
var ATTACHMENT_ACCEPT = "image/*,application/pdf,text/plain,text/csv";
|
|
3642
|
+
var AWAY_THRESHOLD = 60;
|
|
3643
|
+
var HANDOFF_STATUS = {
|
|
350
3644
|
ai: null,
|
|
351
3645
|
awaiting_human: "Connecting you to a person\u2026",
|
|
352
3646
|
human: "You're chatting with a person"
|
|
353
3647
|
};
|
|
354
|
-
var ATTACHMENT_ACCEPT = "image/*,application/pdf,text/plain,text/csv";
|
|
355
|
-
var AGENT_TYPING_TEXT = "The agent is typing\u2026";
|
|
356
3648
|
var OyehelloChatElement = class extends HTMLElement {
|
|
357
|
-
static observedAttributes = ["api-key", "agent-id", "base-url", "title"];
|
|
3649
|
+
static observedAttributes = ["api-key", "agent-id", "base-url", "title", "theme"];
|
|
3650
|
+
// ── live client state ──
|
|
358
3651
|
client = null;
|
|
359
3652
|
off = null;
|
|
360
3653
|
messages = [];
|
|
361
3654
|
state = "idle";
|
|
362
3655
|
agentName = null;
|
|
363
3656
|
handoffState = "ai";
|
|
364
|
-
// Transient "agent is typing…" affordance (Phase 7 followups) - never a message, only rendered
|
|
365
|
-
// while a handoff is active (human/awaiting_human).
|
|
366
3657
|
agentTyping = false;
|
|
367
|
-
// Last connection/runtime error message (client emits an 'error' event on a failed start() or
|
|
368
|
-
// send). Surfaced as a visible banner so a disabled composer always shows WHY, instead of sitting
|
|
369
|
-
// dead. Cleared when the client reaches a healthy state again.
|
|
370
3658
|
lastError = null;
|
|
371
|
-
// registerTools() may be called before connectedCallback creates the client (e.g. right after
|
|
372
|
-
// document.createElement, before the element is attached). Buffer until the client exists.
|
|
373
3659
|
pendingTools = {};
|
|
374
|
-
// Files picked in the file input, staged until the form submits alongside the text.
|
|
375
3660
|
pendingFiles = [];
|
|
376
|
-
// Best-effort local thumbnail cache for images THIS widget instance just sent, keyed by filename -
|
|
377
|
-
// an instant blob src, no round-trip needed.
|
|
378
3661
|
imagePreviewCache = /* @__PURE__ */ new Map();
|
|
379
|
-
// Read-back URLs resolved lazily (via client.getAttachmentUrl) for images with no local blob (a
|
|
380
|
-
// reconnect, or an `attachment` SSE echo), keyed by storageRef. Cached across re-renders so the
|
|
381
|
-
// same image isn't re-fetched on every render() call.
|
|
382
3662
|
resolvedUrlCache = /* @__PURE__ */ new Map();
|
|
3663
|
+
mdCache = /* @__PURE__ */ new Map();
|
|
3664
|
+
receivedAt = /* @__PURE__ */ new Map();
|
|
3665
|
+
// ── widget UI state ──
|
|
3666
|
+
uiOpen = false;
|
|
3667
|
+
started = false;
|
|
3668
|
+
uiMax = false;
|
|
3669
|
+
emojiOpen = false;
|
|
3670
|
+
emojiQuery = "";
|
|
3671
|
+
away = false;
|
|
3672
|
+
// reader scrolled up
|
|
3673
|
+
unseen = 0;
|
|
3674
|
+
focused = false;
|
|
3675
|
+
teaserActive = false;
|
|
3676
|
+
renderedCount = 0;
|
|
3677
|
+
renderedBotFinal = 0;
|
|
3678
|
+
timers = [];
|
|
3679
|
+
// ── shadow refs ──
|
|
3680
|
+
oc;
|
|
3681
|
+
bodyEl;
|
|
3682
|
+
textareaEl;
|
|
3683
|
+
fileEl;
|
|
3684
|
+
titleEl;
|
|
3685
|
+
statusEl;
|
|
3686
|
+
errEl;
|
|
3687
|
+
emojiListEl;
|
|
3688
|
+
emojiSearchEl;
|
|
383
3689
|
connectedCallback() {
|
|
384
3690
|
if (!this.shadowRoot) this.attachShadow({ mode: "open" });
|
|
385
3691
|
const apiKey = this.getAttribute("api-key");
|
|
@@ -394,23 +3700,44 @@ var OyehelloChat = (function (exports) {
|
|
|
394
3700
|
this.client.registerTools(this.pendingTools);
|
|
395
3701
|
this.pendingTools = {};
|
|
396
3702
|
}
|
|
397
|
-
this.off = this.client.on((e) =>
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
|
|
3703
|
+
this.off = this.client.on((e) => this.onClientEvent(e));
|
|
3704
|
+
this.renderShell();
|
|
3705
|
+
this.renderMessages();
|
|
3706
|
+
this.updateHeader();
|
|
3707
|
+
this.updateStatus();
|
|
3708
|
+
this.updateClasses();
|
|
3709
|
+
let wasOpen = false;
|
|
3710
|
+
try {
|
|
3711
|
+
wasOpen = sessionStorage.getItem(this.key("open")) === "1";
|
|
3712
|
+
} catch {
|
|
3713
|
+
}
|
|
3714
|
+
if (wasOpen) {
|
|
3715
|
+
this.openPanel();
|
|
3716
|
+
return;
|
|
3717
|
+
}
|
|
3718
|
+
this.updateClasses(true);
|
|
3719
|
+
this.timers.push(setTimeout(() => {
|
|
3720
|
+
this.oc?.classList.remove("ring");
|
|
3721
|
+
}, 6e3));
|
|
3722
|
+
const teaserText = this.getAttribute("teaser");
|
|
3723
|
+
let dismissed = false;
|
|
3724
|
+
try {
|
|
3725
|
+
dismissed = sessionStorage.getItem(this.key("teaser")) === "0";
|
|
3726
|
+
} catch {
|
|
3727
|
+
}
|
|
3728
|
+
if (teaserText && !dismissed) {
|
|
3729
|
+
this.timers.push(setTimeout(() => {
|
|
3730
|
+
if (!this.uiOpen) {
|
|
3731
|
+
this.teaserActive = true;
|
|
3732
|
+
this.updateClasses();
|
|
3733
|
+
}
|
|
3734
|
+
}, 1400));
|
|
3735
|
+
}
|
|
410
3736
|
}
|
|
411
3737
|
disconnectedCallback() {
|
|
412
3738
|
this.off?.();
|
|
413
3739
|
void this.client?.end();
|
|
3740
|
+
for (const t of this.timers) clearTimeout(t);
|
|
414
3741
|
for (const url of this.imagePreviewCache.values()) {
|
|
415
3742
|
if (typeof URL.revokeObjectURL === "function") URL.revokeObjectURL(url);
|
|
416
3743
|
}
|
|
@@ -420,37 +3747,394 @@ var OyehelloChat = (function (exports) {
|
|
|
420
3747
|
if (this.client) this.client.registerTools(handlers);
|
|
421
3748
|
else Object.assign(this.pendingTools, handlers);
|
|
422
3749
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
3750
|
+
key(k2) {
|
|
3751
|
+
return `oyehello-chat:${k2}:${this.getAttribute("agent-id") ?? ""}`;
|
|
3752
|
+
}
|
|
3753
|
+
get suggestions() {
|
|
3754
|
+
return (this.getAttribute("suggestions") ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
3755
|
+
}
|
|
3756
|
+
// ── Shell (built once) ─────────────────────────────────────────────────────────────────────────
|
|
3757
|
+
renderShell() {
|
|
3758
|
+
const root = this.shadowRoot;
|
|
3759
|
+
const hasTeaser = !!this.getAttribute("teaser");
|
|
3760
|
+
const hasPrivacy = !!this.getAttribute("privacy-url");
|
|
3761
|
+
const teaserText = this.getAttribute("teaser") ?? "";
|
|
3762
|
+
root.innerHTML = `
|
|
3763
|
+
<style>${STYLES}</style>
|
|
3764
|
+
<div class="oc${hasTeaser ? " has-teaser" : ""}${hasPrivacy ? " has-privacy" : ""}">
|
|
3765
|
+
<div class="panel" role="dialog" aria-label="Chat">
|
|
3766
|
+
<div class="hd">
|
|
3767
|
+
<span class="hd-grid"></span>
|
|
3768
|
+
<span class="logo">${logoMark("currentColor")}</span>
|
|
3769
|
+
<span class="hd-txt"><span class="hd-title">Chat</span><span class="hd-status"><span class="dot"></span><span class="t"></span></span></span>
|
|
3770
|
+
<button type="button" class="hd-btn max" aria-label="Expand"><span class="i i-expand">${ICON.expand}</span><span class="i i-shrink">${ICON.shrink}</span></button>
|
|
3771
|
+
<button type="button" class="hd-btn min" aria-label="Minimise">${ICON.minus}</button>
|
|
3772
|
+
</div>
|
|
3773
|
+
<div class="err" hidden></div>
|
|
3774
|
+
<div class="body"></div>
|
|
3775
|
+
<span class="emoji-scrim"></span>
|
|
3776
|
+
<div class="emoji-panel">
|
|
3777
|
+
<div class="emoji-search">${ICON.search}<input type="text" placeholder="Search emoji\u2026" aria-label="Search emoji" /></div>
|
|
3778
|
+
<div class="emoji-list"></div>
|
|
3779
|
+
</div>
|
|
3780
|
+
<div class="jump-wrap"><button type="button" class="jump" aria-label="Jump to latest">${ICON.chevronDown}</button></div>
|
|
3781
|
+
<div class="composer">
|
|
3782
|
+
<form class="field">
|
|
3783
|
+
<textarea class="input" rows="1" aria-label="message" placeholder="Ask a question\u2026"></textarea>
|
|
3784
|
+
<div class="acts">
|
|
3785
|
+
<button type="button" class="act attach" aria-label="Attach a file">${ICON.paperclip}</button>
|
|
3786
|
+
<input type="file" accept="${ATTACHMENT_ACCEPT}" multiple hidden />
|
|
3787
|
+
<button type="button" class="act emoji-btn" aria-label="Insert emoji">${ICON.emoji}</button>
|
|
3788
|
+
<button type="button" class="act mic" aria-label="Send a voice note">${ICON.mic}</button>
|
|
3789
|
+
<button type="submit" class="send" aria-label="Send">${ICON.send}</button>
|
|
3790
|
+
</div>
|
|
3791
|
+
</form>
|
|
3792
|
+
<div class="foot">
|
|
3793
|
+
<span>By chatting with us, you agree to our </span><span class="priv">Privacy Policy</span>
|
|
3794
|
+
<span class="tip"><span class="tip-card">By chatting with us, you agree to the monitoring and recording of this chat to deliver our services and processing of your personal data in accordance with our Privacy Policy. <a href="${this.escapeAttr(this.getAttribute("privacy-url") ?? "#")}" target="_blank" rel="noopener noreferrer">See our Privacy Policy</a>.</span></span>
|
|
3795
|
+
</div>
|
|
3796
|
+
</div>
|
|
3797
|
+
</div>
|
|
3798
|
+
|
|
3799
|
+
<div class="teaser">
|
|
3800
|
+
<button type="button" class="teaser-btn"><span class="logo">${logoMark("currentColor")}</span><span>${escapeHtml(teaserText)}</span></button>
|
|
3801
|
+
<button type="button" class="teaser-x" aria-label="Dismiss">${ICON.teaserDismiss}</button>
|
|
3802
|
+
</div>
|
|
3803
|
+
|
|
3804
|
+
<button type="button" class="launcher" aria-label="Open chat">
|
|
3805
|
+
<span class="ring"></span>
|
|
3806
|
+
<span class="ic-chat">${logoMark("var(--oc-ac)")}</span>
|
|
3807
|
+
<span class="ic-close">${ICON.close(19)}</span>
|
|
3808
|
+
<span class="badge"></span>
|
|
3809
|
+
</button>
|
|
3810
|
+
</div>`;
|
|
3811
|
+
this.oc = root.querySelector(".oc");
|
|
3812
|
+
this.bodyEl = root.querySelector(".body");
|
|
3813
|
+
this.textareaEl = root.querySelector("textarea.input");
|
|
3814
|
+
this.fileEl = root.querySelector('input[type="file"]');
|
|
3815
|
+
this.titleEl = root.querySelector(".hd-title");
|
|
3816
|
+
this.statusEl = root.querySelector(".hd-status .t");
|
|
3817
|
+
this.errEl = root.querySelector(".err");
|
|
3818
|
+
this.emojiListEl = root.querySelector(".emoji-list");
|
|
3819
|
+
this.emojiSearchEl = root.querySelector(".emoji-search input");
|
|
3820
|
+
root.querySelector(".launcher").addEventListener("click", () => this.toggle());
|
|
3821
|
+
root.querySelector(".hd-btn.min").addEventListener("click", () => this.closePanel());
|
|
3822
|
+
root.querySelector(".hd-btn.max").addEventListener("click", () => {
|
|
3823
|
+
this.uiMax = !this.uiMax;
|
|
3824
|
+
this.updateClasses();
|
|
3825
|
+
});
|
|
3826
|
+
root.querySelector(".teaser-btn").addEventListener("click", () => this.openPanel());
|
|
3827
|
+
root.querySelector(".teaser-x").addEventListener("click", () => this.dismissTeaser());
|
|
3828
|
+
root.querySelector(".jump").addEventListener("click", () => this.scrollToBottom());
|
|
3829
|
+
root.querySelector(".attach").addEventListener("click", () => this.fileEl.click());
|
|
3830
|
+
this.fileEl.addEventListener("change", () => {
|
|
3831
|
+
this.pendingFiles = this.fileEl.files ? Array.from(this.fileEl.files) : [];
|
|
3832
|
+
});
|
|
3833
|
+
root.querySelector(".emoji-btn").addEventListener("click", () => this.toggleEmoji());
|
|
3834
|
+
root.querySelector(".emoji-scrim").addEventListener("click", () => this.closeEmoji());
|
|
3835
|
+
this.emojiSearchEl.addEventListener("input", () => {
|
|
3836
|
+
this.emojiQuery = this.emojiSearchEl.value;
|
|
3837
|
+
this.renderEmoji();
|
|
3838
|
+
});
|
|
3839
|
+
this.bodyEl.addEventListener("scroll", () => this.onScroll());
|
|
3840
|
+
root.querySelector("form.field").addEventListener("submit", (e) => {
|
|
3841
|
+
e.preventDefault();
|
|
3842
|
+
this.doSend();
|
|
3843
|
+
});
|
|
3844
|
+
this.textareaEl.addEventListener("input", () => {
|
|
3845
|
+
this.autoGrow();
|
|
3846
|
+
this.updateClasses();
|
|
3847
|
+
});
|
|
3848
|
+
this.textareaEl.addEventListener("focus", () => {
|
|
3849
|
+
this.focused = true;
|
|
3850
|
+
this.updateClasses();
|
|
3851
|
+
});
|
|
3852
|
+
this.textareaEl.addEventListener("blur", () => {
|
|
3853
|
+
this.focused = false;
|
|
3854
|
+
this.updateClasses();
|
|
3855
|
+
});
|
|
3856
|
+
this.textareaEl.addEventListener("keydown", (e) => {
|
|
3857
|
+
if (e.key === "Enter" && !e.shiftKey && !e.isComposing) {
|
|
3858
|
+
e.preventDefault();
|
|
3859
|
+
this.doSend();
|
|
428
3860
|
}
|
|
429
|
-
|
|
430
|
-
|
|
3861
|
+
if (e.key === "Escape") {
|
|
3862
|
+
if (this.emojiOpen) this.closeEmoji();
|
|
3863
|
+
else this.closePanel();
|
|
3864
|
+
}
|
|
3865
|
+
});
|
|
431
3866
|
}
|
|
432
3867
|
renderError(msg) {
|
|
433
3868
|
if (!this.shadowRoot) this.attachShadow({ mode: "open" });
|
|
434
|
-
|
|
3869
|
+
console.error(msg);
|
|
3870
|
+
this.shadowRoot.innerHTML = `<div style="position:fixed;right:16px;bottom:16px;color:#b91c1c;font:12px system-ui;background:#fef2f2;border:1px solid #fecaca;padding:8px 12px;border-radius:8px">${escapeHtml(msg)}</div>`;
|
|
3871
|
+
}
|
|
3872
|
+
// ── State-class sync ──────────────────────────────────────────────────────────────────────────
|
|
3873
|
+
updateClasses(initialRing = false) {
|
|
3874
|
+
if (!this.oc) return;
|
|
3875
|
+
const c = this.oc.classList;
|
|
3876
|
+
c.toggle("open", this.uiOpen);
|
|
3877
|
+
c.toggle("max", this.uiMax);
|
|
3878
|
+
c.toggle("emoji", this.emojiOpen);
|
|
3879
|
+
c.toggle("teaser", this.teaserActive);
|
|
3880
|
+
c.toggle("away", this.away);
|
|
3881
|
+
c.toggle("focus", this.focused);
|
|
3882
|
+
c.toggle("ready", (this.textareaEl?.value.trim().length ?? 0) > 0);
|
|
3883
|
+
c.toggle("unread", this.unseen > 0);
|
|
3884
|
+
if (initialRing) c.add("ring");
|
|
3885
|
+
const badge = this.oc.querySelector(".badge");
|
|
3886
|
+
if (badge) badge.textContent = this.unseen > 9 ? "9+" : String(this.unseen);
|
|
3887
|
+
const launcher = this.oc.querySelector(".launcher");
|
|
3888
|
+
if (launcher) launcher.setAttribute("aria-label", this.uiOpen ? "Close chat" : "Open chat");
|
|
3889
|
+
}
|
|
3890
|
+
// ── Open / close ───────────────────────────────────────────────────────────────────────────────
|
|
3891
|
+
toggle() {
|
|
3892
|
+
this.uiOpen ? this.closePanel() : this.openPanel();
|
|
3893
|
+
}
|
|
3894
|
+
openPanel() {
|
|
3895
|
+
this.uiOpen = true;
|
|
3896
|
+
this.teaserActive = false;
|
|
3897
|
+
this.unseen = 0;
|
|
3898
|
+
try {
|
|
3899
|
+
sessionStorage.setItem(this.key("open"), "1");
|
|
3900
|
+
} catch {
|
|
3901
|
+
}
|
|
3902
|
+
if (!this.started && this.client) {
|
|
3903
|
+
this.started = true;
|
|
3904
|
+
void this.client.start();
|
|
3905
|
+
}
|
|
3906
|
+
this.updateClasses();
|
|
3907
|
+
this.renderMessages();
|
|
3908
|
+
this.scrollToBottom();
|
|
3909
|
+
if (!this.textareaEl.disabled) setTimeout(() => this.textareaEl.focus(), 60);
|
|
3910
|
+
}
|
|
3911
|
+
closePanel() {
|
|
3912
|
+
this.uiOpen = false;
|
|
3913
|
+
this.uiMax = false;
|
|
3914
|
+
this.emojiOpen = false;
|
|
3915
|
+
try {
|
|
3916
|
+
sessionStorage.setItem(this.key("open"), "0");
|
|
3917
|
+
} catch {
|
|
3918
|
+
}
|
|
3919
|
+
this.updateClasses();
|
|
3920
|
+
}
|
|
3921
|
+
dismissTeaser() {
|
|
3922
|
+
this.teaserActive = false;
|
|
3923
|
+
try {
|
|
3924
|
+
sessionStorage.setItem(this.key("teaser"), "0");
|
|
3925
|
+
} catch {
|
|
3926
|
+
}
|
|
3927
|
+
this.updateClasses();
|
|
3928
|
+
}
|
|
3929
|
+
// ── Client events ─────────────────────────────────────────────────────────────────────────────
|
|
3930
|
+
onClientEvent(e) {
|
|
3931
|
+
if (e.type === "messages") this.messages = e.messages;
|
|
3932
|
+
else if (e.type === "state") {
|
|
3933
|
+
this.state = e.state;
|
|
3934
|
+
if (e.state === "ready" || e.state === "opening") this.lastError = null;
|
|
3935
|
+
} else if (e.type === "agent") {
|
|
3936
|
+
this.agentName = e.agent.name;
|
|
3937
|
+
this.updateHeader();
|
|
3938
|
+
} else if (e.type === "handoff") this.handoffState = e.state;
|
|
3939
|
+
else if (e.type === "agentTyping") this.agentTyping = e.active;
|
|
3940
|
+
else if (e.type === "error") this.lastError = e.error.message;
|
|
3941
|
+
this.updateStatus();
|
|
3942
|
+
this.renderMessages();
|
|
3943
|
+
}
|
|
3944
|
+
updateHeader() {
|
|
3945
|
+
if (this.titleEl) this.titleEl.textContent = this.getAttribute("title") ?? this.agentName ?? "Chat";
|
|
3946
|
+
}
|
|
3947
|
+
updateStatus() {
|
|
3948
|
+
if (!this.textareaEl) return;
|
|
3949
|
+
const disabled = this.state !== "ready";
|
|
3950
|
+
this.textareaEl.disabled = disabled;
|
|
3951
|
+
const handoff = HANDOFF_STATUS[this.handoffState];
|
|
3952
|
+
const text2 = this.state === "opening" ? "Connecting\u2026" : handoff ?? (this.getAttribute("status") ?? DEFAULT_STATUS);
|
|
3953
|
+
if (this.statusEl) this.statusEl.textContent = text2;
|
|
3954
|
+
if (this.state === "error" && this.lastError) {
|
|
3955
|
+
this.errEl.hidden = false;
|
|
3956
|
+
this.errEl.innerHTML = `<span>Couldn't start chat: ${escapeHtml(this.lastError)}</span><button class="retry" type="button">Retry</button>`;
|
|
3957
|
+
this.errEl.querySelector(".retry").addEventListener("click", () => {
|
|
3958
|
+
void this.client?.start();
|
|
3959
|
+
});
|
|
3960
|
+
} else {
|
|
3961
|
+
this.errEl.hidden = true;
|
|
3962
|
+
this.errEl.innerHTML = "";
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3965
|
+
// ── Message list + scroll ─────────────────────────────────────────────────────────────────────
|
|
3966
|
+
renderMessages() {
|
|
3967
|
+
if (!this.bodyEl) return;
|
|
3968
|
+
const body = this.bodyEl;
|
|
3969
|
+
const prevTop = body.scrollTop;
|
|
3970
|
+
const added = this.messages.length - this.renderedCount;
|
|
3971
|
+
const botFinal = this.messages.filter((m2) => m2.role === "assistant" && !m2.streaming).length;
|
|
3972
|
+
const newBotFinal = botFinal > this.renderedBotFinal;
|
|
3973
|
+
const now = Date.now();
|
|
3974
|
+
for (const m2 of this.messages) if (!this.receivedAt.has(m2.id)) this.receivedAt.set(m2.id, now);
|
|
3975
|
+
const lastBot = (() => {
|
|
3976
|
+
for (let i = this.messages.length - 1; i >= 0; i--) if (this.messages[i]?.role === "assistant") return i;
|
|
3977
|
+
return -1;
|
|
3978
|
+
})();
|
|
3979
|
+
let html2 = this.messages.map((m2, i) => this.turnHtml(m2, i === lastBot && !this.agentTyping)).join("");
|
|
3980
|
+
if (this.agentTyping) html2 += '<span class="typing"><span></span><span></span><span></span></span>';
|
|
3981
|
+
const sugg = this.suggestions;
|
|
3982
|
+
if (sugg.length > 0 && !this.agentTyping && this.state === "ready") {
|
|
3983
|
+
html2 += `<span class="chips">${sugg.map((s, i) => `<button type="button" class="chip" data-chip="${i}">${escapeHtml(s)}</button>`).join("")}</span>`;
|
|
3984
|
+
}
|
|
3985
|
+
body.innerHTML = html2;
|
|
3986
|
+
this.hydrateAttachmentImages();
|
|
3987
|
+
this.bindChips();
|
|
3988
|
+
this.renderedCount = this.messages.length;
|
|
3989
|
+
this.renderedBotFinal = botFinal;
|
|
3990
|
+
if (!this.uiOpen) {
|
|
3991
|
+
if (added > 0) this.unseen += added;
|
|
3992
|
+
this.updateClasses();
|
|
3993
|
+
return;
|
|
3994
|
+
}
|
|
3995
|
+
if (newBotFinal && !this.away) this.parkLastQuestion();
|
|
3996
|
+
else if (!this.away) this.scrollToBottom();
|
|
3997
|
+
else {
|
|
3998
|
+
body.scrollTop = prevTop;
|
|
3999
|
+
if (added > 0) this.unseen += added;
|
|
4000
|
+
}
|
|
4001
|
+
this.updateClasses();
|
|
4002
|
+
}
|
|
4003
|
+
// After a reply lands, float the question that prompted it to the top so the answer reads from its
|
|
4004
|
+
// first line rather than its last (the design's behaviour).
|
|
4005
|
+
parkLastQuestion() {
|
|
4006
|
+
const users = this.bodyEl.querySelectorAll(".turn.user");
|
|
4007
|
+
const last = users[users.length - 1];
|
|
4008
|
+
if (!last) {
|
|
4009
|
+
this.scrollToBottom();
|
|
4010
|
+
return;
|
|
4011
|
+
}
|
|
4012
|
+
const top = Math.max(0, Math.min(last.offsetTop - 22, this.bodyEl.scrollHeight - this.bodyEl.clientHeight));
|
|
4013
|
+
this.bodyEl.scrollTo({ top, behavior: "smooth" });
|
|
4014
|
+
}
|
|
4015
|
+
onScroll() {
|
|
4016
|
+
const b2 = this.bodyEl;
|
|
4017
|
+
const away = b2.scrollHeight - b2.scrollTop - b2.clientHeight > AWAY_THRESHOLD;
|
|
4018
|
+
if (away !== this.away) {
|
|
4019
|
+
this.away = away;
|
|
4020
|
+
if (!away) this.unseen = 0;
|
|
4021
|
+
this.updateClasses();
|
|
4022
|
+
}
|
|
4023
|
+
}
|
|
4024
|
+
scrollToBottom() {
|
|
4025
|
+
if (!this.bodyEl) return;
|
|
4026
|
+
this.bodyEl.scrollTop = this.bodyEl.scrollHeight;
|
|
4027
|
+
this.away = false;
|
|
4028
|
+
this.unseen = 0;
|
|
4029
|
+
this.updateClasses();
|
|
4030
|
+
}
|
|
4031
|
+
// ── Composer ──────────────────────────────────────────────────────────────────────────────────
|
|
4032
|
+
autoGrow() {
|
|
4033
|
+
const ta = this.textareaEl;
|
|
4034
|
+
ta.style.height = "auto";
|
|
4035
|
+
ta.style.height = `${Math.min(ta.scrollHeight, 108)}px`;
|
|
4036
|
+
}
|
|
4037
|
+
doSend() {
|
|
4038
|
+
const text2 = this.textareaEl.value;
|
|
4039
|
+
if (!text2.trim()) return;
|
|
4040
|
+
const files = this.pendingFiles;
|
|
4041
|
+
this.pendingFiles = [];
|
|
4042
|
+
this.fileEl.value = "";
|
|
4043
|
+
for (const f2 of files) {
|
|
4044
|
+
if (f2.type.startsWith("image/") && typeof URL.createObjectURL === "function" && !this.imagePreviewCache.has(f2.name)) {
|
|
4045
|
+
this.imagePreviewCache.set(f2.name, URL.createObjectURL(f2));
|
|
4046
|
+
}
|
|
4047
|
+
}
|
|
4048
|
+
this.away = false;
|
|
4049
|
+
this.emojiOpen = false;
|
|
4050
|
+
void this.client?.sendMessage(text2, files.length > 0 ? files : void 0);
|
|
4051
|
+
this.textareaEl.value = "";
|
|
4052
|
+
this.textareaEl.style.height = "auto";
|
|
4053
|
+
this.updateClasses();
|
|
4054
|
+
}
|
|
4055
|
+
sendChip(text2) {
|
|
4056
|
+
this.away = false;
|
|
4057
|
+
this.emojiOpen = false;
|
|
4058
|
+
void this.client?.sendMessage(text2);
|
|
4059
|
+
this.updateClasses();
|
|
4060
|
+
}
|
|
4061
|
+
bindChips() {
|
|
4062
|
+
const sugg = this.suggestions;
|
|
4063
|
+
this.bodyEl.querySelectorAll(".chip[data-chip]").forEach((btn) => {
|
|
4064
|
+
const i = Number(btn.getAttribute("data-chip"));
|
|
4065
|
+
const text2 = sugg[i];
|
|
4066
|
+
if (text2) btn.addEventListener("click", () => this.sendChip(text2));
|
|
4067
|
+
});
|
|
4068
|
+
}
|
|
4069
|
+
// ── Emoji ─────────────────────────────────────────────────────────────────────────────────────
|
|
4070
|
+
toggleEmoji() {
|
|
4071
|
+
this.emojiOpen = !this.emojiOpen;
|
|
4072
|
+
this.emojiQuery = "";
|
|
4073
|
+
this.emojiSearchEl.value = "";
|
|
4074
|
+
this.renderEmoji();
|
|
4075
|
+
this.updateClasses();
|
|
4076
|
+
if (this.emojiOpen) setTimeout(() => this.emojiSearchEl.focus(), 60);
|
|
4077
|
+
}
|
|
4078
|
+
closeEmoji() {
|
|
4079
|
+
this.emojiOpen = false;
|
|
4080
|
+
this.emojiQuery = "";
|
|
4081
|
+
this.updateClasses();
|
|
4082
|
+
}
|
|
4083
|
+
renderEmoji() {
|
|
4084
|
+
const groups = emojiGroups(this.emojiQuery);
|
|
4085
|
+
let html2 = groups.map((g) => `
|
|
4086
|
+
<div class="emoji-grp"><span class="emoji-grp-name">${escapeHtml(g.name)}</span>
|
|
4087
|
+
<div class="emoji-grid">${g.items.map((e) => `<button type="button" title="${this.escapeAttr(e.name)}" aria-label="${this.escapeAttr(e.name)}" data-ch="${this.escapeAttr(e.ch)}">${e.ch}</button>`).join("")}</div>
|
|
4088
|
+
</div>`).join("");
|
|
4089
|
+
if (groups.length === 0) html2 = '<span class="emoji-empty" style="display:flex"><span class="h">No emoji match that</span><span class="s">Try a shorter word, like smile or call.</span></span>';
|
|
4090
|
+
this.emojiListEl.innerHTML = html2;
|
|
4091
|
+
this.emojiListEl.querySelectorAll("button[data-ch]").forEach((btn) => {
|
|
4092
|
+
btn.addEventListener("click", () => {
|
|
4093
|
+
this.textareaEl.value += btn.getAttribute("data-ch") ?? "";
|
|
4094
|
+
this.emojiOpen = false;
|
|
4095
|
+
this.autoGrow();
|
|
4096
|
+
this.updateClasses();
|
|
4097
|
+
this.textareaEl.focus();
|
|
4098
|
+
});
|
|
4099
|
+
});
|
|
4100
|
+
}
|
|
4101
|
+
// ── Bubble rendering ──────────────────────────────────────────────────────────────────────────
|
|
4102
|
+
turnHtml(m2, isLastBot) {
|
|
4103
|
+
const role = m2.role === "user" ? "user" : m2.role === "human" ? "human" : "bot";
|
|
4104
|
+
const atts = (m2.attachments ?? []).map((a) => this.renderAttachment(a)).join("");
|
|
4105
|
+
let content;
|
|
4106
|
+
if (m2.role === "assistant") {
|
|
4107
|
+
let rendered = m2.streaming ? void 0 : this.mdCache.get(m2.id);
|
|
4108
|
+
if (rendered === void 0) {
|
|
4109
|
+
rendered = renderMarkdown(m2.text || "");
|
|
4110
|
+
if (!m2.streaming) this.mdCache.set(m2.id, rendered);
|
|
4111
|
+
}
|
|
4112
|
+
content = `<span class="b">${atts}<span class="md">${rendered}</span></span>`;
|
|
4113
|
+
} else {
|
|
4114
|
+
const label = m2.role === "human" ? '<div class="human-label">Support</div>' : "";
|
|
4115
|
+
content = `<span class="b">${label}${atts}${escapeHtml(m2.text)}</span>`;
|
|
4116
|
+
}
|
|
4117
|
+
const src = m2.sources && m2.sources.length > 0 ? `<span class="src">${ICON.book}<span class="t">${escapeHtml("From " + (m2.sources[0]?.title ?? ""))}</span></span>` : "";
|
|
4118
|
+
const byline = role === "bot" && isLastBot ? `<span class="byline">${escapeHtml((this.agentName ?? "OyeHello") + " \xB7 AI agent \xB7 " + this.relTime(m2.id))}</span>` : "";
|
|
4119
|
+
return `<span class="turn ${role}">${content}${src}${byline}</span>`;
|
|
4120
|
+
}
|
|
4121
|
+
relTime(id) {
|
|
4122
|
+
const t = this.receivedAt.get(id);
|
|
4123
|
+
if (!t) return "just now";
|
|
4124
|
+
const mins = Math.floor((Date.now() - t) / 6e4);
|
|
4125
|
+
return mins <= 0 ? "just now" : `${mins} min ago`;
|
|
435
4126
|
}
|
|
436
4127
|
renderAttachment(a) {
|
|
437
4128
|
if (a.contentType.startsWith("image/")) {
|
|
438
4129
|
const cached = (a.name ? this.imagePreviewCache.get(a.name) : void 0) ?? this.resolvedUrlCache.get(a.storageRef);
|
|
439
4130
|
const srcAttr = cached ? ` src="${cached}"` : "";
|
|
440
|
-
return `<img class="att-thumb" data-oc-ref="${
|
|
4131
|
+
return `<img class="att-thumb" data-oc-ref="${this.escapeAttr(a.storageRef)}"${srcAttr} alt="${this.escapeAttr(a.name ?? "image")}"/>`;
|
|
441
4132
|
}
|
|
442
4133
|
return `<div class="att-chip">\u{1F4CE} ${escapeHtml(a.name ?? a.contentType)}</div>`;
|
|
443
4134
|
}
|
|
444
|
-
renderSource(s) {
|
|
445
|
-
return `<div class="src-chip" title="${escapeHtml(s.snippet)}">${escapeHtml(s.title)}</div>`;
|
|
446
|
-
}
|
|
447
|
-
// After render() attaches the markup, resolve a read-back URL (via the client) for every image
|
|
448
|
-
// placeholder that has no src yet - a local blob or a previously-resolved URL already set one, so
|
|
449
|
-
// those are left untouched (no redundant network call).
|
|
450
4135
|
hydrateAttachmentImages() {
|
|
451
4136
|
if (!this.client) return;
|
|
452
|
-
|
|
453
|
-
imgs.forEach((img) => {
|
|
4137
|
+
this.shadowRoot.querySelectorAll("img.att-thumb[data-oc-ref]").forEach((img) => {
|
|
454
4138
|
if (img.hasAttribute("src")) return;
|
|
455
4139
|
const ref = img.getAttribute("data-oc-ref");
|
|
456
4140
|
if (!ref) return;
|
|
@@ -461,82 +4145,8 @@ var OyehelloChat = (function (exports) {
|
|
|
461
4145
|
});
|
|
462
4146
|
});
|
|
463
4147
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
const bubbles = this.messages.map((m) => {
|
|
467
|
-
const atts = (m.attachments ?? []).map((a) => this.renderAttachment(a)).join("");
|
|
468
|
-
const label = m.role === "human" ? '<div class="human-label">Support</div>' : "";
|
|
469
|
-
const bubble = `<div class="b ${m.role}">${label}${atts}${m.text ? escapeHtml(m.text) : ""}${m.streaming ? "\u2026" : ""}</div>`;
|
|
470
|
-
const sources = m.sources && m.sources.length > 0 ? `<div class="src-row">${m.sources.map((s) => this.renderSource(s)).join("")}</div>` : "";
|
|
471
|
-
return bubble + sources;
|
|
472
|
-
}).join("");
|
|
473
|
-
const statusText = HANDOFF_STATUS_TEXT[this.handoffState];
|
|
474
|
-
const status = statusText ? `<div class="status">${escapeHtml(statusText)}</div>` : "";
|
|
475
|
-
const errBanner = this.state === "error" && this.lastError ? `<div class="err">Couldn't start chat: ${escapeHtml(this.lastError)}</div>` : "";
|
|
476
|
-
const showTyping = this.agentTyping && (this.handoffState === "human" || this.handoffState === "awaiting_human");
|
|
477
|
-
const typingIndicator = showTyping ? `<div class="b assistant typing">${escapeHtml(AGENT_TYPING_TEXT)}</div>` : "";
|
|
478
|
-
const disabled = this.state !== "ready" ? "disabled" : "";
|
|
479
|
-
const prevInput = this.shadowRoot.querySelector('input[aria-label="message"]');
|
|
480
|
-
const prevValue = prevInput?.value ?? "";
|
|
481
|
-
const prevSelectionStart = prevInput?.selectionStart ?? null;
|
|
482
|
-
const prevSelectionEnd = prevInput?.selectionEnd ?? null;
|
|
483
|
-
const hadFocus = !!prevInput && this.shadowRoot.activeElement === prevInput;
|
|
484
|
-
this.shadowRoot.innerHTML = `
|
|
485
|
-
<style>
|
|
486
|
-
:host{display:block;height:100%;min-height:320px;font-family:system-ui,sans-serif;--oc-accent:#2563eb}
|
|
487
|
-
.wrap{display:flex;flex-direction:column;height:100%;border:1px solid #e5e7eb;border-radius:12px;overflow:hidden}
|
|
488
|
-
.hd{padding:10px 14px;border-bottom:1px solid #e5e7eb;font-weight:600}
|
|
489
|
-
.body{flex:1;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:8px}
|
|
490
|
-
.b{max-width:80%;padding:8px 12px;border-radius:12px;white-space:pre-wrap;word-break:break-word}
|
|
491
|
-
.b.user{align-self:flex-end;background:var(--oc-accent);color:#fff}
|
|
492
|
-
.b.assistant{align-self:flex-start;background:#f3f4f6;color:#111}
|
|
493
|
-
.b.human{align-self:flex-start;background:#dbeafe;color:#111}
|
|
494
|
-
.b.typing{font-style:italic;color:#6b7280;opacity:.85}
|
|
495
|
-
.human-label{font-size:11px;font-weight:600;opacity:.7;margin-bottom:2px}
|
|
496
|
-
.status{padding:6px 14px;font-size:12px;color:#6b7280;background:#f9fafb;border-bottom:1px solid #e5e7eb}
|
|
497
|
-
.err{padding:8px 14px;font-size:12px;color:#b91c1c;background:#fef2f2;border-bottom:1px solid #fecaca}
|
|
498
|
-
.att-thumb{display:block;max-width:160px;max-height:160px;border-radius:8px;margin-bottom:6px}
|
|
499
|
-
.att-chip{display:inline-block;font-size:12px;background:rgba(0,0,0,.08);border-radius:6px;padding:2px 8px;margin:0 0 6px}
|
|
500
|
-
.b.user .att-chip{background:rgba(255,255,255,.25)}
|
|
501
|
-
.src-row{align-self:flex-start;display:flex;flex-wrap:wrap;gap:6px;max-width:80%}
|
|
502
|
-
.src-chip{display:inline-block;font-size:11px;background:rgba(0,0,0,.06);color:#374151;border-radius:6px;padding:2px 8px;cursor:default}
|
|
503
|
-
form{display:flex;gap:8px;padding:10px;border-top:1px solid #e5e7eb;align-items:center}
|
|
504
|
-
input[aria-label="message"]{flex:1;padding:8px 10px;border-radius:8px;border:1px solid #d1d5db;font:inherit}
|
|
505
|
-
input[type="file"]{max-width:120px;font-size:12px}
|
|
506
|
-
button{padding:8px 14px;border-radius:8px;border:none;background:var(--oc-accent);color:#fff;font-weight:600;cursor:pointer}
|
|
507
|
-
button:disabled,input:disabled{opacity:.6;cursor:not-allowed}
|
|
508
|
-
</style>
|
|
509
|
-
<div class="wrap">
|
|
510
|
-
<div class="hd">${escapeHtml(title)}</div>
|
|
511
|
-
${status}${errBanner}
|
|
512
|
-
<div class="body">${bubbles}${typingIndicator}</div>
|
|
513
|
-
<form>
|
|
514
|
-
<input aria-label="message" placeholder="Type a message\u2026" ${disabled}/>
|
|
515
|
-
<input type="file" accept="${ATTACHMENT_ACCEPT}" multiple ${disabled}/>
|
|
516
|
-
<button type="submit" ${disabled}>Send</button>
|
|
517
|
-
</form>
|
|
518
|
-
</div>`;
|
|
519
|
-
const form = this.shadowRoot.querySelector("form");
|
|
520
|
-
const input = this.shadowRoot.querySelector('input[aria-label="message"]');
|
|
521
|
-
const fileInput = this.shadowRoot.querySelector('input[type="file"]');
|
|
522
|
-
fileInput.addEventListener("change", () => {
|
|
523
|
-
this.pendingFiles = fileInput.files ? Array.from(fileInput.files) : [];
|
|
524
|
-
});
|
|
525
|
-
form.addEventListener("submit", (e) => {
|
|
526
|
-
e.preventDefault();
|
|
527
|
-
const files = this.pendingFiles;
|
|
528
|
-
this.pendingFiles = [];
|
|
529
|
-
this.send(input.value, files);
|
|
530
|
-
input.value = "";
|
|
531
|
-
});
|
|
532
|
-
if (prevValue) {
|
|
533
|
-
input.value = prevValue;
|
|
534
|
-
if (prevSelectionStart !== null && prevSelectionEnd !== null) input.setSelectionRange(prevSelectionStart, prevSelectionEnd);
|
|
535
|
-
}
|
|
536
|
-
if (hadFocus) input.focus();
|
|
537
|
-
const body = this.shadowRoot.querySelector(".body");
|
|
538
|
-
body.scrollTop = body.scrollHeight;
|
|
539
|
-
this.hydrateAttachmentImages();
|
|
4148
|
+
escapeAttr(s) {
|
|
4149
|
+
return s.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]);
|
|
540
4150
|
}
|
|
541
4151
|
};
|
|
542
4152
|
function escapeHtml(s) {
|
|
@@ -547,6 +4157,11 @@ var OyehelloChat = (function (exports) {
|
|
|
547
4157
|
if (typeof customElements !== "undefined" && !customElements.get("oyehello-chat")) {
|
|
548
4158
|
customElements.define("oyehello-chat", OyehelloChatElement);
|
|
549
4159
|
}
|
|
4160
|
+
/*! Bundled license information:
|
|
4161
|
+
|
|
4162
|
+
dompurify/dist/purify.es.mjs:
|
|
4163
|
+
(*! @license DOMPurify 3.4.15 | (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.15/LICENSE *)
|
|
4164
|
+
*/
|
|
550
4165
|
|
|
551
4166
|
exports.ChatApiError = ChatApiError;
|
|
552
4167
|
exports.OyehelloChatElement = OyehelloChatElement;
|