@will1123/lx-ui-utils 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +747 -120
  2. package/dist/dist/index.esm.js +69039 -469
  3. package/dist/dist/index.esm.min.js +62900 -328
  4. package/dist/dist/index.esm.min.js.map +1 -1
  5. package/dist/dist/index.umd.js +69038 -468
  6. package/dist/dist/index.umd.min.js +346 -13
  7. package/dist/dist/index.umd.min.js.map +1 -1
  8. package/dist/es/helper.js +59 -0
  9. package/dist/es/helper.js.map +1 -0
  10. package/dist/es/index.js +13 -11
  11. package/dist/es/index.js.map +1 -1
  12. package/dist/es/markdown.js +248 -267
  13. package/dist/es/markdown.js.map +1 -1
  14. package/dist/es/node_modules/katex/dist/katex.js +14455 -0
  15. package/dist/es/node_modules/katex/dist/katex.js.map +1 -0
  16. package/dist/es/sse.js +34 -142
  17. package/dist/es/sse.js.map +1 -1
  18. package/dist/es/thinking.js +19 -138
  19. package/dist/es/thinking.js.map +1 -1
  20. package/dist/lib/helper.js +59 -0
  21. package/dist/lib/helper.js.map +1 -0
  22. package/dist/lib/index.js +9 -7
  23. package/dist/lib/index.js.map +1 -1
  24. package/dist/lib/markdown.js +249 -268
  25. package/dist/lib/markdown.js.map +1 -1
  26. package/dist/lib/node_modules/katex/dist/katex.js +14454 -0
  27. package/dist/lib/node_modules/katex/dist/katex.js.map +1 -0
  28. package/dist/lib/sse.js +34 -142
  29. package/dist/lib/sse.js.map +1 -1
  30. package/dist/lib/thinking.js +19 -138
  31. package/dist/lib/thinking.js.map +1 -1
  32. package/dist/types/helper.d.ts +46 -0
  33. package/dist/types/helper.d.ts.map +1 -0
  34. package/dist/types/index.d.ts +1 -0
  35. package/dist/types/index.d.ts.map +1 -1
  36. package/dist/types/markdown.d.ts +69 -100
  37. package/dist/types/markdown.d.ts.map +1 -1
  38. package/dist/types/sse.d.ts +48 -48
  39. package/dist/types/sse.d.ts.map +1 -1
  40. package/dist/types/thinking.d.ts +25 -48
  41. package/dist/types/thinking.d.ts.map +1 -1
  42. package/package.json +21 -4
