ibc-ai-web-sdk 2.0.5 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -2,7 +2,6 @@
2
2
  * 错误码常量
3
3
  * 统一定义所有错误码,方便维护
4
4
  */
5
-
6
5
  const ERROR_CODES = {
7
6
  // 客户端错误 (40000-49999)
8
7
  AGENT_NOT_FOUND: 40001,
@@ -11,7 +10,6 @@ const ERROR_CODES = {
11
10
  // 提示词不能为空
12
11
  AUTH_FAILED: 40301,
13
12
  // 鉴权失败
14
-
15
13
  // 服务器错误 (50000-59999)
16
14
  NETWORK_ERROR: 500,
17
15
  // 网络请求失败
@@ -19,7 +17,6 @@ const ERROR_CODES = {
19
17
  // 服务器内部错误
20
18
  TIMEOUT_ERROR: 50002,
21
19
  // 请求超时
22
-
23
20
  // 取消
24
21
  REQUEST_CANCELLED: 0 // 请求已取消
25
22
  };
@@ -620,14 +617,14 @@ class AIChatClient {
620
617
  const message = parsed && (parsed.message || parsed.errorMessage) || data || '流式请求失败';
621
618
  const code = parsed && (parsed.code || parsed.errCode || parsed.status);
622
619
  if (code && this.isAuthErrorCode(code)) {
623
- const error = new Error(message);
624
- error.authError = true;
625
- error.code = code;
626
- throw error;
620
+ const authErr = new Error(message);
621
+ authErr.authError = true;
622
+ authErr.code = code;
623
+ throw authErr;
627
624
  }
628
- const error = new Error(message);
629
- error.sseData = parsed || data;
630
- throw error;
625
+ const sseErr = new Error(message);
626
+ sseErr.sseData = parsed || data;
627
+ throw sseErr;
631
628
  }
632
629
  if ((META_EVENTS.has(event) || MESSAGE_EVENTS.has(event)) && data.startsWith('[META]')) {
633
630
  const meta = tryParseJson(data.slice('[META]'.length));
@@ -872,7 +869,7 @@ class AIChatClient {
872
869
  }
873
870
 
874
871
  /**
875
- * marked v18.0.5 - a markdown parser
872
+ * marked v18.0.2 - a markdown parser
876
873
  * Copyright (c) 2018-2026, MarkedJS. (MIT License)
877
874
  * Copyright (c) 2011-2018, Christopher Jeffrey. (MIT License)
878
875
  * https://github.com/markedjs/marked
@@ -883,12 +880,12 @@ class AIChatClient {
883
880
  * The code in this file is generated from files in ./src/
884
881
  */
885
882
 
886
- 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} *[^
887
- ]`).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(`
883
+ 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} *[^
884
+ ]`).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(`
888
885
  `),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(`
889
- `)}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(`
886
+ `)}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(`
890
887
  `).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(`
891
- `)}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],`
888
+ `)}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],`
892
889
  `),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],`
893
890
  `)}}blockquote(e){let t=this.rules.block.blockquote.exec(e);if(t){let n=$(t[0],`
894
891
  `).split(`
@@ -896,24 +893,24 @@ function M(){return {async:false,breaks:false,extensions:null,gfm:true,hooks:nul
896
893
  `),p=c.replace(this.rules.other.blockquoteSetextReplace,`
897
894
  $1`).replace(this.rules.other.blockquoteSetextReplace2,"");s=s?`${s}
898
895
  ${c}`:c,r=r?`${r}
899
- ${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+`
896
+ ${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+`
900
897
  `+n.join(`
901
898
  `),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+`
902
899
  `+n.join(`
903
900
  `),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(`
904
- `);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(`
901
+ `);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(`
905
902
  `,1)[0],t[1].length),h=e.split(`
906
- `,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+`
907
- `,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(`
908
- `,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+=`
909
- `+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+=`
910
- `+h;}R=!h.trim(),c+=G+`
911
- `,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],`
912
- `),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(`
903
+ `,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+`
904
+ `,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(`
905
+ `,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+=`
906
+ `+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+=`
907
+ `+h;}R=!h.trim(),c+=Z+`
908
+ `,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],`
909
+ `),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(`
913
910
  `):[],i={type:"table",raw:$(t[0],`
914
- `),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],`
911
+ `),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],`
915
912
  `),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)===`
916
- `?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,`
913
+ `?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,`
917
914
  `),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+=`
918
915
  `: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(`
919
916
  `)?"":`
@@ -927,7 +924,7 @@ ${p}`:p;let k=this.lexer.state.top;if(this.lexer.state.top=true,this.lexer.block
927
924
  `+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(`
928
925
  `)?"":`
929
926
  `)+r.raw,o.text+=`
930
- `+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,"")+`
927
+ `+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,"")+`
931
928
  `;return s?'<pre><code class="language-'+O(s)+'">'+(n?r:O(r,true))+`</code></pre>
932
929
  `:"<pre><code>"+(n?r:O(r,true))+`</code></pre>
933
930
  `}blockquote({tokens:e}){return `<blockquote>
@@ -945,68 +942,27 @@ ${this.parser.parse(e)}</blockquote>
945
942
  `}tablerow({text:e}){return `<tr>
946
943
  ${e}</tr>
947
944
  `}tablecell(e){let t=this.parser.parseInline(e.tokens),n=e.header?"th":"td";return (e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+`</${n}>
948
- `}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+=`
949
- 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;
950
-
951
- /*! @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 */
952
-
953
- function _arrayLikeToArray(r, a) {
954
- (null == a || a > r.length) && (a = r.length);
955
- for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
956
- return n;
957
- }
958
- function _arrayWithHoles(r) {
959
- if (Array.isArray(r)) return r;
960
- }
961
- function _iterableToArrayLimit(r, l) {
962
- var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
963
- if (null != t) {
964
- var e,
965
- n,
966
- i,
967
- u,
968
- a = [],
969
- f = true,
970
- o = false;
971
- try {
972
- 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);
973
- } catch (r) {
974
- o = true, n = r;
975
- } finally {
976
- try {
977
- if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
978
- } finally {
979
- if (o) throw n;
980
- }
981
- }
982
- return a;
983
- }
984
- }
985
- function _nonIterableRest() {
986
- throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
987
- }
988
- function _slicedToArray(r, e) {
989
- return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
990
- }
991
- function _unsupportedIterableToArray(r, a) {
992
- if (r) {
993
- if ("string" == typeof r) return _arrayLikeToArray(r, a);
994
- var t = {}.toString.call(r).slice(8, -1);
995
- 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;
996
- }
997
- }
998
-
999
- const entries = Object.entries,
1000
- setPrototypeOf = Object.setPrototypeOf,
1001
- isFrozen = Object.isFrozen,
1002
- getPrototypeOf = Object.getPrototypeOf,
1003
- getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
1004
- let freeze = Object.freeze,
1005
- seal = Object.seal,
1006
- create = Object.create; // eslint-disable-line import/no-mutable-exports
1007
- let _ref = typeof Reflect !== 'undefined' && Reflect,
1008
- apply = _ref.apply,
1009
- construct = _ref.construct;
945
+ `}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+=`
946
+ 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;
947
+
948
+ /*! @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 */
949
+
950
+ const {
951
+ entries,
952
+ setPrototypeOf,
953
+ isFrozen,
954
+ getPrototypeOf,
955
+ getOwnPropertyDescriptor
956
+ } = Object;
957
+ let {
958
+ freeze,
959
+ seal,
960
+ create
961
+ } = Object; // eslint-disable-line import/no-mutable-exports
962
+ let {
963
+ apply,
964
+ construct
965
+ } = typeof Reflect !== 'undefined' && Reflect;
1010
966
  if (!freeze) {
1011
967
  freeze = function freeze(x) {
1012
968
  return x;
@@ -1143,10 +1099,7 @@ function cleanArray(array) {
1143
1099
  */
1144
1100
  function clone(object) {
1145
1101
  const newObject = create(null);
1146
- for (const _ref2 of entries(object)) {
1147
- var _ref3 = _slicedToArray(_ref2, 2);
1148
- const property = _ref3[0];
1149
- const value = _ref3[1];
1102
+ for (const [property, value] of entries(object)) {
1150
1103
  const isPropertyExist = objectHasOwnProperty(object, property);
1151
1104
  if (isPropertyExist) {
1152
1105
  if (arrayIsArray(value)) {
@@ -1260,14 +1213,15 @@ const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mgly
1260
1213
  const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
1261
1214
  const text = freeze(['#text']);
1262
1215
 
1263
- 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']);
1216
+ 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']);
1264
1217
  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']);
1265
1218
  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']);
1266
1219
  const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
1267
1220
 
1268
- const MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g);
1269
- const ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g);
1270
- const TMPLIT_EXPR = seal(/\${[\w\W]*/g);
1221
+ // eslint-disable-next-line unicorn/better-regex
1222
+ const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
1223
+ const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
1224
+ const TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); // eslint-disable-line unicorn/better-regex
1271
1225
  const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
1272
1226
  const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
1273
1227
  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
@@ -1278,24 +1232,29 @@ const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205
1278
1232
  const DOCTYPE_NAME = seal(/^html$/i);
1279
1233
  const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
1280
1234
 
1235
+ var EXPRESSIONS = /*#__PURE__*/Object.freeze({
1236
+ __proto__: null,
1237
+ ARIA_ATTR: ARIA_ATTR,
1238
+ ATTR_WHITESPACE: ATTR_WHITESPACE,
1239
+ CUSTOM_ELEMENT: CUSTOM_ELEMENT,
1240
+ DATA_ATTR: DATA_ATTR,
1241
+ DOCTYPE_NAME: DOCTYPE_NAME,
1242
+ ERB_EXPR: ERB_EXPR,
1243
+ IS_ALLOWED_URI: IS_ALLOWED_URI,
1244
+ IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,
1245
+ MUSTACHE_EXPR: MUSTACHE_EXPR,
1246
+ TMPLIT_EXPR: TMPLIT_EXPR
1247
+ });
1248
+
1281
1249
  /* eslint-disable @typescript-eslint/indent */
1282
1250
  // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
1283
1251
  const NODE_TYPE = {
1284
1252
  element: 1,
1285
- attribute: 2,
1286
1253
  text: 3,
1287
- cdataSection: 4,
1288
- entityReference: 5,
1289
- // Deprecated
1290
- entityNode: 6,
1291
1254
  // Deprecated
1292
1255
  progressingInstruction: 7,
1293
1256
  comment: 8,
1294
- document: 9,
1295
- documentType: 10,
1296
- documentFragment: 11,
1297
- notation: 12 // Deprecated
1298
- };
1257
+ document: 9};
1299
1258
  const getGlobal = function getGlobal() {
1300
1259
  return typeof window === 'undefined' ? null : window;
1301
1260
  };
@@ -1353,7 +1312,7 @@ const _createHooksMap = function _createHooksMap() {
1353
1312
  function createDOMPurify() {
1354
1313
  let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
1355
1314
  const DOMPurify = root => createDOMPurify(root);
1356
- DOMPurify.version = '3.4.8';
1315
+ DOMPurify.version = '3.4.1';
1357
1316
  DOMPurify.removed = [];
1358
1317
  if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
1359
1318
  // Not running in a browser, provide a factory function
@@ -1361,29 +1320,28 @@ function createDOMPurify() {
1361
1320
  DOMPurify.isSupported = false;
1362
1321
  return DOMPurify;
1363
1322
  }
1364
- let document = window.document;
1323
+ let {
1324
+ document
1325
+ } = window;
1365
1326
  const originalDocument = document;
1366
1327
  const currentScript = originalDocument.currentScript;
1367
- window.DocumentFragment;
1368
- const HTMLTemplateElement = window.HTMLTemplateElement,
1369
- Node = window.Node,
1370
- Element = window.Element,
1371
- NodeFilter = window.NodeFilter,
1372
- _window$NamedNodeMap = window.NamedNodeMap;
1373
- _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap;
1374
- window.HTMLFormElement;
1375
- const DOMParser = window.DOMParser,
1376
- trustedTypes = window.trustedTypes;
1328
+ const {
1329
+ DocumentFragment,
1330
+ HTMLTemplateElement,
1331
+ Node,
1332
+ Element,
1333
+ NodeFilter,
1334
+ NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,
1335
+ HTMLFormElement,
1336
+ DOMParser,
1337
+ trustedTypes
1338
+ } = window;
1377
1339
  const ElementPrototype = Element.prototype;
1378
1340
  const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
1379
1341
  const remove = lookupGetter(ElementPrototype, 'remove');
1380
1342
  const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
1381
1343
  const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
1382
1344
  const getParentNode = lookupGetter(ElementPrototype, 'parentNode');
1383
- const getShadowRoot = lookupGetter(ElementPrototype, 'shadowRoot');
1384
- const getAttributes = lookupGetter(ElementPrototype, 'attributes');
1385
- const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeType') : null;
1386
- const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeName') : null;
1387
1345
  // As per issue #47, the web-components registry is inherited by a
1388
1346
  // new document created via createHTMLDocument. As per the spec
1389
1347
  // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
@@ -1398,43 +1356,33 @@ function createDOMPurify() {
1398
1356
  }
1399
1357
  let trustedTypesPolicy;
1400
1358
  let emptyHTML = '';
1401
- // Tracks whether we are already inside a call to the configured Trusted Types
1402
- // policy's `createHTML`. If the supplied `TRUSTED_TYPES_POLICY.createHTML`
1403
- // itself calls `DOMPurify.sanitize` (the cause of #1422), `sanitize` would
1404
- // re-enter the policy and recurse until the stack overflows. We detect that
1405
- // re-entry and throw a clear, actionable error instead.
1406
- let IN_POLICY_CREATE_HTML = 0;
1407
- const _createTrustedHTML = function _createTrustedHTML(html) {
1408
- if (IN_POLICY_CREATE_HTML > 0) {
1409
- 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.');
1410
- }
1411
- IN_POLICY_CREATE_HTML++;
1412
- try {
1413
- return trustedTypesPolicy.createHTML(html);
1414
- } finally {
1415
- IN_POLICY_CREATE_HTML--;
1416
- }
1417
- };
1418
- const _document = document,
1419
- implementation = _document.implementation,
1420
- createNodeIterator = _document.createNodeIterator,
1421
- createDocumentFragment = _document.createDocumentFragment,
1422
- getElementsByTagName = _document.getElementsByTagName;
1423
- const importNode = originalDocument.importNode;
1359
+ const {
1360
+ implementation,
1361
+ createNodeIterator,
1362
+ createDocumentFragment,
1363
+ getElementsByTagName
1364
+ } = document;
1365
+ const {
1366
+ importNode
1367
+ } = originalDocument;
1424
1368
  let hooks = _createHooksMap();
1425
1369
  /**
1426
1370
  * Expose whether this browser supports running the full DOMPurify.
1427
1371
  */
1428
1372
  DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;
1429
- const MUSTACHE_EXPR$1 = MUSTACHE_EXPR,
1430
- ERB_EXPR$1 = ERB_EXPR,
1431
- TMPLIT_EXPR$1 = TMPLIT_EXPR,
1432
- DATA_ATTR$1 = DATA_ATTR,
1433
- ARIA_ATTR$1 = ARIA_ATTR,
1434
- IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,
1435
- ATTR_WHITESPACE$1 = ATTR_WHITESPACE,
1436
- CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;
1437
- let IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
1373
+ const {
1374
+ MUSTACHE_EXPR,
1375
+ ERB_EXPR,
1376
+ TMPLIT_EXPR,
1377
+ DATA_ATTR,
1378
+ ARIA_ATTR,
1379
+ IS_SCRIPT_OR_DATA,
1380
+ ATTR_WHITESPACE,
1381
+ CUSTOM_ELEMENT
1382
+ } = EXPRESSIONS;
1383
+ let {
1384
+ IS_ALLOWED_URI: IS_ALLOWED_URI$1
1385
+ } = EXPRESSIONS;
1438
1386
  /**
1439
1387
  * We consider the elements and attributes below to be safe. Ideally
1440
1388
  * don't add any new ones but feel free to remove unwanted ones.
@@ -1742,47 +1690,19 @@ function createDOMPurify() {
1742
1690
  throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
1743
1691
  }
1744
1692
  // Overwrite existing TrustedTypes policy.
1745
- const previousTrustedTypesPolicy = trustedTypesPolicy;
1746
1693
  trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
1747
- // Sign local variables required by `sanitize`. If the supplied policy's
1748
- // `createHTML` is circular (i.e. it calls `DOMPurify.sanitize`), this
1749
- // throws via the re-entrancy guard. Restore the previous policy first so
1750
- // the instance is not left in a poisoned state. See #1422.
1751
- try {
1752
- emptyHTML = _createTrustedHTML('');
1753
- } catch (error) {
1754
- trustedTypesPolicy = previousTrustedTypesPolicy;
1755
- throw error;
1756
- }
1694
+ // Sign local variables required by `sanitize`.
1695
+ emptyHTML = trustedTypesPolicy.createHTML('');
1757
1696
  } else {
1758
1697
  // Uninitialized policy, attempt to initialize the internal dompurify policy.
1759
- if (trustedTypesPolicy === undefined && cfg.TRUSTED_TYPES_POLICY !== null) {
1698
+ if (trustedTypesPolicy === undefined) {
1760
1699
  trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
1761
1700
  }
1762
1701
  // If creating the internal policy succeeded sign internal variables.
1763
- // Note: a falsy `trustedTypesPolicy` (null when policy creation failed or
1764
- // was skipped via `TRUSTED_TYPES_POLICY: null`, or undefined when no
1765
- // policy has been initialized yet) must be excluded here, otherwise we
1766
- // would call `.createHTML` on a non-policy and throw. See #1422.
1767
- if (trustedTypesPolicy && typeof emptyHTML === 'string') {
1768
- emptyHTML = _createTrustedHTML('');
1702
+ if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {
1703
+ emptyHTML = trustedTypesPolicy.createHTML('');
1769
1704
  }
1770
1705
  }
1771
- /*
1772
- * Mirror the clone-before-mutate pattern already applied above for
1773
- * cfg.ADD_TAGS / cfg.ADD_ATTR: if any uponSanitize* hook is
1774
- * registered AND the set still points at the default constant,
1775
- * clone it. The hook then mutates the clone (in-call widening
1776
- * still works exactly as documented) and the next default-cfg
1777
- * call rebinds to the untouched original via the reassignment at
1778
- * the top of this function.
1779
- */
1780
- if ((hooks.uponSanitizeElement.length > 0 || hooks.uponSanitizeAttribute.length > 0) && ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
1781
- ALLOWED_TAGS = clone(ALLOWED_TAGS);
1782
- }
1783
- if (hooks.uponSanitizeAttribute.length > 0 && ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
1784
- ALLOWED_ATTR = clone(ALLOWED_ATTR);
1785
- }
1786
1706
  // Prevent further manipulation of configuration.
1787
1707
  // Not available in IE8, Safari 5, etc.
1788
1708
  if (freeze) {
@@ -1942,7 +1862,7 @@ function createDOMPurify() {
1942
1862
  // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
1943
1863
  dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
1944
1864
  }
1945
- const dirtyPayload = trustedTypesPolicy ? _createTrustedHTML(dirty) : dirty;
1865
+ const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
1946
1866
  /*
1947
1867
  * Use the DOMParser API by default, fallback later if needs be
1948
1868
  * DOMParser not work for svg when has multiple root element.
@@ -1982,142 +1902,23 @@ function createDOMPurify() {
1982
1902
  // eslint-disable-next-line no-bitwise
1983
1903
  NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);
1984
1904
  };
1985
- /**
1986
- * Strip template-engine expressions ({{...}}, ${...}, <%...%>) from the
1987
- * character data of an element subtree. Used as the final safety net for
1988
- * SAFE_FOR_TEMPLATES on every DOM-returning code path so that expressions
1989
- * which only form after text-node normalization (e.g. fragments split across
1990
- * stripped elements) cannot survive into a template-evaluating framework.
1991
- *
1992
- * Walks text/comment/CDATA/processing-instruction nodes and mutates `.data`
1993
- * in place rather than round-tripping through innerHTML. This preserves
1994
- * descendant node references (important for IN_PLACE callers), avoids a
1995
- * serialize/reparse cycle, and reads literal character data — which means
1996
- * `<%...%>` in text content matches the ERB regex against its real bytes
1997
- * instead of the HTML-entity-escaped form innerHTML would produce.
1998
- *
1999
- * Attribute values are not visited here; SAFE_FOR_TEMPLATES handling for
2000
- * attributes is performed during the per-node `_sanitizeAttributes` pass.
2001
- *
2002
- * @param node The root element whose character data should be scrubbed.
2003
- */
2004
- const _scrubTemplateExpressions2 = function _scrubTemplateExpressions(node) {
2005
- var _node$querySelectorAl, _node$querySelectorAl2;
2006
- node.normalize();
2007
- const walker = createNodeIterator.call(node.ownerDocument || node, node,
2008
- // eslint-disable-next-line no-bitwise
2009
- NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_CDATA_SECTION | NodeFilter.SHOW_PROCESSING_INSTRUCTION, null);
2010
- let currentNode = walker.nextNode();
2011
- while (currentNode) {
2012
- let data = currentNode.data;
2013
- arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
2014
- data = stringReplace(data, expr, ' ');
2015
- });
2016
- currentNode.data = data;
2017
- currentNode = walker.nextNode();
2018
- }
2019
- // NodeIterator does not descend into <template>.content per the DOM spec,
2020
- // so we must explicitly recurse into each template's content fragment,
2021
- // mirroring the approach used by _sanitizeShadowDOM.
2022
- 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 : [];
2023
- arrayForEach(Array.from(templates), tmpl => {
2024
- if (_isDocumentFragment(tmpl.content)) {
2025
- _scrubTemplateExpressions2(tmpl.content);
2026
- }
2027
- });
2028
- };
2029
1905
  /**
2030
1906
  * _isClobbered
2031
1907
  *
2032
- * Detect DOM-clobbering on HTMLFormElement nodes. Form is the only HTML
2033
- * interface with [LegacyOverrideBuiltIns]; a descendant element with a
2034
- * `name` attribute matching a prototype property shadows that property
2035
- * on direct reads. We use this check at the IN_PLACE entry-point and
2036
- * during attribute sanitization to refuse clobbered forms.
2037
- *
2038
1908
  * @param element element to check for clobbering attacks
2039
1909
  * @return true if clobbered, false if safe
2040
1910
  */
2041
1911
  const _isClobbered = function _isClobbered(element) {
2042
- // Realm-independent tag-name probe. If we can't determine the tag
2043
- // name at all, we can't reason about clobbering — return false
2044
- // (the caller's other defences still apply).
2045
- const realTagName = getNodeName ? getNodeName(element) : null;
2046
- if (typeof realTagName !== 'string') {
2047
- return false;
2048
- }
2049
- if (transformCaseFunc(realTagName) !== 'form') {
2050
- return false;
2051
- }
2052
- return typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' ||
2053
- // Realm-safe NamedNodeMap detection: equality against the cached
2054
- // prototype getter. Clobbered .attributes (e.g. <input name="attributes">)
2055
- // makes the direct read diverge from the cached read; a clean form
2056
- // (same-realm OR foreign-realm) has both reads pointing at the same
2057
- // canonical NamedNodeMap.
2058
- element.attributes !== getAttributes(element) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function' ||
2059
- // NodeType clobbering probe. Cached Node.prototype.nodeType getter
2060
- // returns the integer 1 for any Element regardless of realm; direct
2061
- // read on a clobbered form (e.g. <input name="nodeType">) returns
2062
- // the named child element. Cheap addition — nodeType is read from
2063
- // an internal slot, no serialization cost — and removes a residual
2064
- // clobbering surface used by several mXSS / PI / comment branches
2065
- // in _sanitizeElements that compare currentNode.nodeType directly.
2066
- element.nodeType !== getNodeType(element) ||
2067
- // HTMLFormElement has [LegacyOverrideBuiltIns]: a descendant named
2068
- // "childNodes" shadows the prototype getter. Direct reads of
2069
- // form.childNodes from a clobbered form return the named child
2070
- // instead of the real NodeList, so any walk that reads it directly
2071
- // skips the form's real children. Compare the direct read to the
2072
- // cached Node.prototype getter — when the form's named-property
2073
- // getter intercepts the read, the two values differ and we flag
2074
- // the form. This catches every clobbering child type (input,
2075
- // select, etc.) regardless of whether the named child happens to
2076
- // carry a numeric .length, which a typeof-based probe would miss
2077
- // (e.g. HTMLSelectElement.length is a defined unsigned-long).
2078
- element.childNodes !== getChildNodes(element);
2079
- };
2080
- /**
2081
- * Checks whether the given value is a DocumentFragment from any realm.
2082
- *
2083
- * The realm-independent replacement reads `nodeType` through the cached
2084
- * Node.prototype getter and compares to the DOCUMENT_FRAGMENT_NODE
2085
- * constant (11). nodeType is a numeric value resolved from the node's
2086
- * internal slot, identical across realms for the same kind of node.
2087
- *
2088
- * @param value object to check
2089
- * @return true if value is a DocumentFragment-shaped node from any realm
2090
- */
2091
- const _isDocumentFragment = function _isDocumentFragment(value) {
2092
- if (!getNodeType || typeof value !== 'object' || value === null) {
2093
- return false;
2094
- }
2095
- try {
2096
- return getNodeType(value) === NODE_TYPE.documentFragment;
2097
- } catch (_) {
2098
- return false;
2099
- }
1912
+ 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');
2100
1913
  };
2101
1914
  /**
2102
- * Checks whether the given object is a DOM node, including nodes that
2103
- * originate from a different window/realm (e.g. an iframe's
2104
- * contentDocument). The previous `value instanceof Node` check was
2105
- * realm-bound: nodes from a different window failed it, causing
2106
- * sanitize() to silently stringify them and reset IN_PLACE to false,
2107
- * returning the original node unsanitized. See GHSA-4w3q-35jp-p934.
1915
+ * Checks whether the given object is a DOM node.
2108
1916
  *
2109
1917
  * @param value object to check whether it's a DOM node
2110
- * @return true if value is a DOM node from any realm
1918
+ * @return true is object is a DOM node
2111
1919
  */
2112
1920
  const _isNode = function _isNode(value) {
2113
- if (!getNodeType || typeof value !== 'object' || value === null) {
2114
- return false;
2115
- }
2116
- try {
2117
- return typeof getNodeType(value) === 'number';
2118
- } catch (_) {
2119
- return false;
2120
- }
1921
+ return typeof Node === 'function' && value instanceof Node;
2121
1922
  };
2122
1923
  function _executeHooks(hooks, currentNode, data) {
2123
1924
  arrayForEach(hooks, hook => {
@@ -2143,7 +1944,7 @@ function createDOMPurify() {
2143
1944
  return true;
2144
1945
  }
2145
1946
  /* Now let's check the element's type and name */
2146
- const tagName = transformCaseFunc(getNodeName ? getNodeName(currentNode) : currentNode.nodeName);
1947
+ const tagName = transformCaseFunc(currentNode.nodeName);
2147
1948
  /* Execute a hook if present */
2148
1949
  _executeHooks(hooks.uponSanitizeElement, currentNode, {
2149
1950
  tagName,
@@ -2180,17 +1981,10 @@ function createDOMPurify() {
2180
1981
  return false;
2181
1982
  }
2182
1983
  }
2183
- /* Keep content except for bad-listed elements.
2184
- Use the cached prototype getters exclusively — the previous code
2185
- had `|| currentNode.parentNode` / `|| currentNode.childNodes`
2186
- fallbacks, but the cached getters always return the canonical
2187
- value (or null for a real parent-less node), so the fallback
2188
- path was dead in safe cases and a clobbering surface in unsafe
2189
- ones. Falsy cached results stay falsy; the `if (childNodes &&
2190
- parentNode)` check already gates correctly. */
1984
+ /* Keep content except for bad-listed elements */
2191
1985
  if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
2192
- const parentNode = getParentNode(currentNode);
2193
- const childNodes = getChildNodes(currentNode);
1986
+ const parentNode = getParentNode(currentNode) || currentNode.parentNode;
1987
+ const childNodes = getChildNodes(currentNode) || currentNode.childNodes;
2194
1988
  if (childNodes && parentNode) {
2195
1989
  const childCount = childNodes.length;
2196
1990
  for (let i = childCount - 1; i >= 0; --i) {
@@ -2202,14 +1996,8 @@ function createDOMPurify() {
2202
1996
  _forceRemove(currentNode);
2203
1997
  return true;
2204
1998
  }
2205
- /* Check whether element has a valid namespace.
2206
- Realm-safe check (GHSA-hpcv-96wg-7vj8): use the cached Node.prototype
2207
- nodeType getter rather than `instanceof Element`, which is realm-
2208
- bound and short-circuits to false for any node minted in a different
2209
- realm — letting a foreign-realm element with a forbidden namespace
2210
- slip past the namespace check entirely. */
2211
- const nt = getNodeType ? getNodeType(currentNode) : currentNode.nodeType;
2212
- if (nt === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
1999
+ /* Check whether element has a valid namespace */
2000
+ if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
2213
2001
  _forceRemove(currentNode);
2214
2002
  return true;
2215
2003
  }
@@ -2222,7 +2010,7 @@ function createDOMPurify() {
2222
2010
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
2223
2011
  /* Get the element's text content */
2224
2012
  content = currentNode.textContent;
2225
- arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
2013
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
2226
2014
  content = stringReplace(content, expr, ' ');
2227
2015
  });
2228
2016
  if (currentNode.textContent !== content) {
@@ -2254,12 +2042,11 @@ function createDOMPurify() {
2254
2042
  if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
2255
2043
  return false;
2256
2044
  }
2257
- const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
2258
2045
  /* Allow valid data-* attributes: At least one character after "-"
2259
2046
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
2260
2047
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
2261
2048
  We don't need to check the value; it's always URI safe. */
2262
- 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]) {
2049
+ 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]) {
2263
2050
  if (
2264
2051
  // First condition does a very basic check if a) it's basically a valid custom element tagname AND
2265
2052
  // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
@@ -2271,7 +2058,7 @@ function createDOMPurify() {
2271
2058
  return false;
2272
2059
  }
2273
2060
  /* Check value is safe. First, is attr inert? If so, is safe */
2274
- } 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) {
2061
+ } 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) {
2275
2062
  return false;
2276
2063
  } else ;
2277
2064
  return true;
@@ -2289,7 +2076,7 @@ function createDOMPurify() {
2289
2076
  * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
2290
2077
  */
2291
2078
  const _isBasicCustomElement = function _isBasicCustomElement(tagName) {
2292
- return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName);
2079
+ return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT, tagName);
2293
2080
  };
2294
2081
  /**
2295
2082
  * _sanitizeAttributes
@@ -2304,7 +2091,9 @@ function createDOMPurify() {
2304
2091
  const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
2305
2092
  /* Execute a hook if present */
2306
2093
  _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
2307
- const attributes = currentNode.attributes;
2094
+ const {
2095
+ attributes
2096
+ } = currentNode;
2308
2097
  /* Check if we have attributes; if not we might have a text node */
2309
2098
  if (!attributes || _isClobbered(currentNode)) {
2310
2099
  return;
@@ -2320,9 +2109,11 @@ function createDOMPurify() {
2320
2109
  /* Go backwards over all attributes; safely remove bad ones */
2321
2110
  while (l--) {
2322
2111
  const attr = attributes[l];
2323
- const name = attr.name,
2324
- namespaceURI = attr.namespaceURI,
2325
- attrValue = attr.value;
2112
+ const {
2113
+ name,
2114
+ namespaceURI,
2115
+ value: attrValue
2116
+ } = attr;
2326
2117
  const lcName = transformCaseFunc(name);
2327
2118
  const initValue = attrValue;
2328
2119
  let value = name === 'value' ? initValue : stringTrim(initValue);
@@ -2370,7 +2161,7 @@ function createDOMPurify() {
2370
2161
  }
2371
2162
  /* Sanitize attribute content to be template-safe */
2372
2163
  if (SAFE_FOR_TEMPLATES) {
2373
- arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
2164
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
2374
2165
  value = stringReplace(value, expr, ' ');
2375
2166
  });
2376
2167
  }
@@ -2386,7 +2177,7 @@ function createDOMPurify() {
2386
2177
  switch (trustedTypes.getAttributeType(lcTag, lcName)) {
2387
2178
  case 'TrustedHTML':
2388
2179
  {
2389
- value = _createTrustedHTML(value);
2180
+ value = trustedTypesPolicy.createHTML(value);
2390
2181
  break;
2391
2182
  }
2392
2183
  case 'TrustedScriptURL':
@@ -2436,98 +2227,14 @@ function createDOMPurify() {
2436
2227
  _sanitizeElements(shadowNode);
2437
2228
  /* Check attributes next */
2438
2229
  _sanitizeAttributes(shadowNode);
2439
- /* Deep shadow DOM detected.
2440
- Realm-safe check (GHSA-hpcv-96wg-7vj8): use nodeType against the
2441
- DOCUMENT_FRAGMENT_NODE constant rather than instanceof, so we
2442
- recurse into <template>.content from foreign realms too. */
2443
- if (_isDocumentFragment(shadowNode.content)) {
2230
+ /* Deep shadow DOM detected */
2231
+ if (shadowNode.content instanceof DocumentFragment) {
2444
2232
  _sanitizeShadowDOM2(shadowNode.content);
2445
2233
  }
2446
- /* An element iterated here may itself host an attached
2447
- shadow root. The default NodeIterator does not enter shadow
2448
- trees, so a shadow root nested inside template.content was
2449
- previously reached by no walk at all (the pre-pass at
2450
- _sanitizeAttachedShadowRoots descends via childNodes, which
2451
- doesn't enter template.content; the template-content recursion
2452
- above iterates the content but never inspected shadowRoot).
2453
- Walk it explicitly. The nodeType guard avoids reading
2454
- shadowRoot off text / comment / CDATA / PI nodes that the
2455
- iterator also surfaces. */
2456
- const shadowNodeType = getNodeType ? getNodeType(shadowNode) : shadowNode.nodeType;
2457
- if (shadowNodeType === NODE_TYPE.element) {
2458
- const innerSr = getShadowRoot ? getShadowRoot(shadowNode) : shadowNode.shadowRoot;
2459
- if (_isDocumentFragment(innerSr)) {
2460
- _sanitizeAttachedShadowRoots2(innerSr);
2461
- _sanitizeShadowDOM2(innerSr);
2462
- }
2463
- }
2464
2234
  }
2465
2235
  /* Execute a hook if present */
2466
2236
  _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
2467
2237
  };
2468
- /**
2469
- * _sanitizeAttachedShadowRoots
2470
- *
2471
- * Walks `root` and feeds every attached shadow root we encounter into
2472
- * the existing _sanitizeShadowDOM pipeline. The default node iterator
2473
- * does not descend into shadow trees, so nodes inside an attached
2474
- * shadow root would otherwise be skipped entirely.
2475
- *
2476
- * Two real input paths put attached shadow roots in front of us:
2477
- * 1. IN_PLACE on a DOM node that already has shadow roots attached.
2478
- * 2. DOM-node input where importNode(dirty, true) deep-clones the
2479
- * shadow root because it was created with `clonable: true`.
2480
- *
2481
- * This pass runs once, up front, so the main iteration loop (and the
2482
- * existing _sanitizeShadowDOM template-content recursion) stay
2483
- * untouched — string-input paths are not affected.
2484
- *
2485
- * @param root the subtree root to walk for attached shadow roots
2486
- */
2487
- const _sanitizeAttachedShadowRoots2 = function _sanitizeAttachedShadowRoots(root) {
2488
- const nodeType = getNodeType ? getNodeType(root) : root.nodeType;
2489
- if (nodeType === NODE_TYPE.element) {
2490
- const sr = getShadowRoot ? getShadowRoot(root) : root.shadowRoot;
2491
- // Realm-safe check (GHSA-hpcv-96wg-7vj8): use nodeType-based
2492
- // detection rather than `instanceof DocumentFragment`, which is
2493
- // realm-bound and silently skipped shadow roots whose host element
2494
- // belonged to a foreign realm (e.g. iframe.contentDocument
2495
- // attachShadow). A foreign-realm ShadowRoot extends the foreign
2496
- // realm's DocumentFragment, not ours, so the old instanceof check
2497
- // returned false and the shadow subtree was never walked.
2498
- if (_isDocumentFragment(sr)) {
2499
- // Recurse first so that nested shadow roots are reached even if
2500
- // _sanitizeShadowDOM removes hosts at this level.
2501
- _sanitizeAttachedShadowRoots2(sr);
2502
- _sanitizeShadowDOM2(sr);
2503
- }
2504
- }
2505
- // Snapshot children before recursing. Sanitization of one subtree
2506
- // (e.g. via an uponSanitizeShadowNode hook) may detach siblings,
2507
- // and naive nextSibling traversal would silently skip the rest of
2508
- // the list once a node is detached.
2509
- const childNodes = getChildNodes ? getChildNodes(root) : root.childNodes;
2510
- if (!childNodes) {
2511
- return;
2512
- }
2513
- const snapshot = [];
2514
- arrayForEach(childNodes, child => {
2515
- arrayPush(snapshot, child);
2516
- });
2517
- for (const child of snapshot) {
2518
- _sanitizeAttachedShadowRoots2(child);
2519
- }
2520
- /* When the root is a <template>, also descend into root.content */
2521
- if (nodeType === NODE_TYPE.element) {
2522
- const rootName = getNodeName ? getNodeName(root) : null;
2523
- if (typeof rootName === 'string' && transformCaseFunc(rootName) === 'template') {
2524
- const content = root.content;
2525
- if (_isDocumentFragment(content)) {
2526
- _sanitizeAttachedShadowRoots2(content);
2527
- }
2528
- }
2529
- }
2530
- };
2531
2238
  // eslint-disable-next-line complexity
2532
2239
  DOMPurify.sanitize = function (dirty) {
2533
2240
  let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -2564,35 +2271,15 @@ function createDOMPurify() {
2564
2271
  IN_PLACE = false;
2565
2272
  }
2566
2273
  if (IN_PLACE) {
2567
- /* Do some early pre-sanitization to avoid unsafe root nodes.
2568
- Read nodeName through the cached prototype getter — a clobbering
2569
- child named "nodeName" on the form root would otherwise shadow
2570
- the property and let this check skip the root-allowlist
2571
- validation entirely. */
2572
- const nn = getNodeName ? getNodeName(dirty) : dirty.nodeName;
2274
+ /* Do some early pre-sanitization to avoid unsafe root nodes */
2275
+ const nn = dirty.nodeName;
2573
2276
  if (typeof nn === 'string') {
2574
2277
  const tagName = transformCaseFunc(nn);
2575
2278
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
2576
2279
  throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
2577
2280
  }
2578
2281
  }
2579
- /* Pre-flight the root through _isClobbered. The iterator-driven
2580
- removal path can not detach a parent-less root: _forceRemove
2581
- falls through to Element.prototype.remove(), which per spec
2582
- is a no-op on a node with no parent. A clobbered root would
2583
- then survive the main loop with its attributes uninspected,
2584
- because _sanitizeAttributes early-returns on _isClobbered. The
2585
- result would be an attacker-controlled form, complete with any
2586
- event-handler attributes the caller passed in, handed back to
2587
- the application unsanitized. Refuse to sanitize such a root
2588
- the same way we refuse a forbidden tag. GHSA-r47g-fvhr-h676. */
2589
- if (_isClobbered(dirty)) {
2590
- throw typeErrorCreate('root node is clobbered and cannot be sanitized in-place');
2591
- }
2592
- /* Sanitize attached shadow roots before the main iterator runs.
2593
- The iterator does not descend into shadow trees. */
2594
- _sanitizeAttachedShadowRoots2(dirty);
2595
- } else if (_isNode(dirty)) {
2282
+ } else if (dirty instanceof Node) {
2596
2283
  /* If dirty is a DOM element, append to an empty document to avoid
2597
2284
  elements being stripped by the parser */
2598
2285
  body = _initDocument('<!---->');
@@ -2606,18 +2293,12 @@ function createDOMPurify() {
2606
2293
  // eslint-disable-next-line unicorn/prefer-dom-node-append
2607
2294
  body.appendChild(importedNode);
2608
2295
  }
2609
- /* Clonable shadow roots are deep-cloned by importNode(); sanitize
2610
- them before the main iterator runs, since the iterator does not
2611
- descend into shadow trees. The walk routes every read through a
2612
- cached prototype getter so clobbering descendants on a form root
2613
- cannot hide a shadow host from this pass. */
2614
- _sanitizeAttachedShadowRoots2(importedNode);
2615
2296
  } else {
2616
2297
  /* Exit directly if we have nothing to do */
2617
2298
  if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
2618
2299
  // eslint-disable-next-line unicorn/prefer-includes
2619
2300
  dirty.indexOf('<') === -1) {
2620
- return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(dirty) : dirty;
2301
+ return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
2621
2302
  }
2622
2303
  /* Initialize the document to work on */
2623
2304
  body = _initDocument(dirty);
@@ -2638,25 +2319,24 @@ function createDOMPurify() {
2638
2319
  _sanitizeElements(currentNode);
2639
2320
  /* Check attributes next */
2640
2321
  _sanitizeAttributes(currentNode);
2641
- /* Shadow DOM detected, sanitize it.
2642
- Realm-safe check (GHSA-hpcv-96wg-7vj8): nodeType-based detection
2643
- instead of instanceof, so foreign-realm <template>.content is
2644
- walked correctly. */
2645
- if (_isDocumentFragment(currentNode.content)) {
2322
+ /* Shadow DOM detected, sanitize it */
2323
+ if (currentNode.content instanceof DocumentFragment) {
2646
2324
  _sanitizeShadowDOM2(currentNode.content);
2647
2325
  }
2648
2326
  }
2649
2327
  /* If we sanitized `dirty` in-place, return it. */
2650
2328
  if (IN_PLACE) {
2651
- if (SAFE_FOR_TEMPLATES) {
2652
- _scrubTemplateExpressions2(dirty);
2653
- }
2654
2329
  return dirty;
2655
2330
  }
2656
2331
  /* Return sanitized string or DOM */
2657
2332
  if (RETURN_DOM) {
2658
2333
  if (SAFE_FOR_TEMPLATES) {
2659
- _scrubTemplateExpressions2(body);
2334
+ body.normalize();
2335
+ let html = body.innerHTML;
2336
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
2337
+ html = stringReplace(html, expr, ' ');
2338
+ });
2339
+ body.innerHTML = html;
2660
2340
  }
2661
2341
  if (RETURN_DOM_FRAGMENT) {
2662
2342
  returnNode = createDocumentFragment.call(body.ownerDocument);
@@ -2686,11 +2366,11 @@ function createDOMPurify() {
2686
2366
  }
2687
2367
  /* Sanitize final string template-safe */
2688
2368
  if (SAFE_FOR_TEMPLATES) {
2689
- arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
2369
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
2690
2370
  serializedHTML = stringReplace(serializedHTML, expr, ' ');
2691
2371
  });
2692
2372
  }
2693
- return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(serializedHTML) : serializedHTML;
2373
+ return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
2694
2374
  };
2695
2375
  DOMPurify.setConfig = function () {
2696
2376
  let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -2737,7 +2417,6 @@ var purify = createDOMPurify();
2737
2417
  * 预设主题配置
2738
2418
  * 提供多种常用主题,用户可以直接使用或自定义
2739
2419
  */
2740
-
2741
2420
  /**
2742
2421
  * 默认主题(蓝色渐变)
2743
2422
  */
@@ -2788,7 +2467,6 @@ const DEFAULT_THEME = {
2788
2467
  button: '0 4px 12px rgba(24, 144, 255, 0.35)'
2789
2468
  }
2790
2469
  };
2791
-
2792
2470
  /**
2793
2471
  * 深色主题
2794
2472
  */
@@ -2839,7 +2517,6 @@ const DARK_THEME = {
2839
2517
  button: '0 4px 12px rgba(24, 144, 255, 0.4)'
2840
2518
  }
2841
2519
  };
2842
-
2843
2520
  /**
2844
2521
  * 清新主题(绿色系)
2845
2522
  */
@@ -2890,7 +2567,6 @@ const FRESH_THEME = {
2890
2567
  button: '0 4px 12px rgba(82, 196, 26, 0.35)'
2891
2568
  }
2892
2569
  };
2893
-
2894
2570
  /**
2895
2571
  * 活力主题(橙色系)
2896
2572
  */
@@ -2941,7 +2617,6 @@ const VIBRANT_THEME = {
2941
2617
  button: '0 4px 12px rgba(250, 140, 22, 0.35)'
2942
2618
  }
2943
2619
  };
2944
-
2945
2620
  /**
2946
2621
  * 浪漫主题(粉色系)
2947
2622
  */
@@ -2992,7 +2667,6 @@ const ROMANTIC_THEME = {
2992
2667
  button: '0 4px 12px rgba(235, 47, 150, 0.35)'
2993
2668
  }
2994
2669
  };
2995
-
2996
2670
  /**
2997
2671
  * 紫色主题(优雅神秘)
2998
2672
  */
@@ -3043,7 +2717,6 @@ const PURPLE_THEME = {
3043
2717
  button: '0 4px 12px rgba(114, 46, 209, 0.35)'
3044
2718
  }
3045
2719
  };
3046
-
3047
2720
  /**
3048
2721
  * 海洋主题(深蓝深海)
3049
2722
  */
@@ -3094,7 +2767,6 @@ const OCEAN_THEME = {
3094
2767
  button: '0 4px 12px rgba(0, 119, 182, 0.35)'
3095
2768
  }
3096
2769
  };
3097
-
3098
2770
  /**
3099
2771
  * 暮光主题(紫罗兰渐变)
3100
2772
  */
@@ -3145,7 +2817,6 @@ const TWILIGHT_THEME = {
3145
2817
  button: '0 4px 12px rgba(147, 51, 234, 0.35)'
3146
2818
  }
3147
2819
  };
3148
-
3149
2820
  /**
3150
2821
  * 薄荷主题(青绿色)
3151
2822
  */
@@ -3196,7 +2867,6 @@ const MINT_THEME = {
3196
2867
  button: '0 4px 12px rgba(20, 184, 166, 0.35)'
3197
2868
  }
3198
2869
  };
3199
-
3200
2870
  /**
3201
2871
  * 玫瑰主题(深红色)
3202
2872
  */
@@ -3247,7 +2917,6 @@ const ROSE_THEME = {
3247
2917
  button: '0 4px 12px rgba(225, 29, 72, 0.35)'
3248
2918
  }
3249
2919
  };
3250
-
3251
2920
  /**
3252
2921
  * 极光主题(蓝绿渐变)
3253
2922
  */
@@ -3298,7 +2967,6 @@ const AURORA_THEME = {
3298
2967
  button: '0 4px 12px rgba(14, 165, 233, 0.35)'
3299
2968
  }
3300
2969
  };
3301
-
3302
2970
  /**
3303
2971
  * 薰衣草主题(淡紫色)
3304
2972
  */
@@ -3349,7 +3017,6 @@ const LAVENDER_THEME = {
3349
3017
  button: '0 4px 12px rgba(139, 92, 246, 0.35)'
3350
3018
  }
3351
3019
  };
3352
-
3353
3020
  /**
3354
3021
  * 珊瑚主题(粉橙色)
3355
3022
  */
@@ -3400,7 +3067,6 @@ const CORAL_THEME = {
3400
3067
  button: '0 4px 12px rgba(249, 115, 22, 0.35)'
3401
3068
  }
3402
3069
  };
3403
-
3404
3070
  /**
3405
3071
  * 翡翠主题(深绿色)
3406
3072
  */
@@ -3451,7 +3117,6 @@ const JADE_THEME = {
3451
3117
  button: '0 4px 12px rgba(5, 150, 105, 0.35)'
3452
3118
  }
3453
3119
  };
3454
-
3455
3120
  /**
3456
3121
  * 星空主题(深蓝紫色)
3457
3122
  */
@@ -3502,7 +3167,6 @@ const STARSKY_THEME = {
3502
3167
  button: '0 4px 12px rgba(99, 102, 241, 0.4)'
3503
3168
  }
3504
3169
  };
3505
-
3506
3170
  /**
3507
3171
  * 日落主题(暖色调)
3508
3172
  */
@@ -3553,7 +3217,6 @@ const SUNSET_THEME = {
3553
3217
  button: '0 4px 12px rgba(234, 88, 12, 0.35)'
3554
3218
  }
3555
3219
  };
3556
-
3557
3220
  /**
3558
3221
  * 所有预设主题列表
3559
3222
  */
@@ -3579,27 +3242,21 @@ const PRESET_THEMES = {
3579
3242
  /**
3580
3243
  * AIChatDialog - 纯JavaScript实现的AI对话组件 (Web Components)
3581
3244
  * 样式与功能完全对齐 Vue 版本(1:1 复刻)
3582
- *
3245
+ *
3583
3246
  * @author IBC AI Team
3584
- * @version 2.0.5
3247
+ * @version 2.1.0
3585
3248
  */
3586
-
3587
-
3249
+ // 导入 marked Markdown 解析库 + DOMPurify XSS防护 + 主题配置
3588
3250
  // 运行时占位符(对齐 portal)
3589
3251
  const RUNTIME_PLACEHOLDERS = ['请求已受理', '任务已受理', '正在思考', '正在执行', '结果处理中', '已进入助手运行时', '任务运行时', 'SSE 连接已建立'];
3590
3252
  const DEFAULT_DIALOG_TOP = '96px';
3591
-
3592
3253
  // ========== marked 配置(安全且功能完整) ==========
3254
+ // marked v18 移除了 headerIds/mangle,仅保留 breaks 和 gfm
3593
3255
  g.setOptions({
3594
3256
  breaks: true,
3595
3257
  // 支持GFM换行(单换行变<br>)
3596
- gfm: true,
3597
- // GitHub Flavored Markdown
3598
- headerIds: false,
3599
- // 不生成标题id
3600
- mangle: false // 不转义邮箱
3601
- });
3602
-
3258
+ gfm: true // GitHub Flavored Markdown
3259
+ } /* marked v18 types are strict */);
3603
3260
  // Vue themes.js 的 camelCase key → JS _themeVars CSS变量名 映射表
3604
3261
  const THEME_COLOR_KEY_MAP = {
3605
3262
  primary: '--ai-primary',
@@ -3628,14 +3285,82 @@ const THEME_COLOR_KEY_MAP = {
3628
3285
  error: '--ai-error',
3629
3286
  warning: '--ai-warning'
3630
3287
  };
3631
-
3632
3288
  // ========== 16种预设主题(与Vue版themes.js完全一致) ==========
3633
3289
  class AIChatDialog extends HTMLElement {
3290
+ // ====== 类型声明(HTMLElement 子类必需) ======
3634
3291
  static get observedAttributes() {
3635
3292
  return ['visible'];
3636
3293
  }
3637
3294
  constructor() {
3638
3295
  super();
3296
+ // 核心状态
3297
+ this._messages = [];
3298
+ this._isLoading = false;
3299
+ this._config = null;
3300
+ this._mockMode = false;
3301
+ this._isDragging = false;
3302
+ this._isExpanded = false;
3303
+ this._chatClient = null;
3304
+ this._attachments = [];
3305
+ this._dragStartX = 0;
3306
+ this._dragStartY = 0;
3307
+ this._dialogX = 0;
3308
+ this._dialogY = 0;
3309
+ this._appDetail = null;
3310
+ this._historyVisible = false;
3311
+ this._historyRecords = [];
3312
+ this._historyLoading = false;
3313
+ this._historyLoaded = false;
3314
+ this._historyPageIndex = 1;
3315
+ this._historyHasMore = false;
3316
+ this._isMobile = false;
3317
+ // 流式渲染
3318
+ this._streamTextEl = null;
3319
+ this._streamInitDone = false;
3320
+ this._streamFullText = '';
3321
+ this._streamVisibleLength = 0;
3322
+ this._streamTypeRaf = null;
3323
+ this._streaming = false;
3324
+ // 运行时面板
3325
+ this._runtimePanelEl = null;
3326
+ this._runtimeEventsContainerEl = null;
3327
+ this._runtimeStatusEl = null;
3328
+ this._runtimeCountEl = null;
3329
+ // 页面上下文
3330
+ this._context = {};
3331
+ // 主题
3332
+ this._themeVars = {};
3333
+ // 事件处理器引用(用于清理)
3334
+ this._handleOnline = null;
3335
+ this._handleOffline = null;
3336
+ this._handleResize = null;
3337
+ // DOM 缓存引用
3338
+ this._dialog = null;
3339
+ this._body = null;
3340
+ this._input = null;
3341
+ this._sendBtn = null;
3342
+ this._attachBtn = null;
3343
+ this._attachmentInput = null;
3344
+ this._closeBtn = null;
3345
+ this._expandBtn = null;
3346
+ this._newChatBtn = null;
3347
+ this._historyBtn = null;
3348
+ this._floatBtn = null;
3349
+ this._inputContainer = null;
3350
+ // 会话
3351
+ this._conversationId = null;
3352
+ // 防抖
3353
+ this._lastSendTime = 0;
3354
+ // 拖拽处理器引用
3355
+ this._dragMouseDownHandler = null;
3356
+ this._dragMouseMoveHandler = null;
3357
+ this._dragMouseUpHandler = null;
3358
+ this._dragTouchStartHandler = null;
3359
+ this._dragTouchMoveHandler = null;
3360
+ this._dragTouchEndHandler = null;
3361
+ this._dragInitialized = false;
3362
+ // 错误标记
3363
+ this._ERROR_CONTENT_PATTERNS = ['(请求超时', '(等待AI处理', '(无回复)', '(已停止)', '(AI 处理超时', '错误:', '网络错误:', '抱歉,'];
3639
3364
  this.attachShadow({
3640
3365
  mode: 'open'
3641
3366
  });
@@ -3674,7 +3399,6 @@ class AIChatDialog extends HTMLElement {
3674
3399
  this._runtimeCountEl = null;
3675
3400
  // P3: 页面上下文数据(宿主页面选中的数据)
3676
3401
  this._context = {};
3677
-
3678
3402
  // ====== 默认主题配置(与 themes.js DEFAULT_THEME 完全一致) ======
3679
3403
  this._themeVars = {
3680
3404
  '--ai-primary': '#1890ff',
@@ -3717,9 +3441,7 @@ class AIChatDialog extends HTMLElement {
3717
3441
  this.render();
3718
3442
  this.bindEvents();
3719
3443
  }
3720
-
3721
3444
  // ==================== 生命周期 ====================
3722
-
3723
3445
  connectedCallback() {
3724
3446
  // P1-8: 网络状态监控(与Vue版一致)
3725
3447
  this._handleOnline = () => {
@@ -3732,12 +3454,11 @@ class AIChatDialog extends HTMLElement {
3732
3454
  tip.className = 'network-tip';
3733
3455
  tip.textContent = '网络连接已断开,请检查网络后重试';
3734
3456
  this._dialog?.prepend(tip);
3735
- setTimeout(() => tip.remove(), 5000);
3457
+ window.setTimeout(() => tip.remove(), 5000);
3736
3458
  }
3737
3459
  };
3738
3460
  window.addEventListener('online', this._handleOnline);
3739
3461
  window.addEventListener('offline', this._handleOffline);
3740
-
3741
3462
  // P2-17: 移动端环境检测(与Vue版 detectEnvironment 一致)
3742
3463
  this._detectMobile();
3743
3464
  // P2-17: 窗口resize时重新检测移动端
@@ -3750,7 +3471,6 @@ class AIChatDialog extends HTMLElement {
3750
3471
  }
3751
3472
  };
3752
3473
  window.addEventListener('resize', this._handleResize);
3753
-
3754
3474
  // 恢复后台Token刷新定时器(SPA路由切换后 re-attach 场景)
3755
3475
  if (this._chatClient) this._chatClient.startBackgroundRefresh();
3756
3476
  }
@@ -3768,7 +3488,6 @@ class AIChatDialog extends HTMLElement {
3768
3488
  this._chatClient.cancelCurrentRequest();
3769
3489
  }
3770
3490
  }
3771
-
3772
3491
  // P2-17: 移动端4维检测(与Vue版 isMobileDevice 计算属性完全一致)
3773
3492
  _detectMobile() {
3774
3493
  // 1. 优先使用显式配置
@@ -3776,31 +3495,25 @@ class AIChatDialog extends HTMLElement {
3776
3495
  this._isMobile = !!this._config.mobileMode;
3777
3496
  return;
3778
3497
  }
3779
-
3780
3498
  // 2. 微信小程序环境检测
3781
3499
  if (typeof wx !== 'undefined' && wx.getSystemInfoSync) {
3782
3500
  this._isMobile = true;
3783
3501
  return;
3784
3502
  }
3785
-
3786
3503
  // 3. 浏览器环境
3787
3504
  if (typeof window === 'undefined') {
3788
3505
  this._isMobile = false;
3789
3506
  return;
3790
3507
  }
3791
-
3792
3508
  // 4. User Agent 正则匹配
3793
3509
  const ua = navigator.userAgent || '';
3794
3510
  const isMobileUA = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua);
3795
-
3796
3511
  // 5. 屏幕宽度 < 768px + 触摸支持
3797
3512
  const isSmallScreen = window.innerWidth < 768;
3798
3513
  const hasTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
3799
-
3800
3514
  // 综合判断:UA匹配 或 (小屏幕+触摸)
3801
3515
  this._isMobile = isMobileUA || isSmallScreen && hasTouch;
3802
3516
  }
3803
-
3804
3517
  // P2-17: 应用移动端/桌面端布局(自动全屏或恢复浮动气泡)
3805
3518
  _applyMobileLayout() {
3806
3519
  if (!this._dialog) return;
@@ -3845,9 +3558,7 @@ class AIChatDialog extends HTMLElement {
3845
3558
  if (visible) this.showDialog();else this.hideDialog();
3846
3559
  }
3847
3560
  }
3848
-
3849
3561
  // ==================== 属性访问器 ====================
3850
-
3851
3562
  get visible() {
3852
3563
  return this.hasAttribute('visible');
3853
3564
  }
@@ -3863,9 +3574,7 @@ class AIChatDialog extends HTMLElement {
3863
3574
  get config() {
3864
3575
  return this._config;
3865
3576
  }
3866
-
3867
3577
  // ==================== 公共API ====================
3868
-
3869
3578
  init(config = {}) {
3870
3579
  this._config = {
3871
3580
  apiBaseUrl: '',
@@ -4024,7 +3733,6 @@ class AIChatDialog extends HTMLElement {
4024
3733
  this._mockMode = false;
4025
3734
  return this;
4026
3735
  }
4027
-
4028
3736
  /**
4029
3737
  * 设置页面上下文数据(宿主页面选中的数据,随每次请求发送)
4030
3738
  * @param {Object} context - 上下文数据对象,传 null 清空
@@ -4036,7 +3744,6 @@ class AIChatDialog extends HTMLElement {
4036
3744
  } : {};
4037
3745
  return this;
4038
3746
  }
4039
-
4040
3747
  /**
4041
3748
  * 获取当前上下文数据
4042
3749
  * @returns {Object}
@@ -4046,7 +3753,6 @@ class AIChatDialog extends HTMLElement {
4046
3753
  ...this._context
4047
3754
  };
4048
3755
  }
4049
-
4050
3756
  /**
4051
3757
  * 外部触发表态发送(业务层主动调用,如点击外部按钮触发 AI 请求)
4052
3758
  * @param {string} text - 要发送的消息内容
@@ -4062,9 +3768,7 @@ class AIChatDialog extends HTMLElement {
4062
3768
  this.handleSend();
4063
3769
  return this;
4064
3770
  }
4065
-
4066
3771
  // ==================== 显示/隐藏 ====================
4067
-
4068
3772
  showDialog() {
4069
3773
  const dialog = this.shadowRoot.querySelector('.ai-chat-dialog');
4070
3774
  const btn = this.shadowRoot.querySelector('.float-button');
@@ -4079,9 +3783,7 @@ class AIChatDialog extends HTMLElement {
4079
3783
  if (dialog) dialog.classList.remove('dialog-visible');
4080
3784
  if (btn) btn.style.display = 'flex';
4081
3785
  }
4082
-
4083
3786
  // ==================== 渲染(完整CSS对齐theme.css) ====================
4084
-
4085
3787
  render() {
4086
3788
  const cssVarsStr = Object.entries(this._themeVars).map(([k, v]) => `${k}:${v};`).join('\n ');
4087
3789
  this.shadowRoot.innerHTML = `
