{"_id":"@caizk/moyuan-markdown-editor","name":"@caizk/moyuan-markdown-editor","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@caizk/moyuan-markdown-editor","version":"1.0.0","description":"A React Markdown editor component with live preview, consumable via npm or a script tag.","license":"MIT","type":"module","main":"./dist/moyuan-markdown-editor.umd.js","module":"./dist/moyuan-markdown-editor.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/moyuan-markdown-editor.mjs","require":"./dist/moyuan-markdown-editor.umd.js"},"./style.css":"./dist/style.css"},"sideEffects":["**/*.css"],"scripts":{"dev":"vite build --watch","build":"tsc --noEmit && vite build --config vite.config.umd.ts && vite build","prepublishOnly":"pnpm run build"},"dependencies":{"@excalidraw/excalidraw":"^0.18.1","@floating-ui/react":"^0.27.20","@lexical/a11y":"^0.49.0","@lexical/clipboard":"^0.49.0","@lexical/code":"^0.49.0","@lexical/code-core":"^0.49.0","@lexical/code-prism":"^0.49.0","@lexical/extension":"^0.49.0","@lexical/hashtag":"^0.49.0","@lexical/history":"^0.49.0","@lexical/html":"^0.49.0","@lexical/link":"^0.49.0","@lexical/list":"^0.49.0","@lexical/mark":"^0.49.0","@lexical/markdown":"^0.49.0","@lexical/react":"^0.49.0","@lexical/rich-text":"^0.49.0","@lexical/selection":"^0.49.0","@lexical/table":"^0.49.0","@lexical/utils":"^0.49.0","lexical":"^0.49.0","mermaid":"^11.16.1","mind-elixir":"~5.15.1"},"devDependencies":{"@types/node":"^20.17.0","@types/react":"^18.3.12","@types/react-dom":"^18.3.1","@vitejs/plugin-react":"^4.3.4","jsdom":"^30.0.1","react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.6.3","vite":"^5.4.11","vite-plugin-dts":"^4.3.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_id":"@caizk/moyuan-markdown-editor@1.0.0","gitHead":"a060b59db9967958a6dd8e585e66633f76641e29","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-33wus0qlJNanV/yEX7BZCBSjLQ9kqooCDgWJKkxXYMp1vzwRvOeRJKo3rZD/APwXyU+j3l0k5xbIhgw6myI1/g==","shasum":"2c64673f921dac5b1b3c6c86fea7666a7ad3f837","tarball":"https://registry.npmjs.org/@caizk/moyuan-markdown-editor/-/moyuan-markdown-editor-1.0.0.tgz","fileCount":147,"unpackedSize":12693180,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBsrRG58z22qVq8YeGQNyJizVnVcQURSjiPVFqOQXgXdAiEA30S0TdkRokXQkhubprftsFZbzH/RmC1R3KYzvkQ1esU="}]},"_npmUser":{"name":"choikeith","email":"aksoncai@gmail.com"},"directories":{},"maintainers":[{"name":"choikeith","email":"aksoncai@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/moyuan-markdown-editor_1.0.0_1787316734824_0.89076228709677"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-21T12:52:14.719Z","1.0.0":"2026-08-21T12:52:15.064Z","modified":"2026-08-21T12:52:15.233Z"},"maintainers":[{"name":"choikeith","email":"aksoncai@gmail.com"}],"description":"A React Markdown editor component with live preview, consumable via npm or a script tag.","license":"MIT","readme":"# @caizk/moyuan-markdown-editor\n\n[中文文档](./README-zh.md)\n\nA React Markdown editor component built on Lexical: WYSIWYG editing (typing `# `, `**`, `- ` and other Markdown syntax converts to rich text live), with content exposed as a controlled Markdown string.\n\n> This component depends on the DOM and only supports client-side rendering (no SSR). React >= 18 is required (peer dependency).\n\n## Features\n\n- **WYSIWYG Markdown editing** — type Markdown syntax and it converts to rich text in place; content is emitted as a Markdown string via `onChange`.\n- **Block insert menu** — a \"+\" floating menu (also available via the \"/\" command menu) with four categories:\n  - **Basic**: paragraph, heading 1–3, ordered/unordered list, link, divider, quote, code block, check list\n  - **Common**: image, table, columns layout, collapsible container\n  - **Drawing**: Excalidraw board, mind map, Mermaid diagram\n  - **Embeds**: YouTube, X (Twitter), Figma\n- **Selection floating toolbar** — appears when text is selected: block-type dropdown, alignment dropdown, bold / italic / strikethrough / underline / link, text color, background color, and comment.\n- **Mermaid diagrams** — card with live preview plus a fullscreen editor (code editing with real-time preview, built-in templates: flowchart, sequence, class, ER, gantt, pie, mindmap). Round-trips through Markdown as a ```` ```mermaid ```` code block.\n- **Mind maps** — card plus a fullscreen editor (add child/sibling nodes, edit text, delete, drag to restructure, undo/redo, zoom, layout direction, themes). Data round-trips through editor JSON serialization.\n- **Inline comments** — select text and mark it with a comment; a side drawer shows threads with quote, avatar, author, relative time, replies, and edit/delete for your own comments. Uses an in-memory store with mock users (no backend).\n- **History records** — a read-only history mode with a side panel: snapshots recorded automatically (debounced), grouped by day, with prev/next navigation, per-block diff highlighting with author tags (add/modify/delete, including deleted blocks rendered in place with red strikethrough), and one-click restore with confirmation.\n\n### Markdown serialization policy\n\nBlocks that Markdown cannot express follow a fixed policy when serialized via `onChange`: Mermaid is exported as a ```` ```mermaid ```` code block (and re-imported as a diagram card); columns layout and collapsible containers export their child content; YouTube / X / Figma blocks export their URL; Excalidraw boards and mind maps are omitted. Comment marks and comment content are dropped from Markdown output. Serialization never crashes on these blocks.\n\n## Installation\n\n```bash\nnpm install @caizk/moyuan-markdown-editor\n```\n\n## Usage via npm (ESM)\n\n```tsx\nimport { useState } from 'react'\nimport { MarkdownEditor } from '@caizk/moyuan-markdown-editor'\nimport '@caizk/moyuan-markdown-editor/style.css'\n\nfunction Editor() {\n  const [value, setValue] = useState('# Hello')\n  return (\n    <MarkdownEditor\n      value={value}\n      onChange={setValue}\n      placeholder=\"Enter some text...\"\n    />\n  )\n}\n```\n\n### Props\n\n| Prop | Type | Description |\n| --- | --- | --- |\n| `value` | `string` | Current document content (Markdown string, controlled) |\n| `onChange` | `(value: string) => void` | Called with the serialized Markdown whenever the user edits |\n| `placeholder?` | `string` | Placeholder text of the editing area |\n| `className?` | `string` | Extra class on the root element |\n| `commentDrawerContainer?` | `string` | CSS selector of the portal mount point for the comment drawer/badges (e.g. `'#comment-drawer-root'`). Falls back to `document.body` (fixed to the viewport's right edge) when omitted or not found; when matched, mounts inside that element (absolute to its right edge — the container needs `relative`/`absolute` positioning) |\n| `commentStore?` | `CommentStore` | Externally injected comment store (created internally when omitted) |\n| `historyMode?` | `boolean` | History mode (controlled): when `true`, the editor is read-only and shows the history panel |\n| `onHistoryModeChange?` | `(historyMode: boolean) => void` | Called when the panel's \"Back to document\" / \"Restore\" actions run; the consumer should set `historyMode` back to `false` |\n| `historyPanelContainer?` | `string` | CSS selector of the portal mount point for the history panel; falls back to `document.body` when omitted |\n| `historyStore?` | `HistoryStore` | Externally injected history store (created internally when omitted) |\n\n### Exported stores and helpers\n\n```ts\nimport {\n  CommentStore, CURRENT_USER, MOCK_COMMENTER,\n  HistoryStore, buildHistoryView, blockSignaturesFromState, splitBlocks,\n} from '@caizk/moyuan-markdown-editor'\n```\n\n- `CommentStore` — in-memory comment store: `createThread(quote)`, `getThread(id)`, `getThreads()`, `addComment(...)`, `updateComment(...)`, `deleteComment(...)`, `subscribe(listener)`. `CURRENT_USER` / `MOCK_COMMENTER` are the built-in mock authors.\n- `HistoryStore` — in-memory snapshot store: `record(markdown, author?, state?)`, `getSnapshots()`, `subscribe(listener)`. Snapshots carry the EditorState JSON so decorated blocks (images, mind maps, Excalidraw) survive history viewing and restore.\n\n## Usage via a script tag (UMD)\n\nReact must load before this library — the UMD build reads `window.React` / `window.ReactDOM`:\n\n```html\n<link rel=\"stylesheet\" href=\"https://unpkg.com/@caizk/moyuan-markdown-editor/dist/style.css\" />\n<script crossorigin src=\"https://unpkg.com/react@18/umd/react.production.min.js\"></script>\n<script crossorigin src=\"https://unpkg.com/react-dom@18/umd/react-dom.production.min.js\"></script>\n<script src=\"https://unpkg.com/@caizk/moyuan-markdown-editor/dist/moyuan-markdown-editor.umd.js\"></script>\n\n<div id=\"root\"></div>\n<script>\n  const { MarkdownEditor } = window.MoyuanMarkdownEditor\n  function App() {\n    const [value, setValue] = React.useState('# Hello')\n    return React.createElement(MarkdownEditor, { value, onChange: setValue })\n  }\n  ReactDOM.createRoot(document.getElementById('root')).render(React.createElement(App))\n</script>\n```\n\n`demo/umd.html` in this repository is a complete, directly openable example (run `pnpm build` first).\n\n> **Excalidraw note**: with ESM (npm), Excalidraw is lazy-loaded on demand — nothing extra needed. With the script tag (UMD) build, the Excalidraw board feature requires a global `window.Excalidraw` (e.g. from Excalidraw's UMD build); without it, all other features work normally.\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-fde4ee672db1af5a3b412308fc8fd12e"}