Преглед изворни кода

perf(base-卡6a): 新增公共 src/utils/markdownSafe.ts(marked+DOMPurify 消毒管线),ventAI chatModal utils 转调避免漂移

86132 пре 1 недеља
родитељ
комит
934b59b3cf

+ 31 - 0
src/utils/markdownSafe.ts

@@ -0,0 +1,31 @@
+// [perf-base-v1] 卡6: 公共 Markdown 渲染 + XSS 消毒管线
+// 实现源自 src/views/ventAI/manageAssistent/components/chatModal/utils.ts 的既有消毒配置
+// (marked 渲染 + DOMPurify.sanitize,ADD_TAGS:['img']),迁移为公共 util;
+// ventAI chatModal/utils.ts 转调本文件,避免多处实现漂移。
+// 所有 v-html 绑定的 markdown/HTML 内容必须先经过本模块消毒。
+import { marked } from 'marked';
+import DOMPurify from 'dompurify';
+
+/**
+ * 对已生成的 HTML 做 DOMPurify 白名单消毒(v-html 前必须经过此函数)
+ * @param html 待消毒 HTML
+ * @param addAttr 额外放行的属性(如 data-action 等交互属性、target 等)
+ */
+export function sanitizeHtml(html: string, addAttr: string[] = []): string {
+  if (!html) return '';
+  return DOMPurify.sanitize(html, {
+    ADD_TAGS: ['img'],
+    ...(addAttr.length ? { ADD_ATTR: addAttr } : {}),
+  });
+}
+
+/**
+ * marked 渲染 + DOMPurify 消毒(ADD_TAGS:['img']),返回可直接用于 v-html 的安全 HTML
+ * @param text markdown 原文
+ * @param addAttr 额外放行的属性
+ */
+export function renderMarkdownSafe(text: string, addAttr: string[] = []): string {
+  if (!text) return '';
+  const html = marked.parse(text) as string;
+  return sanitizeHtml(html, addAttr);
+}

+ 4 - 5
src/views/ventAI/manageAssistent/components/chatModal/utils.ts

@@ -1,7 +1,8 @@
 import { marked, Renderer } from 'marked';
 import type { Tokens } from 'marked';
 import katex from 'katex';
-import DOMPurify from 'dompurify';
+// [perf-base-v1] 卡6: DOMPurify 消毒实现迁到公共 util,本文件转调避免两处漂移
+import { sanitizeHtml } from '/@/utils/markdownSafe';
 
 const mdRenderer = new Renderer();
 const defaultLinkRenderer = mdRenderer.link.bind(mdRenderer);
@@ -57,10 +58,8 @@ export const renderMarkdown = (
   html = processFootnotes(html, maxCitationId);
   html = renderLatexInHtml(html);
   // Sanitize HTML to prevent XSS attacks
-  html = DOMPurify.sanitize(html, {
-    ADD_TAGS: ['img'],
-    ADD_ATTR: ['target', 'data-action', 'data-table', 'data-icon', 'data-icon-success', 'data-n'],
-  });
+  // [perf-base-v1] 卡6: 转调公共 sanitizeHtml(DOMPurify,ADD_TAGS:['img']),保留本模块额外交互属性白名单
+  html = sanitizeHtml(html, ['target', 'data-action', 'data-table', 'data-icon', 'data-icon-success', 'data-n']);
   // 原始 HTML 锚点不经过 marked link renderer,统一补 target/rel
   html = html.replace(/<a\b[^>]*>/gi, (tag) => {
     let attrs = '';