From e23b70ffcaf41ba0163e6b39c6fe28a4d4aaf1f7 Mon Sep 17 00:00:00 2001 From: wanghanlin <1533525126@qq.com> Date: Tue, 18 Aug 2026 18:52:04 +0800 Subject: [PATCH] =?UTF-8?q?feat(client):=20SDK=20=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=94=B9=E7=94=A8=20TDesign=20Web=20Componen?= =?UTF-8?q?ts=20=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 聊天核心:消息气泡/输入框/操作栏/加载态改用 t-chat-message/t-chat-sender/t-chat-action/t-chat-loading - 外围 UI:知识库下拉/推荐问题/离线横幅改用 t-select/t-tag/t-alert - Markdown 渲染由 t-chat-item 内置 cherry-markdown 承担,移除自研 marked 渲染器与 marked.min.js - 构建管线:引入 tdesign-web-components@1.2.10 按需打包,mermaid 用本地 stub 替换省约 1.2MB - 清理重构后死代码与死样式(escapeHtml/getLocale/appendStreamingCaret/offlineBannerEl 等) - 同步更新测试面板断言(T3/T6/T10 适配 t-chat-sender)与 README/CLAUDE.md --- client/CLAUDE.md | 10 +- client/README.md | 20 +- client/assets/marked.min.js | 69 - client/package-lock.json | 2526 ++++++++++++++++++++++- client/package.json | 6 + client/rollup.config.js | 24 +- client/src/chat.ts | 257 +-- client/src/dom.ts | 611 +++--- client/src/i18n.ts | 7 - client/src/index.ts | 86 +- client/src/markdown.ts | 242 --- client/src/mermaid-stub.ts | 39 + client/src/styles.ts | 581 +----- client/src/utils.ts | 12 - frontend/src/sdk-test/SdkTestPanel.vue | 27 +- src/main/resources/static/sdk/test.html | 4 +- 16 files changed, 3046 insertions(+), 1475 deletions(-) delete mode 100644 client/assets/marked.min.js delete mode 100644 client/src/markdown.ts create mode 100644 client/src/mermaid-stub.ts diff --git a/client/CLAUDE.md b/client/CLAUDE.md index 5d1cdbf..ded1e16 100644 --- a/client/CLAUDE.md +++ b/client/CLAUDE.md @@ -25,7 +25,7 @@ npm run dev - 构建工具:Rollup + `@rollup/plugin-typescript` + `@rollup/plugin-terser`,配置见 `rollup.config.js` - TypeScript 配置:`tsconfig.json`,`target: ES2017`,`strict: true`,`rootDir: ./src`,不生成 `.d.ts` -- 产物双份:`chatbot-sdk.js`(未压缩 + sourcemap,~93KB)和 `chatbot-sdk.min.js`(压缩,~45KB) +- 产物双份:`chatbot-sdk.js`(未压缩 + sourcemap,~5.6MB)和 `chatbot-sdk.min.js`(压缩,~4.0MB,gzip ~1.1MB)。体积主要由内置的 TDesign Web Components 组件库贡献(按需 tree-shaking 后打包进 IIFE) - **无测试框架**:验证通过后端的 `http://localhost:9090/sdk/test.html` 运行 10 个浏览器端核心用例(见 README 第十四节),本工程内没有可运行的自动化测试 ## 运行时依赖 @@ -64,11 +64,11 @@ init(rawConfig) ### 关键模块 -- **`chat.ts`**(最大、最核心):对话状态机。处理发送、SSE 流式追加、Markdown 渲染、RAG 来源展示、流中断兜底、无流内容降级为同步、`chatId` 自动管理逻辑、清空会话。修改对话行为优先改这里。 +- **`chat.ts`**(最大、最核心):对话状态机。处理发送、SSE 流式追加、RAG 来源展示、流中断兜底、无流内容降级为同步、`chatId` 自动管理逻辑、清空会话。Markdown 渲染由 `t-chat-item` 内置 cherry-markdown 处理。修改对话行为优先改这里。 - **`api.ts`**:HTTP 封装 + SSE 流解析。三种 SSE 接口(普通流式、RAG 流式、同步)的解析逻辑都在这里,注意流式解析的边界处理。 - **`dom.ts`**:纯 DOM 构建与事件绑定,含知识库下拉、RAG 来源卡片、历史会话面板的渲染。 -- **`styles.ts`**:所有 CSS 字符串模板,按 `primaryColor` 动态着色。改动 UI 视觉改这里,**不要**在 `dom.ts` 里写内联样式。 -- **`markdown.ts`**:基于 marked(源文件 `assets/marked.min.js`,实际为 **v15.0.12**,构建时由 rollup 自动复制到 `dist/` 与后端 `static/sdk/`)的 Markdown 渲染器,`preloadMarked` 异步加载并缓存安全实例。**安全模型**:自定义 renderer 全接管输出,链接/图片仅允许 http/https,禁止 raw HTML,代码内容 escapeHtml 转义;修改渲染器时必须维持这一 XSS 防护顺序。**列表渲染坑**:`list(token)` 渲染列表项必须调用 `this.listitem(item)`,**不可** `this.parser.parse([item])` —— marked v15 的 `Parser.parse` 按 `token.type` 做 switch 分发、无 `list_item` 分支,直接 parse 会抛 `Token with "list_item" type was not found`,被 `renderMarkdown` 的 catch 降级为纯文本,导致整段回复挤成一行。 +- **`styles.ts`**:所有 CSS 字符串模板,按 `primaryColor` 动态着色,并通过 `--td-*` CSS 变量透传给 TDesign 组件。改动 UI 视觉改这里,**不要**在 `dom.ts` 里写内联样式。 +- **`markdown.ts`**:已废弃并移除。原基于 marked 的 Markdown 渲染器改由 TDesign Chat 组件(`t-chat-item`)内置 cherry-markdown 承担,无需额外加载 `marked.min.js`。cherry-markdown 的 XSS 防护由 TDesign 组件保证;如后续需要自定义渲染,仍需维持白名单/转义等安全策略。 ### 单例与生命周期 @@ -102,4 +102,4 @@ init(rawConfig) ## 部署 -构建脚本(`rollup.config.js` 的 `copyAssets` 插件)会自动把 `chatbot-sdk.js` / `chatbot-sdk.min.js`、`marked.min.js`(运行时依赖,由 `markdown.ts` 动态加载)和 `launcher-logo.png` 复制到后端 `src/main/resources/static/sdk/`,宿主页面通过 `` 引入;CDN 分发时需同时部署这三类文件,且 `marked.min.js` 必须与 SDK 同目录(`getSdkBasePath()` 从 script src 推断加载路径)。`README.md` 有完整接入示例与全部配置参数表,文档是 SDK 对外契约的一部分,改公开 API(`init/destroy/open/close/toggle/clearHistory`)或 `SDKConfig` 字段时同步更新 README。 +构建脚本(`rollup.config.js` 的 `copyAssets` 插件)会自动把 `chatbot-sdk.js` / `chatbot-sdk.min.js` 和 `launcher-logo.png` 复制到后端 `src/main/resources/static/sdk/`,宿主页面通过 `` 引入即可;CDN 分发时同样只需部署这三类文件(`chatbot-sdk.js` / `chatbot-sdk.min.js` / `launcher-logo.png`)。`README.md` 有完整接入示例与全部配置参数表,文档是 SDK 对外契约的一部分,改公开 API(`init/destroy/open/close/toggle/clearHistory`)或 `SDKConfig` 字段时同步更新 README。 diff --git a/client/README.md b/client/README.md index 974ea86..49ab818 100644 --- a/client/README.md +++ b/client/README.md @@ -63,10 +63,10 @@ SDK 产物位于 `client/dist/` 目录: | 文件 | 大小 | 说明 | |------|------|------| -| `chatbot-sdk.js` | 93KB | 未压缩开发版(含 sourcemap) | -| `chatbot-sdk.min.js` | 45KB | 压缩生产版(gzip ~15KB) | +| `chatbot-sdk.js` | ~5.6MB | 未压缩开发版(含 sourcemap) | +| `chatbot-sdk.min.js` | ~4.0MB | 压缩生产版(gzip ~1.1MB) | -**部署路径:** 将 `.min.js` 文件上传到后端 `static/sdk/` 目录或任意 CDN。 +**部署路径:** 将 `.min.js` 文件上传到后端 `static/sdk/` 目录或任意 CDN。SDK 内置 TDesign Web Components 组件库(`t-chat-*` + 通用组件),按需 tree-shaking 后打包进 IIFE,无需额外加载组件库 CDN。 --- @@ -131,9 +131,9 @@ AI 回复支持 Markdown 格式渲染,包括: - 引用块(`>` ) - 水平线(`---`) -> **XSS 安全**:所有非代码块内容先转义 HTML,再转换 Markdown 语法为安全 HTML 标签。代码块内容同样转义。 +> **XSS 安全**:Markdown 渲染由 TDesign Chat 组件内置 cherry-markdown 处理,HTML 标签默认被转义,仅保留安全的 Markdown 语法输出。 -> **实现说明**:渲染基于 marked v15.0.12(外部脚本 `marked.min.js`,SDK 运行时异步加载,未就绪时降级为纯文本)。自定义 renderer 的列表项须用 `this.listitem(item)` 渲染,不能 `this.parser.parse([item])` —— marked v15 的 `Parser.parse` 无 `list_item` 分支,会抛异常并降级为纯文本,导致整段回复换行折叠成一行。 +> **实现说明**:渲染由 TDesign Chat 组件(``)内置 cherry-markdown 承担,无需额外加载 `marked.min.js`。SDK 不再依赖自研 Markdown 渲染器,列表、代码块、表格等样式由 TDesign 统一保证。 ### 4.3 知识库联动 @@ -354,10 +354,11 @@ z-index 分层:悬浮按钮 9998,弹窗 9999。 - **语言**:TypeScript → ES2017 - **打包**:Rollup → IIFE 格式 - **压缩**:Terser -- **Markdown**:基于 marked v15.0.12(`assets/marked.min.js`,构建时自动复制到 `static/sdk/`) +- **UI 组件**:TDesign Web Components 1.2.10(`t-chat-*` 聊天组件 + `t-select`/`t-tag`/`t-button`/`t-alert` 等通用组件) +- **Markdown**:由 TDesign Chat 组件内置 cherry-markdown 渲染 - **国际化**:内置 i18n 字典 - **浏览器兼容**:Chrome 70+, Firefox 70+, Safari 13+, Edge 79+ -- **产物大小**:`.min.js` ~45KB(gzip ~15KB) +- **产物大小**:`.min.js` ~4.0MB(gzip ~1.1MB),体积主要由内置的 TDesign Web Components 组件库贡献(按需 tree-shaking 后) --- @@ -389,9 +390,8 @@ client/ │ ├── storage.ts # localStorage 封装 │ ├── api.ts # HTTP 封装 + SSE 流式 + P1 RAG + P2 会话 │ ├── dom.ts # DOM 构建 + 拖拽 + P1 来源/分类 + P2 面板 -│ ├── styles.ts # CSS 注入 + 主题 + P1 Markdown/来源 + P2 面板 -│ ├── chat.ts # 对话核心 + P1 Markdown/RAG + P2 i18n -│ ├── markdown.ts # P1 Markdown 渲染器(基于 marked v15) +│ ├── styles.ts # CSS 注入 + 主题(--csk-* 与 --td-* 变量透传) +│ ├── chat.ts # 对话核心 + P1 RAG + P2 i18n(Markdown 由 t-chat-item 内置 cherry-markdown 处理) │ ├── i18n.ts # P2 多语言国际化 │ └── utils.ts # UUID、防抖、XSS 转义 ├── dist/ # 构建产物 diff --git a/client/assets/marked.min.js b/client/assets/marked.min.js deleted file mode 100644 index b4e0d73..0000000 --- a/client/assets/marked.min.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * marked v15.0.12 - a markdown parser - * Copyright (c) 2011-2025, Christopher Jeffrey. (MIT Licensed) - * https://github.com/markedjs/marked - */ - -/** - * DO NOT EDIT THIS FILE - * The code in this file is generated from files in ./src/ - */ -(function(g,f){if(typeof exports=="object"&&typeof module<"u"){module.exports=f()}else if("function"==typeof define && define.amd){define("marked",f)}else {g["marked"]=f()}}(typeof globalThis < "u" ? globalThis : typeof self < "u" ? self : this,function(){var exports={};var __exports=exports;var module={exports}; -"use strict";var H=Object.defineProperty;var be=Object.getOwnPropertyDescriptor;var Te=Object.getOwnPropertyNames;var we=Object.prototype.hasOwnProperty;var ye=(l,e)=>{for(var t in e)H(l,t,{get:e[t],enumerable:!0})},Re=(l,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Te(e))!we.call(l,s)&&s!==t&&H(l,s,{get:()=>e[s],enumerable:!(n=be(e,s))||n.enumerable});return l};var Se=l=>Re(H({},"__esModule",{value:!0}),l);var kt={};ye(kt,{Hooks:()=>L,Lexer:()=>x,Marked:()=>E,Parser:()=>b,Renderer:()=>$,TextRenderer:()=>_,Tokenizer:()=>S,defaults:()=>w,getDefaults:()=>z,lexer:()=>ht,marked:()=>k,options:()=>it,parse:()=>pt,parseInline:()=>ct,parser:()=>ut,setOptions:()=>ot,use:()=>lt,walkTokens:()=>at});module.exports=Se(kt);function z(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var w=z();function N(l){w=l}var I={exec:()=>null};function h(l,e=""){let t=typeof l=="string"?l:l.source,n={replace:(s,i)=>{let r=typeof i=="string"?i:i.source;return r=r.replace(m.caret,"$1"),t=t.replace(s,r),n},getRegex:()=>new RegExp(t,e)};return n}var m={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceTabs:/^\t+/,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] /,listReplaceTask:/^\[[ xX]\] +/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^$/,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,unescapeTest:/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig,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")},$e=/^(?:[ \t]*(?:\n|$))+/,_e=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,Le=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,O=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,ze=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,F=/(?:[*+-]|\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=h(ie).replace(/bull/g,F).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(),Me=h(ie).replace(/bull/g,F).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(),Q=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,Pe=/^[^\n]+/,U=/(?!\s*\])(?:\\.|[^\[\]\\])+/,Ae=h(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",U).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),Ee=h(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,F).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",K=/|$))/,Ce=h("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))","i").replace("comment",K).replace("tag",v).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),le=h(Q).replace("hr",O).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[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",v).getRegex(),Ie=h(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",le).getRegex(),X={blockquote:Ie,code:_e,def:Ae,fences:Le,heading:ze,hr:O,html:Ce,lheading:oe,list:Ee,newline:$e,paragraph:le,table:I,text:Pe},re=h("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",O).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[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",v).getRegex(),Oe={...X,lheading:Me,table:re,paragraph:h(Q).replace("hr",O).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[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",v).getRegex()},Be={...X,html:h(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\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:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:I,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:h(Q).replace("hr",O).replace("heading",` *#{1,6} *[^ -]`).replace("lheading",oe).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},qe=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,ve=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,ae=/^( {2,}|\\)\n(?!\s*$)/,De=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\]*?>/g,ue=/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/,je=h(ue,"u").replace(/punct/g,D).getRegex(),Fe=h(ue,"u").replace(/punct/g,pe).getRegex(),he="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",Qe=h(he,"gu").replace(/notPunctSpace/g,ce).replace(/punctSpace/g,W).replace(/punct/g,D).getRegex(),Ue=h(he,"gu").replace(/notPunctSpace/g,He).replace(/punctSpace/g,Ge).replace(/punct/g,pe).getRegex(),Ke=h("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,ce).replace(/punctSpace/g,W).replace(/punct/g,D).getRegex(),Xe=h(/\\(punct)/,"gu").replace(/punct/g,D).getRegex(),We=h(/^<(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=h(K).replace("(?:-->|$)","-->").getRegex(),Ve=h("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",Je).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),q=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,Ye=h(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]*(?:\n[ \t]*)?)(title))?\s*\)/).replace("label",q).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),ke=h(/^!?\[(label)\]\[(ref)\]/).replace("label",q).replace("ref",U).getRegex(),ge=h(/^!?\[(ref)\](?:\[\])?/).replace("ref",U).getRegex(),et=h("reflink|nolink(?!\\()","g").replace("reflink",ke).replace("nolink",ge).getRegex(),J={_backpedal:I,anyPunctuation:Xe,autolink:We,blockSkip:Ne,br:ae,code:ve,del:I,emStrongLDelim:je,emStrongRDelimAst:Qe,emStrongRDelimUnd:Ke,escape:qe,link:Ye,nolink:ge,punctuation:Ze,reflink:ke,reflinkSearch:et,tag:Ve,text:De,url:I},tt={...J,link:h(/^!?\[(label)\]\((.*?)\)/).replace("label",q).getRegex(),reflink:h(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",q).getRegex()},j={...J,emStrongRDelimAst:Ue,emStrongLDelim:Fe,url:h(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,"i").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~\\]))\1(?=[^~]|$)/,text:/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\":">",'"':""","'":"'"},fe=l=>st[l];function R(l,e){if(e){if(m.escapeTest.test(l))return l.replace(m.escapeReplace,fe)}else if(m.escapeTestNoEncode.test(l))return l.replace(m.escapeReplaceNoEncode,fe);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,(i,r,o)=>{let a=!1,c=r;for(;--c>=0&&o[c]==="\\";)a=!a;return a?"|":" |"}),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.length0?-2:-1}function me(l,e,t,n,s){let i=e.href,r=e.title||null,o=l[1].replace(s.other.outputLinkReplace,"$1");n.state.inLink=!0;let a={type:l[0].charAt(0)==="!"?"image":"link",raw:t,href:i,title:r,text:o,tokens:n.inlineTokens(o)};return n.state.inLink=!1,a}function rt(l,e,t){let n=l.match(t.other.indentCodeCompensation);if(n===null)return e;let s=n[1];return e.split(` -`).map(i=>{let r=i.match(t.other.beginningSpace);if(r===null)return i;let[o]=r;return o.length>=s.length?i.slice(s.length):i}).join(` -`)}var S=class{options;rules;lexer;constructor(e){this.options=e||w}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=t[0].replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?n:A(n,` -`)}}}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=A(n,"#");(this.options.pedantic||!s||this.rules.other.endingSpaceChar.test(s))&&(n=s.trim())}return{type:"heading",raw:t[0],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:A(t[0],` -`)}}blockquote(e){let t=this.rules.block.blockquote.exec(e);if(t){let n=A(t[0],` -`).split(` -`),s="",i="",r=[];for(;n.length>0;){let o=!1,a=[],c;for(c=0;c1,i={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:!1,items:[]};n=s?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");let r=this.rules.other.listItemRegex(n),o=!1;for(;e;){let c=!1,p="",u="";if(!(t=r.exec(e))||this.rules.block.hr.test(e))break;p=t[0],e=e.substring(p.length);let d=t[2].split(` -`,1)[0].replace(this.rules.other.listReplaceTabs,Z=>" ".repeat(3*Z.length)),g=e.split(` -`,1)[0],T=!d.trim(),f=0;if(this.options.pedantic?(f=2,u=d.trimStart()):T?f=t[1].length+1:(f=t[2].search(this.rules.other.nonSpaceChar),f=f>4?1:f,u=d.slice(f),f+=t[1].length),T&&this.rules.other.blankLine.test(g)&&(p+=g+` -`,e=e.substring(g.length+1),c=!0),!c){let Z=this.rules.other.nextBulletRegex(f),te=this.rules.other.hrRegex(f),ne=this.rules.other.fencesBeginRegex(f),se=this.rules.other.headingBeginRegex(f),xe=this.rules.other.htmlBeginRegex(f);for(;e;){let G=e.split(` -`,1)[0],C;if(g=G,this.options.pedantic?(g=g.replace(this.rules.other.listReplaceNesting," "),C=g):C=g.replace(this.rules.other.tabCharGlobal," "),ne.test(g)||se.test(g)||xe.test(g)||Z.test(g)||te.test(g))break;if(C.search(this.rules.other.nonSpaceChar)>=f||!g.trim())u+=` -`+C.slice(f);else{if(T||d.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||ne.test(d)||se.test(d)||te.test(d))break;u+=` -`+g}!T&&!g.trim()&&(T=!0),p+=G+` -`,e=e.substring(G.length+1),d=C.slice(f)}}i.loose||(o?i.loose=!0:this.rules.other.doubleBlankLine.test(p)&&(o=!0));let y=null,ee;this.options.gfm&&(y=this.rules.other.listIsTask.exec(u),y&&(ee=y[0]!=="[ ] ",u=u.replace(this.rules.other.listReplaceTask,""))),i.items.push({type:"list_item",raw:p,task:!!y,checked:ee,loose:!1,text:u,tokens:[]}),i.raw+=p}let a=i.items.at(-1);if(a)a.raw=a.raw.trimEnd(),a.text=a.text.trimEnd();else return;i.raw=i.raw.trimEnd();for(let c=0;cd.type==="space"),u=p.length>0&&p.some(d=>this.rules.other.anyLine.test(d.raw));i.loose=u}if(i.loose)for(let c=0;c({text:a,tokens:this.lexer.inline(a),header:!1,align:r.align[c]})));return r}}lheading(e){let t=this.rules.block.lheading.exec(e);if(t)return{type:"heading",raw:t[0],depth:t[2].charAt(0)==="="?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){let t=this.rules.block.paragraph.exec(e);if(t){let n=t[1].charAt(t[1].length-1)===` -`?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=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,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 r=A(n.slice(0,-1),"\\");if((n.length-r.length)%2===0)return}else{let r=de(t[2],"()");if(r===-2)return;if(r>-1){let a=(t[0].indexOf("!")===0?5:4)+t[1].length+r;t[2]=t[2].substring(0,r),t[0]=t[0].substring(0,a).trim(),t[3]=""}}let s=t[2],i="";if(this.options.pedantic){let r=this.rules.other.pedanticHrefTitle.exec(s);r&&(s=r[1],i=r[3])}else i=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:i&&i.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," "),i=t[s.toLowerCase()];if(!i){let r=n[0].charAt(0);return{type:"text",raw:r,text:r}}return me(n,i,n[0],this.lexer,this.rules)}}emStrong(e,t,n=""){let s=this.rules.inline.emStrongLDelim.exec(e);if(!s||s[3]&&n.match(this.rules.other.unicodeAlphaNumeric))return;if(!(s[1]||s[2]||"")||!n||this.rules.inline.punctuation.exec(n)){let r=[...s[0]].length-1,o,a,c=r,p=0,u=s[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(u.lastIndex=0,t=t.slice(-1*e.length+r);(s=u.exec(t))!=null;){if(o=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!o)continue;if(a=[...o].length,s[3]||s[4]){c+=a;continue}else if((s[5]||s[6])&&r%3&&!((r+a)%3)){p+=a;continue}if(c-=a,c>0)continue;a=Math.min(a,a+c+p);let d=[...s[0]][0].length,g=e.slice(0,r+s.index+d+a);if(Math.min(r,a)%2){let f=g.slice(1,-1);return{type:"em",raw:g,text:f,tokens:this.lexer.inlineTokens(f)}}let T=g.slice(2,-2);return{type:"strong",raw:g,text:T,tokens:this.lexer.inlineTokens(T)}}}}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),i=this.rules.other.startingSpaceChar.test(n)&&this.rules.other.endingSpaceChar.test(n);return s&&i&&(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){let t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}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 i;do i=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??"";while(i!==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;tokenizer;inlineQueue;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||w,this.options.tokenizer=this.options.tokenizer||new S,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};let t={other:m,block:B.normal,inline:P.normal};this.options.pedantic?(t.block=B.pedantic,t.inline=P.pedantic):this.options.gfm&&(t.block=B.gfm,this.options.breaks?t.inline=P.breaks:t.inline=P.gfm),this.tokenizer.rules=t}static get rules(){return{block:B,inline:P}}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,` -`),this.blockTokens(e,this.tokens);for(let t=0;t(s=r.call({lexer:this},e,t))?(e=e.substring(s.raw.length),t.push(s),!0):!1))continue;if(s=this.tokenizer.space(e)){e=e.substring(s.raw.length);let r=t.at(-1);s.raw.length===1&&r!==void 0?r.raw+=` -`:t.push(s);continue}if(s=this.tokenizer.code(e)){e=e.substring(s.raw.length);let r=t.at(-1);r?.type==="paragraph"||r?.type==="text"?(r.raw+=` -`+s.raw,r.text+=` -`+s.text,this.inlineQueue.at(-1).src=r.text):t.push(s);continue}if(s=this.tokenizer.fences(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.heading(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.hr(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.blockquote(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.list(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.html(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.def(e)){e=e.substring(s.raw.length);let r=t.at(-1);r?.type==="paragraph"||r?.type==="text"?(r.raw+=` -`+s.raw,r.text+=` -`+s.raw,this.inlineQueue.at(-1).src=r.text):this.tokens.links[s.tag]||(this.tokens.links[s.tag]={href:s.href,title:s.title});continue}if(s=this.tokenizer.table(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.lheading(e)){e=e.substring(s.raw.length),t.push(s);continue}let i=e;if(this.options.extensions?.startBlock){let r=1/0,o=e.slice(1),a;this.options.extensions.startBlock.forEach(c=>{a=c.call({lexer:this},o),typeof a=="number"&&a>=0&&(r=Math.min(r,a))}),r<1/0&&r>=0&&(i=e.substring(0,r+1))}if(this.state.top&&(s=this.tokenizer.paragraph(i))){let r=t.at(-1);n&&r?.type==="paragraph"?(r.raw+=` -`+s.raw,r.text+=` -`+s.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=r.text):t.push(s),n=i.length!==e.length,e=e.substring(s.raw.length);continue}if(s=this.tokenizer.text(e)){e=e.substring(s.raw.length);let r=t.at(-1);r?.type==="text"?(r.raw+=` -`+s.raw,r.text+=` -`+s.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=r.text):t.push(s);continue}if(e){let r="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(r);break}else throw new Error(r)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n=e,s=null;if(this.tokens.links){let o=Object.keys(this.tokens.links);if(o.length>0)for(;(s=this.tokenizer.rules.inline.reflinkSearch.exec(n))!=null;)o.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);for(;(s=this.tokenizer.rules.inline.blockSkip.exec(n))!=null;)n=n.slice(0,s.index)+"["+"a".repeat(s[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);let i=!1,r="";for(;e;){i||(r=""),i=!1;let o;if(this.options.extensions?.inline?.some(c=>(o=c.call({lexer:this},e,t))?(e=e.substring(o.raw.length),t.push(o),!0):!1))continue;if(o=this.tokenizer.escape(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.tag(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.link(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(o.raw.length);let c=t.at(-1);o.type==="text"&&c?.type==="text"?(c.raw+=o.raw,c.text+=o.text):t.push(o);continue}if(o=this.tokenizer.emStrong(e,n,r)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.codespan(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.br(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.del(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.autolink(e)){e=e.substring(o.raw.length),t.push(o);continue}if(!this.state.inLink&&(o=this.tokenizer.url(e))){e=e.substring(o.raw.length),t.push(o);continue}let a=e;if(this.options.extensions?.startInline){let c=1/0,p=e.slice(1),u;this.options.extensions.startInline.forEach(d=>{u=d.call({lexer:this},p),typeof u=="number"&&u>=0&&(c=Math.min(c,u))}),c<1/0&&c>=0&&(a=e.substring(0,c+1))}if(o=this.tokenizer.inlineText(a)){e=e.substring(o.raw.length),o.raw.slice(-1)!=="_"&&(r=o.raw.slice(-1)),i=!0;let c=t.at(-1);c?.type==="text"?(c.raw+=o.raw,c.text+=o.text):t.push(o);continue}if(e){let c="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(c);break}else throw new Error(c)}}return t}};var $=class{options;parser;constructor(e){this.options=e||w}space(e){return""}code({text:e,lang:t,escaped:n}){let s=(t||"").match(m.notSpaceStart)?.[0],i=e.replace(m.endingNewline,"")+` -`;return s?'
'+(n?i:R(i,!0))+`
-`:"
"+(n?i:R(i,!0))+`
-`}blockquote({tokens:e}){return`
-${this.parser.parse(e)}
-`}html({text:e}){return e}heading({tokens:e,depth:t}){return`${this.parser.parseInline(e)} -`}hr(e){return`
-`}list(e){let t=e.ordered,n=e.start,s="";for(let o=0;o -`+s+" -`}listitem(e){let t="";if(e.task){let n=this.checkbox({checked:!!e.checked});e.loose?e.tokens[0]?.type==="paragraph"?(e.tokens[0].text=n+" "+e.tokens[0].text,e.tokens[0].tokens&&e.tokens[0].tokens.length>0&&e.tokens[0].tokens[0].type==="text"&&(e.tokens[0].tokens[0].text=n+" "+R(e.tokens[0].tokens[0].text),e.tokens[0].tokens[0].escaped=!0)):e.tokens.unshift({type:"text",raw:n+" ",text:n+" ",escaped:!0}):t+=n+" "}return t+=this.parser.parse(e.tokens,!!e.loose),`
  • ${t}
  • -`}checkbox({checked:e}){return"'}paragraph({tokens:e}){return`

    ${this.parser.parseInline(e)}

    -`}table(e){let t="",n="";for(let i=0;i${s}`),` - -`+t+` -`+s+`
    -`}tablerow({text:e}){return` -${e} -`}tablecell(e){let t=this.parser.parseInline(e.tokens),n=e.header?"th":"td";return(e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+` -`}strong({tokens:e}){return`${this.parser.parseInline(e)}`}em({tokens:e}){return`${this.parser.parseInline(e)}`}codespan({text:e}){return`${R(e,!0)}`}br(e){return"
    "}del({tokens:e}){return`${this.parser.parseInline(e)}`}link({href:e,title:t,tokens:n}){let s=this.parser.parseInline(n),i=V(e);if(i===null)return s;e=i;let r='
    ",r}image({href:e,title:t,text:n,tokens:s}){s&&(n=this.parser.parseInline(s,this.parser.textRenderer));let i=V(e);if(i===null)return R(n);e=i;let r=`${n}{let o=i[r].flat(1/0);n=n.concat(this.walkTokens(o,t))}):i.tokens&&(n=n.concat(this.walkTokens(i.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||!1,n.extensions&&(n.extensions.forEach(i=>{if(!i.name)throw new Error("extension name required");if("renderer"in i){let r=t.renderers[i.name];r?t.renderers[i.name]=function(...o){let a=i.renderer.apply(this,o);return a===!1&&(a=r.apply(this,o)),a}:t.renderers[i.name]=i.renderer}if("tokenizer"in i){if(!i.level||i.level!=="block"&&i.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");let r=t[i.level];r?r.unshift(i.tokenizer):t[i.level]=[i.tokenizer],i.start&&(i.level==="block"?t.startBlock?t.startBlock.push(i.start):t.startBlock=[i.start]:i.level==="inline"&&(t.startInline?t.startInline.push(i.start):t.startInline=[i.start]))}"childTokens"in i&&i.childTokens&&(t.childTokens[i.name]=i.childTokens)}),s.extensions=t),n.renderer){let i=this.defaults.renderer||new $(this.defaults);for(let r in n.renderer){if(!(r in i))throw new Error(`renderer '${r}' does not exist`);if(["options","parser"].includes(r))continue;let o=r,a=n.renderer[o],c=i[o];i[o]=(...p)=>{let u=a.apply(i,p);return u===!1&&(u=c.apply(i,p)),u||""}}s.renderer=i}if(n.tokenizer){let i=this.defaults.tokenizer||new S(this.defaults);for(let r in n.tokenizer){if(!(r in i))throw new Error(`tokenizer '${r}' does not exist`);if(["options","rules","lexer"].includes(r))continue;let o=r,a=n.tokenizer[o],c=i[o];i[o]=(...p)=>{let u=a.apply(i,p);return u===!1&&(u=c.apply(i,p)),u}}s.tokenizer=i}if(n.hooks){let i=this.defaults.hooks||new L;for(let r in n.hooks){if(!(r in i))throw new Error(`hook '${r}' does not exist`);if(["options","block"].includes(r))continue;let o=r,a=n.hooks[o],c=i[o];L.passThroughHooks.has(r)?i[o]=p=>{if(this.defaults.async)return Promise.resolve(a.call(i,p)).then(d=>c.call(i,d));let u=a.call(i,p);return c.call(i,u)}:i[o]=(...p)=>{let u=a.apply(i,p);return u===!1&&(u=c.apply(i,p)),u}}s.hooks=i}if(n.walkTokens){let i=this.defaults.walkTokens,r=n.walkTokens;s.walkTokens=function(o){let a=[];return a.push(r.call(this,o)),i&&(a=a.concat(i.call(this,o))),a}}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 i={...s},r={...this.defaults,...i},o=this.onError(!!r.silent,!!r.async);if(this.defaults.async===!0&&i.async===!1)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"));r.hooks&&(r.hooks.options=r,r.hooks.block=e);let a=r.hooks?r.hooks.provideLexer():e?x.lex:x.lexInline,c=r.hooks?r.hooks.provideParser():e?b.parse:b.parseInline;if(r.async)return Promise.resolve(r.hooks?r.hooks.preprocess(n):n).then(p=>a(p,r)).then(p=>r.hooks?r.hooks.processAllTokens(p):p).then(p=>r.walkTokens?Promise.all(this.walkTokens(p,r.walkTokens)).then(()=>p):p).then(p=>c(p,r)).then(p=>r.hooks?r.hooks.postprocess(p):p).catch(o);try{r.hooks&&(n=r.hooks.preprocess(n));let p=a(n,r);r.hooks&&(p=r.hooks.processAllTokens(p)),r.walkTokens&&this.walkTokens(p,r.walkTokens);let u=c(p,r);return r.hooks&&(u=r.hooks.postprocess(u)),u}catch(p){return o(p)}}}onError(e,t){return n=>{if(n.message+=` -Please report this to https://github.com/markedjs/marked.`,e){let s="

    An error occurred:

    "+R(n.message+"",!0)+"
    ";return t?Promise.resolve(s):s}if(t)return Promise.reject(n);throw n}}};var M=new E;function k(l,e){return M.parse(l,e)}k.options=k.setOptions=function(l){return M.setOptions(l),k.defaults=M.defaults,N(k.defaults),k};k.getDefaults=z;k.defaults=w;k.use=function(...l){return M.use(...l),k.defaults=M.defaults,N(k.defaults),k};k.walkTokens=function(l,e){return M.walkTokens(l,e)};k.parseInline=M.parseInline;k.Parser=b;k.parser=b.parse;k.Renderer=$;k.TextRenderer=_;k.Lexer=x;k.lexer=x.lex;k.Tokenizer=S;k.Hooks=L;k.parse=k;var it=k.options,ot=k.setOptions,lt=k.use,at=k.walkTokens,ct=k.parseInline,pt=k,ut=b.parse,ht=x.lex; - -if(__exports != exports)module.exports = exports;return module.exports})); diff --git a/client/package-lock.json b/client/package-lock.json index 3b336e8..981adda 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -7,7 +7,13 @@ "": { "name": "chatbot-sdk", "version": "1.0.0", + "dependencies": { + "tdesign-web-components": "^1.2.10" + }, "devDependencies": { + "@rollup/plugin-commonjs": "^29.0.3", + "@rollup/plugin-node-resolve": "^16.0.3", + "@rollup/plugin-replace": "^6.0.3", "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^12.1.0", "rollup": "^4.30.0", @@ -16,6 +22,94 @@ "vitest": "^3.2.6" } }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "license": "MIT", + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@antfu/install-pkg/node_modules/tinyexec": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/@braintree/sanitize-url/-/sanitize-url-7.1.2.tgz", + "integrity": "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==", + "license": "MIT" + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmmirror.com/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/cst-dts-gen/node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmmirror.com/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast/node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmmirror.com/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmmirror.com/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmmirror.com/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "license": "Apache-2.0" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.12", "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", @@ -458,6 +552,23 @@ "node": ">=18" } }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "3.1.4", + "resolved": "https://registry.npmmirror.com/@iconify/utils/-/utils-3.1.4.tgz", + "integrity": "sha512-b1S7B1k9ohZ+iNTi2ATxbRYG9fTrJmUT0rc46bvVnNxqNRGW7dyo/vRREwyniI5IRN2RSJHDcm+s3BjWrSAjHw==", + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^1.1.0", + "@iconify/types": "^2.0.0", + "import-meta-resolve": "^4.2.0" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -508,6 +619,99 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mermaid-js/parser": { + "version": "0.6.3", + "resolved": "https://registry.npmmirror.com/@mermaid-js/parser/-/parser-0.6.3.tgz", + "integrity": "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==", + "license": "MIT", + "dependencies": { + "langium": "3.3.1" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmmirror.com/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rollup/plugin-commonjs": { + "version": "29.0.3", + "resolved": "https://registry.npmmirror.com/@rollup/plugin-commonjs/-/plugin-commonjs-29.0.3.tgz", + "integrity": "sha512-ZaOxZceP7SOUW7Lqw5IRVweSQYWaeIPnXIGLiB690EBA3FGJTO40EEr2L5yZplJWsgTCogILRSpcAe7+U0Otdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "fdir": "^6.2.0", + "is-reference": "1.2.1", + "magic-string": "^0.30.3", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=16.0.0 || 14 >= 14.17" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "16.0.3", + "resolved": "https://registry.npmmirror.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.3.tgz", + "integrity": "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-replace": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/@rollup/plugin-replace/-/plugin-replace-6.0.3.tgz", + "integrity": "sha512-J4RZarRvQAm5IF0/LwUUg+obsm+xZhYnbMXmXROyoSE1ATJe3oXSb9L5MMppdxP2ylNSjv6zFBwKYjcKMucVfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/plugin-terser": { "version": "0.4.4", "resolved": "https://registry.npmmirror.com/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", @@ -931,6 +1135,15 @@ "win32" ] }, + "node_modules/@tootallnate/once": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-2.0.1.tgz", + "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/@types/chai": { "version": "5.2.3", "resolved": "https://registry.npmmirror.com/@types/chai/-/chai-5.2.3.tgz", @@ -942,6 +1155,268 @@ "assertion-error": "^2.0.1" } }, + "node_modules/@types/codemirror": { + "version": "0.0.108", + "resolved": "https://registry.npmmirror.com/@types/codemirror/-/codemirror-0.0.108.tgz", + "integrity": "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw==", + "license": "MIT", + "dependencies": { + "@types/tern": "*" + } + }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmmirror.com/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmmirror.com/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmmirror.com/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmmirror.com/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmmirror.com/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmmirror.com/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", + "license": "MIT" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.7", + "resolved": "https://registry.npmmirror.com/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", + "license": "MIT" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmmirror.com/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmmirror.com/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmmirror.com/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "license": "MIT", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmmirror.com/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "license": "MIT" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", + "license": "MIT" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/@types/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-65Emv9fQiQQqphLlRkuQ5ypPsOmWPhtBGCMv61JDPEPMvsx+gzhGf74yw1a78xFKPj6zw4AgQICJoQv0vK9M2w==", + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmmirror.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", + "license": "MIT" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmmirror.com/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", + "license": "MIT" + }, + "node_modules/@types/d3-random": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/d3-random/-/d3-random-3.0.4.tgz", + "integrity": "sha512-UHYId5WTCx4L4YNel7NU00XUXXgvgpgZOvp10PuvsQENjMDXhh2RyFc0KBjO7B45ne4Ha1yVH7ii0vnzKkuzWA==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmmirror.com/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", + "license": "MIT" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmmirror.com/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmmirror.com/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmmirror.com/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmmirror.com/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, "node_modules/@types/deep-eql": { "version": "4.0.2", "resolved": "https://registry.npmmirror.com/@types/deep-eql/-/deep-eql-4.0.2.tgz", @@ -953,9 +1428,37 @@ "version": "1.0.9", "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz", "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "license": "MIT" + }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmmirror.com/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "license": "MIT" + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmmirror.com/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "dev": true, "license": "MIT" }, + "node_modules/@types/tern": { + "version": "0.23.9", + "resolved": "https://registry.npmmirror.com/@types/tern/-/tern-0.23.9.tgz", + "integrity": "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/@vitest/expect": { "version": "3.2.6", "resolved": "https://registry.npmmirror.com/@vitest/expect/-/expect-3.2.6.tgz", @@ -1081,11 +1584,17 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "license": "BSD-3-Clause" + }, "node_modules/acorn": { "version": "8.17.0", "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.17.0.tgz", "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -1094,6 +1603,49 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "license": "MIT", + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/assertion-error/-/assertion-error-2.0.1.tgz", @@ -1104,6 +1656,18 @@ "node": ">=12" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "license": "BSD-2-Clause" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", @@ -1121,6 +1685,19 @@ "node": ">=8" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/chai": { "version": "5.3.3", "resolved": "https://registry.npmmirror.com/chai/-/chai-5.3.3.tgz", @@ -1148,46 +1725,961 @@ "node": ">= 16" } }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "license": "MIT" + "node_modules/cherry-markdown": { + "version": "0.10.3", + "resolved": "https://registry.npmmirror.com/cherry-markdown/-/cherry-markdown-0.10.3.tgz", + "integrity": "sha512-lyrEO6QFhyBYDKSG7uoYLncqnszsm1zJFnxXh1j8D7FKB/7u0jft08sEzfoZ0OkcxaP8+aOUL8Ji9SpA75djVA==", + "license": "Apache-2.0", + "dependencies": { + "@types/codemirror": "^0.0.108", + "crypto-js": "^4.2.0", + "dompurify": "^3.2.6", + "htmlparser2": "^10.0.0", + "jsdom": "~19.0.0", + "ws": "^8.18.0" + }, + "optionalDependencies": { + "mermaid": "9.4.3" + } }, - "node_modules/debug": { + "node_modules/cherry-markdown/node_modules/@braintree/sanitize-url": { + "version": "6.0.4", + "resolved": "https://registry.npmmirror.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz", + "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==", + "license": "MIT", + "optional": true + }, + "node_modules/cherry-markdown/node_modules/dagre-d3-es": { + "version": "7.0.9", + "resolved": "https://registry.npmmirror.com/dagre-d3-es/-/dagre-d3-es-7.0.9.tgz", + "integrity": "sha512-rYR4QfVmy+sR44IBDvVtcAmOReGBvRCWDpO2QjYwqgh9yijw6eSHBqaPG/LIOEy7aBsniLvtMW6pg19qJhq60w==", + "license": "MIT", + "optional": true, + "dependencies": { + "d3": "^7.8.2", + "lodash-es": "^4.17.21" + } + }, + "node_modules/cherry-markdown/node_modules/mermaid": { + "version": "9.4.3", + "resolved": "https://registry.npmmirror.com/mermaid/-/mermaid-9.4.3.tgz", + "integrity": "sha512-TLkQEtqhRSuEHSE34lh5bCa94KATCyluAXmFnNI2PRZwOpXFeqiJWwZl+d2CcemE1RS6QbbueSSq9QIg8Uxcyw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@braintree/sanitize-url": "^6.0.0", + "cytoscape": "^3.23.0", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.1.0", + "d3": "^7.4.0", + "dagre-d3-es": "7.0.9", + "dayjs": "^1.11.7", + "dompurify": "2.4.3", + "elkjs": "^0.8.2", + "khroma": "^2.0.0", + "lodash-es": "^4.17.21", + "non-layered-tidy-tree-layout": "^2.0.2", + "stylis": "^4.1.2", + "ts-dedent": "^2.2.0", + "uuid": "^9.0.0", + "web-worker": "^1.2.0" + } + }, + "node_modules/cherry-markdown/node_modules/mermaid/node_modules/dompurify": { + "version": "2.4.3", + "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-2.4.3.tgz", + "integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optional": true + }, + "node_modules/cherry-markdown/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmmirror.com/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "license": "MIT", + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } + }, + "node_modules/chevrotain/node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmmirror.com/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, + "node_modules/construct-style-sheets-polyfill": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/construct-style-sheets-polyfill/-/construct-style-sheets-polyfill-3.0.1.tgz", + "integrity": "sha512-vyAiTcS3i29IxjzJ12K2MGUUBYgrF69p6fKD+8ZPRLFhwTtuaxXLpazl4Yw4FITsQXwUMrh8juI1bOHWYjzkwA==", + "license": "MIT", + "engines": { + "npm": ">=7" + } + }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "license": "MIT", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "license": "MIT", + "dependencies": { + "layout-base": "^1.0.0" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "deprecated": "Active development of CryptoJS has been discontinued. This library is no longer maintained.", + "license": "MIT" + }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmmirror.com/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "license": "MIT", + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmmirror.com/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "license": "MIT" + }, + "node_modules/cytoscape": { + "version": "3.34.1", + "resolved": "https://registry.npmmirror.com/cytoscape/-/cytoscape-3.34.1.tgz", + "integrity": "sha512-Lr0RvH9H75y9ar8h9Toy6u4lxRSCcxUq+hHcQ26sVWo6BnaQp1gwEZOYqwuYTZhyW7npyKnNLP8oJ2p1/3OZ7g==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "license": "MIT", + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "license": "MIT" + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmmirror.com/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "license": "ISC", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmmirror.com/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmmirror.com/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmmirror.com/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmmirror.com/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmmirror.com/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmmirror.com/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre-d3-es": { + "version": "7.0.11", + "resolved": "https://registry.npmmirror.com/dagre-d3-es/-/dagre-d3-es-7.0.11.tgz", + "integrity": "sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "lodash-es": "^4.17.21" + } + }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "license": "MIT", + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "license": "MIT", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dayjs": { + "version": "1.11.23", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.23.tgz", + "integrity": "sha512-QDTCU0M0MxR3hQfnlDJfwekQiaanm1ubOD231u73WBckQ/fsamwRLiE2GBz6D3a/xF1NgfiDLJjXBa1hYOYTtQ==", + "license": "MIT" + }, + "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "license": "MIT" + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmmirror.com/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delaunator": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/delaunator/-/delaunator-5.1.0.tgz", + "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==", + "license": "ISC", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", + "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "webidl-conversions": "^7.0.0" }, "engines": { - "node": ">=6.0" + "node": ">=12" + } + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmmirror.com/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, + "node_modules/dompurify": { + "version": "3.4.13", + "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.4.13.tgz", + "integrity": "sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + } + }, + "node_modules/elkjs": { + "version": "0.8.2", + "resolved": "https://registry.npmmirror.com/elkjs/-/elkjs-0.8.2.tgz", + "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==", + "license": "EPL-2.0", + "optional": true + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" } }, "node_modules/es-errors": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -1200,6 +2692,33 @@ "dev": true, "license": "MIT" }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.25.12", "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.12.tgz", @@ -1242,6 +2761,49 @@ "@esbuild/win32-x64": "0.25.12" } }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", @@ -1249,6 +2811,15 @@ "dev": true, "license": "MIT" }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/expect-type": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/expect-type/-/expect-type-1.4.0.tgz", @@ -1259,6 +2830,12 @@ "node": ">=12.0.0" } }, + "node_modules/fast-json-patch": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/fast-json-patch/-/fast-json-patch-3.1.1.tgz", + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", + "license": "MIT" + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", @@ -1277,6 +2854,22 @@ } } }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", @@ -1296,17 +2889,97 @@ "version": "1.1.2", "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmmirror.com/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "license": "MIT" + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.4", "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.4.tgz", "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -1315,6 +2988,111 @@ "node": ">= 0.4" } }, + "node_modules/htm": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/htm/-/htm-3.1.1.tgz", + "integrity": "sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==", + "license": "Apache-2.0" + }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immer": { + "version": "10.2.0", + "resolved": "https://registry.npmmirror.com/immer/-/immer-10.2.0.tgz", + "integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/is-core-module": { "version": "2.16.2", "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.2.tgz", @@ -1322,20 +3100,147 @@ "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.3" + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "license": "MIT" + }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsdom": { + "version": "19.0.0", + "resolved": "https://registry.npmmirror.com/jsdom/-/jsdom-19.0.0.tgz", + "integrity": "sha512-RYAyjCbxy/vri/CfnjUWJQQtZ3LKlLnDqj+9XLNnJPgEGeirZs3hllKR20re8LUZ6o1b1X4Jat+Qd26zmP41+A==", + "license": "MIT", + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.5.0", + "acorn-globals": "^6.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.1", + "decimal.js": "^10.3.1", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^3.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^10.0.0", + "ws": "^8.2.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/katex": { + "version": "0.16.47", + "resolved": "https://registry.npmmirror.com/katex/-/katex-0.16.47.tgz", + "integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" + }, + "node_modules/langium": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/langium/-/langium-3.3.1.tgz", + "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", + "license": "MIT", + "dependencies": { + "chevrotain": "~11.0.3", + "chevrotain-allstar": "~0.3.0", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.0.8" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=16.0.0" } }, - "node_modules/js-tokens": { - "version": "9.0.1", - "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-9.0.1.tgz", - "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", - "dev": true, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", "license": "MIT" }, "node_modules/loupe": { @@ -1355,11 +3260,86 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/markdown-it-fence": { + "version": "0.1.3", + "resolved": "https://registry.npmmirror.com/markdown-it-fence/-/markdown-it-fence-0.1.3.tgz", + "integrity": "sha512-mdZbkwJUyZXhyDX4QzD+WnIhxWBq9oIIJU22E6jCT7MHgIp79oEOJfwXIl/HqmfIxnXEdC47sBGn4h6chM4DKw==", + "license": "MIT" + }, + "node_modules/marked": { + "version": "16.4.2", + "resolved": "https://registry.npmmirror.com/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mermaid": { + "version": "11.12.0", + "resolved": "https://registry.npmmirror.com/mermaid/-/mermaid-11.12.0.tgz", + "integrity": "sha512-ZudVx73BwrMJfCFmSSJT84y6u5brEoV8DOItdHomNLz32uBjNrelm7mg95X7g+C6UoQH/W6mBLGDEDv73JdxBg==", + "license": "MIT", + "dependencies": { + "@braintree/sanitize-url": "^7.1.1", + "@iconify/utils": "^3.0.1", + "@mermaid-js/parser": "^0.6.2", + "@types/d3": "^7.4.3", + "cytoscape": "^3.29.3", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.11", + "dayjs": "^1.11.18", + "dompurify": "^3.2.5", + "katex": "^0.16.22", + "khroma": "^2.1.0", + "lodash-es": "^4.17.21", + "marked": "^16.2.1", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/nanoid": { @@ -1381,6 +3361,72 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/nanostores": { + "version": "0.11.4", + "resolved": "https://registry.npmmirror.com/nanostores/-/nanostores-0.11.4.tgz", + "integrity": "sha512-k1oiVNN4hDK8NcNERSZLQiMfRzEGtfnvZvdBvey3SQbgn8Dcrk0h1I6vpxApjb10PFUflZrgJ2WEZyJQ+5v7YQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/non-layered-tidy-tree-layout": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", + "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==", + "license": "MIT", + "optional": true + }, + "node_modules/nwsapi": { + "version": "2.2.24", + "resolved": "https://registry.npmmirror.com/nwsapi/-/nwsapi-2.2.24.tgz", + "integrity": "sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==", + "license": "MIT" + }, + "node_modules/omi": { + "version": "7.7.13", + "resolved": "https://registry.npmmirror.com/omi/-/omi-7.7.13.tgz", + "integrity": "sha512-LA/rLhGE7PO/OVN9Mp4TG4YL3Dt5dERM9fsVyiPmE75CRCuyW7vVfrYK8Ee7EPbQuTycYRsfbrD1YBQytOY/jw==", + "license": "MIT", + "dependencies": { + "construct-style-sheets-polyfill": "3.0.1", + "reactive-signal": "^2.0.1", + "weakmap-polyfill": "2.0.4" + } + }, + "node_modules/omi-transition": { + "version": "0.1.11", + "resolved": "https://registry.npmmirror.com/omi-transition/-/omi-transition-0.1.11.tgz", + "integrity": "sha512-AsiLCOzMUuFRQ2juGXnSVjcOA2eOb4WdZzbiALbeyXCUgxdRTlE0ekO08IgyvAe9Rdc9fhx0iEgLnwd7ufneCg==", + "license": "MIT", + "dependencies": { + "omi": "latest" + } + }, + "node_modules/package-manager-detector": { + "version": "1.8.0", + "resolved": "https://registry.npmmirror.com/package-manager-detector/-/package-manager-detector-1.8.0.tgz", + "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==", + "license": "MIT" + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "license": "MIT" + }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "license": "MIT" + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", @@ -1425,6 +3471,22 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "license": "MIT" + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "license": "MIT", + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, "node_modules/postcss": { "version": "8.5.16", "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.16.tgz", @@ -1454,6 +3516,33 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmmirror.com/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT" + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", @@ -1464,6 +3553,18 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/reactive-signal": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/reactive-signal/-/reactive-signal-2.0.1.tgz", + "integrity": "sha512-c+avHi2L+sHn9kkEsDZskRGtkfj6PtoTn1wGgutY2NZR9jCI0InXY7zqWbUXz6cGcuIXKMkQq/mtUiUXBFmKVA==", + "license": "MIT" + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.12", "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.12.tgz", @@ -1486,6 +3587,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/robust-predicates": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/robust-predicates/-/robust-predicates-3.0.3.tgz", + "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==", + "license": "Unlicense" + }, "node_modules/rollup": { "version": "4.62.2", "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.62.2.tgz", @@ -1531,6 +3638,24 @@ "fsevents": "~2.3.2" } }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmmirror.com/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "license": "MIT", + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1552,6 +3677,24 @@ ], "license": "MIT" }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -1580,7 +3723,7 @@ "version": "0.6.1", "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "devOptional": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -1634,6 +3777,12 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/stylis": { + "version": "4.4.0", + "resolved": "https://registry.npmmirror.com/stylis/-/stylis-4.4.0.tgz", + "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==", + "license": "MIT" + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -1647,6 +3796,64 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmmirror.com/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "license": "MIT" + }, + "node_modules/tailwind-merge": { + "version": "2.6.1", + "resolved": "https://registry.npmmirror.com/tailwind-merge/-/tailwind-merge-2.6.1.tgz", + "integrity": "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tdesign-icons-web-components": { + "version": "0.3.7", + "resolved": "https://registry.npmmirror.com/tdesign-icons-web-components/-/tdesign-icons-web-components-0.3.7.tgz", + "integrity": "sha512-y0+tN6A9wgtbx1+j1APyKwrUcsJfzbzEzR/Sy+ioJuyUA9xfTPnvq6eEPMUSrzEKScTDHojP+vgwLUtszrdqmg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.16.5", + "clsx": "^2.1.1", + "omi": "^7.6.17", + "tailwind-merge": "^2.3.0" + }, + "peerDependencies": { + "omi": ">=7.6.17" + } + }, + "node_modules/tdesign-web-components": { + "version": "1.2.10", + "resolved": "https://registry.npmmirror.com/tdesign-web-components/-/tdesign-web-components-1.2.10.tgz", + "integrity": "sha512-ro06t9n+7/khY1d6U91c7X+DcrFfjAKVHBQCGReKyIVR5hzV5I48xC1kAnl04dBZT906Ez4Y44VFIIqekaBwnw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@popperjs/core": "^2.11.8", + "cherry-markdown": "^0.10.1-alpha.0", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "copy-to-clipboard": "^3.3.3", + "dayjs": "^1.11.19", + "fast-json-patch": "3.1.1", + "htm": "^3.1.1", + "immer": "^10.1.1", + "lodash-es": "^4.17.21", + "markdown-it-fence": "^0.1.3", + "mermaid": "11.12.0", + "nanostores": "^0.11.4", + "omi": "^7.7.13", + "omi-transition": "^0.1.11", + "tailwind-merge": "^2.2.1", + "tdesign-icons-web-components": "^0.3.2", + "zod": "^3.23.8" + } + }, "node_modules/terser": { "version": "5.48.0", "resolved": "https://registry.npmmirror.com/terser/-/terser-5.48.0.tgz", @@ -1727,6 +3934,48 @@ "node": ">=14.0.0" } }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", + "license": "MIT" + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmmirror.com/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/ts-dedent": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/ts-dedent/-/ts-dedent-2.3.0.tgz", + "integrity": "sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==", + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", @@ -1748,6 +3997,38 @@ "node": ">=14.17" } }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmmirror.com/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/vite": { "version": "6.4.3", "resolved": "https://registry.npmmirror.com/vite/-/vite-6.4.3.tgz", @@ -1919,6 +4200,136 @@ } } }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "license": "MIT", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmmirror.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmmirror.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmmirror.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "license": "MIT" + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", + "license": "MIT", + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", + "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", + "license": "MIT", + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/weakmap-polyfill": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/weakmap-polyfill/-/weakmap-polyfill-2.0.4.tgz", + "integrity": "sha512-ZzxBf288iALJseijWelmECm/1x7ZwQn3sMYIkDr2VvZp7r6SEKuT8D0O9Wiq6L9Nl5mazrOMcmiZE/2NCenaxw==", + "license": "MIT", + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/web-worker": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/web-worker/-/web-worker-1.5.0.tgz", + "integrity": "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "10.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-10.0.0.tgz", + "integrity": "sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w==", + "license": "MIT", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmmirror.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz", @@ -1935,6 +4346,51 @@ "engines": { "node": ">=8" } + }, + "node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmmirror.com/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "license": "MIT" + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmmirror.com/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/client/package.json b/client/package.json index 44e74b5..35ad9ec 100644 --- a/client/package.json +++ b/client/package.json @@ -14,11 +14,17 @@ "test:watch": "vitest" }, "devDependencies": { + "@rollup/plugin-commonjs": "^29.0.3", + "@rollup/plugin-node-resolve": "^16.0.3", + "@rollup/plugin-replace": "^6.0.3", "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^12.1.0", "rollup": "^4.30.0", "tslib": "^2.8.0", "typescript": "^5.7.0", "vitest": "^3.2.6" + }, + "dependencies": { + "tdesign-web-components": "^1.2.10" } } diff --git a/client/rollup.config.js b/client/rollup.config.js index 36ed811..6ae5b53 100644 --- a/client/rollup.config.js +++ b/client/rollup.config.js @@ -1,5 +1,8 @@ import typescript from '@rollup/plugin-typescript'; import terser from '@rollup/plugin-terser'; +import { nodeResolve } from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import replace from '@rollup/plugin-replace'; import { copyFileSync, existsSync, mkdirSync } from 'fs'; import { dirname, resolve } from 'path'; @@ -9,7 +12,6 @@ const BACKEND_DIR = resolve(ROOT, '../src/main/resources/static/sdk'); const ASSETS = [ { src: resolve(ROOT, 'assets/launcher-logo.png'), name: 'launcher-logo.png' }, - { src: resolve(ROOT, 'assets/marked.min.js'), name: 'marked.min.js' }, ]; const BUNDLE_FILES = ['chatbot-sdk.js', 'chatbot-sdk.min.js']; @@ -57,16 +59,36 @@ export default { format: 'iife', name: 'ChatbotSDK', sourcemap: false, + inlineDynamicImports: true, }, { file: 'dist/chatbot-sdk.min.js', format: 'iife', name: 'ChatbotSDK', sourcemap: false, + inlineDynamicImports: true, plugins: [terser()], }, ], plugins: [ + // mermaid 不打包(省约 1.2MB gzip),用本地 stub 替换,避免 markdown-content 模块顶层 + // Cherry.usePlugin 注册 mermaid 插件时因缺少 mermaid 抛异常导致 IIFE 加载失败 + { + name: 'mermaid-stub', + resolveId(source) { + if (source === 'mermaid') return resolve(ROOT, 'src/mermaid-stub.ts'); + return null; + }, + }, + replace({ + preventAssignment: true, + 'process.env.NODE_ENV': JSON.stringify('production'), + }), + nodeResolve({ + browser: true, + preferBuiltins: false, + }), + commonjs(), typescript({ tsconfig: './tsconfig.json', declaration: false, diff --git a/client/src/chat.ts b/client/src/chat.ts index 3a5d632..41b9902 100644 --- a/client/src/chat.ts +++ b/client/src/chat.ts @@ -29,22 +29,22 @@ import { import { renderUserBubble, renderAIBubble, + renderErrorBubble, createEmptyAIBubble, scrollToBottom, renderSources, renderHistoryList, - appendStreamingCaret, finalizeAIBubble, - updateFeedbackUI, showOfflineBanner, hideOfflineBanner, renderSuggestions, removeSuggestions, showFeedbackReasonPanel, + resetChatActionFeedback, + confirmWithDialog, HistoryItemData, } from './dom'; import { saveMessages, loadMessages, clearMessages } from './storage'; -import { renderMarkdown } from './markdown'; import { logger } from './logger'; import { t } from './i18n'; import { uuid, now } from './utils'; @@ -52,12 +52,10 @@ import { uuid, now } from './utils'; let config: ResolvedConfig | null = null; let messages: ChatMessage[] = []; let messagesContainer: HTMLElement | null = null; -let inputEl: HTMLTextAreaElement | null = null; -let inputWrap: HTMLElement | null = null; -let sendBtn: HTMLElement | null = null; +let inputEl: HTMLElement | null = null; let clearBtn: HTMLElement | null = null; -let categorySelect: HTMLSelectElement | null = null; -let roleSelect: HTMLSelectElement | null = null; +let categorySelect: HTMLElement | null = null; +let roleSelect: HTMLElement | null = null; let historyPanel: HTMLElement | null = null; let welcomeEl: HTMLElement | null = null; let newMsgBtn: HTMLElement | null = null; @@ -90,11 +88,10 @@ export function initChat( cfg: ResolvedConfig, dom: { messagesContainer: HTMLElement; - inputEl: HTMLTextAreaElement; - sendBtn: HTMLElement; + inputEl: HTMLElement; clearBtn: HTMLElement | null; - categorySelect: HTMLSelectElement | null; - roleSelect: HTMLSelectElement | null; + categorySelect: HTMLElement | null; + roleSelect: HTMLElement | null; historyPanel: HTMLElement; welcomeEl: HTMLElement; newMsgBtn: HTMLElement; @@ -107,8 +104,6 @@ export function initChat( config = cfg; messagesContainer = dom.messagesContainer; inputEl = dom.inputEl; - inputWrap = dom.inputEl.parentElement; - sendBtn = dom.sendBtn; clearBtn = dom.clearBtn; categorySelect = dom.categorySelect; roleSelect = dom.roleSelect; @@ -196,38 +191,22 @@ async function loadHistoryFromBackend(): Promise { /** 绑定发送相关事件 */ function bindSendEvents(): void { - if (!inputEl || !sendBtn) return; + if (!inputEl) return; - // 发送按钮:发送态点击发送,停止态点击中断流式 - sendBtn.addEventListener('click', () => { - if (isSending && abortController) { - abortController.abort(); - return; - } - handleSend(); + // t-chat-sender:send 事件(点击发送/回车)携带 value;stop 事件(loading 态点击)中断流式 + inputEl.addEventListener('send', (e) => { + const detail = (e as CustomEvent).detail as { value?: string } | undefined; + const value = (detail?.value || '').trim(); + if (!value || isSending) return; + handleSend(value); }); - inputEl.addEventListener('keydown', (e: KeyboardEvent) => { - // IME 组合输入期间(中文/日文输入法选词回车)不触发发送 - if (e.key === 'Enter' && !e.shiftKey && !e.isComposing) { - e.preventDefault(); - handleSend(); + inputEl.addEventListener('stop', () => { + if (isSending && abortController) { + abortController.abort(); } }); - inputEl.addEventListener('input', () => { - updateSendBtnState(); - autoResizeInput(); - }); - - // 输入框聚焦/失焦高亮容器 - inputEl.addEventListener('focus', () => { - if (inputWrap) inputWrap.classList.add('csk-input-wrap--focus'); - }); - inputEl.addEventListener('blur', () => { - if (inputWrap) inputWrap.classList.remove('csk-input-wrap--focus'); - }); - if (clearBtn) { clearBtn.addEventListener('click', () => handleClear()); } @@ -273,21 +252,14 @@ function smartScrollToBottom(): void { } } -/** 切换发送按钮模式:发送 / 停止生成 */ +/** 切换发送按钮模式:发送 / 停止生成(由 t-chat-sender 的 loading 属性承载) */ function setSendButtonMode(mode: 'send' | 'stop'): void { - if (!sendBtn) return; + if (!inputEl) return; + // loading 为 Boolean 简单类型,omi 下须用 setAttribute/removeAttribute(property 赋值静默失效) if (mode === 'stop') { - sendBtn.classList.add('csk-send-btn--stop'); - sendBtn.removeAttribute('disabled'); - sendBtn.setAttribute('title', t('stop')); - sendBtn.setAttribute('aria-label', t('stop')); - sendBtn.innerHTML = ``; + inputEl.setAttribute('loading', ''); } else { - sendBtn.classList.remove('csk-send-btn--stop'); - sendBtn.setAttribute('title', t('send')); - sendBtn.setAttribute('aria-label', t('send')); - sendBtn.innerHTML = ``; - updateSendBtnState(); + inputEl.removeAttribute('loading'); } } @@ -320,7 +292,7 @@ function renderFilteredHistory(): void { (conversationId: string) => { switchToConversation(conversationId); }, (id: string) => { window.open(getConversationExportUrl(id), '_blank'); }, async (id: string) => { - if (!confirm(t('history_delete_confirm'))) return; + if (!(await confirmWithDialog(t('history_delete_confirm')))) return; const ok = await deleteConversation(id); if (ok) { if (id === getChatId()) { @@ -355,27 +327,25 @@ function announceMessage(text: string): void { /** * 处理消息反馈:切换 AI 消息的点赞/点踩状态 * 前端状态持久化(存入 messages 数组 + localStorage)+ 调用后端 API 记录反馈 + * 图标高亮由 t-chat-action 内部管理,active 反映本次点击是激活还是取消 * 点踩时弹出原因选择弹窗,点赞直接提交 */ -export function handleFeedback(msgId: string, value: 'up' | 'down'): void { - if (!messagesContainer) return; +export function handleFeedback(msgId: string, value: 'up' | 'down', active: boolean): void { + if (!messagesContainer || !config) return; + const cfg = config; const msg = messages.find(m => m.id === msgId && m.role === 'ai'); if (!msg) return; if (value === 'up') { // 点赞:直接切换提交,无需原因 - const newValue = msg.feedback === 'up' ? undefined : 'up'; - msg.feedback = newValue; + msg.feedback = active ? 'up' : undefined; msg.feedbackReason = undefined; msg.feedbackComment = undefined; - const wrapper = messagesContainer.querySelector(`[data-csk-msg-id="${msgId}"]`) as HTMLElement; - if (wrapper) updateFeedbackUI(wrapper, newValue); - - if (config) saveMessages(config.integrateId, messages); + saveMessages(cfg.integrateId, messages); - if (newValue) { + if (active) { submitFeedbackApi(String(msgId), 'THUMBS_UP').then(success => { if (success) { logger.info(`消息反馈已提交 msgId=${msgId} value=up`); @@ -389,46 +359,38 @@ export function handleFeedback(msgId: string, value: 'up' | 'down'): void { return; } - // 点踩:弹出原因选择弹窗 - if (value === 'down') { - const wrapper = messagesContainer.querySelector(`[data-csk-msg-id="${msgId}"]`) as HTMLElement; - if (!wrapper) return; - - // 如果已点踩,取消(同 SDK 现有行为) - if (msg.feedback === 'down') { - msg.feedback = undefined; - msg.feedbackReason = undefined; - msg.feedbackComment = undefined; - if (wrapper) updateFeedbackUI(wrapper, undefined); - if (config) saveMessages(config.integrateId, messages); - logger.info(`消息反馈已取消 msgId=${msgId}`); - return; - } + // 点踩 + const wrapper = messagesContainer.querySelector(`[data-csk-msg-id="${msgId}"]`) as HTMLElement; + if (!wrapper) return; - // 弹出原因选择面板 - showFeedbackReasonPanel(wrapper, msgId, (reason, comment) => { - msg.feedback = 'down'; - msg.feedbackReason = reason; - msg.feedbackComment = comment; + if (!active) { + // 取消点踩(图标已由组件内部回滚) + msg.feedback = undefined; + msg.feedbackReason = undefined; + msg.feedbackComment = undefined; + saveMessages(cfg.integrateId, messages); + logger.info(`消息反馈已取消 msgId=${msgId}`); + return; + } - if (wrapper) updateFeedbackUI(wrapper, 'down'); + // 点踩:弹出原因选择面板;用户关闭面板(不选原因)时回滚图标 + showFeedbackReasonPanel(wrapper, msgId, (reason, comment) => { + msg.feedback = 'down'; + msg.feedbackReason = reason; + msg.feedbackComment = comment; - if (config) saveMessages(config.integrateId, messages); + saveMessages(cfg.integrateId, messages); - submitFeedbackApi(String(msgId), 'THUMBS_DOWN', reason, comment).then(success => { - if (success) { - logger.info(`消息反馈已提交 msgId=${msgId} value=down reason=${reason}`); - } else { - logger.warn(`消息反馈提交失败 msgId=${msgId}(本地状态已更新)`); - } - }); + submitFeedbackApi(String(msgId), 'THUMBS_DOWN', reason, comment).then(success => { + if (success) { + logger.info(`消息反馈已提交 msgId=${msgId} value=down reason=${reason}`); + } else { + logger.warn(`消息反馈提交失败 msgId=${msgId}(本地状态已更新)`); + } }); - } -} -function autoResizeInput(): void { - if (!inputEl) return; - inputEl.style.height = 'auto'; - inputEl.style.height = `${Math.min(inputEl.scrollHeight, 120)}px`; + }, () => { + resetChatActionFeedback(wrapper); + }); } /** 根据消息数量切换欢迎空状态显隐 */ @@ -439,32 +401,17 @@ function updateEmptyState(): void { welcomeEl.style.display = hasMessages ? 'none' : ''; } -/** 更新发送按钮状态 */ -function updateSendBtnState(): void { - if (!sendBtn || !inputEl) return; - const hasText = inputEl.value.trim().length > 0; - if (hasText && !isSending) { - sendBtn.removeAttribute('disabled'); - } else { - sendBtn.setAttribute('disabled', 'true'); - } -} - -/** 处理发送消息 */ -async function handleSend(): Promise { - if (!inputEl || !config || isSending) return; +/** 处理发送消息(text 来自 t-chat-sender 的 send 事件,或快捷问题/重试的显式调用) */ +async function handleSend(text?: string): Promise { + if (!config || isSending) return; - const text = inputEl.value.trim(); - if (text === '') return; - - inputEl.value = ''; - updateSendBtnState(); - inputEl.style.height = 'auto'; + const input = (text ?? '').trim(); + if (input === '') return; // 1. 渲染用户气泡 const userTimestamp = now(); - const userMsg: ChatMessage = { id: uuid(), role: 'user', content: text, timestamp: userTimestamp }; - if (messagesContainer) renderUserBubble(messagesContainer, text, userTimestamp); + const userMsg: ChatMessage = { id: uuid(), role: 'user', content: input, timestamp: userTimestamp }; + if (messagesContainer) renderUserBubble(messagesContainer, input, userTimestamp); messages.push(userMsg); updateEmptyState(); @@ -472,7 +419,7 @@ async function handleSend(): Promise { if (messagesContainer) smartScrollToBottom(); // 2. 生成 AI 回复 - await produceAIReply(text); + await produceAIReply(input); } /** @@ -508,7 +455,7 @@ async function produceAIReply(userText: string): Promise { aiContent = await chatRequest(userText); if (hideLoadingFn) hideLoadingFn(); if (messagesContainer) { - renderAIBubble(messagesContainer, aiContent, aiTimestamp, renderMarkdown, aiMsgId); + renderAIBubble(messagesContainer, aiContent, aiTimestamp, aiMsgId); } } const aiMsg: ChatMessage = { id: aiMsgId, role: 'ai', content: aiContent, timestamp: aiTimestamp }; @@ -540,21 +487,13 @@ async function produceAIReply(userText: string): Promise { const errMsg = err instanceof CskError ? err.message : t('error_send'); if (messagesContainer) { - const errorBubble = document.createElement('div'); - errorBubble.className = 'csk-msg csk-msg--ai'; - const bubble = document.createElement('div'); - bubble.className = 'csk-msg__bubble'; - bubble.style.color = '#DC2626'; - bubble.textContent = `⚠ ${errMsg}`; - errorBubble.appendChild(bubble); - messagesContainer.appendChild(errorBubble); + renderErrorBubble(messagesContainer, errMsg, now()); } logger.error(`发送失败 integrateId=${config.integrateId}`, err); } finally { isSending = false; abortController = null; setSendButtonMode('send'); - updateSendBtnState(); } } @@ -585,20 +524,22 @@ async function sendStreamMessage(text: string, aiTimestamp: number, shouldUseRag streamStarted = true; } if (bubbleEl) { - bubbleEl.innerHTML = renderMarkdown(accumulated); - appendStreamingCaret(bubbleEl); + (bubbleEl as unknown as { content: unknown[] }).content = [{ type: 'markdown', data: accumulated }]; } if (messagesContainer) smartScrollToBottom(); }, () => { // 流结束 + // 无流内容降级为同步请求(须在 wrapperEl/bubbleEl 判断之外: + // 二者仅在 onChunk 收到首个 token 时才赋值,否则此分支不可达) + if (!streamStarted && accumulated === '') { + chatRequest(text).then(resolve).catch(reject); + return; + } if (wrapperEl && bubbleEl) { - // 无流内容降级为同步请求 - if (!streamStarted && accumulated === '') { - chatRequest(text).then(resolve).catch(reject); - return; + if (accumulated) { + (bubbleEl as unknown as { content: unknown[] }).content = [{ type: 'markdown', data: accumulated }]; } - if (accumulated) bubbleEl.innerHTML = renderMarkdown(accumulated); finalizeAIBubble(wrapperEl, bubbleEl); } resolve(accumulated); @@ -610,7 +551,7 @@ async function sendStreamMessage(text: string, aiTimestamp: number, shouldUseRag } if (accumulated.length > 0) { if (bubbleEl) { - bubbleEl.innerHTML = renderMarkdown(accumulated + '\n\n' + t('stream_interrupted')); + (bubbleEl as unknown as { content: unknown[] }).content = [{ type: 'markdown', data: accumulated + '\n\n' + t('stream_interrupted') }]; if (wrapperEl) finalizeAIBubble(wrapperEl, bubbleEl); } resolve(accumulated); @@ -629,10 +570,8 @@ async function sendStreamMessage(text: string, aiTimestamp: number, shouldUseRag * 快捷问题发送:欢迎态点击芯片,直接以该文本发送 */ export function sendQuickReply(text: string): Promise { - if (!inputEl || isSending) return Promise.resolve(); - inputEl.value = text; - updateSendBtnState(); - return handleSend(); + if (isSending) return Promise.resolve(); + return handleSend(text); } /** @@ -694,25 +633,27 @@ async function fetchAndRenderSources(message: string, aiMsg: ChatMessage): Promi } } -/** 加载知识库分类到下拉框 */ +/** 加载知识库分类到下拉框(t-select,选项含缩进前缀表达层级) */ async function loadCategories(): Promise { if (!categorySelect) return; try { const tree = await fetchCategoryTree(); if (tree.length === 0) return; - categorySelect.innerHTML = ``; + const options: Array<{ label: string; value: string }> = [{ label: t('category_all'), value: '' }]; const addOptions = (nodes: typeof tree, indent: number = 0) => { for (const node of nodes) { - const option = document.createElement('option'); - option.value = String(node.id); - option.textContent = `${' '.repeat(indent)}${node.name}`; - if (currentCategoryId !== undefined && String(node.id) === String(currentCategoryId)) option.selected = true; - categorySelect!.appendChild(option); + options.push({ label: `${' '.repeat(indent)}${node.name}`, value: String(node.id) }); if (node.children && node.children.length > 0) addOptions(node.children, indent + 1); } }; addOptions(tree); + + (categorySelect as unknown as { options: Array<{ label: string; value: string }> }).options = options; + // 若已有选中分类,回填选中值 + if (currentCategoryId !== undefined) { + (categorySelect as unknown as { value: string }).value = String(currentCategoryId); + } logger.info(`知识库分类加载成功 count=${tree.length}`); } catch (err) { logger.error(t('category_load_error'), err); @@ -731,9 +672,8 @@ function renderHistory(): void { if (msg.role === 'user') { renderUserBubble(messagesContainer, msg.content, msg.timestamp); } else { - const wrapper = renderAIBubble(messagesContainer, msg.content, msg.timestamp, renderMarkdown, msg.id); + const wrapper = renderAIBubble(messagesContainer, msg.content, msg.timestamp, msg.id, msg.feedback); if (msg.sources && msg.sources.length > 0) renderSources(wrapper, msg.sources); - if (msg.feedback) updateFeedbackUI(wrapper, msg.feedback); } } @@ -827,9 +767,9 @@ export async function switchRole(newRoleId: string): Promise { // 6. 更新 API 层的 integrateId(必须在 initChatId 之前) setActiveRoleId(newRoleId); - // 7. 更新角色下拉框高亮项 + // 7. 更新角色下拉框选中项 if (roleSelect) { - roleSelect.value = newRoleId; + (roleSelect as unknown as { value: string }).value = newRoleId; } // 8. 强制查询后端会话列表(跳过 localStorage 缓存) @@ -890,7 +830,7 @@ export async function loadHistoryConversations(): Promise { (conversationId: string) => { switchToConversation(conversationId); }, (id: string) => { window.open(getConversationExportUrl(id), '_blank'); }, async (id: string) => { - if (!confirm(t('history_delete_confirm'))) return; + if (!(await confirmWithDialog(t('history_delete_confirm')))) return; const ok = await deleteConversation(id); if (ok) { if (id === getChatId()) { @@ -934,9 +874,9 @@ export async function switchToConversation(conversationId: string): Promise ${convRoleId}`); setActiveRoleId(convRoleId); - // 更新角色下拉框高亮项 + // 更新角色下拉框选中项 if (roleSelect) { - roleSelect.value = convRoleId; + (roleSelect as unknown as { value: string }).value = convRoleId; } } } @@ -1005,7 +945,8 @@ async function fetchAndShowSuggestions(aiMsgId: string): Promise { const wrapper = messagesContainer.querySelector(`[data-csk-msg-id="${aiMsgId}"]`) as HTMLElement; if (wrapper) renderSuggestions(wrapper, suggestions, sendQuickReply); } - } catch { - // 静默降级 + } catch (err) { + // 推荐问题拉取失败不影响主流程,仅记录日志便于排查 + logger.warn('拉取推荐问题失败', err); } } diff --git a/client/src/dom.ts b/client/src/dom.ts index 61223ba..609c38a 100644 --- a/client/src/dom.ts +++ b/client/src/dom.ts @@ -10,6 +10,30 @@ import { ResolvedConfig, RagSource } from './types'; import { debounce, formatTime } from './utils'; import { t } from './i18n'; +import { DialogPlugin } from 'tdesign-web-components/lib/dialog/index.js'; +// omi 的 render/h 用于创建带 on* 函数回调的组件(见 createEventful 说明) +import { render, h } from 'omi'; + +/** + * 用 omi render 创建带函数事件回调的 TDesign 组件。 + * + * 为什么不能直接 createElement + property 赋值: + * omi(tdesign-web-components 底层框架)的 isComplexType 对 /^on|children/ 前缀返回 false, + * 纯 DOM 下 on* 回调(onChange/onClick 等)既不走 handleComplexProps 的 accessor,也无法从 + * attribute 读取,导致 `el.onChange = fn` 静默失效;而 select/tag 内部是直接 + * `this.props.onChange.call()`,没有 fire 的 dispatchEvent 兜底,必须借助 omi render 把 + * 函数作为 vnode attributes 同步进 props。 + */ +function createEventful( + tagName: string, + props: Record, + container: HTMLElement, + children?: string | unknown[], +): HTMLElement { + // children 作为 vnode 的 children 传入(tag/button 等通过 children/slot 渲染文本,而非 content) + const vnode = children !== undefined ? h(tagName, props, children) : h(tagName, props); + return render(vnode, container) as HTMLElement; +} // ==================== 图标常量 ==================== @@ -101,11 +125,10 @@ function createWatermarkPattern(config: ResolvedConfig): string { export function createChatWindow(config: ResolvedConfig): { window: HTMLElement; messagesContainer: HTMLElement; - inputEl: HTMLTextAreaElement; - sendBtn: HTMLElement; + inputEl: HTMLElement; clearBtn: HTMLElement | null; - categorySelect: HTMLSelectElement | null; - roleSelect: HTMLSelectElement | null; + categorySelect: HTMLElement | null; + roleSelect: HTMLElement | null; historyPanel: HTMLElement; welcomeEl: HTMLElement; newMsgBtn: HTMLElement; @@ -163,36 +186,30 @@ export function createChatWindow(config: ResolvedConfig): { headerLeft.appendChild(headerAvatar); headerLeft.appendChild(headerInfo); - // === 角色选择器(仅当有多个角色时显示) === - let roleSelect: HTMLSelectElement | null = null; + // === 角色选择器(仅当有多个角色时显示,t-select) === + let roleSelect: HTMLElement | null = null; const roles = config.roles; if (roles && roles.length > 1) { - roleSelect = document.createElement('select'); - roleSelect.className = 'csk-role-select'; - roleSelect.setAttribute('aria-label', t('role_selector_label')); - - for (const role of roles) { - const option = document.createElement('option'); - option.value = String(role.id); - option.textContent = role.name || String(role.id); - if (String(role.id) === String(config.integrateId)) { - option.selected = true; - } - roleSelect.appendChild(option); - } - - // onChange 触发自定义事件 - roleSelect.addEventListener('change', () => { - const selectedValue = roleSelect!.value; - windowEl.dispatchEvent(new CustomEvent('csk:roleChange', { - detail: { roleId: selectedValue } - })); - }); - // 包装后插入到 headerLeft 之后、actions 之前 const roleWrap = document.createElement('div'); roleWrap.className = 'csk-role-select-wrap'; - roleWrap.appendChild(roleSelect); + + // on* 回调(onChange)必须经 omi render 创建,纯 DOM property 赋值无法传入 props + roleSelect = createEventful('t-select', { + options: roles.map(role => ({ label: role.name || String(role.id), value: String(role.id) })), + value: String(config.integrateId), + // onChange 触发自定义事件(受控:同步回写选中值) + onChange: (value: string | number) => { + if (roleSelect) { + (roleSelect as unknown as { value: string | number }).value = String(value); + } + windowEl.dispatchEvent(new CustomEvent('csk:roleChange', { + detail: { roleId: String(value) } + })); + }, + }, roleWrap); + roleSelect.setAttribute('aria-label', t('role_selector_label')); + header.appendChild(headerLeft); header.appendChild(roleWrap); } else { @@ -245,19 +262,19 @@ export function createChatWindow(config: ResolvedConfig): {
    ${t('welcome_desc')}
    `; - // 快捷问题芯片(点击即自动发送) + // 快捷问题芯片(点击即自动发送,由 t-tag 承载) if (config.quickReplies.length > 0) { const chips = document.createElement('div'); chips.className = 'csk-quick-replies'; for (const reply of config.quickReplies) { - const chip = document.createElement('button'); - chip.type = 'button'; - chip.className = 'csk-quick-reply'; - chip.textContent = reply; - chip.addEventListener('click', () => { - windowEl.dispatchEvent(new CustomEvent('csk:quickReply', { detail: { text: reply } })); - }); - chips.appendChild(chip); + // on* 回调(onClick)必须经 omi render 创建;文本经 children 传入(tag 的 children 优先于 content) + createEventful('t-tag', { + theme: 'primary', + variant: 'light-outline', + onClick: () => { + windowEl.dispatchEvent(new CustomEvent('csk:quickReply', { detail: { text: reply } })); + }, + }, chips, reply); } welcomeEl.appendChild(chips); } @@ -312,8 +329,8 @@ export function createChatWindow(config: ResolvedConfig): { } }); - // === 知识库分类下拉框(P1) === - let categorySelect: HTMLSelectElement | null = null; + // === 知识库分类下拉框(t-select,选项由 loadCategories 异步填充) === + let categorySelect: HTMLElement | null = null; if (config.showCategorySwitch) { const categoryBar = document.createElement('div'); categoryBar.className = 'csk-category-bar'; @@ -321,22 +338,24 @@ export function createChatWindow(config: ResolvedConfig): { const categoryLabel = document.createElement('span'); categoryLabel.className = 'csk-category-bar__label'; categoryLabel.textContent = '📚'; + categoryBar.appendChild(categoryLabel); - categorySelect = document.createElement('select'); + // on* 回调(onChange)必须经 omi render 创建,纯 DOM property 赋值无法传入 props + categorySelect = createEventful('t-select', { + options: [{ label: t('category_all'), value: '' }], + value: '', + // onChange 触发自定义事件(受控:同步回写选中值) + onChange: (value: string | number) => { + if (categorySelect) { + (categorySelect as unknown as { value: string | number }).value = String(value); + } + const selectedId = String(value); + windowEl.dispatchEvent(new CustomEvent('csk:categoryChange', { + detail: { categoryId: selectedId ? Number(selectedId) : undefined } + })); + }, + }, categoryBar); categorySelect.id = 'csk-category-select'; - categorySelect.className = 'csk-category-select'; - categorySelect.innerHTML = ``; - - // onChange 触发自定义事件 - categorySelect.addEventListener('change', () => { - const selectedId = categorySelect!.value; - windowEl.dispatchEvent(new CustomEvent('csk:categoryChange', { - detail: { categoryId: selectedId ? Number(selectedId) : undefined } - })); - }); - - categoryBar.appendChild(categoryLabel); - categoryBar.appendChild(categorySelect); // 插入到 messages 和 inputArea 之间 windowEl.appendChild(header); @@ -351,32 +370,19 @@ export function createChatWindow(config: ResolvedConfig): { const inputArea = document.createElement('div'); inputArea.className = 'csk-input-area'; - const inputWrap = document.createElement('div'); - inputWrap.className = 'csk-input-wrap'; - - const inputEl = document.createElement('textarea'); + // 输入框 + 发送/停止按钮统一由 t-chat-sender 承担(loading 控制 send/stop 切换,Enter 发送已内置) + const inputEl = document.createElement('t-chat-sender'); inputEl.id = 'csk-input'; - inputEl.className = 'csk-input'; inputEl.setAttribute('placeholder', t('placeholder')); - inputEl.setAttribute('rows', '1'); - inputEl.setAttribute('autofocus', ''); - - const sendBtn = document.createElement('button'); - sendBtn.id = 'csk-send-btn'; - sendBtn.className = 'csk-send-btn'; - sendBtn.setAttribute('title', t('send')); - sendBtn.setAttribute('disabled', 'true'); - sendBtn.innerHTML = ``; - - inputWrap.appendChild(inputEl); - inputWrap.appendChild(sendBtn); - inputArea.appendChild(inputWrap); + inputArea.appendChild(inputEl); // === 保密声明脚注 === const disclaimer = document.createElement('div'); disclaimer.className = 'csk-disclaimer'; if (config.disclaimer !== undefined) { - // 用户自定义或传空串隐藏 + // 用户自定义或传空串隐藏。 + // 注意:disclaimer 语义为「受信 HTML」(由宿主开发者或后端管理员配置), + // 此处直接 innerHTML 注入属设计内行为,请勿传入不可信用户输入。 disclaimer.innerHTML = config.disclaimer; if (!config.disclaimer) { disclaimer.style.display = 'none'; @@ -404,19 +410,12 @@ export function createChatWindow(config: ResolvedConfig): { function showLoading(): HTMLElement { if (loadingEl) { - loadingEl.style.display = 'flex'; + loadingEl.style.display = ''; return loadingEl; } - const el = document.createElement('div'); - el.className = 'csk-loading'; - el.innerHTML = ` -
    ${BOT_ICON}
    -
    -
    -
    -
    -
    - `; + const el = document.createElement('t-chat-loading'); + el.setAttribute('animation', 'dots'); + el.setAttribute('text', t('loading')); messagesContainer.appendChild(el); loadingEl = el; return el; @@ -443,10 +442,16 @@ export function createChatWindow(config: ResolvedConfig): { const teaserEl = document.createElement('div'); teaserEl.className = `csk-teaser csk-teaser--${config.position === 'left-bottom' ? 'left' : 'right'} csk-teaser--hidden`; teaserEl.setAttribute('role', 'status'); - teaserEl.innerHTML = ` - - ${config.teaserText || t('teaser_text')} - `; + const teaserCloseBtn = document.createElement('button'); + teaserCloseBtn.className = 'csk-teaser__close'; + teaserCloseBtn.setAttribute('aria-label', t('close')); + teaserCloseBtn.type = 'button'; + teaserCloseBtn.textContent = '×'; + const teaserTextSpan = document.createElement('span'); + // 文本语义:teaserText 使用 textContent 注入,避免宿主传入未信任内容时构成 XSS + teaserTextSpan.textContent = config.teaserText || t('teaser_text'); + teaserEl.appendChild(teaserCloseBtn); + teaserEl.appendChild(teaserTextSpan); // === 缩放拖拽手柄(右下角) === const resizeHandle = document.createElement('div'); @@ -460,7 +465,6 @@ export function createChatWindow(config: ResolvedConfig): { window: windowEl, messagesContainer, inputEl, - sendBtn, clearBtn, categorySelect, historyPanel, @@ -812,278 +816,145 @@ export function enableResize( // ==================== 消息渲染 ==================== /** 渲染用户消息气泡 */ +/** 创建一个 t-chat-item 消息元素(TDesign Chat 消息气泡,实际标签为 t-chat-item) */ +function createChatItemMsg(role: 'user' | 'assistant', content: unknown[], timestamp: number, msgId?: string): HTMLElement { + const msg = document.createElement('t-chat-item'); + // omi 组件约定:复杂类型(Array/Object)用 property 赋值;简单类型(String/Boolean)用 setAttribute + msg.setAttribute('role', role); + msg.setAttribute('datetime', formatTime(timestamp)); + if (msgId) msg.setAttribute('id', msgId); + (msg as unknown as { content: unknown[] }).content = content; + if (role === 'user') { + msg.setAttribute('placement', 'right'); + msg.setAttribute('variant', 'base'); + } else { + msg.setAttribute('placement', 'left'); + msg.setAttribute('variant', 'text'); + } + return msg; +} + export function renderUserBubble(container: HTMLElement, text: string, timestamp: number): HTMLElement { const wrapper = document.createElement('div'); wrapper.className = 'csk-msg csk-msg--user'; - const avatar = document.createElement('div'); - avatar.className = 'csk-msg__avatar csk-msg__avatar--user'; - avatar.innerHTML = USER_ICON; - - const content = document.createElement('div'); - content.className = 'csk-msg__content'; + wrapper.appendChild(createChatItemMsg('user', [{ type: 'text', data: text }], timestamp)); - const bubble = document.createElement('div'); - bubble.className = 'csk-msg__bubble'; - bubble.textContent = text; + container.appendChild(wrapper); - const time = document.createElement('div'); - time.className = 'csk-msg__time'; - time.textContent = formatTime(timestamp); + return wrapper; +} - content.appendChild(time); - content.appendChild(bubble); - wrapper.appendChild(avatar); - wrapper.appendChild(content); +/** 渲染错误气泡(发送失败提示,用 t-chat-item 的 error 状态承载) */ +export function renderErrorBubble(container: HTMLElement, errMsg: string, timestamp: number): HTMLElement { + const wrapper = document.createElement('div'); + wrapper.className = 'csk-msg csk-msg--ai'; + const msg = createChatItemMsg('assistant', [{ type: 'text', data: `⚠ ${errMsg}` }], timestamp); + msg.setAttribute('status', 'error'); + wrapper.appendChild(msg); container.appendChild(wrapper); - return wrapper; } -/** 渲染 AI 消息气泡(支持 Markdown) */ -export function renderAIBubble(container: HTMLElement, text: string, timestamp: number, renderMd?: (text: string) => string, msgId?: string): HTMLElement { +/** 渲染 AI 消息气泡(Markdown 由 t-chat-item 内置 cherry-markdown 渲染) */ +export function renderAIBubble(container: HTMLElement, text: string, timestamp: number, msgId?: string, feedback?: 'up' | 'down'): HTMLElement { const wrapper = document.createElement('div'); wrapper.className = 'csk-msg csk-msg--ai'; if (msgId) wrapper.dataset.cskMsgId = msgId; - const avatar = document.createElement('div'); - avatar.className = 'csk-msg__avatar csk-msg__avatar--ai'; - avatar.innerHTML = BOT_ICON; - - const content = document.createElement('div'); - content.className = 'csk-msg__content'; - - const bubble = document.createElement('div'); - bubble.className = 'csk-msg__bubble'; - // 支持 Markdown 渲染,传入渲染函数则使用,否则纯文本 - if (renderMd) { - bubble.innerHTML = renderMd(text); - } else { - bubble.textContent = text; - } + const msg = createChatItemMsg('assistant', [{ type: 'markdown', data: text }], timestamp, msgId); + msg.setAttribute('status', 'complete'); + // 操作栏投射到 t-chat-item 的 actionbar 插槽 + msg.appendChild(createChatAction(wrapper, text, msgId, feedback)); + wrapper.appendChild(msg); - const time = document.createElement('div'); - time.className = 'csk-msg__time'; - time.textContent = formatTime(timestamp); - - content.appendChild(time); - content.appendChild(bubble); - // 操作栏:位于气泡下方 - const meta = document.createElement('div'); - meta.className = 'csk-msg__meta'; - meta.appendChild(buildAIActions(bubble, wrapper)); - content.appendChild(meta); - wrapper.appendChild(avatar); - wrapper.appendChild(content); container.appendChild(wrapper); - // 代码块复制按钮 - enhanceCodeBlocks(bubble); - return wrapper; } /** 创建空的 AI 气泡(流式追加用) */ export function createEmptyAIBubble(container: HTMLElement, timestamp: number, msgId?: string): { wrapper: HTMLElement; bubble: HTMLElement } { const wrapper = document.createElement('div'); - wrapper.className = 'csk-msg csk-msg--ai csk-msg--streaming'; + wrapper.className = 'csk-msg csk-msg--ai'; if (msgId) wrapper.dataset.cskMsgId = msgId; - const avatar = document.createElement('div'); - avatar.className = 'csk-msg__avatar csk-msg__avatar--ai'; - avatar.innerHTML = BOT_ICON; - - const content = document.createElement('div'); - content.className = 'csk-msg__content'; - - const bubble = document.createElement('div'); - bubble.className = 'csk-msg__bubble'; - bubble.innerHTML = ''; - - const time = document.createElement('div'); - time.className = 'csk-msg__time'; - time.textContent = formatTime(timestamp); - - content.appendChild(time); - content.appendChild(bubble); - // 操作栏:位于气泡下方 - const meta = document.createElement('div'); - meta.className = 'csk-msg__meta'; - meta.appendChild(buildAIActions(bubble, wrapper)); - content.appendChild(meta); - wrapper.appendChild(avatar); - wrapper.appendChild(content); + const msg = createChatItemMsg('assistant', [], timestamp, msgId); + msg.setAttribute('status', 'streaming'); + // 操作栏投射到 t-chat-item 的 actionbar 插槽(流式期间 copyText 为空,结束由 finalizeAIBubble 补全) + msg.appendChild(createChatAction(wrapper, '', msgId)); + wrapper.appendChild(msg); + container.appendChild(wrapper); - return { wrapper, bubble }; + return { wrapper, bubble: msg }; } // ==================== AI 消息操作条 + 代码块复制 ==================== -/** 复制图标 */ -const COPY_ICON = ``; -/** 重试图标 */ -const RETRY_ICON = ``; - -/** 构建 AI 消息操作条(复制 / 重试 / 反馈) */ -function buildAIActions(bubble: HTMLElement, wrapper: HTMLElement): HTMLElement { - const bar = document.createElement('div'); - bar.className = 'csk-msg__actions'; - - // 复制按钮 - const copyBtn = document.createElement('button'); - copyBtn.type = 'button'; - copyBtn.className = 'csk-action-btn'; - copyBtn.setAttribute('title', t('copy')); - copyBtn.setAttribute('aria-label', t('copy')); - copyBtn.innerHTML = COPY_ICON; - copyBtn.addEventListener('click', async (e) => { - e.stopPropagation(); - const text = bubble.textContent || ''; - await copyToClipboard(text, copyBtn); - }); - - // 重试按钮 - const retryBtn = document.createElement('button'); - retryBtn.type = 'button'; - retryBtn.className = 'csk-action-btn'; - retryBtn.setAttribute('title', t('retry')); - retryBtn.setAttribute('aria-label', t('retry')); - retryBtn.innerHTML = RETRY_ICON; - retryBtn.addEventListener('click', (e) => { - e.stopPropagation(); - const root = wrapper.closest('.csk-window'); - if (root) { - root.dispatchEvent(new CustomEvent('csk:retry', { - detail: { msgId: wrapper.dataset.cskMsgId || '' } - })); - } - }); - - // 反馈按钮(👍 / 👎) - const THUMB_UP = ``; - const THUMB_DOWN = ``; - - const upBtn = document.createElement('button'); - upBtn.type = 'button'; - upBtn.className = 'csk-feedback-btn'; - upBtn.setAttribute('title', t('feedback_up')); - upBtn.setAttribute('aria-label', t('feedback_up')); - upBtn.innerHTML = THUMB_UP; - upBtn.addEventListener('click', (e) => { - e.stopPropagation(); - const root = wrapper.closest('.csk-window'); - if (root) { - root.dispatchEvent(new CustomEvent('csk:feedback', { - detail: { msgId: wrapper.dataset.cskMsgId || '', value: 'up' } - })); - } - }); - - const downBtn = document.createElement('button'); - downBtn.type = 'button'; - downBtn.className = 'csk-feedback-btn'; - downBtn.setAttribute('title', t('feedback_down')); - downBtn.setAttribute('aria-label', t('feedback_down')); - downBtn.innerHTML = THUMB_DOWN; - downBtn.addEventListener('click', (e) => { - e.stopPropagation(); +/** + * 创建 AI 消息操作条(t-chat-action,投射到 t-chat-item 的 actionbar 插槽) + * 复制/重试/点赞/点踩均由 TDesign 组件承担;handleAction 回调负责分发 SDK 自定义事件 + */ +function createChatAction(wrapper: HTMLElement, text: string, msgId?: string, feedback?: 'up' | 'down'): HTMLElement { + const actionEl = document.createElement('t-chat-action'); + actionEl.setAttribute('slot', 'actionbar'); + const el = actionEl as unknown as { + actionBar: string[]; + handleAction: (action: string, data: { event?: Event; active?: boolean }) => void; + }; + el.actionBar = ['replay', 'copy', 'good', 'bad']; + // copyText/comment 为 String 简单类型,须用 setAttribute(property 赋值在 omi 下静默失效) + actionEl.setAttribute('copyText', text); + actionEl.setAttribute('comment', feedback === 'up' ? 'good' : feedback === 'down' ? 'bad' : ''); + el.handleAction = (action, data) => { const root = wrapper.closest('.csk-window'); - if (root) { + if (!root) return; + if (action === 'replay') { + root.dispatchEvent(new CustomEvent('csk:retry', { detail: { msgId: msgId || '' } })); + } else if (action === 'good' || action === 'bad') { root.dispatchEvent(new CustomEvent('csk:feedback', { - detail: { msgId: wrapper.dataset.cskMsgId || '', value: 'down' } + detail: { msgId: msgId || '', value: action === 'good' ? 'up' : 'down', active: !!data?.active } })); } - }); - - bar.appendChild(copyBtn); - bar.appendChild(retryBtn); - bar.appendChild(upBtn); - bar.appendChild(downBtn); - return bar; + // copy 由 t-chat-action 内部处理(用 copyText 调 navigator.clipboard),无需分发 + }; + return actionEl; } /** - * 更新反馈按钮的视觉状态(由 chat.ts 调用) - * @param wrapper 消息 wrapper 元素 - * @param value 当前反馈值:'up' | 'down' | undefined + * 回滚 t-chat-action 的反馈图标状态(重建组件为 comment='')。 + * t-chat-action 的 comment 仅在首次挂载时生效,运行时无法外部更新, + * 点踩弹原因面板被用户关闭时,通过重建组件来恢复未选中状态。 */ -export function updateFeedbackUI(wrapper: HTMLElement, value: 'up' | 'down' | undefined): void { - const btns = wrapper.querySelectorAll('.csk-feedback-btn'); - if (btns.length < 2) return; - btns.forEach((btn) => btn.classList.remove('csk-feedback-btn--active', 'down')); - if (value === 'up' && btns[0]) btns[0].classList.add('csk-feedback-btn--active'); - if (value === 'down' && btns[1]) btns[1].classList.add('csk-feedback-btn--active', 'down'); -} - -/** 复制文本到剪贴板,带"已复制"反馈 */ -async function copyToClipboard(text: string, btn: HTMLElement): Promise { - const original = btn.innerHTML; - try { - if (navigator.clipboard && window.isSecureContext) { - await navigator.clipboard.writeText(text); - } else { - // 降级方案:execCommand - const ta = document.createElement('textarea'); - ta.value = text; - ta.style.position = 'fixed'; - ta.style.opacity = '0'; - document.body.appendChild(ta); - ta.select(); - document.execCommand('copy'); - document.body.removeChild(ta); - } - btn.innerHTML = ``; - btn.classList.add('csk-action-btn--done'); - setTimeout(() => { - btn.innerHTML = original; - btn.classList.remove('csk-action-btn--done'); - }, 1500); - } catch { - // 复制失败静默处理 - } -} - -/** 为气泡内所有代码块添加复制按钮 */ -function enhanceCodeBlocks(bubble: HTMLElement): void { - const blocks = bubble.querySelectorAll('.csk-md-code-block'); - blocks.forEach((pre) => { - if (pre.querySelector('.csk-md-code-copy')) return; - const codeEl = pre.querySelector('code'); - const btn = document.createElement('button'); - btn.type = 'button'; - btn.className = 'csk-md-code-copy'; - btn.setAttribute('title', t('copy')); - btn.setAttribute('aria-label', t('copy')); - btn.innerHTML = COPY_ICON; - btn.addEventListener('click', async (e) => { - e.stopPropagation(); - await copyToClipboard(codeEl?.textContent || '', btn); - }); - (pre as HTMLElement).appendChild(btn); - }); -} - -/** 流式打字光标:追加到气泡末尾(每次 chunk 后调用) */ -export function appendStreamingCaret(bubble: HTMLElement): void { - if (bubble.querySelector('.csk-caret')) return; - const caret = document.createElement('span'); - caret.className = 'csk-caret'; - caret.setAttribute('aria-hidden', 'true'); - bubble.appendChild(caret); +export function resetChatActionFeedback(wrapper: HTMLElement): void { + const msg = wrapper.querySelector('t-chat-item'); + const actionEl = wrapper.querySelector('t-chat-action'); + if (!msg || !actionEl) return; + const text = actionEl.getAttribute('copyText') || ''; + const msgId = wrapper.dataset.cskMsgId; + actionEl.remove(); + msg.appendChild(createChatAction(wrapper, text, msgId, undefined)); } -/** 标记 AI 气泡流式结束:移除流式态、补代码块复制按钮 */ +/** 标记 AI 气泡流式结束:切换 status 为 complete,并同步复制内容为最终 markdown 原文 */ export function finalizeAIBubble(wrapper: HTMLElement, bubble: HTMLElement): void { - wrapper.classList.remove('csk-msg--streaming'); - const caret = bubble.querySelector('.csk-caret'); - if (caret) caret.remove(); - enhanceCodeBlocks(bubble); + bubble.setAttribute('status', 'complete'); + // 流式期间 copyText 为空,结束后同步为最终原文(t-chat-action 的 copyText 支持运行时更新) + const contentArr = (bubble as unknown as { content?: Array<{ data?: string }> }).content; + const text = (contentArr?.map(c => c.data || '').join('') || ''); + const actionEl = wrapper.querySelector('t-chat-action'); + if (actionEl) actionEl.setAttribute('copyText', text); } // ==================== P1: RAG 引用来源渲染 ==================== -/** 渲染 RAG 引用来源卡片 */ +/** + * 渲染 RAG 引用来源卡片(自定义折叠) + * 说明:尝试用 替换,但 tdesign-web-components 的 collapse/collapse-panel + * 依赖 omi 的 provide/inject 机制,在纯 DOM(createElement + appendChild)下无法建立 + * 注入链路(报 `this.injection.getCollapseValue is not a function`),故保留轻量自定义折叠。 + */ export function renderSources(wrapper: HTMLElement, sources: RagSource[]): void { // 移除已有的来源卡片 const existing = wrapper.querySelector('.csk-sources'); @@ -1149,10 +1020,10 @@ export function renderSources(wrapper: HTMLElement, sources: RagSource[]): void sourcesEl.appendChild(header); sourcesEl.appendChild(body); - // 插入到元信息行之后(来源卡片紧接在 meta 行下方) - const metaEl = wrapper.querySelector('.csk-msg__meta'); - if (metaEl && metaEl.parentNode) { - metaEl.parentNode.insertBefore(sourcesEl, metaEl.nextSibling); + // 插入到消息气泡(t-chat-item)之后,作为来源卡片紧随气泡下方 + const msgEl = wrapper.querySelector('t-chat-item'); + if (msgEl && msgEl.parentNode) { + msgEl.parentNode.insertBefore(sourcesEl, msgEl.nextSibling); } else { wrapper.appendChild(sourcesEl); } @@ -1330,24 +1201,21 @@ export function scrollToBottom(container: HTMLElement): void { // ==================== 离线提示横幅 ==================== -let offlineBannerEl: HTMLElement | null = null; - -/** 在消息区顶部展示离线提示横幅 */ +/** 在消息区顶部展示离线提示横幅(t-alert,theme=warning) */ export function showOfflineBanner(messagesContainer: HTMLElement): void { if (document.getElementById('csk-offline-banner')) return; - const banner = document.createElement('div'); + const banner = document.createElement('t-alert'); banner.id = 'csk-offline-banner'; - banner.className = 'csk-offline-banner'; - banner.textContent = t('error_offline'); + // message 为复杂类型(Object/Function 等),用 property;theme 为 String 简单类型,用 setAttribute + (banner as unknown as { message: string }).message = t('error_offline'); + banner.setAttribute('theme', 'warning'); messagesContainer.insertBefore(banner, messagesContainer.firstChild); - offlineBannerEl = banner; } /** 隐藏离线提示横幅 */ export function hideOfflineBanner(): void { const el = document.getElementById('csk-offline-banner'); if (el) el.remove(); - offlineBannerEl = null; } // ==================== 建议问题(suggest-message-list) ==================== @@ -1375,25 +1243,20 @@ export function renderSuggestions( list.className = 'csk-suggestions__list'; for (const text of suggestions) { - const chip = document.createElement('button'); - chip.type = 'button'; - chip.className = 'csk-suggestion-item'; - chip.textContent = text; - chip.addEventListener('click', (e) => { - e.stopPropagation(); - onClick(text); - }); - list.appendChild(chip); + // on* 回调(onClick)必须经 omi render 创建;tag 的 onClick 首参为原生事件,文本经 children 传入 + createEventful('t-tag', { + theme: 'primary', + variant: 'light-outline', + onClick: (e: Event) => { + e.stopPropagation(); + onClick(text); + }, + }, list, text); } section.appendChild(list); - // 插入到操作栏和来源卡片之间(在 content 内末尾) - const content = wrapper.querySelector('.csk-msg__content'); - if (content) { - content.appendChild(section); - } else { - wrapper.appendChild(section); - } + // 直接追加到 wrapper 末尾(wrapper 内即 t-chat-item,无 .csk-msg__content 中间层) + wrapper.appendChild(section); } /** @@ -1404,7 +1267,7 @@ export function removeSuggestions(wrapper: HTMLElement): void { if (existing) existing.remove(); } -// ==================== 反馈原因选择面板 ==================== +// ==================== 确认弹窗 + 反馈原因选择 ==================== /** 点踩原因选项(与后端 MessageFeedback.reasonCategory 枚举一致) */ const REASON_OPTIONS: { key: string; labelKey: string }[] = [ @@ -1415,13 +1278,50 @@ const REASON_OPTIONS: { key: string; labelKey: string }[] = [ ]; /** - * 在消息气泡下方展示点踩原因选择面板 - * 用户选择原因后回调 onConfirm(reason, comment),取消时回调 undefined 参数 + * 命令式确认弹窗(DialogPlugin.confirm),替代原生 confirm() + * @returns 确认返回 true,取消/关闭返回 false + */ +export function confirmWithDialog(message: string): Promise { + return new Promise((resolve) => { + let settled = false; + const finish = (val: boolean): void => { + if (settled) return; + settled = true; + resolve(val); + }; + const dlg = DialogPlugin.confirm({ + header: t('confirm'), + body: message, + confirmBtn: t('confirm'), + cancelBtn: t('cancel'), + onConfirm: () => { + finish(true); + dlg.destroy(); + }, + onCancel: () => { + finish(false); + dlg.destroy(); + }, + onClose: () => { + // ESC / 遮罩点击 / 关闭按钮兜底 + finish(false); + dlg.destroy(); + }, + }); + }); +} + +/** + * 在消息气泡下方展示点踩原因选择面板(内联,按钮用 t-button) + * 说明:尝试用 改为模态弹窗,但 dialog 的 visible/confirmBtn/cancelBtn 属性 + * 未在 omi propTypes 声明,纯 DOM property 赋值不生效(渲染为 display:none),且复杂 + * body 无法通过 DialogPlugin 注入,故保留内联面板形态,仅将按钮升级为 t-button。 */ export function showFeedbackReasonPanel( wrapper: HTMLElement, - msgId: string, + _msgId: string, onConfirm: (reason: 'inaccurate' | 'irrelevant' | 'incomplete' | 'other', comment?: string) => void, + onCancel?: () => void, ): void { // 移除已存在的原因面板 const existing = wrapper.querySelector('.csk-feedback-reason'); @@ -1436,14 +1336,16 @@ export function showFeedbackReasonPanel( title.textContent = t('feedback_reason_title'); panel.appendChild(title); - // 原因选项按钮 + // 原因选项按钮(t-button,点击即确认) const optionsRow = document.createElement('div'); optionsRow.className = 'csk-feedback-reason__options'; REASON_OPTIONS.forEach((opt) => { - const btn = document.createElement('button'); - btn.type = 'button'; - btn.className = 'csk-feedback-reason__btn'; + const btn = document.createElement('t-button'); + // t-button 文本通过 渲染(light DOM children),须用 textContent 而非 content 属性 btn.textContent = t(opt.labelKey); + btn.setAttribute('theme', 'default'); + btn.setAttribute('variant', 'outline'); + // button 的 click 经 eventDispose → fire 派发 CustomEvent('click'),用 addEventListener 监听 btn.addEventListener('click', (e) => { e.stopPropagation(); onConfirm(opt.key as 'inaccurate' | 'irrelevant' | 'incomplete' | 'other'); @@ -1463,10 +1365,10 @@ export function showFeedbackReasonPanel( commentInput.maxLength = 200; commentRow.appendChild(commentInput); - const submitBtn = document.createElement('button'); - submitBtn.type = 'button'; - submitBtn.className = 'csk-feedback-reason__submit'; + const submitBtn = document.createElement('t-button'); submitBtn.textContent = t('feedback_reason_submit'); + submitBtn.setAttribute('theme', 'primary'); + submitBtn.setAttribute('variant', 'base'); submitBtn.addEventListener('click', (e) => { e.stopPropagation(); const comment = commentInput.value.trim() || undefined; @@ -1476,7 +1378,7 @@ export function showFeedbackReasonPanel( commentRow.appendChild(submitBtn); panel.appendChild(commentRow); - // 关闭按钮 + // 关闭按钮(右上角,轻量原生 button 承载 X 图标) const closeBtn = document.createElement('button'); closeBtn.type = 'button'; closeBtn.className = 'csk-feedback-reason__close'; @@ -1485,6 +1387,7 @@ export function showFeedbackReasonPanel( closeBtn.addEventListener('click', (e) => { e.stopPropagation(); panel.remove(); + if (onCancel) onCancel(); }); panel.appendChild(closeBtn); diff --git a/client/src/i18n.ts b/client/src/i18n.ts index 13f31d3..078f2f6 100644 --- a/client/src/i18n.ts +++ b/client/src/i18n.ts @@ -213,10 +213,3 @@ export function t(key: string, params?: Record): string return text; } - -/** - * 获取当前语言 - */ -function getLocale(): string { - return currentLocale; -} diff --git a/client/src/index.ts b/client/src/index.ts index 3613154..e18c045 100644 --- a/client/src/index.ts +++ b/client/src/index.ts @@ -7,12 +7,25 @@ * userId → accountId(客户账号 ID) * chatId → 自动管理(从 /conversation/list 获取或自动生成) */ +// TDesign Web Components:聊天组件注册(side-effect import,构建时打进 IIFE) +// 注意:消息气泡组件 ChatMessage 实际注册的标签是 t-chat-item(非 t-chat-message) +import 'tdesign-web-components/lib/chat-message/index.js'; +import 'tdesign-web-components/lib/chat-sender/index.js'; +import 'tdesign-web-components/lib/chat-action/index.js'; +import 'tdesign-web-components/lib/chat-loading/index.js'; +import 'tdesign-web-components/lib/style/index.js'; + +// TDesign Web Components:通用组件注册(Phase 2 外围 UI 替换) +import 'tdesign-web-components/lib/alert/index.js'; +import 'tdesign-web-components/lib/tag/index.js'; +import 'tdesign-web-components/lib/select/index.js'; +import 'tdesign-web-components/lib/button/index.js'; + import { SDKConfig, ResolvedConfig, ChatbotSDKInstance } from './types'; import { parseConfig } from './config'; import { setDebug, logger, setErrorCallback } from './logger'; import { setApiConfig, clearApiConfig, fetchSystemConfig } from './api'; import { injectStyles, removeStyles } from './styles'; -import { preloadMarked, resetMarked } from './markdown'; import { createLauncher, createChatWindow, enableDrag, enableLauncherDrag, enableResize } from './dom'; import { initChat, initChatHistory, setCategory, loadHistoryConversations, sendQuickReply, retryFromMessage, handleFeedback, switchRole } from './chat'; import { clearMessages } from './storage'; @@ -31,6 +44,42 @@ export type { ChatbotSDKInstance, } from './types'; +// ==================== 剪贴板降级 polyfill ==================== +// t-chat-action 的复制动作内部直接调用 navigator.clipboard.writeText, +// 在 HTTP(非安全上下文)或旧浏览器下 navigator.clipboard 为 undefined, +// 点击复制会同步抛 TypeError 且无 execCommand 降级。此处兜底: +// 当 navigator.clipboard 缺失时,注入带 execCommand('copy') 降级的实现, +// 保证复制功能在非 HTTPS 环境仍可用。 +if (typeof navigator !== 'undefined' && !navigator.clipboard) { + const fallbackCopy = (text: string): Promise => { + return new Promise((resolve, reject) => { + const ta = document.createElement('textarea'); + ta.value = text; + ta.setAttribute('readonly', ''); + ta.style.position = 'fixed'; + ta.style.left = '-9999px'; + document.body.appendChild(ta); + ta.select(); + let ok = false; + try { + ok = document.execCommand('copy'); + } catch { + ok = false; + } + document.body.removeChild(ta); + ok ? resolve() : reject(new Error('execCommand copy 失败')); + }); + }; + try { + Object.defineProperty(navigator, 'clipboard', { + value: { writeText: fallbackCopy }, + configurable: true, + }); + } catch { + // 某些宿主环境 navigator 只读,忽略 polyfill 失败 + } +} + // ==================== 单例状态 ==================== let config: ResolvedConfig | null = null; @@ -38,10 +87,9 @@ let isInitialized = false; let launcherEl: HTMLElement | null = null; let windowEl: HTMLElement | null = null; let messagesContainer: HTMLElement | null = null; -let inputEl: HTMLTextAreaElement | null = null; -let sendBtn: HTMLElement | null = null; +let inputEl: HTMLElement | null = null; let clearBtn: HTMLElement | null = null; -let categorySelect: HTMLSelectElement | null = null; +let categorySelect: HTMLElement | null = null; let historyPanel: HTMLElement | null = null; let showLoadingFn: (() => HTMLElement) | null = null; let hideLoadingFn: (() => void) | null = null; @@ -94,9 +142,6 @@ function init(rawConfig: SDKConfig): void { // 5. 注入样式 injectStyles(config); - // 5.1 预加载 marked(外部 Markdown 渲染库,异步不阻塞 UI) - preloadMarked(); - // 6. 创建悬浮按钮 launcherEl = createLauncher(config, toggle); document.body.appendChild(launcherEl); @@ -133,7 +178,6 @@ function init(rawConfig: SDKConfig): void { windowEl = dom.window; messagesContainer = dom.messagesContainer; inputEl = dom.inputEl; - sendBtn = dom.sendBtn; clearBtn = dom.clearBtn; categorySelect = dom.categorySelect; historyPanel = dom.historyPanel; @@ -172,7 +216,6 @@ function init(rawConfig: SDKConfig): void { initChat(config, { messagesContainer, inputEl, - sendBtn, clearBtn, categorySelect, historyPanel, @@ -207,7 +250,7 @@ function init(rawConfig: SDKConfig): void { // 15. 监听消息反馈事件(👍 / 👎) windowEl.addEventListener('csk:feedback', ((e: CustomEvent) => { - handleFeedback(e.detail.msgId, e.detail.value); + handleFeedback(e.detail.msgId, e.detail.value, !!e.detail.active); }) as EventListener); // 16. 新消息到达通知(用于未读徽章 + 提示音 + 桌面通知) @@ -257,6 +300,7 @@ function init(rawConfig: SDKConfig): void { if (config.disclaimer === undefined) { fetchSystemConfig('disclaimer').then(html => { if (html && disclaimerEl) { + // 后端 system_config 表中的声明为「受信 HTML」(仅 admin 可配置),直接注入属设计内行为 disclaimerEl.innerHTML = html; disclaimerEl.style.display = ''; } @@ -411,7 +455,6 @@ function destroy(): void { isInitialized = false; messagesContainer = null; inputEl = null; - sendBtn = null; clearBtn = null; categorySelect = null; historyPanel = null; @@ -421,17 +464,34 @@ function destroy(): void { audioCtx = null; disclaimerEl = null; clearApiConfig(); - resetMarked(); // 重置 marked 加载状态,允许下次 init 重试 logger.lifecycleDestroy(oldIntegrateId || ''); } +// 聚焦输入框:t-chat-sender 是 omi 自定义元素,宿主元素无 tabindex, +// 直接调用原生 HTMLElement.focus() 只会聚焦宿主、光标进不了内部 textarea。 +// 主路径调用组件实例暴露的 focus() 方法(聚焦内部 t-textarea → 原生 textarea); +// 若组件内部 ref 尚未就绪导致 focus() 静默无效,再穿透 shadow DOM 兜底聚焦。 +function focusInput(): void { + if (!inputEl) return; + // 主路径:调用组件 focus()(omi 在 constructor 用 own property 定义,非原生 focus) + (inputEl as unknown as { focus?: (opts?: FocusOptions) => void }).focus?.(); + // 兜底:焦点未真正落到内部 textarea 时,穿透两层 shadow DOM 直接聚焦 + const textarea = inputEl.shadowRoot + ?.querySelector('t-textarea') + ?.shadowRoot + ?.querySelector('textarea') as HTMLTextAreaElement | null | undefined; + if (textarea && document.activeElement !== textarea) { + textarea.focus(); + } +} + function open(): void { if (!windowEl) return; windowEl.classList.remove('csk-window--hidden'); hideTeaser(); hideBadge(); - setTimeout(() => { if (inputEl) inputEl.focus(); }, 80); + setTimeout(() => { focusInput(); }, 80); } function close(): void { diff --git a/client/src/markdown.ts b/client/src/markdown.ts deleted file mode 100644 index b0c6f27..0000000 --- a/client/src/markdown.ts +++ /dev/null @@ -1,242 +0,0 @@ -/** - * Markdown 渲染模块 - 基于 marked 外部脚本 - * - * marked v15.0.12 以静态文件方式由 SDK 自动加载,宿主无需手动引入。 - * 加载失败或未就绪时降级为纯文本渲染,不丢消息。 - * - * XSS 安全策略: - * 1. 自定义 Renderer 全面接管输出,所有类名/标签由 SDK 生成 - * 2. 链接/图片 URL 白名单校验(仅 http/https) - * 3. 禁止 raw HTML 渲染 - * 4. 代码内容使用 escapeHtml 转义 - */ -import { escapeHtml } from './utils'; - -/** marked 是否已加载并完成配置 */ -let markedReady = false; - -/** 加载 Promise,用于等待就绪 */ -let markedLoadPromise: Promise | null = null; - -/** 已配置安全的 marked 实例闭包引用(不反复读取 window.marked,防止篡改) */ -let _markedInstance: any = null; - -// ==================== 工具函数 ==================== - -/** 从当前页面的 chatbot-sdk 脚本 src 推断 SDK 基础路径 */ -function getSdkBasePath(): string { - if (typeof document === 'undefined') return '/sdk/'; - const scripts = document.getElementsByTagName('script'); - for (let i = 0; i < scripts.length; i++) { - const src = scripts[i].src; - if (src && /\/chatbot-sdk(\.min)?\.js([?#].*)?$/.test(src)) { - return src.replace(/chatbot-sdk(\.min)?\.js.*$/, ''); - } - } - return '/sdk/'; -} - -/** 校验 URL 安全性:仅允许 http/https 且不含 HTML 属性破坏字符 */ -function isSafeUrl(url: string): boolean { - return /^https?:\/\/[^\s"'<>]*$/i.test(url.trim()); -} - -// ==================== marked 配置 ==================== - -/** - * 配置 marked 实例 - * - 输出统一使用 csk-md-* 类名前缀(兼容现有 styles.ts) - * - 链接/图片仅允许 http/https - * - 禁止 raw HTML - */ -function setupMarked(m: any): void { - // 保存到闭包变量,后续 renderMarkdown 只使用此引用,防止 window.marked 被篡改 - _markedInstance = m; - - // 全局选项:聊天场景保留换行,启用 GFM - m.setOptions({ breaks: true, gfm: true }); - - m.use({ - renderer: { - /** 标题 → */ - heading(this: any, token: any): string { - const text = this.parser.parseInline(token.tokens); - return `${text}\n`; - }, - - /** 段落 →

    */ - paragraph(this: any, token: any): string { - const text = this.parser.parseInline(token.tokens); - return `

    ${text}

    \n`; - }, - - /** 代码块 →
     */
    -      code(token: any): string {
    -        const langClass = token.lang ? ` class="language-${escapeHtml(token.lang)}"` : '';
    -        return `
    ${escapeHtml(token.text)}
    \n`; - }, - - /** 行内代码 → */ - codespan(token: any): string { - return `${escapeHtml(token.text)}`; - }, - - /** 斜体(补充 csk-md-* 类名体系) */ - em(this: any, token: any): string { - return `${this.parser.parseInline(token.tokens)}`; - }, - - /** 粗体(补充 csk-md-* 类名体系) */ - strong(this: any, token: any): string { - return `${this.parser.parseInline(token.tokens)}`; - }, - - /** 删除线(补充 csk-md-* 类名体系) */ - del(this: any, token: any): string { - return `${this.parser.parseInline(token.tokens)}`; - }, - - /** 引用块 →
    */ - blockquote(this: any, token: any): string { - const body = this.parser.parse(token.tokens); - return `
    \n${body}
    \n`; - }, - - /** 列表 →
      /
        */ - list(this: any, token: any): string { - const tag = token.ordered ? 'ol' : 'ul'; - const cls = token.ordered ? 'csk-md-ol' : 'csk-md-ul'; - const startAttr = token.ordered && token.start !== 1 ? ` start="${token.start}"` : ''; - // 列表项须用 this.listitem(item) 渲染,不可 this.parser.parse([item]): - // marked v15 的 Parser.parse 按 token.type 做 switch 分发,无 "list_item" 分支,直接 parse 会抛异常 - const body = token.items.map((item: any) => this.listitem(item)).join(''); - return `<${tag} class="${cls}"${startAttr}>\n${body}\n`; - }, - - /** 列表项(支持任务列表 checkbox) */ - listitem(this: any, token: any): string { - let checkbox = ''; - if (token.task) { - checkbox = token.checked - ? ' ' - : ' '; - } - const body = this.parser.parse(token.tokens); - return `
      1. ${checkbox}${body}
      2. \n`; - }, - - /** 表格(包裹在可滚动容器中) */ - table(this: any, token: any): string { - const headerCells = token.header.map((cell: any) => { - const align = cell.align ? ` class="csk-md-align-${cell.align}"` : ''; - return `${this.parser.parseInline(cell.tokens)}`; - }).join(''); - const bodyRows = token.rows.map((row: any) => { - const cells = row.map((cell: any) => { - const align = cell.align ? ` class="csk-md-align-${cell.align}"` : ''; - return `${this.parser.parseInline(cell.tokens)}`; - }).join(''); - return `${cells}`; - }).join(''); - return `
        \n${headerCells}\n${bodyRows}\n
        \n`; - }, - - /** 链接 →
        (仅允许 http/https) */ - link(this: any, token: any): string { - const safeHref = isSafeUrl(token.href) ? token.href : '#'; - const titleAttr = token.title ? ` title="${escapeHtml(token.title)}"` : ''; - const text = this.parser.parseInline(token.tokens); - return `${text}`; - }, - - /** 图片 → (仅允许 http/https,非法降级为 alt 文本) */ - image(token: any): string { - if (!isSafeUrl(token.href)) return escapeHtml(token.text); - const titleAttr = token.title ? ` title="${escapeHtml(token.title)}"` : ''; - return `${escapeHtml(token.text)}`; - }, - - /** 水平线 →
        */ - hr(): string { - return '
        \n'; - }, - - /** 禁止 raw HTML(关键 XSS 防线) */ - html(): string { - return ''; - }, - }, - }); -} - -// ==================== 公开 API ==================== - -/** - * 预加载 marked 外部脚本 - * 在 SDK init 时调用,尽早开始加载,减少首次渲染时的等待 - */ -export function preloadMarked(): void { - if (markedLoadPromise) return; - - markedLoadPromise = new Promise((resolve) => { - // 1. 检查是否已存在(宿主手动引入或相同域名已加载) - const existing = (window as any).marked; - if (existing && typeof existing.parse === 'function') { - setupMarked(existing); - markedReady = true; - resolve(true); - return; - } - - // 2. 动态创建 + @@ -13,7 +13,7 @@ - +