@@ -5172,16 +4874,43 @@ class AIChatDialog extends HTMLElement {
5172
4874
  :host(.dark-theme) blockquote { background: rgba(110, 168, 254, 0.08); }
5173
4875
  :host(.dark-theme) th { background: rgba(110, 168, 254, 0.12); }
5174
4876
  :host(.dark-theme) hr { border-top-color: var(--ai-border); }
4877
+
4878
+ /* ========== 插槽样式(自定义内容区域) ========== */
4879
+ /* header-title 插槽 */
4880
+ ::slotted([slot="header-title"]) {
4881
+ font-size: var(--ai-font-title, 15px);
4882
+ font-weight: 650;
4883
+ color: var(--ai-text);
4884
+ overflow: hidden;
4885
+ text-overflow: ellipsis;
4886
+ white-space: nowrap;
4887
+ }
4888
+ /* input-prepend 插槽 — 输入区上方附加内容 */
4889
+ ::slotted([slot="input-prepend"]) {
4890
+ display: block;
4891
+ padding: 0 4px 8px;
4892
+ }
4893
+ /* footer 插槽 */
4894
+ ::slotted([slot="footer"]) {
4895
+ display: flex;
4896
+ justify-content: space-between;
4897
+ gap: 12px;
4898
+ color: #b5bbc5;
4899
+ font-size: 12px;
4900
+ line-height: 1;
4901
+ }
5175
4902
  </style>
5176
4903
 
5177
4904
  <div class="ai-float-container">
5178
4905
  <!-- 对话框 -->
5179
4906
  <div class="ai-chat-dialog">
5180
- <!-- 头部(含展开/关闭按钮) -->
5181
- <div class="dialog-header">
5182
- <div class="header-left">
5183
- <span class="header-title">${this.escapeHtml(this._config?.title || 'AI 助手')}</span>
5184
- </div>
4907
+ <!-- 头部(含展开/关闭按钮) -->
4908
+ <div class="dialog-header">
4909
+ <div class="header-left">
4910
+ <slot name="header-title">
4911
+ <span class="header-title">${this.escapeHtml(this._config?.title || 'AI 助手')}</span>
4912
+ </slot>
4913
+ </div>
5185
4914
  <div class="header-right">
5186
4915
  <button class="new-chat-btn history-btn" type="button" title="历史记录" aria-label="历史记录">
5187
4916
  <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>
@@ -5205,9 +4934,10 @@ class AIChatDialog extends HTMLElement {
5205
4934
  <!-- 消息区域 -->
5206
4935
  <div class="dialog-body" id="messagesContainer"></div>
5207
4936
 
5208
- <!-- 输入区域 -->
5209
- <div class="dialog-footer">
5210
- <div class="input-container" id="inputContainer">
4937
+ <!-- 输入区域 -->
4938
+ <div class="dialog-footer">
4939
+ <slot name="input-prepend"></slot>
4940
+ <div class="input-container" id="inputContainer">
5211
4941
  <textarea class="message-input" id="msgInput"
5212
4942
  placeholder="请输入您的问题..." autocomplete="off" rows="2"></textarea>
5213
4943
  <div class="input-tools">
@@ -5220,10 +4950,12 @@ class AIChatDialog extends HTMLElement {
5220
4950
  </button>
5221
4951
  </div>
5222
4952
  </div>
5223
- <div class="footer-note">
5224
- <span class="footer-note-left">${this.escapeHtml(this._config?.footerDisclaimer || '')}</span>
5225
- <span class="footer-note-right">${this.escapeHtml(this._config?.footerIdentity || '')}</span>
5226
- </div>
4953
+ <div class="footer-note">
4954
+ <slot name="footer">
4955
+ <span class="footer-note-left">${this.escapeHtml(this._config?.footerDisclaimer || '')}</span>
4956
+ <span class="footer-note-right">${this.escapeHtml(this._config?.footerIdentity || '')}</span>
4957
+ </slot>
4958
+ </div>
5227
4959
  </div>
5228
4960
  </div>
5229
4961
 
@@ -5231,7 +4963,6 @@ class AIChatDialog extends HTMLElement {
5231
4963
  <div class="float-button" id="floatBtn" title="打开AI助手"></div>
5232
4964
  </div>
5233
4965
  `;
5234
-
5235
4966
  // 缓存DOM引用
5236
4967
  this._dialog = this.shadowRoot.querySelector('.ai-chat-dialog');
5237
4968
  this._body = this.shadowRoot.querySelector('#messagesContainer');
@@ -5253,28 +4984,21 @@ class AIChatDialog extends HTMLElement {
5253
4984
  requestAnimationFrame(() => {
5254
4985
  // 关闭按钮
5255
4986
  if (this._closeBtn) this._closeBtn.addEventListener('click', () => this.close());
5256
-
5257
4987
  // 展开/收起按钮
5258
4988
  if (this._expandBtn) this._expandBtn.addEventListener('click', () => this.toggleExpand());
5259
-
5260
4989
  // 新会话按钮
5261
4990
  if (this._newChatBtn) this._newChatBtn.addEventListener('click', () => this.clearChat());
5262
-
5263
4991
  // 历史记录按钮
5264
4992
  if (this._historyBtn) this._historyBtn.addEventListener('click', () => this.toggleHistory());
5265
-
5266
4993
  // 悬浮按钮打开
5267
4994
  if (this._floatBtn) this._floatBtn.addEventListener('click', () => this.open());
5268
-
5269
4995
  // 发送按钮
5270
4996
  if (this._sendBtn) this._sendBtn.addEventListener('click', () => this.handleSend());
5271
-
5272
4997
  // 附件选择
5273
4998
  if (this._attachBtn && this._attachmentInput) {
5274
4999
  this._attachBtn.addEventListener('click', () => this._attachmentInput.click());
5275
5000
  this._attachmentInput.addEventListener('change', () => this._handleAttachmentSelect());
5276
5001
  }
5277
-
5278
5002
  // 输入回车发送
5279
5003
  if (this._input) {
5280
5004
  this._autoResizeInput();
@@ -5290,19 +5014,15 @@ class AIChatDialog extends HTMLElement {
5290
5014
  }
5291
5015
  });
5292
5016
  }
5293
-
5294
5017
  // 拖拽(内嵌模式禁用)— 由 init() 在 _config 就绪后触发
5295
5018
  // initDraggable 延迟到 init() 中执行以免 _config 为空
5296
5019
  });
5297
5020
  }
5298
-
5299
5021
  // ==================== 展开/收起 ====================
5300
-
5301
5022
  toggleExpand() {
5302
5023
  this._isExpanded = !this._isExpanded;
5303
5024
  const dlg = this._dialog;
5304
5025
  if (!dlg) return;
5305
-
5306
5026
  // P2-17: 移动端始终全屏,展开/收起无意义(与Vue版 dialogStyle 一致)
5307
5027
  if (this._isMobile) {
5308
5028
  this._isExpanded = false; // 移动端不记录展开状态
@@ -5339,13 +5059,10 @@ class AIChatDialog extends HTMLElement {
5339
5059
  detail: this._isExpanded
5340
5060
  }));
5341
5061
  }
5342
-
5343
5062
  // ==================== 拖拽(与Vue startDrag/onDrag/stopDrag 一致) ====================
5344
-
5345
5063
  initDraggable() {
5346
5064
  const header = this.shadowRoot?.querySelector('.dialog-header');
5347
5065
  if (!header) return;
5348
-
5349
5066
  // 清理上一次遗留的 document 级监听(SPA 路由切换场景)
5350
5067
  this._cleanupDragListeners();
5351
5068
  const self = this;
@@ -5373,7 +5090,6 @@ class AIChatDialog extends HTMLElement {
5373
5090
  self._dialog.classList.remove('dragging');
5374
5091
  }
5375
5092
  };
5376
-
5377
5093
  // 鼠标事件(桌面端)— 保存引用以便清理
5378
5094
  this._dragMouseDownHandler = e => {
5379
5095
  if (e.target.closest('button, .header-icon')) return;
@@ -5387,7 +5103,6 @@ class AIChatDialog extends HTMLElement {
5387
5103
  header.addEventListener('mousedown', this._dragMouseDownHandler);
5388
5104
  document.addEventListener('mousemove', this._dragMouseMoveHandler);
5389
5105
  document.addEventListener('mouseup', this._dragMouseUpHandler);
5390
-
5391
5106
  // P1-7: 触摸事件(移动端,与Vue版一致)
5392
5107
  this._dragTouchStartHandler = e => {
5393
5108
  if (self._isExpanded) return;
@@ -5410,7 +5125,6 @@ class AIChatDialog extends HTMLElement {
5410
5125
  document.addEventListener('touchend', this._dragTouchEndHandler);
5411
5126
  this._dragInitialized = true;
5412
5127
  }
5413
-
5414
5128
  // P0: 清理拖拽事件监听(SPA disconnectedCallback / re-init 调用)
5415
5129
  _cleanupDragListeners() {
5416
5130
  if (this._dragMouseDownHandler) {
@@ -5442,12 +5156,10 @@ class AIChatDialog extends HTMLElement {
5442
5156
  // 更新标题
5443
5157
  const titleEl = this.shadowRoot.querySelector('.header-title');
5444
5158
  if (titleEl && this._config.title) titleEl.textContent = this._config.title;
5445
-
5446
5159
  // 更新placeholder
5447
5160
  if (this._input && this._config.placeholder) this._input.placeholder = this._config.placeholder;
5448
5161
  // P1-11: 动态设置输入框最大长度
5449
5162
  if (this._input && this._config.maxLength) this._input.maxLength = this._config.maxLength;
5450
-
5451
5163
  // ====== 主题处理:16种字符串预设 + 对象自定义 ======
5452
5164
  const t = this._config.theme;
5453
5165
  const host = this.shadowRoot.host;
@@ -5476,7 +5188,6 @@ class AIChatDialog extends HTMLElement {
5476
5188
  }
5477
5189
  host.classList.toggle('dark-theme', ['dark', 'starsky'].includes(t.toLowerCase()));
5478
5190
  }
5479
-
5480
5191
  // 对象形式自定义主题 - 也先重置再合并
5481
5192
  if (t && typeof t === 'object') {
5482
5193
  this._resetThemeVars();
@@ -5491,7 +5202,6 @@ class AIChatDialog extends HTMLElement {
5491
5202
  });
5492
5203
  host.classList.remove('dark-theme');
5493
5204
  }
5494
-
5495
5205
  // 应用所有CSS变量到host
5496
5206
  Object.entries(this._themeVars).forEach(([k, v]) => host.style.setProperty(k, v));
5497
5207
  }
@@ -5546,9 +5256,7 @@ class AIChatDialog extends HTMLElement {
5546
5256
  questions
5547
5257
  };
5548
5258
  }
5549
-
5550
5259
  // ==================== 渲染消息(与Vue模板结构一致) ====================
5551
-
5552
5260
  renderMessages(options = {}) {
5553
5261
  if (!this._body) return;
5554
5262
  if (this._historyVisible) {
@@ -5610,14 +5318,12 @@ class AIChatDialog extends HTMLElement {
5610
5318
  </div>
5611
5319
  </div>`;
5612
5320
  });
5613
-
5614
5321
  // 加载状态 — 有执行过程时不展示思考中
5615
5322
  if (this._isLoading && !runtimeExists) {
5616
5323
  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>';
5617
5324
  }
5618
5325
  html += '</div>';
5619
5326
  this._body.innerHTML = html;
5620
-
5621
5327
  // 绑定复制事件
5622
5328
  this._body.querySelectorAll('.copy-btn').forEach(btn => {
5623
5329
  btn.addEventListener('click', () => {
@@ -5626,7 +5332,6 @@ class AIChatDialog extends HTMLElement {
5626
5332
  if (msg) this.copyMessage(msg.content, idx);
5627
5333
  });
5628
5334
  });
5629
-
5630
5335
  // 绑定重新生成事件
5631
5336
  this._body.querySelectorAll('.regenerate-btn').forEach(btn => {
5632
5337
  btn.addEventListener('click', () => {
@@ -5634,7 +5339,6 @@ class AIChatDialog extends HTMLElement {
5634
5339
  this.regenerate(idx);
5635
5340
  });
5636
5341
  });
5637
-
5638
5342
  // P4: 绑定自定义操作按钮
5639
5343
  this._body.querySelectorAll('.custom-action-btn').forEach(btn => {
5640
5344
  btn.addEventListener('click', () => {
@@ -5652,7 +5356,6 @@ class AIChatDialog extends HTMLElement {
5652
5356
  }
5653
5357
  });
5654
5358
  });
5655
-
5656
5359
  // 绑定执行过程面板折叠/展开(Shadow DOM 下 inline onclick 不可靠)
5657
5360
  this._body.querySelectorAll('.runtime-header').forEach(header => {
5658
5361
  header.addEventListener('click', () => {
@@ -5895,9 +5598,7 @@ class AIChatDialog extends HTMLElement {
5895
5598
  }
5896
5599
  this._updateSendButtonState();
5897
5600
  }
5898
-
5899
5601
  // ==================== 发送消息(与Vue sendMessage 一致) ====================
5900
-
5901
5602
  async handleSend() {
5902
5603
  const content = this._input ? this._input.value.trim() : '';
5903
5604
  const attachments = [...(this._attachments || [])];
@@ -5906,14 +5607,12 @@ class AIChatDialog extends HTMLElement {
5906
5607
  return;
5907
5608
  }
5908
5609
  if (this._isLoading || this._streaming) return;
5909
-
5910
5610
  // P1-11: 字数限制检查
5911
5611
  const maxLen = this._config?.maxLength ?? 500;
5912
5612
  if (content.length > maxLen) {
5913
5613
  this.showToast(`输入内容不能超过${maxLen}个字符(当前${content.length}字)`);
5914
5614
  return;
5915
5615
  }
5916
-
5917
5616
  // 防抖:500ms内不允许重复发送
5918
5617
  const now = Date.now();
5919
5618
  if (this._lastSendTime && now - this._lastSendTime < 500) return;
@@ -5961,7 +5660,6 @@ class AIChatDialog extends HTMLElement {
5961
5660
  attachmentIds.push(res.data.attachmentId);
5962
5661
  }
5963
5662
  }
5964
-
5965
5663
  // P3: 收集页面上下文(setContext + onBeforeSend)
5966
5664
  let context = {
5967
5665
  ...(this._context || {})
@@ -6040,10 +5738,9 @@ class AIChatDialog extends HTMLElement {
6040
5738
  }
6041
5739
  }
6042
5740
  async mockResponse(userContent) {
6043
- await new Promise(r => setTimeout(r, 600 + Math.random() * 800));
5741
+ await new Promise(r => window.setTimeout(r, 600 + Math.random() * 800));
6044
5742
  const responses = [`关于"${(userContent || '').substring(0, 20)}"这个问题,我来为您详细解答...`, `这是一个很好的问题!根据我的理解:\n\n1. 首先,我们需要分析需求\n2. 其次,设计实现方案\n3. 最后,进行测试验证`, `收到您的问题。让我来帮您分析一下...\n\n根据您的描述,我建议您可以按照以下步骤操作:`, `感谢您的提问!以下是我的看法:\n\n• 第一点很关键,需要注意细节\n• 第二点值得关注\n• 第三点是核心所在`];
6045
5743
  const mockContent = responses[Math.floor(Math.random() * responses.length)];
6046
-
6047
5744
  // 流式效果
6048
5745
  const tempId = this.generateId();
6049
5746
  this._messages.push({
@@ -6054,7 +5751,7 @@ class AIChatDialog extends HTMLElement {
6054
5751
  });
6055
5752
  this.renderMessages();
6056
5753
  for (let i = 0; i < mockContent.length; i++) {
6057
- await new Promise(r => setTimeout(r, 12 + Math.random() * 20));
5754
+ await new Promise(r => window.setTimeout(r, 12 + Math.random() * 20));
6058
5755
  const msgIdx = this._messages.findIndex(m => m.id === tempId);
6059
5756
  if (msgIdx >= 0) {
6060
5757
  this._messages[msgIdx].content = mockContent.substring(0, i + 1);
@@ -6086,9 +5783,7 @@ class AIChatDialog extends HTMLElement {
6086
5783
  if (idx >= 0) delete this._messages[idx]._isStreaming;
6087
5784
  this.renderMessages();
6088
5785
  }
6089
-
6090
5786
  // P0: 会话ID管理
6091
- _conversationId = null;
6092
5787
  async _directApiCallStream(msgId, content, requestOptions = {}) {
6093
5788
  if (!this._chatClient) {
6094
5789
  this._chatClient = new AIChatClient(this._config || {});
@@ -6279,10 +5974,8 @@ class AIChatDialog extends HTMLElement {
6279
5974
  const idx = this._messages.findIndex(m => m.id === msgId);
6280
5975
  if (idx < 0) return;
6281
5976
  this._messages[idx].content = content;
6282
-
6283
5977
  // Detect if there are runtime events (for typewriter mode check)
6284
5978
  const hasRuntime = !!(this._messages[idx]._runtimeEvents && this._messages[idx]._runtimeEvents.length > 0);
6285
-
6286
5979
  // Accumulate full content
6287
5980
  if (content.startsWith(this._streamFullText)) {
6288
5981
  this._streamFullText = content;
@@ -6343,7 +6036,6 @@ class AIChatDialog extends HTMLElement {
6343
6036
  this.renderMessages();
6344
6037
  }
6345
6038
  }
6346
-
6347
6039
  // 运行时占位符过滤(对齐 portal)
6348
6040
  _isPlaceholder(text) {
6349
6041
  if (!text || typeof text !== 'string') return false;
@@ -6362,14 +6054,11 @@ class AIChatDialog extends HTMLElement {
6362
6054
  } catch (e) {}
6363
6055
  return false;
6364
6056
  }
6365
-
6366
6057
  // 判断错误标记内容(替换脆弱的前缀检查 startsWith('('))
6367
- _ERROR_CONTENT_PATTERNS = ['(请求超时', '(等待AI处理', '(无回复)', '(已停止)', '(AI 处理超时', '错误:', '网络错误:', '抱歉,'];
6368
6058
  _isErrorContent(content) {
6369
6059
  if (!content) return true;
6370
6060
  return this._ERROR_CONTENT_PATTERNS.some(p => content.startsWith(p));
6371
6061
  }
6372
-
6373
6062
  // P3: 将上下文对象格式化为可读文本(拼入 prompt 前缀)
6374
6063
  _formatContextText(context) {
6375
6064
  if (!context || typeof context !== 'object') return '';
@@ -6390,7 +6079,6 @@ class AIChatDialog extends HTMLElement {
6390
6079
  }
6391
6080
  return lines.join('\n');
6392
6081
  }
6393
-
6394
6082
  // 运行时事件管理 – incremental DOM, no renderMessages
6395
6083
  _addRuntimeEvent(msgId, event) {
6396
6084
  const idx = this._messages.findIndex(m => m.id === msgId);
@@ -6418,7 +6106,6 @@ class AIChatDialog extends HTMLElement {
6418
6106
  if (this._shouldAutoScroll()) this.scrollToBottom();
6419
6107
  return;
6420
6108
  }
6421
-
6422
6109
  // Path 2: first event – inject runtime panel DOM next to the streaming bubble
6423
6110
  const msgContent = this._findStreamingMessageContent();
6424
6111
  if (msgContent) {
@@ -6485,7 +6172,6 @@ class AIChatDialog extends HTMLElement {
6485
6172
  panel.appendChild(eventsContainer);
6486
6173
  return panel;
6487
6174
  }
6488
-
6489
6175
  // P4: 获取自定义操作按钮列表(缓存结果避免重复调用 onMessageActions)
6490
6176
  _getCustomActions(msg, idx) {
6491
6177
  const key = '_customActions_' + idx;
@@ -6499,7 +6185,6 @@ class AIChatDialog extends HTMLElement {
6499
6185
  }
6500
6186
  return msg[key] || [];
6501
6187
  }
6502
-
6503
6188
  // P4: 生成自定义操作按钮 HTML
6504
6189
  _buildCustomActions(msg, idx) {
6505
6190
  const actions = this._getCustomActions(msg, idx);
@@ -6525,7 +6210,7 @@ class AIChatDialog extends HTMLElement {
6525
6210
  }
6526
6211
  async _fetchConversationResult(conversationId) {
6527
6212
  for (let i = 0; i < 8; i++) {
6528
- await new Promise(r => setTimeout(r, 1000));
6213
+ await new Promise(r => window.setTimeout(r, 1000));
6529
6214
  try {
6530
6215
  const response = await this._chatClient.queryConversation({
6531
6216
  conversationId,
@@ -6541,9 +6226,7 @@ class AIChatDialog extends HTMLElement {
6541
6226
  }
6542
6227
  return '(AI 处理超时,请稍后查看对话记录)';
6543
6228
  }
6544
-
6545
6229
  // ==================== 重新生成(与Vue regenerate 一致) ====================
6546
-
6547
6230
  async regenerate(index) {
6548
6231
  if (this._isLoading || this._streaming) return;
6549
6232
  const aiMessage = this._messages[index];
@@ -6588,14 +6271,12 @@ class AIChatDialog extends HTMLElement {
6588
6271
  toast.className = 'error-toast';
6589
6272
  toast.textContent = msg;
6590
6273
  this._dialog?.appendChild(toast);
6591
- setTimeout(() => toast.remove(), 3000);
6274
+ window.setTimeout(() => toast.remove(), 3000);
6592
6275
  }
6593
-
6594
6276
  // P1-6: 精细化错误处理(与Vue版 handleErrorMsg 一致,按HTTP状态码+业务错误码分类)
6595
6277
  handleError(err) {
6596
6278
  let displayMsg = '抱歉,网络请求失败,请稍后重试';
6597
6279
  const errMsg = err?.message || '';
6598
-
6599
6280
  // 按错误类型分类
6600
6281
  if (errMsg.includes('Failed to fetch') || errMsg.includes('NetworkError') || errMsg.includes('网络')) {
6601
6282
  displayMsg = '网络连接失败,请检查网络后重试';
@@ -6629,9 +6310,7 @@ class AIChatDialog extends HTMLElement {
6629
6310
  detail: err
6630
6311
  }));
6631
6312
  }
6632
-
6633
6313
  // ==================== 复制(与Vue copyMessage 一致) ====================
6634
-
6635
6314
  async copyContent(text) {
6636
6315
  // P1-10: 微信环境优先使用 wx.setClipboardData(与Vue版一致)
6637
6316
  if (typeof wx !== 'undefined' && wx.setClipboardData) {
@@ -6674,7 +6353,7 @@ class AIChatDialog extends HTMLElement {
6674
6353
  await this.copyContent(content);
6675
6354
  if (this._messages[idx]) this._messages[idx].copied = true;
6676
6355
  this.renderMessages();
6677
- setTimeout(() => {
6356
+ window.setTimeout(() => {
6678
6357
  if (this._messages[idx]) {
6679
6358
  this._messages[idx].copied = false;
6680
6359
  this.renderMessages();
@@ -6723,9 +6402,7 @@ class AIChatDialog extends HTMLElement {
6723
6402
  }
6724
6403
  return response;
6725
6404
  }
6726
-
6727
6405
  // ==================== 工具函数 ====================
6728
-
6729
6406
  generateId() {
6730
6407
  return `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
6731
6408
  }
@@ -6733,7 +6410,6 @@ class AIChatDialog extends HTMLElement {
6733
6410
  const n = new Date();
6734
6411
  return `${String(n.getHours()).padStart(2, '0')}:${String(n.getMinutes()).padStart(2, '0')}`;
6735
6412
  }
6736
-
6737
6413
  /**
6738
6414
  * 调试日志(仅在 config.debug === true 时输出)
6739
6415
  */
@@ -6757,7 +6433,6 @@ class AIChatDialog extends HTMLElement {
6757
6433
  if (!s) return '';
6758
6434
  return s.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
6759
6435
  }
6760
-
6761
6436
  /**
6762
6437
  * 重置 _themeVars 为默认值(主题切换时调用,防止残留)
6763
6438
  */
@@ -6799,7 +6474,6 @@ class AIChatDialog extends HTMLElement {
6799
6474
  '--ai-font-small': '11px'
6800
6475
  });
6801
6476
  }
6802
-
6803
6477
  /**
6804
6478
  * Markdown → HTML 解析(仅用于AI回复,用户消息保持纯文本)
6805
6479
  * 使用 marked + DOMPurify 双重保障安全
@@ -6823,7 +6497,6 @@ class AIChatDialog extends HTMLElement {
6823
6497
  }
6824
6498
  }
6825
6499
  }
6826
-
6827
6500
  // 注册自定义元素
6828
6501
  if (!customElements.get('ai-chat-dialog')) {
6829
6502
  customElements.define('ai-chat-dialog', AIChatDialog);
@@ -6835,17 +6508,15 @@ if (typeof window !== 'undefined') {
6835
6508
  /**
6836
6509
  * IBC AI Web SDK - 纯JavaScript版本
6837
6510
  * 支持任意前端框架:Vue, React, Angular, 原生HTML等
6838
- *
6511
+ *
6839
6512
  * @author IBC AI Team
6840
- * @version 2.0.5
6513
+ * @version 2.1.0
6841
6514
  */
6842
-
6843
-
6515
+ // 导出组件
6844
6516
  // 快速初始化函数
6845
6517
  function createAIChatDialog(options = {}) {
6846
6518
  // 创建自定义元素实例
6847
6519
  const dialog = document.createElement('ai-chat-dialog');
6848
-
6849
6520
  // 设置属性
6850
6521
  if (options.title) dialog.setAttribute('title', options.title);
6851
6522
  if (options.placeholder) dialog.setAttribute('placeholder', options.placeholder);
@@ -6854,7 +6525,6 @@ function createAIChatDialog(options = {}) {
6854
6525
  if (options.height) dialog.style.setProperty('--ai-dialog-height', typeof options.height === 'number' ? `${options.height}px` : options.height);
6855
6526
  if (options.top != null) dialog.style.setProperty('--ai-dialog-top', typeof options.top === 'number' ? `${options.top}px` : options.top);
6856
6527
  if (options.right != null) dialog.style.setProperty('--ai-dialog-right', typeof options.right === 'number' ? `${options.right}px` : options.right);
6857
-
6858
6528
  // 挂载到指定容器或 body
6859
6529
  if (options.target) {
6860
6530
  const container = typeof options.target === 'string' ? document.querySelector(options.target) : options.target;
@@ -6868,12 +6538,10 @@ function createAIChatDialog(options = {}) {
6868
6538
  } else {
6869
6539
  document.body.appendChild(dialog);
6870
6540
  }
6871
-
6872
6541
  // 初始化配置
6873
6542
  if (Object.keys(options).length > 0) {
6874
6543
  dialog.init(options);
6875
6544
  }
6876
-
6877
6545
  // 行内模式:挂载到 DOM 后直接展开
6878
6546
  if (options.target) {
6879
6547
  requestAnimationFrame(() => {
@@ -6898,14 +6566,12 @@ function createAIChatDialog(options = {}) {
6898
6566
  }
6899
6567
  return dialog;
6900
6568
  }
6901
-
6902
6569
  // Vue插件安装方式(向后兼容)
6903
6570
  function installVuePlugin(Vue) {
6904
6571
  if (!Vue) {
6905
6572
  console.warn('[AI Web SDK] Vue instance not provided');
6906
6573
  return;
6907
6574
  }
6908
-
6909
6575
  // 注册全局组件包装器
6910
6576
  Vue.component('AiChatWrapper', {
6911
6577
  props: {
@@ -6961,7 +6627,6 @@ function installVuePlugin(Vue) {
6961
6627
  methods: {
6962
6628
  initDialog() {
6963
6629
  this.dialogInstance = createAIChatDialog(this.config || {});
6964
-
6965
6630
  // 监听事件并转发
6966
6631
  const events = ['open', 'close', 'message-send', 'message-received', 'error'];
6967
6632
  events.forEach(event => {
@@ -6989,9 +6654,6 @@ function installVuePlugin(Vue) {
6989
6654
  }
6990
6655
  });
6991
6656
  }
6992
-
6993
- // React Hook(可选) — 通过 window.React 获取 hooks,兼容 CDN 全局引入
6994
- /* global React */
6995
6657
  function useAIChat(options = {}) {
6996
6658
  if (typeof React === 'undefined') {
6997
6659
  console.warn('[AI Web SDK] React is not loaded, useAIChat skipped');
@@ -7015,7 +6677,6 @@ function useAIChat(options = {}) {
7015
6677
  useEffect(() => {
7016
6678
  if (!dialogRef.current) {
7017
6679
  dialogRef.current = createAIChatDialog(options);
7018
-
7019
6680
  // 监听事件
7020
6681
  dialogRef.current.addEventListener('message-send', e => {
7021
6682
  setMessages(prev => [...prev, e.detail]);
@@ -7070,7 +6731,6 @@ function useAIChat(options = {}) {
7070
6731
  ref: dialogRef
7071
6732
  };
7072
6733
  }
7073
-
7074
6734
  // 默认导出
7075
6735
  var index = {
7076
6736
  AIChatDialog,
@@ -7078,14 +6738,13 @@ var index = {
7078
6738
  createAIChatDialog,
7079
6739
  installVuePlugin,
7080
6740
  useAIChat,
7081
- version: '2.0.5'
6741
+ version: '2.1.0'
7082
6742
  };
7083
-
7084
6743
  // 全局暴露(UMD/浏览器环境)
7085
6744
  if (typeof window !== 'undefined') {
7086
6745
  window.AICreateChatDialog = createAIChatDialog;
7087
6746
  window.AIWebSDK = {
7088
- version: '2.0.5',
6747
+ version: '2.1.0',
7089
6748
  create: createAIChatDialog,
7090
6749
  AIChatDialog,
7091
6750
  AIChatClient,