@@ -0,0 +1,59 @@
1
+ var __async = (__this, __arguments, generator) => {
2
+ return new Promise((resolve, reject) => {
3
+ var fulfilled = (value) => {
4
+ try {
5
+ step(generator.next(value));
6
+ } catch (e) {
7
+ reject(e);
8
+ }
9
+ };
10
+ var rejected = (value) => {
11
+ try {
12
+ step(generator.throw(value));
13
+ } catch (e) {
14
+ reject(e);
15
+ }
16
+ };
17
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
18
+ step((generator = generator.apply(__this, __arguments)).next());
19
+ });
20
+ };
21
+ function copyToClipboard(text) {
22
+ return __async(this, null, function* () {
23
+ if (typeof window === "undefined") return false;
24
+ if (navigator.clipboard && navigator.clipboard.writeText) {
25
+ try {
26
+ yield navigator.clipboard.writeText(text);
27
+ return true;
28
+ } catch (error) {
29
+ console.error("复制失败:", error);
30
+ return false;
31
+ }
32
+ }
33
+ const textArea = document.createElement("textarea");
34
+ textArea.value = text;
35
+ textArea.style.position = "fixed";
36
+ textArea.style.opacity = "0";
37
+ textArea.style.left = "-9999px";
38
+ document.body.appendChild(textArea);
39
+ textArea.focus();
40
+ textArea.select();
41
+ try {
42
+ const successful = document.execCommand("copy");
43
+ document.body.removeChild(textArea);
44
+ return successful;
45
+ } catch (error) {
46
+ console.error("复制失败:", error);
47
+ document.body.removeChild(textArea);
48
+ return false;
49
+ }
50
+ });
51
+ }
52
+ function isDom(val) {
53
+ return val instanceof HTMLElement || val instanceof Document;
54
+ }
55
+ export {
56
+ copyToClipboard,
57
+ isDom
58
+ };
59
+ //# sourceMappingURL=helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helper.js","sources":["../../src/helper.ts"],"sourcesContent":["/**\r\n * 复制文本到剪贴板\r\n *\r\n * @param text - 要复制的文本\r\n * @returns Promise<boolean> - 成功返回 true,失败返回 false\r\n *\r\n * @example\r\n * ```typescript\r\n * import { copyToClipboard } from '@will1123/lx-ui-utils'\r\n *\r\n * // 基础用法\r\n * const success = await copyToClipboard('Hello World')\r\n * if (success) {\r\n * console.log('复制成功')\r\n * } else {\r\n * console.log('复制失败')\r\n * }\r\n *\r\n * // 复制代码\r\n * const code = 'console.log(\"Hello World\")'\r\n * await copyToClipboard(code)\r\n *\r\n * // 复制 HTML 内容\r\n * const html = '<div>Hello</div>'\r\n * await copyToClipboard(html)\r\n * ```\r\n */\r\nexport async function copyToClipboard(text: string): Promise<boolean> {\r\n if (typeof window === 'undefined') return false;\r\n\r\n // 使用现代 Clipboard API\r\n if (navigator.clipboard && navigator.clipboard.writeText) {\r\n try {\r\n await navigator.clipboard.writeText(text);\r\n return true;\r\n } catch (error) {\r\n console.error('复制失败:', error);\r\n return false;\r\n }\r\n }\r\n\r\n // 降级方案:使用 document.execCommand\r\n const textArea = document.createElement('textarea');\r\n textArea.value = text;\r\n textArea.style.position = 'fixed';\r\n textArea.style.opacity = '0';\r\n textArea.style.left = '-9999px';\r\n document.body.appendChild(textArea);\r\n textArea.focus();\r\n textArea.select();\r\n\r\n try {\r\n const successful = document.execCommand('copy');\r\n document.body.removeChild(textArea);\r\n return successful;\r\n } catch (error) {\r\n console.error('复制失败:', error);\r\n document.body.removeChild(textArea);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * 判断值是否为 DOM 元素(HTMLElement 或 Document)\r\n *\r\n * @param val - 要判断的值\r\n * @returns 是否为 DOM 元素\r\n *\r\n * @example\r\n * ```typescript\r\n * import { isDom } from '@will1123/lx-ui-utils'\r\n *\r\n * isDom(document.body) // true\r\n * isDom(document) // true\r\n * isDom({}) // false\r\n * isDom('div') // false\r\n * ```\r\n */\r\nexport function isDom(val: unknown): val is HTMLElement | Document {\r\n return val instanceof HTMLElement || val instanceof Document;\r\n}\r\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AA2BA,SAAsB,gBAAgB,MAAgC;AAAA;AACpE,QAAI,OAAO,WAAW,YAAa,QAAO;AAG1C,QAAI,UAAU,aAAa,UAAU,UAAU,WAAW;AACxD,UAAI;AACF,cAAM,UAAU,UAAU,UAAU,IAAI;AACxC,eAAO;AAAA,MACT,SAAS,OAAO;AACd,gBAAQ,MAAM,SAAS,KAAK;AAC5B,eAAO;AAAA,MACT;AAAA,IACF;AAGA,UAAM,WAAW,SAAS,cAAc,UAAU;AAClD,aAAS,QAAQ;AACjB,aAAS,MAAM,WAAW;AAC1B,aAAS,MAAM,UAAU;AACzB,aAAS,MAAM,OAAO;AACtB,aAAS,KAAK,YAAY,QAAQ;AAClC,aAAS,MAAA;AACT,aAAS,OAAA;AAET,QAAI;AACF,YAAM,aAAa,SAAS,YAAY,MAAM;AAC9C,eAAS,KAAK,YAAY,QAAQ;AAClC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,SAAS,KAAK;AAC5B,eAAS,KAAK,YAAY,QAAQ;AAClC,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAkBO,SAAS,MAAM,KAA6C;AACjE,SAAO,eAAe,eAAe,eAAe;AACtD;"}
package/dist/es/index.js CHANGED
@@ -1,15 +1,17 @@
1
- import { SSEConnection, sse } from "./sse.js";
2
- import { ThinkingStreamExtractor, createThinkingExtractor, extractThinking } from "./thinking.js";
3
- import { MarkdownRenderer, MarkdownStreamRenderer, createMarkdownRenderer, renderMarkdown } from "./markdown.js";
1
+ import { sse } from "./sse.js";
2
+ import { extractThinking } from "./thinking.js";
3
+ import { bindMarkdownCodeBoxEvents, createMarkdownRender, getMarkdownCodeTheme, setMarkdownCodeTheme, toggleMarkdownCodeTheme, updateMarkdownCodeBlocksTheme } from "./markdown.js";
4
+ import { copyToClipboard, isDom } from "./helper.js";
4
5
  export {
5
- MarkdownRenderer,
6
- MarkdownStreamRenderer,
7
- SSEConnection,
8
- ThinkingStreamExtractor,
9
- createMarkdownRenderer,
10
- createThinkingExtractor,
6
+ bindMarkdownCodeBoxEvents,
7
+ copyToClipboard,
8
+ createMarkdownRender,
11
9
  extractThinking,
12
- renderMarkdown,
13
- sse
10
+ getMarkdownCodeTheme,
11
+ isDom,
12
+ setMarkdownCodeTheme,
13
+ sse,
14
+ toggleMarkdownCodeTheme,
15
+ updateMarkdownCodeBlocksTheme
14
16
  };
