diff --git a/src/tiptap/editor.ts b/src/tiptap/editor.ts index b21fddb..b348267 100644 --- a/src/tiptap/editor.ts +++ b/src/tiptap/editor.ts @@ -46,7 +46,7 @@ export class TextEditor { } this.opts = opts; this.element = el; - const html = opts?.html || ''; + const html = opts?.markdown || opts?.html || ''; const items = opts?.items || getSuggestionItems(); const placeholder = opts?.placeholder || 'Type @ to see commands (e.g., @today, @list @test )...'; const suggestionConfig = createSuggestionConfig(items); @@ -54,7 +54,9 @@ export class TextEditor { this.editor = new Editor({ element: el, // 指定编辑器容器 extensions: [ - StarterKit.configure({}), // 使用 StarterKit 包含基础功能 + StarterKit.configure({ + codeBlock: false, + }), // 使用 StarterKit 包含基础功能 Highlight, Placeholder.configure({ placeholder, @@ -62,7 +64,6 @@ export class TextEditor { Typography, Markdown, CodeBlockLowlight.extend({ - name: 'ai-code-block', addKeyboardShortcuts() { return { Tab: () => { diff --git a/src/tiptap/utils/index.ts b/src/tiptap/utils/index.ts index 38f88b0..9db1601 100644 --- a/src/tiptap/utils/index.ts +++ b/src/tiptap/utils/index.ts @@ -1,10 +1,45 @@ -import { marked } from 'marked'; +import { Marked } from 'marked'; import TurndownService from 'turndown'; +import hljs from 'highlight.js'; +import { markedHighlight } from 'marked-highlight'; +// import { marked } from 'marked'; + +const markedAndHighlight = new Marked( + markedHighlight({ + emptyLangClass: 'hljs', + langPrefix: 'hljs language-', + highlight(code, lang, info) { + const language = hljs.getLanguage(lang) ? lang : 'plaintext'; + return hljs.highlight(code, { language }).value; + }, + }), +); + export const md2html = async (md: string) => { - return marked.parse(md); + const html = markedAndHighlight.parse(md); + return html; }; export const html2md = async (html: string, opts?: TurndownService.Options) => { - const turndownService = new TurndownService(opts); - return turndownService.turndown(html); + const turndownService = new TurndownService({ ...opts }); + // 添加代码块规则,保留语言标记 + turndownService.addRule('codeBlocks', { + filter: function (node) { + return node.nodeName === 'PRE' && node.firstChild?.nodeName === 'CODE'; + }, + replacement: function (content, node) { + const code = node.firstChild as HTMLElement; + // 从类名中提取语言 (hljs language-xxx) + const className = code.className || ''; + const language = className.match(/language-(\w+)/)?.[1] || ''; + + // 确保内容首尾没有多余空行 + const trimmedContent = content.trim(); + + return `\n\n\`\`\`${language}\n${trimmedContent}\n\`\`\`\n\n`; + }, + }); + + const md = turndownService.turndown(html); + return md; };