ibc-ai-web-sdk 2.0.5 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -6,7 +6,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
6
6
  * 错误码常量
7
7
  * 统一定义所有错误码,方便维护
8
8
  */
9
-
10
9
  const ERROR_CODES = {
11
10
  // 客户端错误 (40000-49999)
12
11
  AGENT_NOT_FOUND: 40001,
@@ -15,7 +14,6 @@ const ERROR_CODES = {
15
14
  // 提示词不能为空
16
15
  AUTH_FAILED: 40301,
17
16
  // 鉴权失败
18
-
19
17
  // 服务器错误 (50000-59999)
20
18
  NETWORK_ERROR: 500,
21
19
  // 网络请求失败
@@ -23,7 +21,6 @@ const ERROR_CODES = {
23
21
  // 服务器内部错误
24
22
  TIMEOUT_ERROR: 50002,
25
23
  // 请求超时
26
-
27
24
  // 取消
28
25
  REQUEST_CANCELLED: 0 // 请求已取消
29
26
  };
@@ -624,14 +621,14 @@ class AIChatClient {
624
621
  const message = parsed && (parsed.message || parsed.errorMessage) || data || '流式请求失败';
625
622
  const code = parsed && (parsed.code || parsed.errCode || parsed.status);
626
623
  if (code && this.isAuthErrorCode(code)) {
627
- const error = new Error(message);
628
- error.authError = true;
629
- error.code = code;
630
- throw error;
624
+ const authErr = new Error(message);
625
+ authErr.authError = true;
626
+ authErr.code = code;
627
+ throw authErr;
631
628
  }
632
- const error = new Error(message);
633
- error.sseData = parsed || data;
634
- throw error;
629
+ const sseErr = new Error(message);
630
+ sseErr.sseData = parsed || data;
631
+ throw sseErr;
635
632
  }
636
633
  if ((META_EVENTS.has(event) || MESSAGE_EVENTS.has(event)) && data.startsWith('[META]')) {
637
634
  const meta = tryParseJson(data.slice('[META]'.length));
@@ -876,7 +873,7 @@ class AIChatClient {
876
873
  }
877
874
 
878
875
  /**
879
- * marked v18.0.5 - a markdown parser
876
+ * marked v18.0.2 - a markdown parser
880
877
  * Copyright (c) 2018-2026, MarkedJS. (MIT License)
881
878
  * Copyright (c) 2011-2018, Christopher Jeffrey. (MIT License)
882
879
  * https://github.com/markedjs/marked
@@ -887,12 +884,12 @@ class AIChatClient {
887
884
  * The code in this file is generated from files in ./src/
888
885
  */
889
886
 
890
- function M(){return {async:false,breaks:false,extensions:null,gfm:true,hooks:null,pedantic:false,renderer:null,silent:false,tokenizer:null,walkTokens:null}}var T=M();function N(l){T=l;}var _={exec:()=>null};function E(l){let e=[];return t=>{let n=Math.max(0,Math.min(3,t-1)),s=e[n];return s||(s=l(n),e[n]=s),s}}function d(l,e=""){let t=typeof l=="string"?l:l.source,n={replace:(s,r)=>{let i=typeof r=="string"?r:r.source;return i=i.replace(m.caret,"$1"),t=t.replace(s,i),n},getRegex:()=>new RegExp(t,e)};return n}var Te=((l="")=>{try{return !!new RegExp("(?<=1)(?<!1)"+l)}catch{return false}})(),m={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:l=>new RegExp(`^( {0,3}${l})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:E(l=>new RegExp(`^ {0,${l}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`)),hrRegex:E(l=>new RegExp(`^ {0,${l}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`)),fencesBeginRegex:E(l=>new RegExp(`^ {0,${l}}(?:\`\`\`|~~~)`)),headingBeginRegex:E(l=>new RegExp(`^ {0,${l}}#`)),htmlBeginRegex:E(l=>new RegExp(`^ {0,${l}}<(?:[a-z].*>|!--)`,"i")),blockquoteBeginRegex:E(l=>new RegExp(`^ {0,${l}}>`))},Oe=/^(?:[ \t]*(?:\n|$))+/,we=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,ye=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,B=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,Pe=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,j=/ {0,3}(?:[*+-]|\d{1,9}[.)])/,oe=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,ae=d(oe).replace(/bull/g,j).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),Se=d(oe).replace(/bull/g,j).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),F=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,$e=/^[^\n]+/,U=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,Le=d(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",U).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),_e=d(/^(bull)([ \t][^\n]*?)?(?:\n|$)/).replace(/bull/g,j).getRegex(),H="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",K=/<!--(?:-?>|[\s\S]*?(?:-->|$))/,ze=d("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))","i").replace("comment",K).replace("tag",H).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),le=d(F).replace("hr",B).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",H).getRegex(),Me=d(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",le).getRegex(),W={blockquote:Me,code:we,def:Le,fences:ye,heading:Pe,hr:B,html:ze,lheading:ae,list:_e,newline:Oe,paragraph:le,table:_,text:$e},se=d("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",B).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",H).getRegex(),Ee={...W,lheading:Se,table:se,paragraph:d(F).replace("hr",B).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",se).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",H).getRegex()},Ie={...W,html:d(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",K).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:_,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:d(F).replace("hr",B).replace("heading",` *#{1,6} *[^
891
- ]`).replace("lheading",ae).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Ae=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,Ce=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,ue=/^( {2,}|\\)\n(?!\s*$)/,Be=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,I=/[\p{P}\p{S}]/u,Z=/[\s\p{P}\p{S}]/u,X=/[^\s\p{P}\p{S}]/u,De=d(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,Z).getRegex(),pe=/(?!~)[\p{P}\p{S}]/u,qe=/(?!~)[\s\p{P}\p{S}]/u,ve=/(?:[^\s\p{P}\p{S}]|~)/u,He=d(/link|precode-code|html/,"g").replace("link",/\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-",Te?"(?<!`)()":"(^^|[^`])").replace("code",/(?<b>`+)[^`]+\k<b>(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),ce=/^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/,Ze=d(ce,"u").replace(/punct/g,I).getRegex(),Ge=d(ce,"u").replace(/punct/g,pe).getRegex(),he="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",Ne=d(he,"gu").replace(/notPunctSpace/g,X).replace(/punctSpace/g,Z).replace(/punct/g,I).getRegex(),Qe=d(he,"gu").replace(/notPunctSpace/g,ve).replace(/punctSpace/g,qe).replace(/punct/g,pe).getRegex(),je=d("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,X).replace(/punctSpace/g,Z).replace(/punct/g,I).getRegex(),Fe=d(/^~~?(?:((?!~)punct)|[^\s~])/,"u").replace(/punct/g,I).getRegex(),Ue="^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)",Ke=d(Ue,"gu").replace(/notPunctSpace/g,X).replace(/punctSpace/g,Z).replace(/punct/g,I).getRegex(),We=d(/\\(punct)/,"gu").replace(/punct/g,I).getRegex(),Xe=d(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),Je=d(K).replace("(?:-->|$)","-->").getRegex(),Ve=d("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment",Je).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),v=/(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/,Ye=d(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label",v).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),ke=d(/^!?\[(label)\]\[(ref)\]/).replace("label",v).replace("ref",U).getRegex(),de=d(/^!?\[(ref)\](?:\[\])?/).replace("ref",U).getRegex(),et=d("reflink|nolink(?!\\()","g").replace("reflink",ke).replace("nolink",de).getRegex(),ie=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,J={_backpedal:_,anyPunctuation:We,autolink:Xe,blockSkip:He,br:ue,code:Ce,del:_,delLDelim:_,delRDelim:_,emStrongLDelim:Ze,emStrongRDelimAst:Ne,emStrongRDelimUnd:je,escape:Ae,link:Ye,nolink:de,punctuation:De,reflink:ke,reflinkSearch:et,tag:Ve,text:Be,url:_},tt={...J,link:d(/^!?\[(label)\]\((.*?)\)/).replace("label",v).getRegex(),reflink:d(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",v).getRegex()},Q={...J,emStrongRDelimAst:Qe,emStrongLDelim:Ge,delLDelim:Fe,delRDelim:Ke,url:d(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol",ie).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/,text:d(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol",ie).getRegex()},nt={...Q,br:d(ue).replace("{2,}","*").getRegex(),text:d(Q.text).replace("\\b_","\\b_| {2,}\\n").replace(/\{2,\}/g,"*").getRegex()},D={normal:W,gfm:Ee,pedantic:Ie},A={normal:J,gfm:Q,breaks:nt,pedantic:tt};var rt={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},ge=l=>rt[l];function O(l,e){if(e){if(m.escapeTest.test(l))return l.replace(m.escapeReplace,ge)}else if(m.escapeTestNoEncode.test(l))return l.replace(m.escapeReplaceNoEncode,ge);return l}function V(l){try{l=encodeURI(l).replace(m.percentDecode,"%");}catch{return null}return l}function Y(l,e){let t=l.replace(m.findPipe,(r,i,o)=>{let u=false,a=i;for(;--a>=0&&o[a]==="\\";)u=!u;return u?"|":" |"}),n=t.split(m.splitPipe),s=0;if(n[0].trim()||n.shift(),n.length>0&&!n.at(-1)?.trim()&&n.pop(),e)if(n.length>e)n.splice(e);else for(;n.length<e;)n.push("");for(;s<n.length;s++)n[s]=n[s].trim().replace(m.slashPipe,"|");return n}function $(l,e,t){let n=l.length;if(n===0)return "";let s=0;for(;s<n;){let r=l.charAt(n-s-1);if(r===e&&true)s++;else break}return l.slice(0,n-s)}function ee(l){let e=l.split(`
887
+ function z(){return {async:false,breaks:false,extensions:null,gfm:true,hooks:null,pedantic:false,renderer:null,silent:false,tokenizer:null,walkTokens:null}}var T=z();function G(l){T=l;}var _={exec:()=>null};function k(l,e=""){let t=typeof l=="string"?l:l.source,n={replace:(s,r)=>{let i=typeof r=="string"?r:r.source;return i=i.replace(m.caret,"$1"),t=t.replace(s,i),n},getRegex:()=>new RegExp(t,e)};return n}var Re=((l="")=>{try{return !!new RegExp("(?<=1)(?<!1)"+l)}catch{return false}})(),m={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:l=>new RegExp(`^( {0,3}${l})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:l=>new RegExp(`^ {0,${Math.min(3,l-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),hrRegex:l=>new RegExp(`^ {0,${Math.min(3,l-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:l=>new RegExp(`^ {0,${Math.min(3,l-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:l=>new RegExp(`^ {0,${Math.min(3,l-1)}}#`),htmlBeginRegex:l=>new RegExp(`^ {0,${Math.min(3,l-1)}}<(?:[a-z].*>|!--)`,"i"),blockquoteBeginRegex:l=>new RegExp(`^ {0,${Math.min(3,l-1)}}>`)},Te=/^(?:[ \t]*(?:\n|$))+/,Oe=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,we=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,I=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,ye=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,Q=/ {0,3}(?:[*+-]|\d{1,9}[.)])/,ie=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,oe=k(ie).replace(/bull/g,Q).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),Pe=k(ie).replace(/bull/g,Q).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),j=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,Se=/^[^\n]+/,F=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,$e=k(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",F).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),Le=k(/^(bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,Q).getRegex(),v="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",U=/<!--(?:-?>|[\s\S]*?(?:-->|$))/,_e=k("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))","i").replace("comment",U).replace("tag",v).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),ae=k(j).replace("hr",I).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",v).getRegex(),Me=k(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",ae).getRegex(),K={blockquote:Me,code:Oe,def:$e,fences:we,heading:ye,hr:I,html:_e,lheading:oe,list:Le,newline:Te,paragraph:ae,table:_,text:Se},re=k("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",I).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",v).getRegex(),ze={...K,lheading:Pe,table:re,paragraph:k(j).replace("hr",I).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",re).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",v).getRegex()},Ee={...K,html:k(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",U).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:_,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:k(j).replace("hr",I).replace("heading",` *#{1,6} *[^
888
+ ]`).replace("lheading",oe).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Ae=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,Ce=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,le=/^( {2,}|\\)\n(?!\s*$)/,Ie=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,E=/[\p{P}\p{S}]/u,H=/[\s\p{P}\p{S}]/u,W=/[^\s\p{P}\p{S}]/u,Be=k(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,H).getRegex(),ue=/(?!~)[\p{P}\p{S}]/u,De=/(?!~)[\s\p{P}\p{S}]/u,qe=/(?:[^\s\p{P}\p{S}]|~)/u,ve=k(/link|precode-code|html/,"g").replace("link",/\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-",Re?"(?<!`)()":"(^^|[^`])").replace("code",/(?<b>`+)[^`]+\k<b>(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),pe=/^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/,He=k(pe,"u").replace(/punct/g,E).getRegex(),Ze=k(pe,"u").replace(/punct/g,ue).getRegex(),ce="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",Ge=k(ce,"gu").replace(/notPunctSpace/g,W).replace(/punctSpace/g,H).replace(/punct/g,E).getRegex(),Ne=k(ce,"gu").replace(/notPunctSpace/g,qe).replace(/punctSpace/g,De).replace(/punct/g,ue).getRegex(),Qe=k("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,W).replace(/punctSpace/g,H).replace(/punct/g,E).getRegex(),je=k(/^~~?(?:((?!~)punct)|[^\s~])/,"u").replace(/punct/g,E).getRegex(),Fe="^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)",Ue=k(Fe,"gu").replace(/notPunctSpace/g,W).replace(/punctSpace/g,H).replace(/punct/g,E).getRegex(),Ke=k(/\\(punct)/,"gu").replace(/punct/g,E).getRegex(),We=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(),Xe=k(U).replace("(?:-->|$)","-->").getRegex(),Je=k("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment",Xe).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),q=/(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/,Ve=k(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label",q).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),he=k(/^!?\[(label)\]\[(ref)\]/).replace("label",q).replace("ref",F).getRegex(),ke=k(/^!?\[(ref)\](?:\[\])?/).replace("ref",F).getRegex(),Ye=k("reflink|nolink(?!\\()","g").replace("reflink",he).replace("nolink",ke).getRegex(),se=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,X={_backpedal:_,anyPunctuation:Ke,autolink:We,blockSkip:ve,br:le,code:Ce,del:_,delLDelim:_,delRDelim:_,emStrongLDelim:He,emStrongRDelimAst:Ge,emStrongRDelimUnd:Qe,escape:Ae,link:Ve,nolink:ke,punctuation:Be,reflink:he,reflinkSearch:Ye,tag:Je,text:Ie,url:_},et={...X,link:k(/^!?\[(label)\]\((.*?)\)/).replace("label",q).getRegex(),reflink:k(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",q).getRegex()},N={...X,emStrongRDelimAst:Ne,emStrongLDelim:Ze,delLDelim:je,delRDelim:Ue,url:k(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol",se).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/,text:k(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol",se).getRegex()},tt={...N,br:k(le).replace("{2,}","*").getRegex(),text:k(N.text).replace("\\b_","\\b_| {2,}\\n").replace(/\{2,\}/g,"*").getRegex()},B={normal:K,gfm:ze,pedantic:Ee},A={normal:X,gfm:N,breaks:tt,pedantic:et};var nt={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},de=l=>nt[l];function O(l,e){if(e){if(m.escapeTest.test(l))return l.replace(m.escapeReplace,de)}else if(m.escapeTestNoEncode.test(l))return l.replace(m.escapeReplaceNoEncode,de);return l}function J(l){try{l=encodeURI(l).replace(m.percentDecode,"%");}catch{return null}return l}function V(l,e){let t=l.replace(m.findPipe,(r,i,o)=>{let u=false,a=i;for(;--a>=0&&o[a]==="\\";)u=!u;return u?"|":" |"}),n=t.split(m.splitPipe),s=0;if(n[0].trim()||n.shift(),n.length>0&&!n.at(-1)?.trim()&&n.pop(),e)if(n.length>e)n.splice(e);else for(;n.length<e;)n.push("");for(;s<n.length;s++)n[s]=n[s].trim().replace(m.slashPipe,"|");return n}function $(l,e,t){let n=l.length;if(n===0)return "";let s=0;for(;s<n;){let r=l.charAt(n-s-1);if(r===e&&true)s++;else break}return l.slice(0,n-s)}function Y(l){let e=l.split(`
892
889
  `),t=e.length-1;for(;t>=0&&m.blankLine.test(e[t]);)t--;return e.length-t<=2?l:e.slice(0,t+1).join(`
893
- `)}function fe(l,e){if(l.indexOf(e[1])===-1)return -1;let t=0;for(let n=0;n<l.length;n++)if(l[n]==="\\")n++;else if(l[n]===e[0])t++;else if(l[n]===e[1]&&(t--,t<0))return n;return t>0?-2:-1}function me(l,e=0){let t=e,n="";for(let s of l)if(s===" "){let r=4-t%4;n+=" ".repeat(r),t+=r;}else n+=s,t++;return n}function xe(l,e,t,n,s){let r=e.href,i=e.title||null,o=l[1].replace(s.other.outputLinkReplace,"$1");n.state.inLink=true;let u={type:l[0].charAt(0)==="!"?"image":"link",raw:t,href:r,title:i,text:o,tokens:n.inlineTokens(o)};return n.state.inLink=false,u}function st(l,e,t){let n=l.match(t.other.indentCodeCompensation);if(n===null)return e;let s=n[1];return e.split(`
890
+ `)}function ge(l,e){if(l.indexOf(e[1])===-1)return -1;let t=0;for(let n=0;n<l.length;n++)if(l[n]==="\\")n++;else if(l[n]===e[0])t++;else if(l[n]===e[1]&&(t--,t<0))return n;return t>0?-2:-1}function fe(l,e=0){let t=e,n="";for(let s of l)if(s===" "){let r=4-t%4;n+=" ".repeat(r),t+=r;}else n+=s,t++;return n}function me(l,e,t,n,s){let r=e.href,i=e.title||null,o=l[1].replace(s.other.outputLinkReplace,"$1");n.state.inLink=true;let u={type:l[0].charAt(0)==="!"?"image":"link",raw:t,href:r,title:i,text:o,tokens:n.inlineTokens(o)};return n.state.inLink=false,u}function rt(l,e,t){let n=l.match(t.other.indentCodeCompensation);if(n===null)return e;let s=n[1];return e.split(`
894
891
  `).map(r=>{let i=r.match(t.other.beginningSpace);if(i===null)return r;let[o]=i;return o.length>=s.length?r.slice(s.length):r}).join(`
895
- `)}var w=class{options;rules;lexer;constructor(e){this.options=e||T;}space(e){let t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)return {type:"space",raw:t[0]}}code(e){let t=this.rules.block.code.exec(e);if(t){let n=this.options.pedantic?t[0]:ee(t[0]),s=n.replace(this.rules.other.codeRemoveIndent,"");return {type:"code",raw:n,codeBlockStyle:"indented",text:s}}}fences(e){let t=this.rules.block.fences.exec(e);if(t){let n=t[0],s=st(n,t[3]||"",this.rules);return {type:"code",raw:n,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:s}}}heading(e){let t=this.rules.block.heading.exec(e);if(t){let n=t[2].trim();if(this.rules.other.endingHash.test(n)){let s=$(n,"#");(this.options.pedantic||!s||this.rules.other.endingSpaceChar.test(s))&&(n=s.trim());}return {type:"heading",raw:$(t[0],`
892
+ `)}var w=class{options;rules;lexer;constructor(e){this.options=e||T;}space(e){let t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)return {type:"space",raw:t[0]}}code(e){let t=this.rules.block.code.exec(e);if(t){let n=this.options.pedantic?t[0]:Y(t[0]),s=n.replace(this.rules.other.codeRemoveIndent,"");return {type:"code",raw:n,codeBlockStyle:"indented",text:s}}}fences(e){let t=this.rules.block.fences.exec(e);if(t){let n=t[0],s=rt(n,t[3]||"",this.rules);return {type:"code",raw:n,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:s}}}heading(e){let t=this.rules.block.heading.exec(e);if(t){let n=t[2].trim();if(this.rules.other.endingHash.test(n)){let s=$(n,"#");(this.options.pedantic||!s||this.rules.other.endingSpaceChar.test(s))&&(n=s.trim());}return {type:"heading",raw:$(t[0],`
896
893
  `),depth:t[1].length,text:n,tokens:this.lexer.inline(n)}}}hr(e){let t=this.rules.block.hr.exec(e);if(t)return {type:"hr",raw:$(t[0],`
897
894
  `)}}blockquote(e){let t=this.rules.block.blockquote.exec(e);if(t){let n=$(t[0],`
898
895
  `).split(`
@@ -900,24 +897,24 @@ function M(){return {async:false,breaks:false,extensions:null,gfm:true,hooks:nul
900
897
  `),p=c.replace(this.rules.other.blockquoteSetextReplace,`
901
898
  $1`).replace(this.rules.other.blockquoteSetextReplace2,"");s=s?`${s}
902
899
  ${c}`:c,r=r?`${r}
903
- ${p}`:p;let k=this.lexer.state.top;if(this.lexer.state.top=true,this.lexer.blockTokens(p,i,true),this.lexer.state.top=k,n.length===0)break;let h=i.at(-1);if(h?.type==="code")break;if(h?.type==="blockquote"){let R=h,f=R.raw+`
900
+ ${p}`:p;let d=this.lexer.state.top;if(this.lexer.state.top=true,this.lexer.blockTokens(p,i,true),this.lexer.state.top=d,n.length===0)break;let h=i.at(-1);if(h?.type==="code")break;if(h?.type==="blockquote"){let R=h,f=R.raw+`
904
901
  `+n.join(`
905
902
  `),S=this.blockquote(f);i[i.length-1]=S,s=s.substring(0,s.length-R.raw.length)+S.raw,r=r.substring(0,r.length-R.text.length)+S.text;break}else if(h?.type==="list"){let R=h,f=R.raw+`
906
903
  `+n.join(`
907
904
  `),S=this.list(f);i[i.length-1]=S,s=s.substring(0,s.length-h.raw.length)+S.raw,r=r.substring(0,r.length-R.raw.length)+S.raw,n=f.substring(i.at(-1).raw.length).split(`
908
- `);continue}}return {type:"blockquote",raw:s,tokens:i,text:r}}}list(e){let t=this.rules.block.list.exec(e);if(t){let n=t[1].trim(),s=n.length>1,r={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:false,items:[]};n=s?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");let i=this.rules.other.listItemRegex(n),o=false;for(;e;){let a=false,c="",p="";if(!(t=i.exec(e))||this.rules.block.hr.test(e))break;c=t[0],e=e.substring(c.length);let k=me(t[2].split(`
905
+ `);continue}}return {type:"blockquote",raw:s,tokens:i,text:r}}}list(e){let t=this.rules.block.list.exec(e);if(t){let n=t[1].trim(),s=n.length>1,r={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:false,items:[]};n=s?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");let i=this.rules.other.listItemRegex(n),o=false;for(;e;){let a=false,c="",p="";if(!(t=i.exec(e))||this.rules.block.hr.test(e))break;c=t[0],e=e.substring(c.length);let d=fe(t[2].split(`
909
906
  `,1)[0],t[1].length),h=e.split(`
910
- `,1)[0],R=!k.trim(),f=0;if(this.options.pedantic?(f=2,p=k.trimStart()):R?f=t[1].length+1:(f=k.search(this.rules.other.nonSpaceChar),f=f>4?1:f,p=k.slice(f),f+=t[1].length),R&&this.rules.other.blankLine.test(h)&&(c+=h+`
911
- `,e=e.substring(h.length+1),a=true),!a){let S=this.rules.other.nextBulletRegex(f),te=this.rules.other.hrRegex(f),ne=this.rules.other.fencesBeginRegex(f),re=this.rules.other.headingBeginRegex(f),be=this.rules.other.htmlBeginRegex(f),Re=this.rules.other.blockquoteBeginRegex(f);for(;e;){let G=e.split(`
912
- `,1)[0],C;if(h=G,this.options.pedantic?(h=h.replace(this.rules.other.listReplaceNesting," "),C=h):C=h.replace(this.rules.other.tabCharGlobal," "),ne.test(h)||re.test(h)||be.test(h)||Re.test(h)||S.test(h)||te.test(h))break;if(C.search(this.rules.other.nonSpaceChar)>=f||!h.trim())p+=`
913
- `+C.slice(f);else {if(R||k.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||ne.test(k)||re.test(k)||te.test(k))break;p+=`
914
- `+h;}R=!h.trim(),c+=G+`
915
- `,e=e.substring(G.length+1),k=C.slice(f);}}r.loose||(o?r.loose=true:this.rules.other.doubleBlankLine.test(c)&&(o=true)),r.items.push({type:"list_item",raw:c,task:!!this.options.gfm&&this.rules.other.listIsTask.test(p),loose:false,text:p,tokens:[]}),r.raw+=c;}let u=r.items.at(-1);if(u)u.raw=u.raw.trimEnd(),u.text=u.text.trimEnd();else return;r.raw=r.raw.trimEnd();for(let a of r.items){this.lexer.state.top=false,a.tokens=this.lexer.blockTokens(a.text,[]);let c=a.tokens[0];if(a.task&&(c?.type==="text"||c?.type==="paragraph")){a.text=a.text.replace(this.rules.other.listReplaceTask,""),c.raw=c.raw.replace(this.rules.other.listReplaceTask,""),c.text=c.text.replace(this.rules.other.listReplaceTask,"");for(let k=this.lexer.inlineQueue.length-1;k>=0;k--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[k].src)){this.lexer.inlineQueue[k].src=this.lexer.inlineQueue[k].src.replace(this.rules.other.listReplaceTask,"");break}let p=this.rules.other.listTaskCheckbox.exec(a.raw);if(p){let k={type:"checkbox",raw:p[0]+" ",checked:p[0]!=="[ ]"};a.checked=k.checked,r.loose?a.tokens[0]&&["paragraph","text"].includes(a.tokens[0].type)&&"tokens"in a.tokens[0]&&a.tokens[0].tokens?(a.tokens[0].raw=k.raw+a.tokens[0].raw,a.tokens[0].text=k.raw+a.tokens[0].text,a.tokens[0].tokens.unshift(k)):a.tokens.unshift({type:"paragraph",raw:k.raw,text:k.raw,tokens:[k]}):a.tokens.unshift(k);}}else a.task&&(a.task=false);if(!r.loose){let p=a.tokens.filter(h=>h.type==="space"),k=p.length>0&&p.some(h=>this.rules.other.anyLine.test(h.raw));r.loose=k;}}if(r.loose)for(let a of r.items){a.loose=true;for(let c of a.tokens)c.type==="text"&&(c.type="paragraph");}return r}}html(e){let t=this.rules.block.html.exec(e);if(t){let n=ee(t[0]);return {type:"html",block:true,raw:n,pre:t[1]==="pre"||t[1]==="script"||t[1]==="style",text:n}}}def(e){let t=this.rules.block.def.exec(e);if(t){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];return {type:"def",tag:n,raw:$(t[0],`
916
- `),href:s,title:r}}}table(e){let t=this.rules.block.table.exec(e);if(!t||!this.rules.other.tableDelimiter.test(t[2]))return;let n=Y(t[1]),s=t[2].replace(this.rules.other.tableAlignChars,"").split("|"),r=t[3]?.trim()?t[3].replace(this.rules.other.tableRowBlankLine,"").split(`
907
+ `,1)[0],R=!d.trim(),f=0;if(this.options.pedantic?(f=2,p=d.trimStart()):R?f=t[1].length+1:(f=d.search(this.rules.other.nonSpaceChar),f=f>4?1:f,p=d.slice(f),f+=t[1].length),R&&this.rules.other.blankLine.test(h)&&(c+=h+`
908
+ `,e=e.substring(h.length+1),a=true),!a){let S=this.rules.other.nextBulletRegex(f),ee=this.rules.other.hrRegex(f),te=this.rules.other.fencesBeginRegex(f),ne=this.rules.other.headingBeginRegex(f),xe=this.rules.other.htmlBeginRegex(f),be=this.rules.other.blockquoteBeginRegex(f);for(;e;){let Z=e.split(`
909
+ `,1)[0],C;if(h=Z,this.options.pedantic?(h=h.replace(this.rules.other.listReplaceNesting," "),C=h):C=h.replace(this.rules.other.tabCharGlobal," "),te.test(h)||ne.test(h)||xe.test(h)||be.test(h)||S.test(h)||ee.test(h))break;if(C.search(this.rules.other.nonSpaceChar)>=f||!h.trim())p+=`
910
+ `+C.slice(f);else {if(R||d.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||te.test(d)||ne.test(d)||ee.test(d))break;p+=`
911
+ `+h;}R=!h.trim(),c+=Z+`
912
+ `,e=e.substring(Z.length+1),d=C.slice(f);}}r.loose||(o?r.loose=true:this.rules.other.doubleBlankLine.test(c)&&(o=true)),r.items.push({type:"list_item",raw:c,task:!!this.options.gfm&&this.rules.other.listIsTask.test(p),loose:false,text:p,tokens:[]}),r.raw+=c;}let u=r.items.at(-1);if(u)u.raw=u.raw.trimEnd(),u.text=u.text.trimEnd();else return;r.raw=r.raw.trimEnd();for(let a of r.items){if(this.lexer.state.top=false,a.tokens=this.lexer.blockTokens(a.text,[]),a.task){if(a.text=a.text.replace(this.rules.other.listReplaceTask,""),a.tokens[0]?.type==="text"||a.tokens[0]?.type==="paragraph"){a.tokens[0].raw=a.tokens[0].raw.replace(this.rules.other.listReplaceTask,""),a.tokens[0].text=a.tokens[0].text.replace(this.rules.other.listReplaceTask,"");for(let p=this.lexer.inlineQueue.length-1;p>=0;p--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[p].src)){this.lexer.inlineQueue[p].src=this.lexer.inlineQueue[p].src.replace(this.rules.other.listReplaceTask,"");break}}let c=this.rules.other.listTaskCheckbox.exec(a.raw);if(c){let p={type:"checkbox",raw:c[0]+" ",checked:c[0]!=="[ ]"};a.checked=p.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=p.raw+a.tokens[0].raw,a.tokens[0].text=p.raw+a.tokens[0].text,a.tokens[0].tokens.unshift(p)):a.tokens.unshift({type:"paragraph",raw:p.raw,text:p.raw,tokens:[p]}):a.tokens.unshift(p);}}if(!r.loose){let c=a.tokens.filter(d=>d.type==="space"),p=c.length>0&&c.some(d=>this.rules.other.anyLine.test(d.raw));r.loose=p;}}if(r.loose)for(let a of r.items){a.loose=true;for(let c of a.tokens)c.type==="text"&&(c.type="paragraph");}return r}}html(e){let t=this.rules.block.html.exec(e);if(t){let n=Y(t[0]);return {type:"html",block:true,raw:n,pre:t[1]==="pre"||t[1]==="script"||t[1]==="style",text:n}}}def(e){let t=this.rules.block.def.exec(e);if(t){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];return {type:"def",tag:n,raw:$(t[0],`
913
+ `),href:s,title:r}}}table(e){let t=this.rules.block.table.exec(e);if(!t||!this.rules.other.tableDelimiter.test(t[2]))return;let n=V(t[1]),s=t[2].replace(this.rules.other.tableAlignChars,"").split("|"),r=t[3]?.trim()?t[3].replace(this.rules.other.tableRowBlankLine,"").split(`
917
914
  `):[],i={type:"table",raw:$(t[0],`
918
- `),header:[],align:[],rows:[]};if(n.length===s.length){for(let o of s)this.rules.other.tableAlignRight.test(o)?i.align.push("right"):this.rules.other.tableAlignCenter.test(o)?i.align.push("center"):this.rules.other.tableAlignLeft.test(o)?i.align.push("left"):i.align.push(null);for(let o=0;o<n.length;o++)i.header.push({text:n[o],tokens:this.lexer.inline(n[o]),header:true,align:i.align[o]});for(let o of r)i.rows.push(Y(o,i.header.length).map((u,a)=>({text:u,tokens:this.lexer.inline(u),header:false,align:i.align[a]})));return i}}lheading(e){let t=this.rules.block.lheading.exec(e);if(t){let n=t[1].trim();return {type:"heading",raw:$(t[0],`
915
+ `),header:[],align:[],rows:[]};if(n.length===s.length){for(let o of s)this.rules.other.tableAlignRight.test(o)?i.align.push("right"):this.rules.other.tableAlignCenter.test(o)?i.align.push("center"):this.rules.other.tableAlignLeft.test(o)?i.align.push("left"):i.align.push(null);for(let o=0;o<n.length;o++)i.header.push({text:n[o],tokens:this.lexer.inline(n[o]),header:true,align:i.align[o]});for(let o of r)i.rows.push(V(o,i.header.length).map((u,a)=>({text:u,tokens:this.lexer.inline(u),header:false,align:i.align[a]})));return i}}lheading(e){let t=this.rules.block.lheading.exec(e);if(t){let n=t[1].trim();return {type:"heading",raw:$(t[0],`
919
916
  `),depth:t[2].charAt(0)==="="?1:2,text:n,tokens:this.lexer.inline(n)}}}paragraph(e){let t=this.rules.block.paragraph.exec(e);if(t){let n=t[1].charAt(t[1].length-1)===`
920
- `?t[1].slice(0,-1):t[1];return {type:"paragraph",raw:t[0],text:n,tokens:this.lexer.inline(n)}}}text(e){let t=this.rules.block.text.exec(e);if(t)return {type:"text",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){let t=this.rules.inline.escape.exec(e);if(t)return {type:"escape",raw:t[0],text:t[1]}}tag(e){let t=this.rules.inline.tag.exec(e);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]}}link(e){let t=this.rules.inline.link.exec(e);if(t){let n=t[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(n)){if(!this.rules.other.endAngleBracket.test(n))return;let i=$(n.slice(0,-1),"\\");if((n.length-i.length)%2===0)return}else {let i=fe(t[2],"()");if(i===-2)return;if(i>-1){let u=(t[0].indexOf("!")===0?5:4)+t[1].length+i;t[2]=t[2].substring(0,i),t[0]=t[0].substring(0,u).trim(),t[3]="";}}let s=t[2],r="";if(this.options.pedantic){let i=this.rules.other.pedanticHrefTitle.exec(s);i&&(s=i[1],r=i[3]);}else r=t[3]?t[3].slice(1,-1):"";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)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){let s=(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal," "),r=t[s.toLowerCase()];if(!r){let i=n[0].charAt(0);return {type:"text",raw:i,text:i}}return xe(n,r,n[0],this.lexer,this.rules)}}emStrong(e,t,n=""){let s=this.rules.inline.emStrongLDelim.exec(e);if(!s||!s[1]&&!s[2]&&!s[3]&&!s[4]||s[4]&&n.match(this.rules.other.unicodeAlphaNumeric))return;if(!(s[1]||s[3]||"")||!n||this.rules.inline.punctuation.exec(n)){let i=[...s[0]].length-1,o,u,a=i,c=0,p=s[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(p.lastIndex=0,t=t.slice(-1*e.length+i);(s=p.exec(t))!==null;){if(o=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!o)continue;if(u=[...o].length,s[3]||s[4]){a+=u;continue}else if((s[5]||s[6])&&i%3&&!((i+u)%3)){c+=u;continue}if(a-=u,a>0)continue;u=Math.min(u,u+a+c);let k=[...s[0]][0].length,h=e.slice(0,i+s.index+k+u);if(Math.min(i,u)%2){let f=h.slice(1,-1);return {type:"em",raw:h,text:f,tokens:this.lexer.inlineTokens(f)}}let R=h.slice(2,-2);return {type:"strong",raw:h,text:R,tokens:this.lexer.inlineTokens(R)}}}}codespan(e){let t=this.rules.inline.code.exec(e);if(t){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);return s&&r&&(n=n.substring(1,n.length-1)),{type:"codespan",raw:t[0],text:n}}}br(e){let t=this.rules.inline.br.exec(e);if(t)return {type:"br",raw:t[0]}}del(e,t,n=""){let s=this.rules.inline.delLDelim.exec(e);if(!s)return;if(!(s[1]||"")||!n||this.rules.inline.punctuation.exec(n)){let i=[...s[0]].length-1,o,u,a=i,c=this.rules.inline.delRDelim;for(c.lastIndex=0,t=t.slice(-1*e.length+i);(s=c.exec(t))!==null;){if(o=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!o||(u=[...o].length,u!==i))continue;if(s[3]||s[4]){a+=u;continue}if(a-=u,a>0)continue;u=Math.min(u,u+a);let p=[...s[0]][0].length,k=e.slice(0,i+s.index+p+u),h=k.slice(i,-i);return {type:"del",raw:k,text:h,tokens:this.lexer.inlineTokens(h)}}}}autolink(e){let t=this.rules.inline.autolink.exec(e);if(t){let n,s;return t[2]==="@"?(n=t[1],s="mailto:"+n):(n=t[1],s=n),{type:"link",raw:t[0],text:n,href:s,tokens:[{type:"text",raw:n,text:n}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let n,s;if(t[2]==="@")n=t[0],s="mailto:"+n;else {let r;do r=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??"";while(r!==t[0]);n=t[0],t[1]==="www."?s="http://"+t[0]:s=t[0];}return {type:"link",raw:t[0],text:n,href:s,tokens:[{type:"text",raw:n,text:n}]}}}inlineText(e){let t=this.rules.inline.text.exec(e);if(t){let n=this.lexer.state.inRawBlock;return {type:"text",raw:t[0],text:t[0],escaped:n}}}};var x=class l{tokens;options;state;inlineQueue;tokenizer;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||T,this.options.tokenizer=this.options.tokenizer||new w,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:false,inRawBlock:false,top:true};let t={other:m,block:D.normal,inline:A.normal};this.options.pedantic?(t.block=D.pedantic,t.inline=A.pedantic):this.options.gfm&&(t.block=D.gfm,this.options.breaks?t.inline=A.breaks:t.inline=A.gfm),this.tokenizer.rules=t;}static get rules(){return {block:D,inline:A}}static lex(e,t){return new l(t).lex(e)}static lexInline(e,t){return new l(t).inlineTokens(e)}lex(e){e=e.replace(m.carriageReturn,`
917
+ `?t[1].slice(0,-1):t[1];return {type:"paragraph",raw:t[0],text:n,tokens:this.lexer.inline(n)}}}text(e){let t=this.rules.block.text.exec(e);if(t)return {type:"text",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){let t=this.rules.inline.escape.exec(e);if(t)return {type:"escape",raw:t[0],text:t[1]}}tag(e){let t=this.rules.inline.tag.exec(e);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]}}link(e){let t=this.rules.inline.link.exec(e);if(t){let n=t[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(n)){if(!this.rules.other.endAngleBracket.test(n))return;let i=$(n.slice(0,-1),"\\");if((n.length-i.length)%2===0)return}else {let i=ge(t[2],"()");if(i===-2)return;if(i>-1){let u=(t[0].indexOf("!")===0?5:4)+t[1].length+i;t[2]=t[2].substring(0,i),t[0]=t[0].substring(0,u).trim(),t[3]="";}}let s=t[2],r="";if(this.options.pedantic){let i=this.rules.other.pedanticHrefTitle.exec(s);i&&(s=i[1],r=i[3]);}else r=t[3]?t[3].slice(1,-1):"";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)),me(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)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){let s=(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal," "),r=t[s.toLowerCase()];if(!r){let i=n[0].charAt(0);return {type:"text",raw:i,text:i}}return me(n,r,n[0],this.lexer,this.rules)}}emStrong(e,t,n=""){let s=this.rules.inline.emStrongLDelim.exec(e);if(!s||!s[1]&&!s[2]&&!s[3]&&!s[4]||s[4]&&n.match(this.rules.other.unicodeAlphaNumeric))return;if(!(s[1]||s[3]||"")||!n||this.rules.inline.punctuation.exec(n)){let i=[...s[0]].length-1,o,u,a=i,c=0,p=s[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(p.lastIndex=0,t=t.slice(-1*e.length+i);(s=p.exec(t))!==null;){if(o=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!o)continue;if(u=[...o].length,s[3]||s[4]){a+=u;continue}else if((s[5]||s[6])&&i%3&&!((i+u)%3)){c+=u;continue}if(a-=u,a>0)continue;u=Math.min(u,u+a+c);let d=[...s[0]][0].length,h=e.slice(0,i+s.index+d+u);if(Math.min(i,u)%2){let f=h.slice(1,-1);return {type:"em",raw:h,text:f,tokens:this.lexer.inlineTokens(f)}}let R=h.slice(2,-2);return {type:"strong",raw:h,text:R,tokens:this.lexer.inlineTokens(R)}}}}codespan(e){let t=this.rules.inline.code.exec(e);if(t){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);return s&&r&&(n=n.substring(1,n.length-1)),{type:"codespan",raw:t[0],text:n}}}br(e){let t=this.rules.inline.br.exec(e);if(t)return {type:"br",raw:t[0]}}del(e,t,n=""){let s=this.rules.inline.delLDelim.exec(e);if(!s)return;if(!(s[1]||"")||!n||this.rules.inline.punctuation.exec(n)){let i=[...s[0]].length-1,o,u,a=i,c=this.rules.inline.delRDelim;for(c.lastIndex=0,t=t.slice(-1*e.length+i);(s=c.exec(t))!==null;){if(o=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!o||(u=[...o].length,u!==i))continue;if(s[3]||s[4]){a+=u;continue}if(a-=u,a>0)continue;u=Math.min(u,u+a);let p=[...s[0]][0].length,d=e.slice(0,i+s.index+p+u),h=d.slice(i,-i);return {type:"del",raw:d,text:h,tokens:this.lexer.inlineTokens(h)}}}}autolink(e){let t=this.rules.inline.autolink.exec(e);if(t){let n,s;return t[2]==="@"?(n=t[1],s="mailto:"+n):(n=t[1],s=n),{type:"link",raw:t[0],text:n,href:s,tokens:[{type:"text",raw:n,text:n}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let n,s;if(t[2]==="@")n=t[0],s="mailto:"+n;else {let r;do r=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??"";while(r!==t[0]);n=t[0],t[1]==="www."?s="http://"+t[0]:s=t[0];}return {type:"link",raw:t[0],text:n,href:s,tokens:[{type:"text",raw:n,text:n}]}}}inlineText(e){let t=this.rules.inline.text.exec(e);if(t){let n=this.lexer.state.inRawBlock;return {type:"text",raw:t[0],text:t[0],escaped:n}}}};var x=class l{tokens;options;state;inlineQueue;tokenizer;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||T,this.options.tokenizer=this.options.tokenizer||new w,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:false,inRawBlock:false,top:true};let t={other:m,block:B.normal,inline:A.normal};this.options.pedantic?(t.block=B.pedantic,t.inline=A.pedantic):this.options.gfm&&(t.block=B.gfm,this.options.breaks?t.inline=A.breaks:t.inline=A.gfm),this.tokenizer.rules=t;}static get rules(){return {block:B,inline:A}}static lex(e,t){return new l(t).lex(e)}static lexInline(e,t){return new l(t).inlineTokens(e)}lex(e){e=e.replace(m.carriageReturn,`
921
918
  `),this.blockTokens(e,this.tokens);for(let t=0;t<this.inlineQueue.length;t++){let n=this.inlineQueue[t];this.inlineTokens(n.src,n.tokens);}return this.inlineQueue=[],this.tokens}blockTokens(e,t=[],n=false){this.tokenizer.lexer=this,this.options.pedantic&&(e=e.replace(m.tabCharGlobal," ").replace(m.spaceLine,""));let s=1/0;for(;e;){if(e.length<s)s=e.length;else {this.infiniteLoopError(e.charCodeAt(0));break}let r;if(this.options.extensions?.block?.some(o=>(r=o.call({lexer:this},e,t))?(e=e.substring(r.raw.length),t.push(r),true):false))continue;if(r=this.tokenizer.space(e)){e=e.substring(r.raw.length);let o=t.at(-1);r.raw.length===1&&o!==void 0?o.raw+=`
922
919
  `:t.push(r);continue}if(r=this.tokenizer.code(e)){e=e.substring(r.raw.length);let o=t.at(-1);o?.type==="paragraph"||o?.type==="text"?(o.raw+=(o.raw.endsWith(`
923
920
  `)?"":`
@@ -931,7 +928,7 @@ ${p}`:p;let k=this.lexer.state.top;if(this.lexer.state.top=true,this.lexer.block
931
928
  `+r.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=o.text):t.push(r),n=i.length!==e.length,e=e.substring(r.raw.length);continue}if(r=this.tokenizer.text(e)){e=e.substring(r.raw.length);let o=t.at(-1);o?.type==="text"?(o.raw+=(o.raw.endsWith(`
932
929
  `)?"":`
933
930
  `)+r.raw,o.text+=`
934
- `+r.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=o.text):t.push(r);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return this.state.top=true,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){this.tokenizer.lexer=this;let n=e,s=null;if(this.tokens.links){let a=Object.keys(this.tokens.links);if(a.length>0)for(;(s=this.tokenizer.rules.inline.reflinkSearch.exec(n))!==null;)a.includes(s[0].slice(s[0].lastIndexOf("[")+1,-1))&&(n=n.slice(0,s.index)+"["+"a".repeat(s[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex));}for(;(s=this.tokenizer.rules.inline.anyPunctuation.exec(n))!==null;)n=n.slice(0,s.index)+"++"+n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);let r;for(;(s=this.tokenizer.rules.inline.blockSkip.exec(n))!==null;)r=s[2]?s[2].length:0,n=n.slice(0,s.index+r)+"["+"a".repeat(s[0].length-r-2)+"]"+n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);n=this.options.hooks?.emStrongMask?.call({lexer:this},n)??n;let i=false,o="",u=1/0;for(;e;){if(e.length<u)u=e.length;else {this.infiniteLoopError(e.charCodeAt(0));break}i||(o=""),i=false;let a;if(this.options.extensions?.inline?.some(p=>(a=p.call({lexer:this},e,t))?(e=e.substring(a.raw.length),t.push(a),true):false))continue;if(a=this.tokenizer.escape(e)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.tag(e)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.link(e)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(a.raw.length);let p=t.at(-1);a.type==="text"&&p?.type==="text"?(p.raw+=a.raw,p.text+=a.text):t.push(a);continue}if(a=this.tokenizer.emStrong(e,n,o)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.codespan(e)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.br(e)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.del(e,n,o)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.autolink(e)){e=e.substring(a.raw.length),t.push(a);continue}if(!this.state.inLink&&(a=this.tokenizer.url(e))){e=e.substring(a.raw.length),t.push(a);continue}let c=e;if(this.options.extensions?.startInline){let p=1/0,k=e.slice(1),h;this.options.extensions.startInline.forEach(R=>{h=R.call({lexer:this},k),typeof h=="number"&&h>=0&&(p=Math.min(p,h));}),p<1/0&&p>=0&&(c=e.substring(0,p+1));}if(a=this.tokenizer.inlineText(c)){e=e.substring(a.raw.length),a.raw.slice(-1)!=="_"&&(o=a.raw.slice(-1)),i=true;let p=t.at(-1);p?.type==="text"?(p.raw+=a.raw,p.text+=a.text):t.push(a);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return t}infiniteLoopError(e){let t="Infinite loop on byte: "+e;if(this.options.silent)console.error(t);else throw new Error(t)}};var y=class{options;parser;constructor(e){this.options=e||T;}space(e){return ""}code({text:e,lang:t,escaped:n}){let s=(t||"").match(m.notSpaceStart)?.[0],r=e.replace(m.endingNewline,"")+`
931
+ `+r.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=o.text):t.push(r);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return this.state.top=true,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){this.tokenizer.lexer=this;let n=e,s=null;if(this.tokens.links){let a=Object.keys(this.tokens.links);if(a.length>0)for(;(s=this.tokenizer.rules.inline.reflinkSearch.exec(n))!==null;)a.includes(s[0].slice(s[0].lastIndexOf("[")+1,-1))&&(n=n.slice(0,s.index)+"["+"a".repeat(s[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex));}for(;(s=this.tokenizer.rules.inline.anyPunctuation.exec(n))!==null;)n=n.slice(0,s.index)+"++"+n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);let r;for(;(s=this.tokenizer.rules.inline.blockSkip.exec(n))!==null;)r=s[2]?s[2].length:0,n=n.slice(0,s.index+r)+"["+"a".repeat(s[0].length-r-2)+"]"+n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);n=this.options.hooks?.emStrongMask?.call({lexer:this},n)??n;let i=false,o="",u=1/0;for(;e;){if(e.length<u)u=e.length;else {this.infiniteLoopError(e.charCodeAt(0));break}i||(o=""),i=false;let a;if(this.options.extensions?.inline?.some(p=>(a=p.call({lexer:this},e,t))?(e=e.substring(a.raw.length),t.push(a),true):false))continue;if(a=this.tokenizer.escape(e)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.tag(e)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.link(e)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(a.raw.length);let p=t.at(-1);a.type==="text"&&p?.type==="text"?(p.raw+=a.raw,p.text+=a.text):t.push(a);continue}if(a=this.tokenizer.emStrong(e,n,o)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.codespan(e)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.br(e)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.del(e,n,o)){e=e.substring(a.raw.length),t.push(a);continue}if(a=this.tokenizer.autolink(e)){e=e.substring(a.raw.length),t.push(a);continue}if(!this.state.inLink&&(a=this.tokenizer.url(e))){e=e.substring(a.raw.length),t.push(a);continue}let c=e;if(this.options.extensions?.startInline){let p=1/0,d=e.slice(1),h;this.options.extensions.startInline.forEach(R=>{h=R.call({lexer:this},d),typeof h=="number"&&h>=0&&(p=Math.min(p,h));}),p<1/0&&p>=0&&(c=e.substring(0,p+1));}if(a=this.tokenizer.inlineText(c)){e=e.substring(a.raw.length),a.raw.slice(-1)!=="_"&&(o=a.raw.slice(-1)),i=true;let p=t.at(-1);p?.type==="text"?(p.raw+=a.raw,p.text+=a.text):t.push(a);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return t}infiniteLoopError(e){let t="Infinite loop on byte: "+e;if(this.options.silent)console.error(t);else throw new Error(t)}};var y=class{options;parser;constructor(e){this.options=e||T;}space(e){return ""}code({text:e,lang:t,escaped:n}){let s=(t||"").match(m.notSpaceStart)?.[0],r=e.replace(m.endingNewline,"")+`
935
932
  `;return s?'<pre><code class="language-'+O(s)+'">'+(n?r:O(r,true))+`</code></pre>
936
933
  `:"<pre><code>"+(n?r:O(r,true))+`</code></pre>
937
934
  `}blockquote({tokens:e}){return `<blockquote>
@@ -949,68 +946,27 @@ ${this.parser.parse(e)}</blockquote>
949
946
  `}tablerow({text:e}){return `<tr>
950
947
  ${e}</tr>
951
948
  `}tablecell(e){let t=this.parser.parseInline(e.tokens),n=e.header?"th":"td";return (e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+`</${n}>
952
- `}strong({tokens:e}){return `<strong>${this.parser.parseInline(e)}</strong>`}em({tokens:e}){return `<em>${this.parser.parseInline(e)}</em>`}codespan({text:e}){return `<code>${O(e,true)}</code>`}br(e){return "<br>"}del({tokens:e}){return `<del>${this.parser.parseInline(e)}</del>`}link({href:e,title:t,tokens:n}){let s=this.parser.parseInline(n),r=V(e);if(r===null)return s;e=r;let i='<a href="'+e+'"';return t&&(i+=' title="'+O(t)+'"'),i+=">"+s+"</a>",i}image({href:e,title:t,text:n,tokens:s}){s&&(n=this.parser.parseInline(s,this.parser.textRenderer));let r=V(e);if(r===null)return O(n);e=r;let i=`<img src="${e}" alt="${O(n)}"`;return t&&(i+=` title="${O(t)}"`),i+=">",i}text(e){return "tokens"in e&&e.tokens?this.parser.parseInline(e.tokens):"escaped"in e&&e.escaped?e.text:O(e.text)}};var L=class{strong({text:e}){return e}em({text:e}){return e}codespan({text:e}){return e}del({text:e}){return e}html({text:e}){return e}text({text:e}){return e}link({text:e}){return ""+e}image({text:e}){return ""+e}br(){return ""}checkbox({raw:e}){return e}};var b=class l{options;renderer;textRenderer;constructor(e){this.options=e||T,this.options.renderer=this.options.renderer||new y,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new L;}static parse(e,t){return new l(t).parse(e)}static parseInline(e,t){return new l(t).parseInline(e)}parse(e){this.renderer.parser=this;let t="";for(let n=0;n<e.length;n++){let s=e[n];if(this.options.extensions?.renderers?.[s.type]){let i=s,o=this.options.extensions.renderers[i.type].call({parser:this},i);if(o!==false||!["space","hr","heading","code","table","blockquote","list","html","def","paragraph","text"].includes(i.type)){t+=o||"";continue}}let r=s;switch(r.type){case "space":{t+=this.renderer.space(r);break}case "hr":{t+=this.renderer.hr(r);break}case "heading":{t+=this.renderer.heading(r);break}case "code":{t+=this.renderer.code(r);break}case "table":{t+=this.renderer.table(r);break}case "blockquote":{t+=this.renderer.blockquote(r);break}case "list":{t+=this.renderer.list(r);break}case "checkbox":{t+=this.renderer.checkbox(r);break}case "html":{t+=this.renderer.html(r);break}case "def":{t+=this.renderer.def(r);break}case "paragraph":{t+=this.renderer.paragraph(r);break}case "text":{t+=this.renderer.text(r);break}default:{let i='Token with "'+r.type+'" type was not found.';if(this.options.silent)return console.error(i),"";throw new Error(i)}}}return t}parseInline(e,t=this.renderer){this.renderer.parser=this;let n="";for(let s=0;s<e.length;s++){let r=e[s];if(this.options.extensions?.renderers?.[r.type]){let o=this.options.extensions.renderers[r.type].call({parser:this},r);if(o!==false||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(r.type)){n+=o||"";continue}}let i=r;switch(i.type){case "escape":{n+=t.text(i);break}case "html":{n+=t.html(i);break}case "link":{n+=t.link(i);break}case "image":{n+=t.image(i);break}case "checkbox":{n+=t.checkbox(i);break}case "strong":{n+=t.strong(i);break}case "em":{n+=t.em(i);break}case "codespan":{n+=t.codespan(i);break}case "br":{n+=t.br(i);break}case "del":{n+=t.del(i);break}case "text":{n+=t.text(i);break}default:{let o='Token with "'+i.type+'" type was not found.';if(this.options.silent)return console.error(o),"";throw new Error(o)}}}return n}};var P=class{options;block;constructor(e){this.options=e||T;}static passThroughHooks=new Set(["preprocess","postprocess","processAllTokens","emStrongMask"]);static passThroughHooksRespectAsync=new Set(["preprocess","postprocess","processAllTokens"]);preprocess(e){return e}postprocess(e){return e}processAllTokens(e){return e}emStrongMask(e){return e}provideLexer(e=this.block){return e?x.lex:x.lexInline}provideParser(e=this.block){return e?b.parse:b.parseInline}};var q=class{defaults=M();options=this.setOptions;parse=this.parseMarkdown(true);parseInline=this.parseMarkdown(false);Parser=b;Renderer=y;TextRenderer=L;Lexer=x;Tokenizer=w;Hooks=P;constructor(...e){this.use(...e);}walkTokens(e,t){let n=[];for(let s of e)switch(n=n.concat(t.call(this,s)),s.type){case "table":{let r=s;for(let i of r.header)n=n.concat(this.walkTokens(i.tokens,t));for(let i of r.rows)for(let o of i)n=n.concat(this.walkTokens(o.tokens,t));break}case "list":{let r=s;n=n.concat(this.walkTokens(r.items,t));break}default:{let r=s;this.defaults.extensions?.childTokens?.[r.type]?this.defaults.extensions.childTokens[r.type].forEach(i=>{let o=r[i].flat(1/0);n=n.concat(this.walkTokens(o,t));}):r.tokens&&(n=n.concat(this.walkTokens(r.tokens,t)));}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{let s={...n};if(s.async=this.defaults.async||s.async||false,n.extensions&&(n.extensions.forEach(r=>{if(!r.name)throw new Error("extension name required");if("renderer"in r){let i=t.renderers[r.name];i?t.renderers[r.name]=function(...o){let u=r.renderer.apply(this,o);return u===false&&(u=i.apply(this,o)),u}:t.renderers[r.name]=r.renderer;}if("tokenizer"in r){if(!r.level||r.level!=="block"&&r.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");let i=t[r.level];i?i.unshift(r.tokenizer):t[r.level]=[r.tokenizer],r.start&&(r.level==="block"?t.startBlock?t.startBlock.push(r.start):t.startBlock=[r.start]:r.level==="inline"&&(t.startInline?t.startInline.push(r.start):t.startInline=[r.start]));}"childTokens"in r&&r.childTokens&&(t.childTokens[r.name]=r.childTokens);}),s.extensions=t),n.renderer){let r=this.defaults.renderer||new y(this.defaults);for(let i in n.renderer){if(!(i in r))throw new Error(`renderer '${i}' does not exist`);if(["options","parser"].includes(i))continue;let o=i,u=n.renderer[o],a=r[o];r[o]=(...c)=>{let p=u.apply(r,c);return p===false&&(p=a.apply(r,c)),p||""};}s.renderer=r;}if(n.tokenizer){let r=this.defaults.tokenizer||new w(this.defaults);for(let i in n.tokenizer){if(!(i in r))throw new Error(`tokenizer '${i}' does not exist`);if(["options","rules","lexer"].includes(i))continue;let o=i,u=n.tokenizer[o],a=r[o];r[o]=(...c)=>{let p=u.apply(r,c);return p===false&&(p=a.apply(r,c)),p};}s.tokenizer=r;}if(n.hooks){let r=this.defaults.hooks||new P;for(let i in n.hooks){if(!(i in r))throw new Error(`hook '${i}' does not exist`);if(["options","block"].includes(i))continue;let o=i,u=n.hooks[o],a=r[o];P.passThroughHooks.has(i)?r[o]=c=>{if(this.defaults.async&&P.passThroughHooksRespectAsync.has(i))return (async()=>{let k=await u.call(r,c);return a.call(r,k)})();let p=u.call(r,c);return a.call(r,p)}:r[o]=(...c)=>{if(this.defaults.async)return (async()=>{let k=await u.apply(r,c);return k===false&&(k=await a.apply(r,c)),k})();let p=u.apply(r,c);return p===false&&(p=a.apply(r,c)),p};}s.hooks=r;}if(n.walkTokens){let r=this.defaults.walkTokens,i=n.walkTokens;s.walkTokens=function(o){let u=[];return u.push(i.call(this,o)),r&&(u=u.concat(r.call(this,o))),u};}this.defaults={...this.defaults,...s};}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return x.lex(e,t??this.defaults)}parser(e,t){return b.parse(e,t??this.defaults)}parseMarkdown(e){return (n,s)=>{let r={...s},i={...this.defaults,...r},o=this.onError(!!i.silent,!!i.async);if(this.defaults.async===true&&r.async===false)return o(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof n>"u"||n===null)return o(new Error("marked(): input parameter is undefined or null"));if(typeof n!="string")return o(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(n)+", string expected"));if(i.hooks&&(i.hooks.options=i,i.hooks.block=e),i.async)return (async()=>{let u=i.hooks?await i.hooks.preprocess(n):n,c=await(i.hooks?await i.hooks.provideLexer(e):e?x.lex:x.lexInline)(u,i),p=i.hooks?await i.hooks.processAllTokens(c):c;i.walkTokens&&await Promise.all(this.walkTokens(p,i.walkTokens));let h=await(i.hooks?await i.hooks.provideParser(e):e?b.parse:b.parseInline)(p,i);return i.hooks?await i.hooks.postprocess(h):h})().catch(o);try{i.hooks&&(n=i.hooks.preprocess(n));let a=(i.hooks?i.hooks.provideLexer(e):e?x.lex:x.lexInline)(n,i);i.hooks&&(a=i.hooks.processAllTokens(a)),i.walkTokens&&this.walkTokens(a,i.walkTokens);let p=(i.hooks?i.hooks.provideParser(e):e?b.parse:b.parseInline)(a,i);return i.hooks&&(p=i.hooks.postprocess(p)),p}catch(u){return o(u)}}}onError(e,t){return n=>{if(n.message+=`
953
- Please report this to https://github.com/markedjs/marked.`,e){let s="<p>An error occurred:</p><pre>"+O(n.message+"",true)+"</pre>";return t?Promise.resolve(s):s}if(t)return Promise.reject(n);throw n}}};var z=new q;function g(l,e){return z.parse(l,e)}g.options=g.setOptions=function(l){return z.setOptions(l),g.defaults=z.defaults,N(g.defaults),g};g.getDefaults=M;g.defaults=T;g.use=function(...l){return z.use(...l),g.defaults=z.defaults,N(g.defaults),g};g.walkTokens=function(l,e){return z.walkTokens(l,e)};g.parseInline=z.parseInline;g.Parser=b;g.parser=b.parse;g.Renderer=y;g.TextRenderer=L;g.Lexer=x;g.lexer=x.lex;g.Tokenizer=w;g.Hooks=P;g.parse=g;g.options;g.setOptions;g.use;g.walkTokens;g.parseInline;b.parse;x.lex;
954
-
955
- /*! @license DOMPurify 3.4.8 | (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.8/LICENSE */
956
-
957
- function _arrayLikeToArray(r, a) {
958
- (null == a || a > r.length) && (a = r.length);
959
- for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
960
- return n;
961
- }
962
- function _arrayWithHoles(r) {
963
- if (Array.isArray(r)) return r;
964
- }
965
- function _iterableToArrayLimit(r, l) {
966
- var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
967
- if (null != t) {
968
- var e,
969
- n,
970
- i,
971
- u,
972
- a = [],
973
- f = true,
974
- o = false;
975
- try {
976
- if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
977
- } catch (r) {
978
- o = true, n = r;
979
- } finally {
980
- try {
981
- if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
982
- } finally {
983
- if (o) throw n;
984
- }
985
- }
986
- return a;
987
- }
988
- }
989
- function _nonIterableRest() {
990
- throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
991
- }
992
- function _slicedToArray(r, e) {
993
- return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
994
- }
995
- function _unsupportedIterableToArray(r, a) {
996
- if (r) {
997
- if ("string" == typeof r) return _arrayLikeToArray(r, a);
998
- var t = {}.toString.call(r).slice(8, -1);
999
- 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;
1000
- }
1001
- }
1002
-
1003
- const entries = Object.entries,
1004
- setPrototypeOf = Object.setPrototypeOf,
1005
- isFrozen = Object.isFrozen,
1006
- getPrototypeOf = Object.getPrototypeOf,
1007
- getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
1008
- let freeze = Object.freeze,
1009
- seal = Object.seal,
1010
- create = Object.create; // eslint-disable-line import/no-mutable-exports
1011
- let _ref = typeof Reflect !== 'undefined' && Reflect,
1012
- apply = _ref.apply,
1013
- construct = _ref.construct;
949
+ `}strong({tokens:e}){return `<strong>${this.parser.parseInline(e)}</strong>`}em({tokens:e}){return `<em>${this.parser.parseInline(e)}</em>`}codespan({text:e}){return `<code>${O(e,true)}</code>`}br(e){return "<br>"}del({tokens:e}){return `<del>${this.parser.parseInline(e)}</del>`}link({href:e,title:t,tokens:n}){let s=this.parser.parseInline(n),r=J(e);if(r===null)return s;e=r;let i='<a href="'+e+'"';return t&&(i+=' title="'+O(t)+'"'),i+=">"+s+"</a>",i}image({href:e,title:t,text:n,tokens:s}){s&&(n=this.parser.parseInline(s,this.parser.textRenderer));let r=J(e);if(r===null)return O(n);e=r;let i=`<img src="${e}" alt="${O(n)}"`;return t&&(i+=` title="${O(t)}"`),i+=">",i}text(e){return "tokens"in e&&e.tokens?this.parser.parseInline(e.tokens):"escaped"in e&&e.escaped?e.text:O(e.text)}};var L=class{strong({text:e}){return e}em({text:e}){return e}codespan({text:e}){return e}del({text:e}){return e}html({text:e}){return e}text({text:e}){return e}link({text:e}){return ""+e}image({text:e}){return ""+e}br(){return ""}checkbox({raw:e}){return e}};var b=class l{options;renderer;textRenderer;constructor(e){this.options=e||T,this.options.renderer=this.options.renderer||new y,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new L;}static parse(e,t){return new l(t).parse(e)}static parseInline(e,t){return new l(t).parseInline(e)}parse(e){this.renderer.parser=this;let t="";for(let n=0;n<e.length;n++){let s=e[n];if(this.options.extensions?.renderers?.[s.type]){let i=s,o=this.options.extensions.renderers[i.type].call({parser:this},i);if(o!==false||!["space","hr","heading","code","table","blockquote","list","html","def","paragraph","text"].includes(i.type)){t+=o||"";continue}}let r=s;switch(r.type){case "space":{t+=this.renderer.space(r);break}case "hr":{t+=this.renderer.hr(r);break}case "heading":{t+=this.renderer.heading(r);break}case "code":{t+=this.renderer.code(r);break}case "table":{t+=this.renderer.table(r);break}case "blockquote":{t+=this.renderer.blockquote(r);break}case "list":{t+=this.renderer.list(r);break}case "checkbox":{t+=this.renderer.checkbox(r);break}case "html":{t+=this.renderer.html(r);break}case "def":{t+=this.renderer.def(r);break}case "paragraph":{t+=this.renderer.paragraph(r);break}case "text":{t+=this.renderer.text(r);break}default:{let i='Token with "'+r.type+'" type was not found.';if(this.options.silent)return console.error(i),"";throw new Error(i)}}}return t}parseInline(e,t=this.renderer){this.renderer.parser=this;let n="";for(let s=0;s<e.length;s++){let r=e[s];if(this.options.extensions?.renderers?.[r.type]){let o=this.options.extensions.renderers[r.type].call({parser:this},r);if(o!==false||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(r.type)){n+=o||"";continue}}let i=r;switch(i.type){case "escape":{n+=t.text(i);break}case "html":{n+=t.html(i);break}case "link":{n+=t.link(i);break}case "image":{n+=t.image(i);break}case "checkbox":{n+=t.checkbox(i);break}case "strong":{n+=t.strong(i);break}case "em":{n+=t.em(i);break}case "codespan":{n+=t.codespan(i);break}case "br":{n+=t.br(i);break}case "del":{n+=t.del(i);break}case "text":{n+=t.text(i);break}default:{let o='Token with "'+i.type+'" type was not found.';if(this.options.silent)return console.error(o),"";throw new Error(o)}}}return n}};var P=class{options;block;constructor(e){this.options=e||T;}static passThroughHooks=new Set(["preprocess","postprocess","processAllTokens","emStrongMask"]);static passThroughHooksRespectAsync=new Set(["preprocess","postprocess","processAllTokens"]);preprocess(e){return e}postprocess(e){return e}processAllTokens(e){return e}emStrongMask(e){return e}provideLexer(e=this.block){return e?x.lex:x.lexInline}provideParser(e=this.block){return e?b.parse:b.parseInline}};var D=class{defaults=z();options=this.setOptions;parse=this.parseMarkdown(true);parseInline=this.parseMarkdown(false);Parser=b;Renderer=y;TextRenderer=L;Lexer=x;Tokenizer=w;Hooks=P;constructor(...e){this.use(...e);}walkTokens(e,t){let n=[];for(let s of e)switch(n=n.concat(t.call(this,s)),s.type){case "table":{let r=s;for(let i of r.header)n=n.concat(this.walkTokens(i.tokens,t));for(let i of r.rows)for(let o of i)n=n.concat(this.walkTokens(o.tokens,t));break}case "list":{let r=s;n=n.concat(this.walkTokens(r.items,t));break}default:{let r=s;this.defaults.extensions?.childTokens?.[r.type]?this.defaults.extensions.childTokens[r.type].forEach(i=>{let o=r[i].flat(1/0);n=n.concat(this.walkTokens(o,t));}):r.tokens&&(n=n.concat(this.walkTokens(r.tokens,t)));}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{let s={...n};if(s.async=this.defaults.async||s.async||false,n.extensions&&(n.extensions.forEach(r=>{if(!r.name)throw new Error("extension name required");if("renderer"in r){let i=t.renderers[r.name];i?t.renderers[r.name]=function(...o){let u=r.renderer.apply(this,o);return u===false&&(u=i.apply(this,o)),u}:t.renderers[r.name]=r.renderer;}if("tokenizer"in r){if(!r.level||r.level!=="block"&&r.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");let i=t[r.level];i?i.unshift(r.tokenizer):t[r.level]=[r.tokenizer],r.start&&(r.level==="block"?t.startBlock?t.startBlock.push(r.start):t.startBlock=[r.start]:r.level==="inline"&&(t.startInline?t.startInline.push(r.start):t.startInline=[r.start]));}"childTokens"in r&&r.childTokens&&(t.childTokens[r.name]=r.childTokens);}),s.extensions=t),n.renderer){let r=this.defaults.renderer||new y(this.defaults);for(let i in n.renderer){if(!(i in r))throw new Error(`renderer '${i}' does not exist`);if(["options","parser"].includes(i))continue;let o=i,u=n.renderer[o],a=r[o];r[o]=(...c)=>{let p=u.apply(r,c);return p===false&&(p=a.apply(r,c)),p||""};}s.renderer=r;}if(n.tokenizer){let r=this.defaults.tokenizer||new w(this.defaults);for(let i in n.tokenizer){if(!(i in r))throw new Error(`tokenizer '${i}' does not exist`);if(["options","rules","lexer"].includes(i))continue;let o=i,u=n.tokenizer[o],a=r[o];r[o]=(...c)=>{let p=u.apply(r,c);return p===false&&(p=a.apply(r,c)),p};}s.tokenizer=r;}if(n.hooks){let r=this.defaults.hooks||new P;for(let i in n.hooks){if(!(i in r))throw new Error(`hook '${i}' does not exist`);if(["options","block"].includes(i))continue;let o=i,u=n.hooks[o],a=r[o];P.passThroughHooks.has(i)?r[o]=c=>{if(this.defaults.async&&P.passThroughHooksRespectAsync.has(i))return (async()=>{let d=await u.call(r,c);return a.call(r,d)})();let p=u.call(r,c);return a.call(r,p)}:r[o]=(...c)=>{if(this.defaults.async)return (async()=>{let d=await u.apply(r,c);return d===false&&(d=await a.apply(r,c)),d})();let p=u.apply(r,c);return p===false&&(p=a.apply(r,c)),p};}s.hooks=r;}if(n.walkTokens){let r=this.defaults.walkTokens,i=n.walkTokens;s.walkTokens=function(o){let u=[];return u.push(i.call(this,o)),r&&(u=u.concat(r.call(this,o))),u};}this.defaults={...this.defaults,...s};}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return x.lex(e,t??this.defaults)}parser(e,t){return b.parse(e,t??this.defaults)}parseMarkdown(e){return (n,s)=>{let r={...s},i={...this.defaults,...r},o=this.onError(!!i.silent,!!i.async);if(this.defaults.async===true&&r.async===false)return o(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof n>"u"||n===null)return o(new Error("marked(): input parameter is undefined or null"));if(typeof n!="string")return o(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(n)+", string expected"));if(i.hooks&&(i.hooks.options=i,i.hooks.block=e),i.async)return (async()=>{let u=i.hooks?await i.hooks.preprocess(n):n,c=await(i.hooks?await i.hooks.provideLexer(e):e?x.lex:x.lexInline)(u,i),p=i.hooks?await i.hooks.processAllTokens(c):c;i.walkTokens&&await Promise.all(this.walkTokens(p,i.walkTokens));let h=await(i.hooks?await i.hooks.provideParser(e):e?b.parse:b.parseInline)(p,i);return i.hooks?await i.hooks.postprocess(h):h})().catch(o);try{i.hooks&&(n=i.hooks.preprocess(n));let a=(i.hooks?i.hooks.provideLexer(e):e?x.lex:x.lexInline)(n,i);i.hooks&&(a=i.hooks.processAllTokens(a)),i.walkTokens&&this.walkTokens(a,i.walkTokens);let p=(i.hooks?i.hooks.provideParser(e):e?b.parse:b.parseInline)(a,i);return i.hooks&&(p=i.hooks.postprocess(p)),p}catch(u){return o(u)}}}onError(e,t){return n=>{if(n.message+=`
950
+ Please report this to https://github.com/markedjs/marked.`,e){let s="<p>An error occurred:</p><pre>"+O(n.message+"",true)+"</pre>";return t?Promise.resolve(s):s}if(t)return Promise.reject(n);throw n}}};var M=new D;function g(l,e){return M.parse(l,e)}g.options=g.setOptions=function(l){return M.setOptions(l),g.defaults=M.defaults,G(g.defaults),g};g.getDefaults=z;g.defaults=T;g.use=function(...l){return M.use(...l),g.defaults=M.defaults,G(g.defaults),g};g.walkTokens=function(l,e){return M.walkTokens(l,e)};g.parseInline=M.parseInline;g.Parser=b;g.parser=b.parse;g.Renderer=y;g.TextRenderer=L;g.Lexer=x;g.lexer=x.lex;g.Tokenizer=w;g.Hooks=P;g.parse=g;g.options;g.setOptions;g.use;g.walkTokens;g.parseInline;b.parse;x.lex;
951
+
952
+ /*! @license DOMPurify 3.4.1 | (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.1/LICENSE */
953
+
954
+ const {
955
+ entries,
956
+ setPrototypeOf,
957
+ isFrozen,
958
+ getPrototypeOf,
959
+ getOwnPropertyDescriptor
960
+ } = Object;
961
+ let {
962
+ freeze,
963
+ seal,
964
+ create
965
+ } = Object; // eslint-disable-line import/no-mutable-exports
966
+ let {
967
+ apply,
968
+ construct
969
+ } = typeof Reflect !== 'undefined' && Reflect;
1014
970
  if (!freeze) {
1015
971
  freeze = function freeze(x) {
1016
972
  return x;
@@ -1147,10 +1103,7 @@ function cleanArray(array) {
1147
1103
  */
1148
1104
  function clone(object) {
1149
1105
  const newObject = create(null);
1150
- for (const _ref2 of entries(object)) {
1151
- var _ref3 = _slicedToArray(_ref2, 2);
1152
- const property = _ref3[0];
1153
- const value = _ref3[1];
1106
+ for (const [property, value] of entries(object)) {
1154
1107
  const isPropertyExist = objectHasOwnProperty(object, property);
1155
1108
  if (isPropertyExist) {
1156
1109
  if (arrayIsArray(value)) {
@@ -1264,14 +1217,15 @@ const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mgly
1264
1217
  const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
1265
1218
  const text = freeze(['#text']);
1266
1219
 
1267
- const 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']);
1220
+ const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', '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']);
1268
1221
  const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'mask-type', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
1269
1222
  const 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']);
1270
1223
  const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
1271
1224
 
1272
- const MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g);
1273
- const ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g);
1274
- const TMPLIT_EXPR = seal(/\${[\w\W]*/g);
1225
+ // eslint-disable-next-line unicorn/better-regex
1226
+ const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
1227
+ const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
1228
+ const TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); // eslint-disable-line unicorn/better-regex
1275
1229
  const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
1276
1230
  const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
1277
1231
  const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
@@ -1282,24 +1236,29 @@ const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205
1282
1236
  const DOCTYPE_NAME = seal(/^html$/i);
1283
1237
  const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
1284
1238
 
1239
+ var EXPRESSIONS = /*#__PURE__*/Object.freeze({
1240
+ __proto__: null,
1241
+ ARIA_ATTR: ARIA_ATTR,
1242
+ ATTR_WHITESPACE: ATTR_WHITESPACE,
1243
+ CUSTOM_ELEMENT: CUSTOM_ELEMENT,
1244
+ DATA_ATTR: DATA_ATTR,
1245
+ DOCTYPE_NAME: DOCTYPE_NAME,
1246
+ ERB_EXPR: ERB_EXPR,
1247
+ IS_ALLOWED_URI: IS_ALLOWED_URI,
1248
+ IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,
1249
+ MUSTACHE_EXPR: MUSTACHE_EXPR,
1250
+ TMPLIT_EXPR: TMPLIT_EXPR
1251
+ });
1252
+
1285
1253
  /* eslint-disable @typescript-eslint/indent */
1286
1254
  // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
1287
1255
  const NODE_TYPE = {
1288
1256
  element: 1,
1289
- attribute: 2,
1290
1257
  text: 3,
1291
- cdataSection: 4,
1292
- entityReference: 5,
1293
- // Deprecated
1294
- entityNode: 6,
1295
1258
  // Deprecated
1296
1259
  progressingInstruction: 7,
1297
1260
  comment: 8,
1298
- document: 9,
1299
- documentType: 10,
1300
- documentFragment: 11,
1301
- notation: 12 // Deprecated
1302
- };
1261
+ document: 9};
1303
1262
  const getGlobal = function getGlobal() {
1304
1263
  return typeof window === 'undefined' ? null : window;
1305
1264
  };
@@ -1357,7 +1316,7 @@ const _createHooksMap = function _createHooksMap() {
1357
1316
  function createDOMPurify() {
1358
1317
  let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
1359
1318
  const DOMPurify = root => createDOMPurify(root);
1360
- DOMPurify.version = '3.4.8';
1319
+ DOMPurify.version = '3.4.1';
1361
1320
  DOMPurify.removed = [];
1362
1321
  if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
1363
1322
  // Not running in a browser, provide a factory function
@@ -1365,29 +1324,28 @@ function createDOMPurify() {
1365
1324
  DOMPurify.isSupported = false;
1366
1325
  return DOMPurify;
1367
1326
  }
1368
- let document = window.document;
1327
+ let {
1328
+ document
1329
+ } = window;
1369
1330
  const originalDocument = document;
1370
1331
  const currentScript = originalDocument.currentScript;
1371
- window.DocumentFragment;
1372
- const HTMLTemplateElement = window.HTMLTemplateElement,
1373
- Node = window.Node,
1374
- Element = window.Element,
1375
- NodeFilter = window.NodeFilter,
1376
- _window$NamedNodeMap = window.NamedNodeMap;
1377
- _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap;
1378
- window.HTMLFormElement;
1379
- const DOMParser = window.DOMParser,
1380
- trustedTypes = window.trustedTypes;
1332
+ const {
1333
+ DocumentFragment,
1334
+ HTMLTemplateElement,
1335
+ Node,
1336
+ Element,
1337
+ NodeFilter,
1338
+ NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,
1339
+ HTMLFormElement,
1340
+ DOMParser,
1341
+ trustedTypes
1342
+ } = window;
1381
1343
  const ElementPrototype = Element.prototype;
1382
1344
  const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
1383
1345
  const remove = lookupGetter(ElementPrototype, 'remove');
1384
1346
  const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
1385
1347
  const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
1386
1348
  const getParentNode = lookupGetter(ElementPrototype, 'parentNode');
1387
- const getShadowRoot = lookupGetter(ElementPrototype, 'shadowRoot');
1388
- const getAttributes = lookupGetter(ElementPrototype, 'attributes');
1389
- const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeType') : null;
1390
- const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeName') : null;
1391
1349
  // As per issue #47, the web-components registry is inherited by a
1392
1350
  // new document created via createHTMLDocument. As per the spec
1393
1351
  // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
@@ -1402,43 +1360,33 @@ function createDOMPurify() {
1402
1360
  }
1403
1361
  let trustedTypesPolicy;
1404
1362
  let emptyHTML = '';
1405
- // Tracks whether we are already inside a call to the configured Trusted Types
1406
- // policy's `createHTML`. If the supplied `TRUSTED_TYPES_POLICY.createHTML`
1407
- // itself calls `DOMPurify.sanitize` (the cause of #1422), `sanitize` would
1408
- // re-enter the policy and recurse until the stack overflows. We detect that
1409
- // re-entry and throw a clear, actionable error instead.
1410
- let IN_POLICY_CREATE_HTML = 0;
1411
- const _createTrustedHTML = function _createTrustedHTML(html) {
1412
- if (IN_POLICY_CREATE_HTML > 0) {
1413
- throw typeErrorCreate('The configured TRUSTED_TYPES_POLICY.createHTML must not call ' + 'DOMPurify.sanitize, as that causes infinite recursion. Do not pass ' + 'a policy whose createHTML wraps DOMPurify as TRUSTED_TYPES_POLICY; ' + 'see the "DOMPurify and Trusted Types" section of the README.');
1414
- }
1415
- IN_POLICY_CREATE_HTML++;
1416
- try {
1417
- return trustedTypesPolicy.createHTML(html);
1418
- } finally {
1419
- IN_POLICY_CREATE_HTML--;
1420
- }
1421
- };
1422
- const _document = document,
1423
- implementation = _document.implementation,
1424
- createNodeIterator = _document.createNodeIterator,
1425
- createDocumentFragment = _document.createDocumentFragment,
1426
- getElementsByTagName = _document.getElementsByTagName;
1427
- const importNode = originalDocument.importNode;
1363
+ const {
1364
+ implementation,
1365
+ createNodeIterator,
1366
+ createDocumentFragment,
1367
+ getElementsByTagName
1368
+ } = document;
1369
+ const {
1370
+ importNode
1371
+ } = originalDocument;
1428
1372
  let hooks = _createHooksMap();
1429
1373
  /**
1430
1374
  * Expose whether this browser supports running the full DOMPurify.
1431
1375
  */
1432
1376
  DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;
1433
- const MUSTACHE_EXPR$1 = MUSTACHE_EXPR,
1434
- ERB_EXPR$1 = ERB_EXPR,
1435
- TMPLIT_EXPR$1 = TMPLIT_EXPR,
1436
- DATA_ATTR$1 = DATA_ATTR,
1437
- ARIA_ATTR$1 = ARIA_ATTR,
1438
- IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,
1439
- ATTR_WHITESPACE$1 = ATTR_WHITESPACE,
1440
- CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;
1441
- let IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
1377
+ const {
1378
+ MUSTACHE_EXPR,
1379
+ ERB_EXPR,
1380
+ TMPLIT_EXPR,
1381
+ DATA_ATTR,
1382
+ ARIA_ATTR,
1383
+ IS_SCRIPT_OR_DATA,
1384
+ ATTR_WHITESPACE,
1385
+ CUSTOM_ELEMENT
1386
+ } = EXPRESSIONS;
1387
+ let {
1388
+ IS_ALLOWED_URI: IS_ALLOWED_URI$1
1389
+ } = EXPRESSIONS;
1442
1390
  /**
1443
1391
  * We consider the elements and attributes below to be safe. Ideally
1444
1392
  * don't add any new ones but feel free to remove unwanted ones.
@@ -1746,47 +1694,19 @@ function createDOMPurify() {
1746
1694
  throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
1747
1695
  }
1748
1696
  // Overwrite existing TrustedTypes policy.
1749
- const previousTrustedTypesPolicy = trustedTypesPolicy;
1750
1697
  trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
1751
- // Sign local variables required by `sanitize`. If the supplied policy's
1752
- // `createHTML` is circular (i.e. it calls `DOMPurify.sanitize`), this
1753
- // throws via the re-entrancy guard. Restore the previous policy first so
1754
- // the instance is not left in a poisoned state. See #1422.
1755
- try {
1756
- emptyHTML = _createTrustedHTML('');
1757
- } catch (error) {
1758
- trustedTypesPolicy = previousTrustedTypesPolicy;
1759
- throw error;
1760
- }
1698
+ // Sign local variables required by `sanitize`.
1699
+ emptyHTML = trustedTypesPolicy.createHTML('');
1761
1700
  } else {
1762
1701
  // Uninitialized policy, attempt to initialize the internal dompurify policy.
1763
- if (trustedTypesPolicy === undefined && cfg.TRUSTED_TYPES_POLICY !== null) {
1702
+ if (trustedTypesPolicy === undefined) {
1764
1703
  trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
1765
1704
  }
1766
1705
  // If creating the internal policy succeeded sign internal variables.
1767
- // Note: a falsy `trustedTypesPolicy` (null when policy creation failed or
1768
- // was skipped via `TRUSTED_TYPES_POLICY: null`, or undefined when no
1769
- // policy has been initialized yet) must be excluded here, otherwise we
1770
- // would call `.createHTML` on a non-policy and throw. See #1422.
1771
- if (trustedTypesPolicy && typeof emptyHTML === 'string') {
1772
- emptyHTML = _createTrustedHTML('');
1706
+ if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {
1707
+ emptyHTML = trustedTypesPolicy.createHTML('');
1773
1708
  }
1774
1709
  }
1775
- /*
1776
- * Mirror the clone-before-mutate pattern already applied above for
1777
- * cfg.ADD_TAGS / cfg.ADD_ATTR: if any uponSanitize* hook is
1778
- * registered AND the set still points at the default constant,
1779
- * clone it. The hook then mutates the clone (in-call widening
1780
- * still works exactly as documented) and the next default-cfg
1781
- * call rebinds to the untouched original via the reassignment at
1782
- * the top of this function.
1783
- */
1784
- if ((hooks.uponSanitizeElement.length > 0 || hooks.uponSanitizeAttribute.length > 0) && ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
1785
- ALLOWED_TAGS = clone(ALLOWED_TAGS);
1786
- }
1787
- if (hooks.uponSanitizeAttribute.length > 0 && ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
1788
- ALLOWED_ATTR = clone(ALLOWED_ATTR);
1789
- }
1790
1710
  // Prevent further manipulation of configuration.
1791
1711
  // Not available in IE8, Safari 5, etc.
1792
1712
  if (freeze) {
@@ -1946,7 +1866,7 @@ function createDOMPurify() {
1946
1866
  // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
1947
1867
  dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
1948
1868
  }
1949
- const dirtyPayload = trustedTypesPolicy ? _createTrustedHTML(dirty) : dirty;
1869
+ const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
1950
1870
  /*
1951
1871
  * Use the DOMParser API by default, fallback later if needs be
1952
1872
  * DOMParser not work for svg when has multiple root element.
@@ -1986,142 +1906,23 @@ function createDOMPurify() {
1986
1906
  // eslint-disable-next-line no-bitwise
1987
1907
  NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);
1988
1908
  };
1989
- /**
1990
- * Strip template-engine expressions ({{...}}, ${...}, <%...%>) from the
1991
- * character data of an element subtree. Used as the final safety net for
1992
- * SAFE_FOR_TEMPLATES on every DOM-returning code path so that expressions
1993
- * which only form after text-node normalization (e.g. fragments split across
1994
- * stripped elements) cannot survive into a template-evaluating framework.
1995
- *
1996
- * Walks text/comment/CDATA/processing-instruction nodes and mutates `.data`
1997
- * in place rather than round-tripping through innerHTML. This preserves
1998
- * descendant node references (important for IN_PLACE callers), avoids a
1999
- * serialize/reparse cycle, and reads literal character data — which means
2000
- * `<%...%>` in text content matches the ERB regex against its real bytes
2001
- * instead of the HTML-entity-escaped form innerHTML would produce.
2002
- *
2003
- * Attribute values are not visited here; SAFE_FOR_TEMPLATES handling for
2004
- * attributes is performed during the per-node `_sanitizeAttributes` pass.
2005
- *
2006
- * @param node The root element whose character data should be scrubbed.
2007
- */
2008
- const _scrubTemplateExpressions2 = function _scrubTemplateExpressions(node) {
2009
- var _node$querySelectorAl, _node$querySelectorAl2;
2010
- node.normalize();
2011
- const walker = createNodeIterator.call(node.ownerDocument || node, node,
2012
- // eslint-disable-next-line no-bitwise
2013
- NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_CDATA_SECTION | NodeFilter.SHOW_PROCESSING_INSTRUCTION, null);
2014
- let currentNode = walker.nextNode();
2015
- while (currentNode) {
2016
- let data = currentNode.data;
2017
- arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
2018
- data = stringReplace(data, expr, ' ');
2019
- });
2020
- currentNode.data = data;
2021
- currentNode = walker.nextNode();
2022
- }
2023
- // NodeIterator does not descend into <template>.content per the DOM spec,
2024
- // so we must explicitly recurse into each template's content fragment,
2025
- // mirroring the approach used by _sanitizeShadowDOM.
2026
- const templates = (_node$querySelectorAl = (_node$querySelectorAl2 = node.querySelectorAll) === null || _node$querySelectorAl2 === void 0 ? void 0 : _node$querySelectorAl2.call(node, 'template')) !== null && _node$querySelectorAl !== void 0 ? _node$querySelectorAl : [];
2027
- arrayForEach(Array.from(templates), tmpl => {
2028
- if (_isDocumentFragment(tmpl.content)) {
2029
- _scrubTemplateExpressions2(tmpl.content);
2030
- }
2031
- });
2032
- };
2033
1909
  /**
2034
1910
  * _isClobbered
2035
1911
  *
2036
- * Detect DOM-clobbering on HTMLFormElement nodes. Form is the only HTML
2037
- * interface with [LegacyOverrideBuiltIns]; a descendant element with a
2038
- * `name` attribute matching a prototype property shadows that property
2039
- * on direct reads. We use this check at the IN_PLACE entry-point and
2040
- * during attribute sanitization to refuse clobbered forms.
2041
- *
2042
1912
  * @param element element to check for clobbering attacks
2043
1913
  * @return true if clobbered, false if safe
2044
1914
  */
2045
1915
  const _isClobbered = function _isClobbered(element) {
2046
- // Realm-independent tag-name probe. If we can't determine the tag
2047
- // name at all, we can't reason about clobbering — return false
2048
- // (the caller's other defences still apply).
2049
- const realTagName = getNodeName ? getNodeName(element) : null;
2050
- if (typeof realTagName !== 'string') {
2051
- return false;
2052
- }
2053
- if (transformCaseFunc(realTagName) !== 'form') {
2054
- return false;
2055
- }
2056
- return typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' ||
2057
- // Realm-safe NamedNodeMap detection: equality against the cached
2058
- // prototype getter. Clobbered .attributes (e.g. <input name="attributes">)
2059
- // makes the direct read diverge from the cached read; a clean form
2060
- // (same-realm OR foreign-realm) has both reads pointing at the same
2061
- // canonical NamedNodeMap.
2062
- element.attributes !== getAttributes(element) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function' ||
2063
- // NodeType clobbering probe. Cached Node.prototype.nodeType getter
2064
- // returns the integer 1 for any Element regardless of realm; direct
2065
- // read on a clobbered form (e.g. <input name="nodeType">) returns
2066
- // the named child element. Cheap addition — nodeType is read from
2067
- // an internal slot, no serialization cost — and removes a residual
2068
- // clobbering surface used by several mXSS / PI / comment branches
2069
- // in _sanitizeElements that compare currentNode.nodeType directly.
2070
- element.nodeType !== getNodeType(element) ||
2071
- // HTMLFormElement has [LegacyOverrideBuiltIns]: a descendant named
2072
- // "childNodes" shadows the prototype getter. Direct reads of
2073
- // form.childNodes from a clobbered form return the named child
2074
- // instead of the real NodeList, so any walk that reads it directly
2075
- // skips the form's real children. Compare the direct read to the
2076
- // cached Node.prototype getter — when the form's named-property
2077
- // getter intercepts the read, the two values differ and we flag
2078
- // the form. This catches every clobbering child type (input,
2079
- // select, etc.) regardless of whether the named child happens to
2080
- // carry a numeric .length, which a typeof-based probe would miss
2081
- // (e.g. HTMLSelectElement.length is a defined unsigned-long).
2082
- element.childNodes !== getChildNodes(element);
2083
- };
2084
- /**
2085
- * Checks whether the given value is a DocumentFragment from any realm.
2086
- *
2087
- * The realm-independent replacement reads `nodeType` through the cached
2088
- * Node.prototype getter and compares to the DOCUMENT_FRAGMENT_NODE
2089
- * constant (11). nodeType is a numeric value resolved from the node's
2090
- * internal slot, identical across realms for the same kind of node.
2091
- *
2092
- * @param value object to check
2093
- * @return true if value is a DocumentFragment-shaped node from any realm
2094
- */
2095
- const _isDocumentFragment = function _isDocumentFragment(value) {
2096
- if (!getNodeType || typeof value !== 'object' || value === null) {
2097
- return false;
2098
- }
2099
- try {
2100
- return getNodeType(value) === NODE_TYPE.documentFragment;
2101
- } catch (_) {
2102
- return false;
2103
- }
1916
+ return element instanceof HTMLFormElement && (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function');
2104
1917
  };
2105
1918
  /**
2106
- * Checks whether the given object is a DOM node, including nodes that
2107
- * originate from a different window/realm (e.g. an iframe's
2108
- * contentDocument). The previous `value instanceof Node` check was
2109
- * realm-bound: nodes from a different window failed it, causing
2110
- * sanitize() to silently stringify them and reset IN_PLACE to false,
2111
- * returning the original node unsanitized. See GHSA-4w3q-35jp-p934.
1919
+ * Checks whether the given object is a DOM node.
2112
1920
  *
2113
1921
  * @param value object to check whether it's a DOM node
2114
- * @return true if value is a DOM node from any realm
1922
+ * @return true is object is a DOM node
2115
1923
  */
2116
1924
  const _isNode = function _isNode(value) {
2117
- if (!getNodeType || typeof value !== 'object' || value === null) {
2118
- return false;
2119
- }
2120
- try {
2121
- return typeof getNodeType(value) === 'number';
2122
- } catch (_) {
2123
- return false;
2124
- }
1925
+ return typeof Node === 'function' && value instanceof Node;
2125
1926
  };
2126
1927
  function _executeHooks(hooks, currentNode, data) {
2127
1928
  arrayForEach(hooks, hook => {
@@ -2147,7 +1948,7 @@ function createDOMPurify() {
2147
1948
  return true;
2148
1949
  }
2149
1950
  /* Now let's check the element's type and name */
2150
- const tagName = transformCaseFunc(getNodeName ? getNodeName(currentNode) : currentNode.nodeName);
1951
+ const tagName = transformCaseFunc(currentNode.nodeName);
2151
1952
  /* Execute a hook if present */
2152
1953
  _executeHooks(hooks.uponSanitizeElement, currentNode, {
2153
1954
  tagName,
@@ -2184,17 +1985,10 @@ function createDOMPurify() {
2184
1985
  return false;
2185
1986
  }
2186
1987
  }
2187
- /* Keep content except for bad-listed elements.
2188
- Use the cached prototype getters exclusively — the previous code
2189
- had `|| currentNode.parentNode` / `|| currentNode.childNodes`
2190
- fallbacks, but the cached getters always return the canonical
2191
- value (or null for a real parent-less node), so the fallback
2192
- path was dead in safe cases and a clobbering surface in unsafe
2193
- ones. Falsy cached results stay falsy; the `if (childNodes &&
2194
- parentNode)` check already gates correctly. */
1988
+ /* Keep content except for bad-listed elements */
2195
1989
  if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
2196
- const parentNode = getParentNode(currentNode);
2197
- const childNodes = getChildNodes(currentNode);
1990
+ const parentNode = getParentNode(currentNode) || currentNode.parentNode;
1991
+ const childNodes = getChildNodes(currentNode) || currentNode.childNodes;
2198
1992
  if (childNodes && parentNode) {
2199
1993
  const childCount = childNodes.length;
2200
1994
  for (let i = childCount - 1; i >= 0; --i) {
@@ -2206,14 +2000,8 @@ function createDOMPurify() {
2206
2000
  _forceRemove(currentNode);
2207
2001
  return true;
2208
2002
  }
2209
- /* Check whether element has a valid namespace.
2210
- Realm-safe check (GHSA-hpcv-96wg-7vj8): use the cached Node.prototype
2211
- nodeType getter rather than `instanceof Element`, which is realm-
2212
- bound and short-circuits to false for any node minted in a different
2213
- realm — letting a foreign-realm element with a forbidden namespace
2214
- slip past the namespace check entirely. */
2215
- const nt = getNodeType ? getNodeType(currentNode) : currentNode.nodeType;
2216
- if (nt === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
2003
+ /* Check whether element has a valid namespace */
2004
+ if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
2217
2005
  _forceRemove(currentNode);
2218
2006
  return true;
2219
2007
  }
@@ -2226,7 +2014,7 @@ function createDOMPurify() {
2226
2014
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
2227
2015
  /* Get the element's text content */
2228
2016
  content = currentNode.textContent;
2229
- arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
2017
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
2230
2018
  content = stringReplace(content, expr, ' ');
2231
2019
  });
2232
2020
  if (currentNode.textContent !== content) {
@@ -2258,12 +2046,11 @@ function createDOMPurify() {
2258
2046
  if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
2259
2047
  return false;
2260
2048
  }
2261
- const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
2262
2049
  /* Allow valid data-* attributes: At least one character after "-"
2263
2050
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
2264
2051
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
2265
2052
  We don't need to check the value; it's always URI safe. */
2266
- if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) ; else if (!nameIsPermitted || FORBID_ATTR[lcName]) {
2053
+ if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
2267
2054
  if (
2268
2055
  // First condition does a very basic check if a) it's basically a valid custom element tagname AND
2269
2056
  // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
@@ -2275,7 +2062,7 @@ function createDOMPurify() {
2275
2062
  return false;
2276
2063
  }
2277
2064
  /* Check value is safe. First, is attr inert? If so, is safe */
2278
- } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ; else if (value) {
2065
+ } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) {
2279
2066
  return false;
2280
2067
  } else ;
2281
2068
  return true;
@@ -2293,7 +2080,7 @@ function createDOMPurify() {
2293
2080
  * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
2294
2081
  */
2295
2082
  const _isBasicCustomElement = function _isBasicCustomElement(tagName) {
2296
- return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName);
2083
+ return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT, tagName);
2297
2084
  };
2298
2085
  /**
2299
2086
  * _sanitizeAttributes
@@ -2308,7 +2095,9 @@ function createDOMPurify() {
2308
2095
  const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
2309
2096
  /* Execute a hook if present */
2310
2097
  _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
2311
- const attributes = currentNode.attributes;
2098
+ const {
2099
+ attributes
2100
+ } = currentNode;
2312
2101
  /* Check if we have attributes; if not we might have a text node */
2313
2102
  if (!attributes || _isClobbered(currentNode)) {
2314
2103
  return;
@@ -2324,9 +2113,11 @@ function createDOMPurify() {
2324
2113
  /* Go backwards over all attributes; safely remove bad ones */
2325
2114
  while (l--) {
2326
2115
  const attr = attributes[l];
2327
- const name = attr.name,
2328
- namespaceURI = attr.namespaceURI,
2329
- attrValue = attr.value;
2116
+ const {
2117
+ name,
2118
+ namespaceURI,
2119
+ value: attrValue
2120
+ } = attr;
2330
2121
  const lcName = transformCaseFunc(name);
2331
2122
  const initValue = attrValue;
2332
2123
  let value = name === 'value' ? initValue : stringTrim(initValue);
@@ -2374,7 +2165,7 @@ function createDOMPurify() {
2374
2165
  }
2375
2166
  /* Sanitize attribute content to be template-safe */
2376
2167
  if (SAFE_FOR_TEMPLATES) {
2377
- arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
2168
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
2378
2169
  value = stringReplace(value, expr, ' ');
2379
2170
  });
2380
2171
  }
@@ -2390,7 +2181,7 @@ function createDOMPurify() {
2390
2181
  switch (trustedTypes.getAttributeType(lcTag, lcName)) {
2391
2182
  case 'TrustedHTML':
2392
2183
  {
2393
- value = _createTrustedHTML(value);
2184
+ value = trustedTypesPolicy.createHTML(value);
2394
2185
  break;
2395
2186
  }
2396
2187
  case 'TrustedScriptURL':
@@ -2440,98 +2231,14 @@ function createDOMPurify() {
2440
2231
  _sanitizeElements(shadowNode);
2441
2232
  /* Check attributes next */
2442
2233
  _sanitizeAttributes(shadowNode);
2443
- /* Deep shadow DOM detected.
2444
- Realm-safe check (GHSA-hpcv-96wg-7vj8): use nodeType against the
2445
- DOCUMENT_FRAGMENT_NODE constant rather than instanceof, so we
2446
- recurse into <template>.content from foreign realms too. */
2447
- if (_isDocumentFragment(shadowNode.content)) {
2234
+ /* Deep shadow DOM detected */
2235
+ if (shadowNode.content instanceof DocumentFragment) {
2448
2236
  _sanitizeShadowDOM2(shadowNode.content);
2449
2237
  }
2450
- /* An element iterated here may itself host an attached
2451
- shadow root. The default NodeIterator does not enter shadow
2452
- trees, so a shadow root nested inside template.content was
2453
- previously reached by no walk at all (the pre-pass at
2454
- _sanitizeAttachedShadowRoots descends via childNodes, which
2455
- doesn't enter template.content; the template-content recursion
2456
- above iterates the content but never inspected shadowRoot).
2457
- Walk it explicitly. The nodeType guard avoids reading
2458
- shadowRoot off text / comment / CDATA / PI nodes that the
2459
- iterator also surfaces. */
2460
- const shadowNodeType = getNodeType ? getNodeType(shadowNode) : shadowNode.nodeType;
2461
- if (shadowNodeType === NODE_TYPE.element) {
2462
- const innerSr = getShadowRoot ? getShadowRoot(shadowNode) : shadowNode.shadowRoot;
2463
- if (_isDocumentFragment(innerSr)) {
2464
- _sanitizeAttachedShadowRoots2(innerSr);
2465
- _sanitizeShadowDOM2(innerSr);
2466
- }
2467
- }
2468
2238
  }
2469
2239
  /* Execute a hook if present */
2470
2240
  _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
2471
2241
  };
2472
- /**
2473
- * _sanitizeAttachedShadowRoots
2474
- *
2475
- * Walks `root` and feeds every attached shadow root we encounter into
2476
- * the existing _sanitizeShadowDOM pipeline. The default node iterator
2477
- * does not descend into shadow trees, so nodes inside an attached
2478
- * shadow root would otherwise be skipped entirely.
2479
- *
2480
- * Two real input paths put attached shadow roots in front of us:
2481
- * 1. IN_PLACE on a DOM node that already has shadow roots attached.
2482
- * 2. DOM-node input where importNode(dirty, true) deep-clones the
2483
- * shadow root because it was created with `clonable: true`.
2484
- *
2485
- * This pass runs once, up front, so the main iteration loop (and the
2486
- * existing _sanitizeShadowDOM template-content recursion) stay
2487
- * untouched — string-input paths are not affected.
2488
- *
2489
- * @param root the subtree root to walk for attached shadow roots
2490
- */
2491
- const _sanitizeAttachedShadowRoots2 = function _sanitizeAttachedShadowRoots(root) {
2492
- const nodeType = getNodeType ? getNodeType(root) : root.nodeType;
2493
- if (nodeType === NODE_TYPE.element) {
2494
- const sr = getShadowRoot ? getShadowRoot(root) : root.shadowRoot;
2495
- // Realm-safe check (GHSA-hpcv-96wg-7vj8): use nodeType-based
2496
- // detection rather than `instanceof DocumentFragment`, which is
2497
- // realm-bound and silently skipped shadow roots whose host element
2498
- // belonged to a foreign realm (e.g. iframe.contentDocument
2499
- // attachShadow). A foreign-realm ShadowRoot extends the foreign
2500
- // realm's DocumentFragment, not ours, so the old instanceof check
2501
- // returned false and the shadow subtree was never walked.
2502
- if (_isDocumentFragment(sr)) {
2503
- // Recurse first so that nested shadow roots are reached even if
2504
- // _sanitizeShadowDOM removes hosts at this level.
2505
- _sanitizeAttachedShadowRoots2(sr);
2506
- _sanitizeShadowDOM2(sr);
2507
- }
2508
- }
2509
- // Snapshot children before recursing. Sanitization of one subtree
2510
- // (e.g. via an uponSanitizeShadowNode hook) may detach siblings,
2511
- // and naive nextSibling traversal would silently skip the rest of
2512
- // the list once a node is detached.
2513
- const childNodes = getChildNodes ? getChildNodes(root) : root.childNodes;
2514
- if (!childNodes) {
2515
- return;
2516
- }
2517
- const snapshot = [];
2518
- arrayForEach(childNodes, child => {
2519
- arrayPush(snapshot, child);
2520
- });
2521
- for (const child of snapshot) {
2522
- _sanitizeAttachedShadowRoots2(child);
2523
- }
2524
- /* When the root is a <template>, also descend into root.content */
2525
- if (nodeType === NODE_TYPE.element) {
2526
- const rootName = getNodeName ? getNodeName(root) : null;
2527
- if (typeof rootName === 'string' && transformCaseFunc(rootName) === 'template') {
2528
- const content = root.content;
2529
- if (_isDocumentFragment(content)) {
2530
- _sanitizeAttachedShadowRoots2(content);
2531
- }
2532
- }
2533
- }
2534
- };
2535
2242
  // eslint-disable-next-line complexity
2536
2243
  DOMPurify.sanitize = function (dirty) {
2537
2244
  let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -2568,35 +2275,15 @@ function createDOMPurify() {
2568
2275
  IN_PLACE = false;
2569
2276
  }
2570
2277
  if (IN_PLACE) {
2571
- /* Do some early pre-sanitization to avoid unsafe root nodes.
2572
- Read nodeName through the cached prototype getter — a clobbering
2573
- child named "nodeName" on the form root would otherwise shadow
2574
- the property and let this check skip the root-allowlist
2575
- validation entirely. */
2576
- const nn = getNodeName ? getNodeName(dirty) : dirty.nodeName;
2278
+ /* Do some early pre-sanitization to avoid unsafe root nodes */
2279
+ const nn = dirty.nodeName;
2577
2280
  if (typeof nn === 'string') {
2578
2281
  const tagName = transformCaseFunc(nn);
2579
2282
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
2580
2283
  throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
2581
2284
  }
2582
2285
  }
2583
- /* Pre-flight the root through _isClobbered. The iterator-driven
2584
- removal path can not detach a parent-less root: _forceRemove
2585
- falls through to Element.prototype.remove(), which per spec
2586
- is a no-op on a node with no parent. A clobbered root would
2587
- then survive the main loop with its attributes uninspected,
2588
- because _sanitizeAttributes early-returns on _isClobbered. The
2589
- result would be an attacker-controlled form, complete with any
2590
- event-handler attributes the caller passed in, handed back to
2591
- the application unsanitized. Refuse to sanitize such a root
2592
- the same way we refuse a forbidden tag. GHSA-r47g-fvhr-h676. */
2593
- if (_isClobbered(dirty)) {
2594
- throw typeErrorCreate('root node is clobbered and cannot be sanitized in-place');
2595
- }
2596
- /* Sanitize attached shadow roots before the main iterator runs.
2597
- The iterator does not descend into shadow trees. */
2598
- _sanitizeAttachedShadowRoots2(dirty);
2599
- } else if (_isNode(dirty)) {
2286
+ } else if (dirty instanceof Node) {
2600
2287
  /* If dirty is a DOM element, append to an empty document to avoid
2601
2288
  elements being stripped by the parser */
2602
2289
  body = _initDocument('<!---->');
@@ -2610,18 +2297,12 @@ function createDOMPurify() {
2610
2297
  // eslint-disable-next-line unicorn/prefer-dom-node-append
2611
2298
  body.appendChild(importedNode);
2612
2299
  }
2613
- /* Clonable shadow roots are deep-cloned by importNode(); sanitize
2614
- them before the main iterator runs, since the iterator does not
2615
- descend into shadow trees. The walk routes every read through a
2616
- cached prototype getter so clobbering descendants on a form root
2617
- cannot hide a shadow host from this pass. */
2618
- _sanitizeAttachedShadowRoots2(importedNode);
2619
2300
  } else {
2620
2301
  /* Exit directly if we have nothing to do */
2621
2302
  if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
2622
2303
  // eslint-disable-next-line unicorn/prefer-includes
2623
2304
  dirty.indexOf('<') === -1) {
2624
- return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(dirty) : dirty;
2305
+ return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
2625
2306
  }
2626
2307
  /* Initialize the document to work on */
2627
2308
  body = _initDocument(dirty);
@@ -2642,25 +2323,24 @@ function createDOMPurify() {
2642
2323
  _sanitizeElements(currentNode);
2643
2324
  /* Check attributes next */
2644
2325
  _sanitizeAttributes(currentNode);
2645
- /* Shadow DOM detected, sanitize it.
2646
- Realm-safe check (GHSA-hpcv-96wg-7vj8): nodeType-based detection
2647
- instead of instanceof, so foreign-realm <template>.content is
2648
- walked correctly. */
2649
- if (_isDocumentFragment(currentNode.content)) {
2326
+ /* Shadow DOM detected, sanitize it */
2327
+ if (currentNode.content instanceof DocumentFragment) {
2650
2328
  _sanitizeShadowDOM2(currentNode.content);
2651
2329
  }
2652
2330
  }
2653
2331
  /* If we sanitized `dirty` in-place, return it. */
2654
2332
  if (IN_PLACE) {
2655
- if (SAFE_FOR_TEMPLATES) {
2656
- _scrubTemplateExpressions2(dirty);
2657
- }
2658
2333
  return dirty;
2659
2334
  }
2660
2335
  /* Return sanitized string or DOM */
2661
2336
  if (RETURN_DOM) {
2662
2337
  if (SAFE_FOR_TEMPLATES) {
2663
- _scrubTemplateExpressions2(body);
2338
+ body.normalize();
2339
+ let html = body.innerHTML;
2340
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
2341
+ html = stringReplace(html, expr, ' ');
2342
+ });
2343
+ body.innerHTML = html;
2664
2344
  }
2665
2345
  if (RETURN_DOM_FRAGMENT) {
2666
2346
  returnNode = createDocumentFragment.call(body.ownerDocument);
@@ -2690,11 +2370,11 @@ function createDOMPurify() {
2690
2370
  }
2691
2371
  /* Sanitize final string template-safe */
2692
2372
  if (SAFE_FOR_TEMPLATES) {
2693
- arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
2373
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
2694
2374
  serializedHTML = stringReplace(serializedHTML, expr, ' ');
2695
2375
  });
2696
2376
  }
2697
- return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(serializedHTML) : serializedHTML;
2377
+ return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
2698
2378
  };
2699
2379
  DOMPurify.setConfig = function () {
2700
2380
  let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -2741,7 +2421,6 @@ var purify = createDOMPurify();
2741
2421
  * 预设主题配置
2742
2422
  * 提供多种常用主题,用户可以直接使用或自定义
2743
2423
  */
2744
-
2745
2424
  /**
2746
2425
  * 默认主题(蓝色渐变)
2747
2426
  */
@@ -2792,7 +2471,6 @@ const DEFAULT_THEME = {
2792
2471
  button: '0 4px 12px rgba(24, 144, 255, 0.35)'
2793
2472
  }
2794
2473
  };
2795
-
2796
2474
  /**
2797
2475
  * 深色主题
2798
2476
  */
@@ -2843,7 +2521,6 @@ const DARK_THEME = {
2843
2521
  button: '0 4px 12px rgba(24, 144, 255, 0.4)'
2844
2522
  }
2845
2523
  };
2846
-
2847
2524
  /**
2848
2525
  * 清新主题(绿色系)
2849
2526
  */
@@ -2894,7 +2571,6 @@ const FRESH_THEME = {
2894
2571
  button: '0 4px 12px rgba(82, 196, 26, 0.35)'
2895
2572
  }
2896
2573
  };
2897
-
2898
2574
  /**
2899
2575
  * 活力主题(橙色系)
2900
2576
  */
@@ -2945,7 +2621,6 @@ const VIBRANT_THEME = {
2945
2621
  button: '0 4px 12px rgba(250, 140, 22, 0.35)'
2946
2622
  }
2947
2623
  };
2948
-
2949
2624
  /**
2950
2625
  * 浪漫主题(粉色系)
2951
2626
  */
@@ -2996,7 +2671,6 @@ const ROMANTIC_THEME = {
2996
2671
  button: '0 4px 12px rgba(235, 47, 150, 0.35)'
2997
2672
  }
2998
2673
  };
2999
-
3000
2674
  /**
3001
2675
  * 紫色主题(优雅神秘)
3002
2676
  */
@@ -3047,7 +2721,6 @@ const PURPLE_THEME = {
3047
2721
  button: '0 4px 12px rgba(114, 46, 209, 0.35)'
3048
2722
  }
3049
2723
  };
3050
-
3051
2724
  /**
3052
2725
  * 海洋主题(深蓝深海)
3053
2726
  */
@@ -3098,7 +2771,6 @@ const OCEAN_THEME = {
3098
2771
  button: '0 4px 12px rgba(0, 119, 182, 0.35)'
3099
2772
  }
3100
2773
  };
3101
-
3102
2774
  /**
3103
2775
  * 暮光主题(紫罗兰渐变)
3104
2776
  */
@@ -3149,7 +2821,6 @@ const TWILIGHT_THEME = {
3149
2821
  button: '0 4px 12px rgba(147, 51, 234, 0.35)'
3150
2822
  }
3151
2823
  };
3152
-
3153
2824
  /**
3154
2825
  * 薄荷主题(青绿色)
3155
2826
  */
@@ -3200,7 +2871,6 @@ const MINT_THEME = {
3200
2871
  button: '0 4px 12px rgba(20, 184, 166, 0.35)'
3201
2872
  }
3202
2873
  };
3203
-
3204
2874
  /**
3205
2875
  * 玫瑰主题(深红色)
3206
2876
  */
@@ -3251,7 +2921,6 @@ const ROSE_THEME = {
3251
2921
  button: '0 4px 12px rgba(225, 29, 72, 0.35)'
3252
2922
  }
3253
2923
  };
3254
-
3255
2924
  /**
3256
2925
  * 极光主题(蓝绿渐变)
3257
2926
  */
@@ -3302,7 +2971,6 @@ const AURORA_THEME = {
3302
2971
  button: '0 4px 12px rgba(14, 165, 233, 0.35)'
3303
2972
  }
3304
2973
  };
3305
-
3306
2974
  /**
3307
2975
  * 薰衣草主题(淡紫色)
3308
2976
  */
@@ -3353,7 +3021,6 @@ const LAVENDER_THEME = {
3353
3021
  button: '0 4px 12px rgba(139, 92, 246, 0.35)'
3354
3022
  }
3355
3023
  };
3356
-
3357
3024
  /**
3358
3025
  * 珊瑚主题(粉橙色)
3359
3026
  */
@@ -3404,7 +3071,6 @@ const CORAL_THEME = {
3404
3071
  button: '0 4px 12px rgba(249, 115, 22, 0.35)'
3405
3072
  }
3406
3073
  };
3407
-
3408
3074
  /**
3409
3075
  * 翡翠主题(深绿色)
3410
3076
  */
@@ -3455,7 +3121,6 @@ const JADE_THEME = {
3455
3121
  button: '0 4px 12px rgba(5, 150, 105, 0.35)'
3456
3122
  }
3457
3123
  };
3458
-
3459
3124
  /**
3460
3125
  * 星空主题(深蓝紫色)
3461
3126
  */
@@ -3506,7 +3171,6 @@ const STARSKY_THEME = {
3506
3171
  button: '0 4px 12px rgba(99, 102, 241, 0.4)'
3507
3172
  }
3508
3173
  };
3509
-
3510
3174
  /**
3511
3175
  * 日落主题(暖色调)
3512
3176
  */
@@ -3557,7 +3221,6 @@ const SUNSET_THEME = {
3557
3221
  button: '0 4px 12px rgba(234, 88, 12, 0.35)'
3558
3222
  }
3559
3223
  };
3560
-
3561
3224
  /**
3562
3225
  * 所有预设主题列表
3563
3226
  */
@@ -3583,27 +3246,21 @@ const PRESET_THEMES = {
3583
3246
  /**
3584
3247
  * AIChatDialog - 纯JavaScript实现的AI对话组件 (Web Components)
3585
3248
  * 样式与功能完全对齐 Vue 版本(1:1 复刻)
3586
- *
3249
+ *
3587
3250
  * @author IBC AI Team
3588
- * @version 2.0.5
3251
+ * @version 2.1.0
3589
3252
  */
3590
-
3591
-
3253
+ // 导入 marked Markdown 解析库 + DOMPurify XSS防护 + 主题配置
3592
3254
  // 运行时占位符(对齐 portal)
3593
3255
  const RUNTIME_PLACEHOLDERS = ['请求已受理', '任务已受理', '正在思考', '正在执行', '结果处理中', '已进入助手运行时', '任务运行时', 'SSE 连接已建立'];
3594
3256
  const DEFAULT_DIALOG_TOP = '96px';
3595
-
3596
3257
  // ========== marked 配置(安全且功能完整) ==========
3258
+ // marked v18 移除了 headerIds/mangle,仅保留 breaks 和 gfm
3597
3259
  g.setOptions({
3598
3260
  breaks: true,
3599
3261
  // 支持GFM换行(单换行变<br>)
3600
- gfm: true,
3601
- // GitHub Flavored Markdown
3602
- headerIds: false,
3603
- // 不生成标题id
3604
- mangle: false // 不转义邮箱
3605
- });
3606
-
3262
+ gfm: true // GitHub Flavored Markdown
3263
+ } /* marked v18 types are strict */);
3607
3264
  // Vue themes.js 的 camelCase key → JS _themeVars CSS变量名 映射表
3608
3265
  const THEME_COLOR_KEY_MAP = {
3609
3266
  primary: '--ai-primary',
@@ -3632,14 +3289,82 @@ const THEME_COLOR_KEY_MAP = {
3632
3289
  error: '--ai-error',
3633
3290
  warning: '--ai-warning'
3634
3291
  };
3635
-
3636
3292
  // ========== 16种预设主题(与Vue版themes.js完全一致) ==========
3637
3293
  class AIChatDialog extends HTMLElement {
3294
+ // ====== 类型声明(HTMLElement 子类必需) ======
3638
3295
  static get observedAttributes() {
3639
3296
  return ['visible'];
3640
3297
  }
3641
3298
  constructor() {
3642
3299
  super();
3300
+ // 核心状态
3301
+ this._messages = [];
3302
+ this._isLoading = false;
3303
+ this._config = null;
3304
+ this._mockMode = false;
3305
+ this._isDragging = false;
3306
+ this._isExpanded = false;
3307
+ this._chatClient = null;
3308
+ this._attachments = [];
3309
+ this._dragStartX = 0;
3310
+ this._dragStartY = 0;
3311
+ this._dialogX = 0;
3312
+ this._dialogY = 0;
3313
+ this._appDetail = null;
3314
+ this._historyVisible = false;
3315
+ this._historyRecords = [];
3316
+ this._historyLoading = false;
3317
+ this._historyLoaded = false;
3318
+ this._historyPageIndex = 1;
3319
+ this._historyHasMore = false;
3320
+ this._isMobile = false;
3321
+ // 流式渲染
3322
+ this._streamTextEl = null;
3323
+ this._streamInitDone = false;
3324
+ this._streamFullText = '';
3325
+ this._streamVisibleLength = 0;
3326
+ this._streamTypeRaf = null;
3327
+ this._streaming = false;
3328
+ // 运行时面板
3329
+ this._runtimePanelEl = null;
3330
+ this._runtimeEventsContainerEl = null;
3331
+ this._runtimeStatusEl = null;
3332
+ this._runtimeCountEl = null;
3333
+ // 页面上下文
3334
+ this._context = {};
3335
+ // 主题
3336
+ this._themeVars = {};
3337
+ // 事件处理器引用(用于清理)
3338
+ this._handleOnline = null;
3339
+ this._handleOffline = null;
3340
+ this._handleResize = null;
3341
+ // DOM 缓存引用
3342
+ this._dialog = null;
3343
+ this._body = null;
3344
+ this._input = null;
3345
+ this._sendBtn = null;
3346
+ this._attachBtn = null;
3347
+ this._attachmentInput = null;
3348
+ this._closeBtn = null;
3349
+ this._expandBtn = null;
3350
+ this._newChatBtn = null;
3351
+ this._historyBtn = null;
3352
+ this._floatBtn = null;
3353
+ this._inputContainer = null;
3354
+ // 会话
3355
+ this._conversationId = null;
3356
+ // 防抖
3357
+ this._lastSendTime = 0;
3358
+ // 拖拽处理器引用
3359
+ this._dragMouseDownHandler = null;
3360
+ this._dragMouseMoveHandler = null;
3361
+ this._dragMouseUpHandler = null;
3362
+ this._dragTouchStartHandler = null;
3363
+ this._dragTouchMoveHandler = null;
3364
+ this._dragTouchEndHandler = null;
3365
+ this._dragInitialized = false;
3366
+ // 错误标记
3367
+ this._ERROR_CONTENT_PATTERNS = ['(请求超时', '(等待AI处理', '(无回复)', '(已停止)', '(AI 处理超时', '错误:', '网络错误:', '抱歉,'];
3643
3368
  this.attachShadow({
3644
3369
  mode: 'open'
3645
3370
  });
@@ -3678,7 +3403,6 @@ class AIChatDialog extends HTMLElement {
3678
3403
  this._runtimeCountEl = null;
3679
3404
  // P3: 页面上下文数据(宿主页面选中的数据)
3680
3405
  this._context = {};
3681
-
3682
3406
  // ====== 默认主题配置(与 themes.js DEFAULT_THEME 完全一致) ======
3683
3407
  this._themeVars = {
3684
3408
  '--ai-primary': '#1890ff',
@@ -3721,9 +3445,7 @@ class AIChatDialog extends HTMLElement {
3721
3445
  this.render();
3722
3446
  this.bindEvents();
3723
3447
  }
3724
-
3725
3448
  // ==================== 生命周期 ====================
3726
-
3727
3449
  connectedCallback() {
3728
3450
  // P1-8: 网络状态监控(与Vue版一致)
3729
3451
  this._handleOnline = () => {
@@ -3736,12 +3458,11 @@ class AIChatDialog extends HTMLElement {
3736
3458
  tip.className = 'network-tip';
3737
3459
  tip.textContent = '网络连接已断开,请检查网络后重试';
3738
3460
  this._dialog?.prepend(tip);
3739
- setTimeout(() => tip.remove(), 5000);
3461
+ window.setTimeout(() => tip.remove(), 5000);
3740
3462
  }
3741
3463
  };
3742
3464
  window.addEventListener('online', this._handleOnline);
3743
3465
  window.addEventListener('offline', this._handleOffline);
3744
-
3745
3466
  // P2-17: 移动端环境检测(与Vue版 detectEnvironment 一致)
3746
3467
  this._detectMobile();
3747
3468
  // P2-17: 窗口resize时重新检测移动端
@@ -3754,7 +3475,6 @@ class AIChatDialog extends HTMLElement {
3754
3475
  }
3755
3476
  };
3756
3477
  window.addEventListener('resize', this._handleResize);
3757
-
3758
3478
  // 恢复后台Token刷新定时器(SPA路由切换后 re-attach 场景)
3759
3479
  if (this._chatClient) this._chatClient.startBackgroundRefresh();
3760
3480
  }
@@ -3772,7 +3492,6 @@ class AIChatDialog extends HTMLElement {
3772
3492
  this._chatClient.cancelCurrentRequest();
3773
3493
  }
3774
3494
  }
3775
-
3776
3495
  // P2-17: 移动端4维检测(与Vue版 isMobileDevice 计算属性完全一致)
3777
3496
  _detectMobile() {
3778
3497
  // 1. 优先使用显式配置
@@ -3780,31 +3499,25 @@ class AIChatDialog extends HTMLElement {
3780
3499
  this._isMobile = !!this._config.mobileMode;
3781
3500
  return;
3782
3501
  }
3783
-
3784
3502
  // 2. 微信小程序环境检测
3785
3503
  if (typeof wx !== 'undefined' && wx.getSystemInfoSync) {
3786
3504
  this._isMobile = true;
3787
3505
  return;
3788
3506
  }
3789
-
3790
3507
  // 3. 浏览器环境
3791
3508
  if (typeof window === 'undefined') {
3792
3509
  this._isMobile = false;
3793
3510
  return;
3794
3511
  }
3795
-
3796
3512
  // 4. User Agent 正则匹配
3797
3513
  const ua = navigator.userAgent || '';
3798
3514
  const isMobileUA = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua);
3799
-
3800
3515
  // 5. 屏幕宽度 < 768px + 触摸支持
3801
3516
  const isSmallScreen = window.innerWidth < 768;
3802
3517
  const hasTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
3803
-
3804
3518
  // 综合判断:UA匹配 或 (小屏幕+触摸)
3805
3519
  this._isMobile = isMobileUA || isSmallScreen && hasTouch;
3806
3520
  }
3807
-
3808
3521
  // P2-17: 应用移动端/桌面端布局(自动全屏或恢复浮动气泡)
3809
3522
  _applyMobileLayout() {
3810
3523
  if (!this._dialog) return;
@@ -3849,9 +3562,7 @@ class AIChatDialog extends HTMLElement {
3849
3562
  if (visible) this.showDialog();else this.hideDialog();
3850
3563
  }
3851
3564
  }
3852
-
3853
3565
  // ==================== 属性访问器 ====================
3854
-
3855
3566
  get visible() {
3856
3567
  return this.hasAttribute('visible');
3857
3568
  }
@@ -3867,9 +3578,7 @@ class AIChatDialog extends HTMLElement {
3867
3578
  get config() {
3868
3579
  return this._config;
3869
3580
  }
3870
-
3871
3581
  // ==================== 公共API ====================
3872
-
3873
3582
  init(config = {}) {
3874
3583
  this._config = {
3875
3584
  apiBaseUrl: '',
@@ -3925,6 +3634,8 @@ class AIChatDialog extends HTMLElement {
3925
3634
  debug: false,
3926
3635
  // P4: 自定义消息操作按钮 — 返回数组 [{label, className?, onClick}] 在 AI 消息下方渲染
3927
3636
  onMessageActions: null,
3637
+ // P5: 浮窗按钮显隐控制 — false 时浮窗按钮隐藏,对话框只能通过 API 打开(登录页等场景)
3638
+ floatButton: true,
3928
3639
  suggestions: [{
3929
3640
  label: '帮我购买一台轻量应用服务器用于部署应用',
3930
3641
  value: '帮我购买一台轻量应用服务器用于部署应用'
@@ -3938,6 +3649,7 @@ class AIChatDialog extends HTMLElement {
3938
3649
  this._chatClient = new AIChatClient(this._config);
3939
3650
  if (this._conversationId) this._chatClient.setConversationId(this._conversationId);
3940
3651
  this.applyConfig();
3652
+ this.setFloatButtonVisible(this._config.floatButton !== false);
3941
3653
  // P1-2 fix: 在 _config 就绪后初始化拖拽,以正确读取 enableDrag
3942
3654
  if (this._config?.enableDrag !== false && this.getAttribute('mode') !== 'inline' && !this._dragInitialized) {
3943
3655
  this.initDraggable();
@@ -3974,6 +3686,21 @@ class AIChatDialog extends HTMLElement {
3974
3686
  if (this._chatClient) this._chatClient.dispose();
3975
3687
  if (this.parentNode) this.parentNode.removeChild(this);
3976
3688
  }
3689
+ // P5: 运行时动态控制浮窗按钮显隐(SPA 路由切换场景:登录页隐藏,业务页显示)
3690
+ setFloatButtonVisible(show) {
3691
+ if (!this._config) this.init({
3692
+ floatButton: show
3693
+ });else this._config.floatButton = show;
3694
+ const btn = this.shadowRoot?.querySelector('.float-button');
3695
+ if (btn) {
3696
+ const dialog = this.shadowRoot?.querySelector('.ai-chat-dialog');
3697
+ const isOpen = dialog?.classList.contains('dialog-visible');
3698
+ if (!isOpen) {
3699
+ btn.style.display = show ? 'flex' : 'none';
3700
+ }
3701
+ }
3702
+ return this;
3703
+ }
3977
3704
  addMessage(message) {
3978
3705
  if (!message || !message.content) return this;
3979
3706
  const msg = {
@@ -4016,6 +3743,7 @@ class AIChatDialog extends HTMLElement {
4016
3743
  if (!this._config.appId && this._config.agentAppId) this._config.appId = this._config.agentAppId;
4017
3744
  if (this._chatClient) this._chatClient.updateConfig(this._config);
4018
3745
  this.loadAppDetail();
3746
+ if ('floatButton' in config) this.setFloatButtonVisible(this._config.floatButton !== false);
4019
3747
  }
4020
3748
  this.applyConfig();
4021
3749
  return this;
@@ -4028,7 +3756,6 @@ class AIChatDialog extends HTMLElement {
4028
3756
  this._mockMode = false;
4029
3757
  return this;
4030
3758
  }
4031
-
4032
3759
  /**
4033
3760
  * 设置页面上下文数据(宿主页面选中的数据,随每次请求发送)
4034
3761
  * @param {Object} context - 上下文数据对象,传 null 清空
@@ -4040,7 +3767,6 @@ class AIChatDialog extends HTMLElement {
4040
3767
  } : {};
4041
3768
  return this;
4042
3769
  }
4043
-
4044
3770
  /**
4045
3771
  * 获取当前上下文数据
4046
3772
  * @returns {Object}
@@ -4050,7 +3776,6 @@ class AIChatDialog extends HTMLElement {
4050
3776
  ...this._context
4051
3777
  };
4052
3778
  }
4053
-
4054
3779
  /**
4055
3780
  * 外部触发表态发送(业务层主动调用,如点击外部按钮触发 AI 请求)
4056
3781
  * @param {string} text - 要发送的消息内容
@@ -4066,9 +3791,7 @@ class AIChatDialog extends HTMLElement {
4066
3791
  this.handleSend();
4067
3792
  return this;
4068
3793
  }
4069
-
4070
3794
  // ==================== 显示/隐藏 ====================
4071
-
4072
3795
  showDialog() {
4073
3796
  const dialog = this.shadowRoot.querySelector('.ai-chat-dialog');
4074
3797
  const btn = this.shadowRoot.querySelector('.float-button');
@@ -4081,11 +3804,9 @@ class AIChatDialog extends HTMLElement {
4081
3804
  const dialog = this.shadowRoot.querySelector('.ai-chat-dialog');
4082
3805
  const btn = this.shadowRoot.querySelector('.float-button');
4083
3806
  if (dialog) dialog.classList.remove('dialog-visible');
4084
- if (btn) btn.style.display = 'flex';
3807
+ if (btn) btn.style.display = this._config?.floatButton !== false ? 'flex' : 'none';
4085
3808
  }
4086
-
4087
3809
  // ==================== 渲染(完整CSS对齐theme.css) ====================
4088
-
4089
3810
  render() {
4090
3811
  const cssVarsStr = Object.entries(this._themeVars).map(([k, v]) => `${k}:${v};`).join('\n ');
4091
3812
  this.shadowRoot.innerHTML = `
@@ -5176,16 +4897,43 @@ class AIChatDialog extends HTMLElement {
5176
4897
  :host(.dark-theme) blockquote { background: rgba(110, 168, 254, 0.08); }
5177
4898
  :host(.dark-theme) th { background: rgba(110, 168, 254, 0.12); }
5178
4899
  :host(.dark-theme) hr { border-top-color: var(--ai-border); }
4900
+
4901
+ /* ========== 插槽样式(自定义内容区域) ========== */
4902
+ /* header-title 插槽 */
4903
+ ::slotted([slot="header-title"]) {
4904
+ font-size: var(--ai-font-title, 15px);
4905
+ font-weight: 650;
4906
+ color: var(--ai-text);
4907
+ overflow: hidden;
4908
+ text-overflow: ellipsis;
4909
+ white-space: nowrap;
4910
+ }
4911
+ /* input-prepend 插槽 — 输入区上方附加内容 */
4912
+ ::slotted([slot="input-prepend"]) {
4913
+ display: block;
4914
+ padding: 0 4px 8px;
4915
+ }
4916
+ /* footer 插槽 */
4917
+ ::slotted([slot="footer"]) {
4918
+ display: flex;
4919
+ justify-content: space-between;
4920
+ gap: 12px;
4921
+ color: #b5bbc5;
4922
+ font-size: 12px;
4923
+ line-height: 1;
4924
+ }
5179
4925
  </style>
5180
4926
 
5181
4927
  <div class="ai-float-container">
5182
4928
  <!-- 对话框 -->
5183
4929
  <div class="ai-chat-dialog">
5184
- <!-- 头部(含展开/关闭按钮) -->
5185
- <div class="dialog-header">
5186
- <div class="header-left">
5187
- <span class="header-title">${this.escapeHtml(this._config?.title || 'AI 助手')}</span>
5188
- </div>
4930
+ <!-- 头部(含展开/关闭按钮) -->
4931
+ <div class="dialog-header">
4932
+ <div class="header-left">
4933
+ <slot name="header-title">
4934
+ <span class="header-title">${this.escapeHtml(this._config?.title || 'AI 助手')}</span>
4935
+ </slot>
4936
+ </div>
5189
4937
  <div class="header-right">
5190
4938
  <button class="new-chat-btn history-btn" type="button" title="历史记录" aria-label="历史记录">
5191
4939
  <svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 4v5h5"/><path d="M12 7v5l3 2"/></svg>
@@ -5209,9 +4957,10 @@ class AIChatDialog extends HTMLElement {
5209
4957
  <!-- 消息区域 -->
5210
4958
  <div class="dialog-body" id="messagesContainer"></div>
5211
4959
 
5212
- <!-- 输入区域 -->
5213
- <div class="dialog-footer">
5214
- <div class="input-container" id="inputContainer">
4960
+ <!-- 输入区域 -->
4961
+ <div class="dialog-footer">
4962
+ <slot name="input-prepend"></slot>
4963
+ <div class="input-container" id="inputContainer">
5215
4964
  <textarea class="message-input" id="msgInput"
5216
4965
  placeholder="请输入您的问题..." autocomplete="off" rows="2"></textarea>
5217
4966
  <div class="input-tools">
@@ -5224,10 +4973,12 @@ class AIChatDialog extends HTMLElement {
5224
4973
  </button>
5225
4974
  </div>
5226
4975
  </div>
5227
- <div class="footer-note">
5228
- <span class="footer-note-left">${this.escapeHtml(this._config?.footerDisclaimer || '')}</span>
5229
- <span class="footer-note-right">${this.escapeHtml(this._config?.footerIdentity || '')}</span>
5230
- </div>
4976
+ <div class="footer-note">
4977
+ <slot name="footer">
4978
+ <span class="footer-note-left">${this.escapeHtml(this._config?.footerDisclaimer || '')}</span>
4979
+ <span class="footer-note-right">${this.escapeHtml(this._config?.footerIdentity || '')}</span>
4980
+ </slot>
4981
+ </div>
5231
4982
  </div>
5232
4983
  </div>
5233
4984
 
@@ -5235,7 +4986,6 @@ class AIChatDialog extends HTMLElement {
5235
4986
  <div class="float-button" id="floatBtn" title="打开AI助手"></div>
5236
4987
  </div>
5237
4988
  `;
5238
-
5239
4989
  // 缓存DOM引用
5240
4990
  this._dialog = this.shadowRoot.querySelector('.ai-chat-dialog');
5241
4991
  this._body = this.shadowRoot.querySelector('#messagesContainer');
@@ -5257,28 +5007,21 @@ class AIChatDialog extends HTMLElement {
5257
5007
  requestAnimationFrame(() => {
5258
5008
  // 关闭按钮
5259
5009
  if (this._closeBtn) this._closeBtn.addEventListener('click', () => this.close());
5260
-
5261
5010
  // 展开/收起按钮
5262
5011
  if (this._expandBtn) this._expandBtn.addEventListener('click', () => this.toggleExpand());
5263
-
5264
5012
  // 新会话按钮
5265
5013
  if (this._newChatBtn) this._newChatBtn.addEventListener('click', () => this.clearChat());
5266
-
5267
5014
  // 历史记录按钮
5268
5015
  if (this._historyBtn) this._historyBtn.addEventListener('click', () => this.toggleHistory());
5269
-
5270
5016
  // 悬浮按钮打开
5271
5017
  if (this._floatBtn) this._floatBtn.addEventListener('click', () => this.open());
5272
-
5273
5018
  // 发送按钮
5274
5019
  if (this._sendBtn) this._sendBtn.addEventListener('click', () => this.handleSend());
5275
-
5276
5020
  // 附件选择
5277
5021
  if (this._attachBtn && this._attachmentInput) {
5278
5022
  this._attachBtn.addEventListener('click', () => this._attachmentInput.click());
5279
5023
  this._attachmentInput.addEventListener('change', () => this._handleAttachmentSelect());
5280
5024
  }
5281
-
5282
5025
  // 输入回车发送
5283
5026
  if (this._input) {
5284
5027
  this._autoResizeInput();
@@ -5294,19 +5037,15 @@ class AIChatDialog extends HTMLElement {
5294
5037
  }
5295
5038
  });
5296
5039
  }
5297
-
5298
5040
  // 拖拽(内嵌模式禁用)— 由 init() 在 _config 就绪后触发
5299
5041
  // initDraggable 延迟到 init() 中执行以免 _config 为空
5300
5042
  });
5301
5043
  }
5302
-
5303
5044
  // ==================== 展开/收起 ====================
5304
-
5305
5045
  toggleExpand() {
5306
5046
  this._isExpanded = !this._isExpanded;
5307
5047
  const dlg = this._dialog;
5308
5048
  if (!dlg) return;
5309
-
5310
5049
  // P2-17: 移动端始终全屏,展开/收起无意义(与Vue版 dialogStyle 一致)
5311
5050
  if (this._isMobile) {
5312
5051
  this._isExpanded = false; // 移动端不记录展开状态
@@ -5343,13 +5082,10 @@ class AIChatDialog extends HTMLElement {
5343
5082
  detail: this._isExpanded
5344
5083
  }));
5345
5084
  }
5346
-
5347
5085
  // ==================== 拖拽(与Vue startDrag/onDrag/stopDrag 一致) ====================
5348
-
5349
5086
  initDraggable() {
5350
5087
  const header = this.shadowRoot?.querySelector('.dialog-header');
5351
5088
  if (!header) return;
5352
-
5353
5089
  // 清理上一次遗留的 document 级监听(SPA 路由切换场景)
5354
5090
  this._cleanupDragListeners();
5355
5091
  const self = this;
@@ -5377,7 +5113,6 @@ class AIChatDialog extends HTMLElement {
5377
5113
  self._dialog.classList.remove('dragging');
5378
5114
  }
5379
5115
  };
5380
-
5381
5116
  // 鼠标事件(桌面端)— 保存引用以便清理
5382
5117
  this._dragMouseDownHandler = e => {
5383
5118
  if (e.target.closest('button, .header-icon')) return;
@@ -5391,7 +5126,6 @@ class AIChatDialog extends HTMLElement {
5391
5126
  header.addEventListener('mousedown', this._dragMouseDownHandler);
5392
5127
  document.addEventListener('mousemove', this._dragMouseMoveHandler);
5393
5128
  document.addEventListener('mouseup', this._dragMouseUpHandler);
5394
-
5395
5129
  // P1-7: 触摸事件(移动端,与Vue版一致)
5396
5130
  this._dragTouchStartHandler = e => {
5397
5131
  if (self._isExpanded) return;
@@ -5414,7 +5148,6 @@ class AIChatDialog extends HTMLElement {
5414
5148
  document.addEventListener('touchend', this._dragTouchEndHandler);
5415
5149
  this._dragInitialized = true;
5416
5150
  }
5417
-
5418
5151
  // P0: 清理拖拽事件监听(SPA disconnectedCallback / re-init 调用)
5419
5152
  _cleanupDragListeners() {
5420
5153
  if (this._dragMouseDownHandler) {
@@ -5446,12 +5179,10 @@ class AIChatDialog extends HTMLElement {
5446
5179
  // 更新标题
5447
5180
  const titleEl = this.shadowRoot.querySelector('.header-title');
5448
5181
  if (titleEl && this._config.title) titleEl.textContent = this._config.title;
5449
-
5450
5182
  // 更新placeholder
5451
5183
  if (this._input && this._config.placeholder) this._input.placeholder = this._config.placeholder;
5452
5184
  // P1-11: 动态设置输入框最大长度
5453
5185
  if (this._input && this._config.maxLength) this._input.maxLength = this._config.maxLength;
5454
-
5455
5186
  // ====== 主题处理:16种字符串预设 + 对象自定义 ======
5456
5187
  const t = this._config.theme;
5457
5188
  const host = this.shadowRoot.host;
@@ -5480,7 +5211,6 @@ class AIChatDialog extends HTMLElement {
5480
5211
  }
5481
5212
  host.classList.toggle('dark-theme', ['dark', 'starsky'].includes(t.toLowerCase()));
5482
5213
  }
5483
-
5484
5214
  // 对象形式自定义主题 - 也先重置再合并
5485
5215
  if (t && typeof t === 'object') {
5486
5216
  this._resetThemeVars();
@@ -5495,7 +5225,6 @@ class AIChatDialog extends HTMLElement {
5495
5225
  });
5496
5226
  host.classList.remove('dark-theme');
5497
5227
  }
5498
-
5499
5228
  // 应用所有CSS变量到host
5500
5229
  Object.entries(this._themeVars).forEach(([k, v]) => host.style.setProperty(k, v));
5501
5230
  }
@@ -5550,9 +5279,7 @@ class AIChatDialog extends HTMLElement {
5550
5279
  questions
5551
5280
  };
5552
5281
  }
5553
-
5554
5282
  // ==================== 渲染消息(与Vue模板结构一致) ====================
5555
-
5556
5283
  renderMessages(options = {}) {
5557
5284
  if (!this._body) return;
5558
5285
  if (this._historyVisible) {
@@ -5614,14 +5341,12 @@ class AIChatDialog extends HTMLElement {
5614
5341
  </div>
5615
5342
  </div>`;
5616
5343
  });
5617
-
5618
5344
  // 加载状态 — 有执行过程时不展示思考中
5619
5345
  if (this._isLoading && !runtimeExists) {
5620
5346
  html += '<div class="message-item ai">' + '<div class="message-content">' + '<div class="message-bubble loading"><span class="thinking-text">思考中</span><span class="typing-indicator"><span class="typing-dot"></span><span class="typing-dot"></span><span class="typing-dot"></span></span></div>' + '</div>' + '</div>';
5621
5347
  }
5622
5348
  html += '</div>';
5623
5349
  this._body.innerHTML = html;
5624
-
5625
5350
  // 绑定复制事件
5626
5351
  this._body.querySelectorAll('.copy-btn').forEach(btn => {
5627
5352
  btn.addEventListener('click', () => {
@@ -5630,7 +5355,6 @@ class AIChatDialog extends HTMLElement {
5630
5355
  if (msg) this.copyMessage(msg.content, idx);
5631
5356
  });
5632
5357
  });
5633
-
5634
5358
  // 绑定重新生成事件
5635
5359
  this._body.querySelectorAll('.regenerate-btn').forEach(btn => {
5636
5360
  btn.addEventListener('click', () => {
@@ -5638,7 +5362,6 @@ class AIChatDialog extends HTMLElement {
5638
5362
  this.regenerate(idx);
5639
5363
  });
5640
5364
  });
5641
-
5642
5365
  // P4: 绑定自定义操作按钮
5643
5366
  this._body.querySelectorAll('.custom-action-btn').forEach(btn => {
5644
5367
  btn.addEventListener('click', () => {
@@ -5656,7 +5379,6 @@ class AIChatDialog extends HTMLElement {
5656
5379
  }
5657
5380
  });
5658
5381
  });
5659
-
5660
5382
  // 绑定执行过程面板折叠/展开(Shadow DOM 下 inline onclick 不可靠)
5661
5383
  this._body.querySelectorAll('.runtime-header').forEach(header => {
5662
5384
  header.addEventListener('click', () => {
@@ -5899,9 +5621,7 @@ class AIChatDialog extends HTMLElement {
5899
5621
  }
5900
5622
  this._updateSendButtonState();
5901
5623
  }
5902
-
5903
5624
  // ==================== 发送消息(与Vue sendMessage 一致) ====================
5904
-
5905
5625
  async handleSend() {
5906
5626
  const content = this._input ? this._input.value.trim() : '';
5907
5627
  const attachments = [...(this._attachments || [])];
@@ -5910,14 +5630,12 @@ class AIChatDialog extends HTMLElement {
5910
5630
  return;
5911
5631
  }
5912
5632
  if (this._isLoading || this._streaming) return;
5913
-
5914
5633
  // P1-11: 字数限制检查
5915
5634
  const maxLen = this._config?.maxLength ?? 500;
5916
5635
  if (content.length > maxLen) {
5917
5636
  this.showToast(`输入内容不能超过${maxLen}个字符(当前${content.length}字)`);
5918
5637
  return;
5919
5638
  }
5920
-
5921
5639
  // 防抖:500ms内不允许重复发送
5922
5640
  const now = Date.now();
5923
5641
  if (this._lastSendTime && now - this._lastSendTime < 500) return;
@@ -5965,7 +5683,6 @@ class AIChatDialog extends HTMLElement {
5965
5683
  attachmentIds.push(res.data.attachmentId);
5966
5684
  }
5967
5685
  }
5968
-
5969
5686
  // P3: 收集页面上下文(setContext + onBeforeSend)
5970
5687
  let context = {
5971
5688
  ...(this._context || {})
@@ -6044,10 +5761,9 @@ class AIChatDialog extends HTMLElement {
6044
5761
  }
6045
5762
  }
6046
5763
  async mockResponse(userContent) {
6047
- await new Promise(r => setTimeout(r, 600 + Math.random() * 800));
5764
+ await new Promise(r => window.setTimeout(r, 600 + Math.random() * 800));
6048
5765
  const responses = [`关于"${(userContent || '').substring(0, 20)}"这个问题,我来为您详细解答...`, `这是一个很好的问题!根据我的理解:\n\n1. 首先,我们需要分析需求\n2. 其次,设计实现方案\n3. 最后,进行测试验证`, `收到您的问题。让我来帮您分析一下...\n\n根据您的描述,我建议您可以按照以下步骤操作:`, `感谢您的提问!以下是我的看法:\n\n• 第一点很关键,需要注意细节\n• 第二点值得关注\n• 第三点是核心所在`];
6049
5766
  const mockContent = responses[Math.floor(Math.random() * responses.length)];
6050
-
6051
5767
  // 流式效果
6052
5768
  const tempId = this.generateId();
6053
5769
  this._messages.push({
@@ -6058,7 +5774,7 @@ class AIChatDialog extends HTMLElement {
6058
5774
  });
6059
5775
  this.renderMessages();
6060
5776
  for (let i = 0; i < mockContent.length; i++) {
6061
- await new Promise(r => setTimeout(r, 12 + Math.random() * 20));
5777
+ await new Promise(r => window.setTimeout(r, 12 + Math.random() * 20));
6062
5778
  const msgIdx = this._messages.findIndex(m => m.id === tempId);
6063
5779
  if (msgIdx >= 0) {
6064
5780
  this._messages[msgIdx].content = mockContent.substring(0, i + 1);
@@ -6090,9 +5806,7 @@ class AIChatDialog extends HTMLElement {
6090
5806
  if (idx >= 0) delete this._messages[idx]._isStreaming;
6091
5807
  this.renderMessages();
6092
5808
  }
6093
-
6094
5809
  // P0: 会话ID管理
6095
- _conversationId = null;
6096
5810
  async _directApiCallStream(msgId, content, requestOptions = {}) {
6097
5811
  if (!this._chatClient) {
6098
5812
  this._chatClient = new AIChatClient(this._config || {});
@@ -6283,10 +5997,8 @@ class AIChatDialog extends HTMLElement {
6283
5997
  const idx = this._messages.findIndex(m => m.id === msgId);
6284
5998
  if (idx < 0) return;
6285
5999
  this._messages[idx].content = content;
6286
-
6287
6000
  // Detect if there are runtime events (for typewriter mode check)
6288
6001
  const hasRuntime = !!(this._messages[idx]._runtimeEvents && this._messages[idx]._runtimeEvents.length > 0);
6289
-
6290
6002
  // Accumulate full content
6291
6003
  if (content.startsWith(this._streamFullText)) {
6292
6004
  this._streamFullText = content;
@@ -6347,7 +6059,6 @@ class AIChatDialog extends HTMLElement {
6347
6059
  this.renderMessages();
6348
6060
  }
6349
6061
  }
6350
-
6351
6062
  // 运行时占位符过滤(对齐 portal)
6352
6063
  _isPlaceholder(text) {
6353
6064
  if (!text || typeof text !== 'string') return false;
@@ -6366,14 +6077,11 @@ class AIChatDialog extends HTMLElement {
6366
6077
  } catch (e) {}
6367
6078
  return false;
6368
6079
  }
6369
-
6370
6080
  // 判断错误标记内容(替换脆弱的前缀检查 startsWith('('))
6371
- _ERROR_CONTENT_PATTERNS = ['(请求超时', '(等待AI处理', '(无回复)', '(已停止)', '(AI 处理超时', '错误:', '网络错误:', '抱歉,'];
6372
6081
  _isErrorContent(content) {
6373
6082
  if (!content) return true;
6374
6083
  return this._ERROR_CONTENT_PATTERNS.some(p => content.startsWith(p));
6375
6084
  }
6376
-
6377
6085
  // P3: 将上下文对象格式化为可读文本(拼入 prompt 前缀)
6378
6086
  _formatContextText(context) {
6379
6087
  if (!context || typeof context !== 'object') return '';
@@ -6394,7 +6102,6 @@ class AIChatDialog extends HTMLElement {
6394
6102
  }
6395
6103
  return lines.join('\n');
6396
6104
  }
6397
-
6398
6105
  // 运行时事件管理 – incremental DOM, no renderMessages
6399
6106
  _addRuntimeEvent(msgId, event) {
6400
6107
  const idx = this._messages.findIndex(m => m.id === msgId);
@@ -6422,7 +6129,6 @@ class AIChatDialog extends HTMLElement {
6422
6129
  if (this._shouldAutoScroll()) this.scrollToBottom();
6423
6130
  return;
6424
6131
  }
6425
-
6426
6132
  // Path 2: first event – inject runtime panel DOM next to the streaming bubble
6427
6133
  const msgContent = this._findStreamingMessageContent();
6428
6134
  if (msgContent) {
@@ -6489,7 +6195,6 @@ class AIChatDialog extends HTMLElement {
6489
6195
  panel.appendChild(eventsContainer);
6490
6196
  return panel;
6491
6197
  }
6492
-
6493
6198
  // P4: 获取自定义操作按钮列表(缓存结果避免重复调用 onMessageActions)
6494
6199
  _getCustomActions(msg, idx) {
6495
6200
  const key = '_customActions_' + idx;
@@ -6503,7 +6208,6 @@ class AIChatDialog extends HTMLElement {
6503
6208
  }
6504
6209
  return msg[key] || [];
6505
6210
  }
6506
-
6507
6211
  // P4: 生成自定义操作按钮 HTML
6508
6212
  _buildCustomActions(msg, idx) {
6509
6213
  const actions = this._getCustomActions(msg, idx);
@@ -6529,7 +6233,7 @@ class AIChatDialog extends HTMLElement {
6529
6233
  }
6530
6234
  async _fetchConversationResult(conversationId) {
6531
6235
  for (let i = 0; i < 8; i++) {
6532
- await new Promise(r => setTimeout(r, 1000));
6236
+ await new Promise(r => window.setTimeout(r, 1000));
6533
6237
  try {
6534
6238
  const response = await this._chatClient.queryConversation({
6535
6239
  conversationId,
@@ -6545,9 +6249,7 @@ class AIChatDialog extends HTMLElement {
6545
6249
  }
6546
6250
  return '(AI 处理超时,请稍后查看对话记录)';
6547
6251
  }
6548
-
6549
6252
  // ==================== 重新生成(与Vue regenerate 一致) ====================
6550
-
6551
6253
  async regenerate(index) {
6552
6254
  if (this._isLoading || this._streaming) return;
6553
6255
  const aiMessage = this._messages[index];
@@ -6592,14 +6294,12 @@ class AIChatDialog extends HTMLElement {
6592
6294
  toast.className = 'error-toast';
6593
6295
  toast.textContent = msg;
6594
6296
  this._dialog?.appendChild(toast);
6595
- setTimeout(() => toast.remove(), 3000);
6297
+ window.setTimeout(() => toast.remove(), 3000);
6596
6298
  }
6597
-
6598
6299
  // P1-6: 精细化错误处理(与Vue版 handleErrorMsg 一致,按HTTP状态码+业务错误码分类)
6599
6300
  handleError(err) {
6600
6301
  let displayMsg = '抱歉,网络请求失败,请稍后重试';
6601
6302
  const errMsg = err?.message || '';
6602
-
6603
6303
  // 按错误类型分类
6604
6304
  if (errMsg.includes('Failed to fetch') || errMsg.includes('NetworkError') || errMsg.includes('网络')) {
6605
6305
  displayMsg = '网络连接失败,请检查网络后重试';
@@ -6633,9 +6333,7 @@ class AIChatDialog extends HTMLElement {
6633
6333
  detail: err
6634
6334
  }));
6635
6335
  }
6636
-
6637
6336
  // ==================== 复制(与Vue copyMessage 一致) ====================
6638
-
6639
6337
  async copyContent(text) {
6640
6338
  // P1-10: 微信环境优先使用 wx.setClipboardData(与Vue版一致)
6641
6339
  if (typeof wx !== 'undefined' && wx.setClipboardData) {
@@ -6678,7 +6376,7 @@ class AIChatDialog extends HTMLElement {
6678
6376
  await this.copyContent(content);
6679
6377
  if (this._messages[idx]) this._messages[idx].copied = true;
6680
6378
  this.renderMessages();
6681
- setTimeout(() => {
6379
+ window.setTimeout(() => {
6682
6380
  if (this._messages[idx]) {
6683
6381
  this._messages[idx].copied = false;
6684
6382
  this.renderMessages();
@@ -6727,9 +6425,7 @@ class AIChatDialog extends HTMLElement {
6727
6425
  }
6728
6426
  return response;
6729
6427
  }
6730
-
6731
6428
  // ==================== 工具函数 ====================
6732
-
6733
6429
  generateId() {
6734
6430
  return `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
6735
6431
  }
@@ -6737,7 +6433,6 @@ class AIChatDialog extends HTMLElement {
6737
6433
  const n = new Date();
6738
6434
  return `${String(n.getHours()).padStart(2, '0')}:${String(n.getMinutes()).padStart(2, '0')}`;
6739
6435
  }
6740
-
6741
6436
  /**
6742
6437
  * 调试日志(仅在 config.debug === true 时输出)
6743
6438
  */
@@ -6761,7 +6456,6 @@ class AIChatDialog extends HTMLElement {
6761
6456
  if (!s) return '';
6762
6457
  return s.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
6763
6458
  }
6764
-
6765
6459
  /**
6766
6460
  * 重置 _themeVars 为默认值(主题切换时调用,防止残留)
6767
6461
  */
@@ -6803,7 +6497,6 @@ class AIChatDialog extends HTMLElement {
6803
6497
  '--ai-font-small': '11px'
6804
6498
  });
6805
6499
  }
6806
-
6807
6500
  /**
6808
6501
  * Markdown → HTML 解析(仅用于AI回复,用户消息保持纯文本)
6809
6502
  * 使用 marked + DOMPurify 双重保障安全
@@ -6827,7 +6520,6 @@ class AIChatDialog extends HTMLElement {
6827
6520
  }
6828
6521
  }
6829
6522
  }
6830
-
6831
6523
  // 注册自定义元素
6832
6524
  if (!customElements.get('ai-chat-dialog')) {
6833
6525
  customElements.define('ai-chat-dialog', AIChatDialog);
@@ -6839,17 +6531,15 @@ if (typeof window !== 'undefined') {
6839
6531
  /**
6840
6532
  * IBC AI Web SDK - 纯JavaScript版本
6841
6533
  * 支持任意前端框架:Vue, React, Angular, 原生HTML等
6842
- *
6534
+ *
6843
6535
  * @author IBC AI Team
6844
- * @version 2.0.5
6536
+ * @version 2.1.0
6845
6537
  */
6846
-
6847
-
6538
+ // 导出组件
6848
6539
  // 快速初始化函数
6849
6540
  function createAIChatDialog(options = {}) {
6850
6541
  // 创建自定义元素实例
6851
6542
  const dialog = document.createElement('ai-chat-dialog');
6852
-
6853
6543
  // 设置属性
6854
6544
  if (options.title) dialog.setAttribute('title', options.title);
6855
6545
  if (options.placeholder) dialog.setAttribute('placeholder', options.placeholder);
@@ -6858,7 +6548,6 @@ function createAIChatDialog(options = {}) {
6858
6548
  if (options.height) dialog.style.setProperty('--ai-dialog-height', typeof options.height === 'number' ? `${options.height}px` : options.height);
6859
6549
  if (options.top != null) dialog.style.setProperty('--ai-dialog-top', typeof options.top === 'number' ? `${options.top}px` : options.top);
6860
6550
  if (options.right != null) dialog.style.setProperty('--ai-dialog-right', typeof options.right === 'number' ? `${options.right}px` : options.right);
6861
-
6862
6551
  // 挂载到指定容器或 body
6863
6552
  if (options.target) {
6864
6553
  const container = typeof options.target === 'string' ? document.querySelector(options.target) : options.target;
@@ -6872,12 +6561,10 @@ function createAIChatDialog(options = {}) {
6872
6561
  } else {
6873
6562
  document.body.appendChild(dialog);
6874
6563
  }
6875
-
6876
6564
  // 初始化配置
6877
6565
  if (Object.keys(options).length > 0) {
6878
6566
  dialog.init(options);
6879
6567
  }
6880
-
6881
6568
  // 行内模式:挂载到 DOM 后直接展开
6882
6569
  if (options.target) {
6883
6570
  requestAnimationFrame(() => {
@@ -6902,14 +6589,12 @@ function createAIChatDialog(options = {}) {
6902
6589
  }
6903
6590
  return dialog;
6904
6591
  }
6905
-
6906
6592
  // Vue插件安装方式(向后兼容)
6907
6593
  function installVuePlugin(Vue) {
6908
6594
  if (!Vue) {
6909
6595
  console.warn('[AI Web SDK] Vue instance not provided');
6910
6596
  return;
6911
6597
  }
6912
-
6913
6598
  // 注册全局组件包装器
6914
6599
  Vue.component('AiChatWrapper', {
6915
6600
  props: {
@@ -6965,7 +6650,6 @@ function installVuePlugin(Vue) {
6965
6650
  methods: {
6966
6651
  initDialog() {
6967
6652
  this.dialogInstance = createAIChatDialog(this.config || {});
6968
-
6969
6653
  // 监听事件并转发
6970
6654
  const events = ['open', 'close', 'message-send', 'message-received', 'error'];
6971
6655
  events.forEach(event => {
@@ -6993,12 +6677,9 @@ function installVuePlugin(Vue) {
6993
6677
  }
6994
6678
  });
6995
6679
  }
6996
-
6997
- // React Hook(可选) — 通过 window.React 获取 hooks,兼容 CDN 全局引入
6998
- /* global React */
6999
6680
  function useAIChat(options = {}) {
7000
6681
  if (typeof React === 'undefined') {
7001
- console.warn('[AI Web SDK] React is not loaded, useAIChat skipped');
6682
+ console.warn('[AI Web SDK] React is not loaded globally — useAIChat requires React on window (CDN mode) or use the imperative createAIChatDialog() API directly');
7002
6683
  return {
7003
6684
  open: () => {},
7004
6685
  close: () => {},
@@ -7019,7 +6700,6 @@ function useAIChat(options = {}) {
7019
6700
  useEffect(() => {
7020
6701
  if (!dialogRef.current) {
7021
6702
  dialogRef.current = createAIChatDialog(options);
7022
-
7023
6703
  // 监听事件
7024
6704
  dialogRef.current.addEventListener('message-send', e => {
7025
6705
  setMessages(prev => [...prev, e.detail]);
@@ -7074,7 +6754,6 @@ function useAIChat(options = {}) {
7074
6754
  ref: dialogRef
7075
6755
  };
7076
6756
  }
7077
-
7078
6757
  // 默认导出
7079
6758
  var index = {
7080
6759
  AIChatDialog,
@@ -7082,14 +6761,13 @@ var index = {
7082
6761
  createAIChatDialog,
7083
6762
  installVuePlugin,
7084
6763
  useAIChat,
7085
- version: '2.0.5'
6764
+ version: '2.1.0'
7086
6765
  };
7087
-
7088
6766
  // 全局暴露(UMD/浏览器环境)
7089
6767
  if (typeof window !== 'undefined') {
7090
6768
  window.AICreateChatDialog = createAIChatDialog;
7091
6769
  window.AIWebSDK = {
7092
- version: '2.0.5',
6770
+ version: '2.1.0',
7093
6771
  create: createAIChatDialog,
7094
6772
  AIChatDialog,
7095
6773
  AIChatClient,