15
17
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -1,286 +1,267 @@
1
- class MarkdownRenderer {
2
- constructor(config = {}) {
3
- this.config = {
4
- highlight: config.highlight || false,
5
- highlightLanguages: config.highlightLanguages || {},
6
- taskList: config.taskList !== false,
7
- table: config.table !== false,
8
- link: config.link !== false,
9
- image: config.image !== false
10
- };
11
- }
12
- /**
13
- * 渲染 Markdown 为 HTML
14
- */
15
- render(markdown) {
16
- let html = markdown;
17
- html = this.escapeHtml(html);
18
- html = this.renderCodeBlocks(html);
19
- html = this.renderHeadings(html);
20
- html = this.renderEmphasis(html);
21
- if (this.config.taskList) {
22
- html = this.renderTaskLists(html);
23
- }
24
- html = this.renderUnorderedLists(html);
25
- html = this.renderOrderedLists(html);
26
- if (this.config.table) {
27
- html = this.renderTables(html);
28
- }
29
- if (this.config.link) {
30
- html = this.renderLinks(html);
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
5
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
+ var __spreadValues = (a, b) => {
7
+ for (var prop in b || (b = {}))
8
+ if (__hasOwnProp.call(b, prop))
9
+ __defNormalProp(a, prop, b[prop]);
10
+ if (__getOwnPropSymbols)
11
+ for (var prop of __getOwnPropSymbols(b)) {
12
+ if (__propIsEnum.call(b, prop))
13
+ __defNormalProp(a, prop, b[prop]);
31
14
  }
32
- if (this.config.image) {
33
- html = this.renderImages(html);
34
- }
35
- html = this.renderParagraphs(html);
36
- html = this.renderLineBreaks(html);
37
- return html;
38
- }
39
- /**
40
- * 转义 HTML 特殊字符
41
- */
42
- escapeHtml(text) {
43
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
44
- }
45
- /**
46
- * 渲染代码块
47
- */
48
- renderCodeBlocks(text) {
49
- return text.replace(
50
- /`{3}(\w*)\n([\s\S]*?)`{3}/g,
51
- (match, lang, code) => {
52
- const language = lang || "text";
53
- return `<pre><code class="language-${language}">${code.trim()}</code></pre>`;
54
- }
55
- );
56
- }
57
- /**
58
- * 渲染标题
59
- */
60
- renderHeadings(text) {
61
- return text.replace(/^#{6}\s+(.+)$/gm, "<h6>$1</h6>").replace(/^#{5}\s+(.+)$/gm, "<h5>$1</h5>").replace(/^#{4}\s+(.+)$/gm, "<h4>$1</h4>").replace(/^#{3}\s+(.+)$/gm, "<h3>$1</h3>").replace(/^#{2}\s+(.+)$/gm, "<h2>$1</h2>").replace(/^#{1}\s+(.+)$/gm, "<h1>$1</h1>");
62
- }
63
- /**
64
- * 渲染粗体和斜体
65
- */
66
- renderEmphasis(text) {
67
- text = text.replace(/\*\*\*(.+?)\*\*\*/g, "<strong><em>$1</em></strong>");
68
- text = text.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
69
- text = text.replace(/___(.+?)___/g, "<strong><em>$1</em></strong>");
70
- text = text.replace(/__(.+?)__/g, "<strong>$1</strong>");
71
- text = text.replace(/\*(.+?)\*/g, "<em>$1</em>");
72
- text = text.replace(/_(.+?)_/g, "<em>$1</em>");
73
- return text;
74
- }
75
- /**
76
- * 渲染任务列表
77
- */
78
- renderTaskLists(text) {
79
- return text.replace(/^\s*-\s*\[x\]\s+(.+)$/gm, '<li class="task-checked"><input type="checkbox" checked disabled> $1</li>').replace(/^\s*-\s*\[\s*\]\s+(.+)$/gm, '<li><input type="checkbox" disabled> $1</li>');
80
- }
81
- /**
82
- * 渲染无序列表
83
- */
84
- renderUnorderedLists(text) {
85
- const lines = text.split("\n");
86
- const result = [];
87
- const listStack = [];
88
- for (const line of lines) {
89
- const match = line.match(/^(\s*)-\s+(.+)$/);
90
- if (!match) {
91
- while (listStack.length > 0) {
92
- result.push(listStack.pop() || "");
93
- }
94
- result.push(line);
95
- continue;
96
- }
97
- const [_, indent, content] = match;
98
- const indentLevel = indent.length;
99
- while (listStack.length > 0 && listStack.length < indentLevel / 2 + 1) {
100
- result.push(listStack.pop() || "");
15
+ return a;
16
+ };
17
+ var __async = (__this, __arguments, generator) => {
18
+ return new Promise((resolve, reject) => {
19
+ var fulfilled = (value) => {
20
+ try {
21
+ step(generator.next(value));
22
+ } catch (e) {
23
+ reject(e);
101
24
  }
102
- while (listStack.length < indentLevel / 2 + 1) {
103
- listStack.push("<ul>");
104
- result.push("<ul>");
25
+ };
26
+ var rejected = (value) => {
27
+ try {
28
+ step(generator.throw(value));
29
+ } catch (e) {
30
+ reject(e);
105
31
  }
106
- result.push(`<li>${content}</li>`);
107
- }
108
- while (listStack.length > 0) {
109
- result.push("</ul>");
110
- listStack.pop();
111
- }
112
- return result.join("\n");
32
+ };
33
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
34
+ step((generator = generator.apply(__this, __arguments)).next());
35
+ });
36
+ };
37
+ import { marked, Marked } from "marked";
38
+ import { markedHighlight } from "marked-highlight";
39
+ import hljs from "highlight.js";
40
+ import katex from "./node_modules/katex/dist/katex.js";
41
+ import { copyToClipboard, isDom } from "./helper.js";
42
+ function getMarkdownCodeTheme() {
43
+ if (typeof window === "undefined") return "dark";
44
+ return localStorage.getItem("LxUIMdCodeTheme") || "dark";
45
+ }
46
+ function setMarkdownCodeTheme(theme) {
47
+ if (typeof window === "undefined") return;
48
+ localStorage.setItem("LxUIMdCodeTheme", theme);
49
+ }
50
+ function toggleMarkdownCodeTheme() {
51
+ const currentTheme = getMarkdownCodeTheme();
52
+ const newTheme = currentTheme === "dark" ? "light" : "dark";
53
+ setMarkdownCodeTheme(newTheme);
54
+ return newTheme;
55
+ }
56
+ function updateMarkdownCodeBlocksTheme(themeOrContainer, theme) {
57
+ if (typeof window === "undefined") return;
58
+ let actualTheme;
59
+ let container = document.body;
60
+ if (typeof themeOrContainer === "string") {
61
+ actualTheme = themeOrContainer;
62
+ } else {
63
+ container = themeOrContainer;
64
+ actualTheme = theme;
113
65
  }
114
- /**
115
- * 渲染有序列表
116
- */
117
- renderOrderedLists(text) {
118
- const lines = text.split("\n");
119
- const result = [];
120
- let inList = false;
121
- for (const line of lines) {
122
- const match = line.match(/^\s*\d+\.\s+(.+)$/);
123
- if (!match) {
124
- if (inList) {
125
- result.push("</ol>");
126
- inList = false;
127
- }
128
- result.push(line);
129
- continue;
130
- }
131
- const [_, content] = match;
132
- if (!inList) {
133
- result.push("<ol>");
134
- inList = true;
66
+ const codeBoxes = container.querySelectorAll(".lx-ui-code-box");
67
+ codeBoxes.forEach((box) => {
68
+ box.setAttribute("data-theme", actualTheme);
69
+ });
70
+ }
71
+ function createMarkdownRender(createConfig = {}) {
72
+ const {
73
+ codeBoxToolEnable = true,
74
+ katexEnable = true,
75
+ katexOptions
76
+ } = createConfig;
77
+ const markedRenderer = new marked.Renderer();
78
+ const originalLinkRenderer = markedRenderer.link;
79
+ markedRenderer.link = (...arg) => {
80
+ const html = originalLinkRenderer.call(markedRenderer, ...arg);
81
+ return html.replace(/^<a /, '<a target="_blank" ');
82
+ };
83
+ const originalTableRenderer = markedRenderer.table;
84
+ markedRenderer.table = (...arg) => {
85
+ const html = originalTableRenderer.call(markedRenderer, ...arg);
86
+ return `<div class="lx-ui-table-wrapper"><div class="lx-ui-table-box">${html}</div></div>`;
87
+ };
88
+ const originalCodeRenderer = markedRenderer.code;
89
+ markedRenderer.code = (token) => {
90
+ const html = originalCodeRenderer.call(markedRenderer, token);
91
+ const theme = getMarkdownCodeTheme();
92
+ const lang = (token == null ? void 0 : token.lang) || "";
93
+ const codeBoxToolEnableHtml = `<div class="lx-ui-code-box-header">
94
+ <div class="lx-ui-code-box-header-left">
95
+ <span class="lx-ui-code-language">${lang}</span>
96
+ </div>
97
+ <div class="lx-ui-code-box-header-right">
98
+ <i class="lx-ui-code-box-header-copy lx-ui-icon-copy" title="复制">复制</i>
99
+ <i class="lx-ui-code-box-header-theme lx-ui-icon-theme" title="切换主题">切换主题</i>
100
+ </div>
101
+ </div>`;
102
+ const codeBoxToolDisableHtml = `<div class="lx-ui-code-box-header">
103
+ <div class="lx-ui-code-box-header-left">
104
+ <span class="lx-ui-code-language">${lang}</span>
105
+ </div>
106
+ </div>`;
107
+ return `<div class="lx-ui-code-box-wrapper">
108
+ <div class="lx-ui-code-box" data-theme="${theme}">
109
+ ${codeBoxToolEnable ? codeBoxToolEnableHtml : codeBoxToolDisableHtml}
110
+ <div class="lx-ui-code-box-content">
111
+ ${html}
112
+ </div>
113
+ </div>
114
+ </div>`;
115
+ };
116
+ const markdownRender = new Marked(
117
+ markedHighlight({
118
+ langPrefix: "hljs language-",
119
+ highlight(code, lang) {
120
+ const language = hljs.getLanguage(lang) ? lang : "plaintext";
121
+ return hljs.highlight(code, { language }).value;
135
122
  }
136
- result.push(`<li>${content}</li>`);
137
- }
138
- if (inList) {
139
- result.push("</ol>");
140
- }
141
- return result.join("\n");
123
+ })
124
+ );
125
+ markdownRender.setOptions({
126
+ renderer: markedRenderer
127
+ });
128
+ if (katexEnable) {
129
+ markdownRender.use(createKatexExtension(katexOptions));
142
130
  }
143
- /**
144
- * 渲染表格
145
- */
146
- renderTables(text) {
147
- const lines = text.split("\n");
148
- const result = [];
149
- let inTable = false;
150
- let headerRendered = false;
151
- for (let i = 0; i < lines.length; i++) {
152
- const line = lines[i];
153
- if (line.match(/^\|[\s\-:|]+\|$/)) {
154
- continue;
155
- }
156
- const match = line.match(/^\|(.+)\|$/);
157
- if (!match) {
158
- if (inTable) {
159
- result.push("</table>");
160
- inTable = false;
161
- headerRendered = false;
131
+ return markdownRender;
132
+ }
133
+ function createKatexExtension(katexOptions) {
134
+ return {
135
+ extensions: [
136
+ {
137
+ name: "blockMath",
138
+ level: "block",
139
+ start(src) {
140
+ return src.indexOf("$$");
141
+ },
142
+ tokenizer(src) {
143
+ const match = src.match(/^\$\$([\s\S]*?)\$\$(?:\n|$)/);
144
+ if (match) {
145
+ try {
146
+ const formula = match[1].trim();
147
+ const html = katex.renderToString(formula, __spreadValues({
148
+ displayMode: true,
149
+ throwOnError: false
150
+ }, katexOptions));
151
+ return {
152
+ type: "blockMath",
153
+ raw: match[0],
154
+ html: `<div class="lx-ui-katex-block">${html}</div>`
155
+ };
156
+ } catch (e) {
157
+ console.error("块级公式渲染错误:", e);
158
+ return {
159
+ type: "blockMath",
160
+ raw: match[0],
161
+ html: match[0]
162
+ };
163
+ }
164
+ }
165
+ },
166
+ renderer(token) {
167
+ return token.html || "";
168
+ }
169
+ },
170
+ {
171
+ name: "inlineMath",
172
+ level: "inline",
173
+ start(src) {
174
+ return src.indexOf("$");
175
+ },
176
+ tokenizer(src) {
177
+ const match = src.match(/^\$(?!\$)([^\$\n]+?)\$(?!\$)/);
178
+ if (match) {
179
+ try {
180
+ const formula = match[1].trim();
181
+ const html = katex.renderToString(formula, __spreadValues({
182
+ displayMode: false,
183
+ throwOnError: false
184
+ }, katexOptions));
185
+ return {
186
+ type: "inlineMath",
187
+ raw: match[0],
188
+ html: `<span class="lx-ui-katex-inline">${html}</span>`
189
+ };
190
+ } catch (e) {
191
+ console.error("行内公式渲染错误:", e);
192
+ return {
193
+ type: "inlineMath",
194
+ raw: match[0],
195
+ html: match[0]
196
+ };
197
+ }
198
+ }
199
+ },
200
+ renderer(token) {
201
+ return token.html || "";
162
202
  }
163
- result.push(line);
164
- continue;
165
- }
166
- const cells = match[1].split("|").map((cell) => cell.trim());
167
- if (!inTable) {
168
- result.push("<table>");
169
- inTable = true;
170
203
  }
171
- if (!headerRendered) {
172
- result.push("<thead><tr>");
173
- cells.forEach((cell) => {
174
- result.push(`<th>${cell}</th>`);
175
- });
176
- result.push("</tr></thead><tbody>");
177
- headerRendered = true;
178
- } else {
179
- result.push("<tr>");
180
- cells.forEach((cell) => {
181
- result.push(`<td>${cell}</td>`);
182
- });
183
- result.push("</tr>");
204
+ ]
205
+ };
206
+ }
207
+ function bindMarkdownCodeBoxEvents(containerOrConfig, config) {
208
+ if (typeof window === "undefined") {
209
+ return () => {
210
+ };
211
+ }
212
+ let container = document.body;
213
+ let eventsConfig = {};
214
+ if (containerOrConfig) {
215
+ if (isDom(containerOrConfig)) {
216
+ container = containerOrConfig;
217
+ if (config) {
218
+ eventsConfig = config;
184
219
  }
220
+ } else {
221
+ eventsConfig = containerOrConfig;
185
222
  }
186
- if (inTable) {
187
- result.push("</tbody></table>");
188
- }
189
- return result.join("\n");
190
- }
191
- /**
192
- * 渲染链接
193
- */
194
- renderLinks(text) {
195
- return text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank">$1</a>');
196
- }
197
- /**
198
- * 渲染图片
199
- */
200
- renderImages(text) {
201
- return text.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1" />');
202
223
  }
203
- /**
204
- * 渲染段落
205
- */
206
- renderParagraphs(text) {
207
- const lines = text.split("\n");
208
- const result = [];
209
- let inParagraph = false;
210
- for (const line of lines) {
211
- if (!line.trim() || line.match(/^<(h|ul|ol|li|table|pre|div)/)) {
212
- if (inParagraph) {
213
- result.push("</p>");
214
- inParagraph = false;
224
+ const { onCopySuccess, onCopyError, onThemeChange } = eventsConfig;
225
+ const clickHandler = (e) => __async(this, null, function* () {
226
+ const target = e.target;
227
+ const copyButton = target.closest(".lx-ui-icon-copy");
228
+ if (copyButton) {
229
+ const codeBox = copyButton.closest(".lx-ui-code-box");
230
+ const codeElement = codeBox == null ? void 0 : codeBox.querySelector(".lx-ui-code-box-content");
231
+ if (codeElement) {
232
+ const text = codeElement.textContent || "";
233
+ const success = yield copyToClipboard(text);
234
+ if (success) {
235
+ onCopySuccess == null ? void 0 : onCopySuccess(text);
236
+ } else {
237
+ onCopyError == null ? void 0 : onCopyError(new Error("复制失败"));
215
238
  }
216
- result.push(line);
217
- continue;
218
239
  }
219
- if (!inParagraph) {
220
- result.push("<p>");
221
- inParagraph = true;
222
- }
223
- result.push(line);
224
- }
225
- if (inParagraph) {
226
- result.push("</p>");
227
- }
228
- return result.join("\n");
229
- }
230
- /**
231
- * 渲染换行
232
- */
233
- renderLineBreaks(text) {
234
- return text.replace(/(<p>.*?<\/p>|<li>.*?<\/li>)/g, (match) => {
235
- return match.replace(/\n/g, "<br>\n");
236
- });
237
- }
238
- }
239
- function renderMarkdown(markdown, config) {
240
- const renderer = new MarkdownRenderer(config);
241
- return renderer.render(markdown);
242
- }
243
- class MarkdownStreamRenderer {
244
- constructor(config = {}) {
245
- this.buffer = "";
246
- this.config = config;
247
- this.renderer = new MarkdownRenderer(config);
248
- }
249
- /**
250
- * 追加文本并渲染
251
- */
252
- append(text) {
253
- this.buffer += text;
254
- const html = this.renderer.render(this.buffer);
255
- if (this.config.onUpdate) {
256
- this.config.onUpdate(html);
240
+ e.stopPropagation();
241
+ e.preventDefault();
242
+ return;
257
243
  }
258
- return html;
259
- }
260
- /**
261
- * 完成渲染
262
- */
263
- complete() {
264
- const html = this.renderer.render(this.buffer);
265
- if (this.config.onComplete) {
266
- this.config.onComplete(html);
244
+ const themeButton = target.closest(".lx-ui-icon-theme");
245
+ if (themeButton) {
246
+ const newTheme = toggleMarkdownCodeTheme();
247
+ updateMarkdownCodeBlocksTheme(newTheme);
248
+ onThemeChange == null ? void 0 : onThemeChange(newTheme);
249
+ e.stopPropagation();
250
+ e.preventDefault();
251
+ return;
267
252
  }
268
- return html;
269
- }
270
- /**
271
- * 重置渲染器
272
- */
273
- reset() {
274
- this.buffer = "";
275
- }
276
- }
277
- function createMarkdownRenderer(config) {
278
- return new MarkdownStreamRenderer(config);
253
+ });
254
+ container.addEventListener("click", clickHandler);
255
+ return () => {
256
+ container.removeEventListener("click", clickHandler);
257
+ };
279
258
  }
280
259
  export {
281
- MarkdownRenderer,
282
- MarkdownStreamRenderer,
283
- createMarkdownRenderer,
284
- renderMarkdown
260
+ bindMarkdownCodeBoxEvents,
261
+ createMarkdownRender,
262
+ getMarkdownCodeTheme,
263
+ setMarkdownCodeTheme,
264
+ toggleMarkdownCodeTheme,
265
+ updateMarkdownCodeBlocksTheme
285
266
  };
286
267
  //# sourceMappingURL=markdown.js.map