diff --git a/package.json b/package.json index ed6913c..dccb193 100644 --- a/package.json +++ b/package.json @@ -24,10 +24,6 @@ "license": "MIT", "dependencies": { "@kevisual/router": "0.0.10", - "clsx": "^2.1.1", - "dayjs": "^1.11.13", - "lodash-es": "^4.17.21", - "lucide-react": "^0.487.0", "@tiptap/core": "^2.11.7", "@tiptap/extension-code-block-lowlight": "^2.11.7", "@tiptap/extension-document": "^2.11.7", @@ -39,18 +35,23 @@ "@tiptap/pm": "^2.11.7", "@tiptap/starter-kit": "^2.11.7", "@tiptap/suggestion": "^2.11.7", + "clsx": "^2.1.1", + "dayjs": "^1.11.13", "github-markdown-css": "^5.8.1", "highlight.js": "^11.11.1", "idb": "^8.0.2", "idb-keyval": "^6.2.1", "immer": "^10.1.1", + "lodash-es": "^4.17.21", "lowlight": "^3.3.0", + "lucide-react": "^0.487.0", "marked": "^15.0.7", - "tiptap-markdown": "^0.8.10", "nanoid": "^5.1.5", "react": "^19.1.0", "react-dom": "^19.1.0", "react-toastify": "^11.0.5", + "tiptap-markdown": "^0.8.10", + "turndown": "^7.2.0", "zustand": "^5.0.3" }, "exports": { @@ -67,6 +68,7 @@ "@types/node": "^22.14.0", "@types/react": "^19.1.0", "@types/react-dom": "^19.1.1", + "@types/turndown": "^5.0.5", "@vitejs/plugin-basic-ssl": "^2.0.0", "@vitejs/plugin-react": "^4.3.4", "tailwindcss": "^4.1.3", diff --git a/src/tiptap/editor.ts b/src/tiptap/editor.ts index 5ec3b2a..b21fddb 100644 --- a/src/tiptap/editor.ts +++ b/src/tiptap/editor.ts @@ -26,14 +26,21 @@ lowlight.register('js', js); lowlight.register('ts', ts); lowlight.register('markdown', markdown); +export type TextEditorProps = { + markdown?: string; + html?: string; + items?: CommandItem[]; + placeholder?: string; + onUpdateHtml?: (html: string) => void; // +}; export class TextEditor { private editor?: Editor; - private opts?: { markdown?: string; html?: string; items?: CommandItem[]; onUpdateHtml?: (html: string) => void }; + private opts?: TextEditorProps; private element?: HTMLElement; private isInitialSetup: boolean = true; constructor() {} - createEditor(el: HTMLElement, opts?: { markdown?: string; html?: string; items?: CommandItem[]; onUpdateHtml?: (html: string) => void }) { + createEditor(el: HTMLElement, opts?: TextEditorProps) { if (this.editor) { this.destroy(); } @@ -41,19 +48,21 @@ export class TextEditor { this.element = el; const html = opts?.html || ''; const items = opts?.items || getSuggestionItems(); + const placeholder = opts?.placeholder || 'Type @ to see commands (e.g., @today, @list @test )...'; const suggestionConfig = createSuggestionConfig(items); this.isInitialSetup = true; this.editor = new Editor({ element: el, // 指定编辑器容器 extensions: [ - StarterKit, // 使用 StarterKit 包含基础功能 + StarterKit.configure({}), // 使用 StarterKit 包含基础功能 Highlight, Placeholder.configure({ - placeholder: 'Type @ to see commands (e.g., @today, @list @test )...', + placeholder, }), Typography, Markdown, CodeBlockLowlight.extend({ + name: 'ai-code-block', addKeyboardShortcuts() { return { Tab: () => { diff --git a/src/tiptap/extensions/suggestions/commands.ts b/src/tiptap/extensions/suggestions/commands.ts index f7bada2..d6cc19c 100644 --- a/src/tiptap/extensions/suggestions/commands.ts +++ b/src/tiptap/extensions/suggestions/commands.ts @@ -11,7 +11,7 @@ export interface CommandItem { } export const Commands = Extension.create({ - name: 'commands', + name: 'ai-commands', addOptions() { return { diff --git a/src/tiptap/index.ts b/src/tiptap/index.ts index e69de29..fafa9ac 100644 --- a/src/tiptap/index.ts +++ b/src/tiptap/index.ts @@ -0,0 +1 @@ +export { md2html, html2md } from './utils'; diff --git a/src/tiptap/utils/index.ts b/src/tiptap/utils/index.ts new file mode 100644 index 0000000..38f88b0 --- /dev/null +++ b/src/tiptap/utils/index.ts @@ -0,0 +1,10 @@ +import { marked } from 'marked'; +import TurndownService from 'turndown'; +export const md2html = async (md: string) => { + return marked.parse(md); +}; + +export const html2md = async (html: string, opts?: TurndownService.Options) => { + const turndownService = new TurndownService(opts); + return turndownService.turndown(html); +};