|
@@ -38,12 +38,15 @@ app.use(EnesisEditor)
|
|
|
### Props
|
|
### Props
|
|
|
|
|
|
|
|
| Prop | Type | Default | Description |
|
|
| Prop | Type | Default | Description |
|
|
|
-|---|---|---|---|---|
|
|
|
|
|
|
|
+|---|---|---|---|
|
|
|
| `content` (v-model) | `string` | required | Markdown content of the block |
|
|
| `content` (v-model) | `string` | required | Markdown content of the block |
|
|
|
| `focused` | `boolean` | `false` | Whether the block receives focus on mount |
|
|
| `focused` | `boolean` | `false` | Whether the block receives focus on mount |
|
|
|
| `cursorPosition` | `"start" \| "end" \| number` | — | Cursor placement on focus |
|
|
| `cursorPosition` | `"start" \| "end" \| number` | — | Cursor placement on focus |
|
|
|
| `markerMode` | `"live-preview" \| "always-visible"` | `"live-preview"` | When to show markdown delimiters |
|
|
| `markerMode` | `"live-preview" \| "always-visible"` | `"live-preview"` | When to show markdown delimiters |
|
|
|
| `debug` | `string` | — | Namespace filter for debug logs (e.g. `"CodeBlockView"`, `"*"`) |
|
|
| `debug` | `string` | — | Namespace filter for debug logs (e.g. `"CodeBlockView"`, `"*"`) |
|
|
|
|
|
+| `onBoundaryExit` | `(dir: "up" \| "down") => void` | — | Called when code-block cursor exits at a doc boundary. |
|
|
|
|
|
+| `registry` | `FocusRegistry` | — | Cross-block focus registry (see `useFocusRegistry`). |
|
|
|
|
|
+| `depth` | `number` | — | List-item indent depth (0–10). |
|
|
|
|
|
|
|
|
### Emits
|
|
### Emits
|
|
|
|
|
|
|
@@ -74,16 +77,68 @@ blockRef.value?.getContent() // Current markdown content
|
|
|
blockRef.value?.setContent(md)// Set content externally
|
|
blockRef.value?.setContent(md)// Set content externally
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
|
|
+## `<Editor>` API
|
|
|
|
|
+
|
|
|
|
|
+The `Editor` component manages a list of blocks with insertion zones between them. Each block is a `* ` list item in the unified markdown string. The editor owns parsing, serialization, split/merge, indent/outdent, and undo/redo.
|
|
|
|
|
+
|
|
|
|
|
+### Props
|
|
|
|
|
+
|
|
|
|
|
+| Prop | Type | Default | Description |
|
|
|
|
|
+|---|---|---|---|
|
|
|
|
|
+| `content` (v-model) | `string` | required | Full document markdown (all blocks serialized). |
|
|
|
|
|
+| `focused` | `boolean` | `false` | Whether the first block receives focus on mount. |
|
|
|
|
|
+| `markerMode` | `"live-preview" \| "always-visible"` | `"live-preview"` | When to show markdown delimiters. |
|
|
|
|
|
+| `debug` | `string` | — | Namespace filter for debug logs. |
|
|
|
|
|
+| `theme` | `ThemeInput` | — | CSS-variable theme preset or overrides (see `theme.ts`). |
|
|
|
|
|
+
|
|
|
|
|
+### Scoped Slot: `#toolbar`
|
|
|
|
|
+
|
|
|
|
|
+The editor forwards a `#toolbar` slot with bindings from the focused block:
|
|
|
|
|
+
|
|
|
|
|
+```vue
|
|
|
|
|
+<Editor v-model:content="md">
|
|
|
|
|
+ <template #toolbar="{ handlers, selectionVersion, canUndo, canRedo, undo, redo }">
|
|
|
|
|
+ <EditorToolbar :handlers="handlers" :selection-version="selectionVersion" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+</Editor>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+| Binding | Type | Description |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| `handlers` | `FormattingHandlers \| null` | Handler object from the focused block, or `null` if blurred. |
|
|
|
|
|
+| `selectionVersion` | `number` | Incremented on each selection change — use as watch key. |
|
|
|
|
|
+| `canUndo` | `boolean` | Whether undo history has entries. |
|
|
|
|
|
+| `canRedo` | `boolean` | Whether redo history has entries. |
|
|
|
|
|
+| `undo` | `() => void` | Pop and apply the inverse of the last operation. |
|
|
|
|
|
+| `redo` | `() => void` | Re-apply the last undone operation. |
|
|
|
|
|
+
|
|
|
|
|
+### Emits
|
|
|
|
|
+
|
|
|
|
|
+| Event | Payload | Trigger |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| `focus` | `{ view, handlers }` | Any block received focus. |
|
|
|
|
|
+| `blur` | — | All blocks lost focus. |
|
|
|
|
|
+| `selection-change` | `{ from, to, empty }` | Selection changed in the active block. |
|
|
|
|
|
+
|
|
|
|
|
+### Exposed methods
|
|
|
|
|
+
|
|
|
|
|
+```ts
|
|
|
|
|
+const editorRef = ref<{ undo: () => void; redo: () => void; canUndo: Ref<boolean>; canRedo: Ref<boolean> }>()
|
|
|
|
|
+
|
|
|
|
|
+editorRef.value?.undo()
|
|
|
|
|
+editorRef.value?.redo()
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
## Architecture
|
|
## Architecture
|
|
|
|
|
|
|
|
-### Parsing Pipeline (3-stage)
|
|
|
|
|
|
|
+### Parsing Pipeline
|
|
|
|
|
|
|
|
```
|
|
```
|
|
|
[Raw block content string]
|
|
[Raw block content string]
|
|
|
│
|
|
│
|
|
|
├── Phase 1: Lezer AST Walk
|
|
├── Phase 1: Lezer AST Walk
|
|
|
│ ├─ enter → block rules (headings, blockquotes, callouts, tasks)
|
|
│ ├─ enter → block rules (headings, blockquotes, callouts, tasks)
|
|
|
- │ └─ leave → inline rules (bold, italic, code, links, refs, tags)
|
|
|
|
|
|
|
+ │ └─ leave → inline rules (bold, italic, code, links, refs, tags, highlights)
|
|
|
│
|
|
│
|
|
|
├── Phase 2: Property Extraction (key:: value)
|
|
├── Phase 2: Property Extraction (key:: value)
|
|
|
│
|
|
│
|
|
@@ -118,6 +173,9 @@ Formatting is purely decorative — markdown syntax is stored as plain text in P
|
|
|
| Inline Math | `$...$` | `md-math-inline` (+ KaTeX preview on blur) |
|
|
| Inline Math | `$...$` | `md-math-inline` (+ KaTeX preview on blur) |
|
|
|
| Display Math | `$$...$$` | MathBlock node view (+ KaTeX preview) |
|
|
| Display Math | `$$...$$` | MathBlock node view (+ KaTeX preview) |
|
|
|
| Fenced Code Block | `` ```python `` / `~~~js` | CM6 node view |
|
|
| Fenced Code Block | `` ```python `` / `~~~js` | CM6 node view |
|
|
|
|
|
+| Highlight | `^^text^^` | `md-highlight` |
|
|
|
|
|
+
|
|
|
|
|
+> **Priority flags** (`[#A]`, `[#B]`, `[#C]`) and **date emoji** (`📅 YYYY-MM-DD`) were removed from the parser — they render as plain text. Styling classes remain for backward compatibility.
|
|
|
|
|
|
|
|
### Pattern Detection
|
|
### Pattern Detection
|
|
|
|
|
|
|
@@ -167,20 +225,29 @@ pnpm dev # Watch mode rebuild
|
|
|
|---|---|
|
|
|---|---|
|
|
|
| `src/index.ts` | Public API surface |
|
|
| `src/index.ts` | Public API surface |
|
|
|
| `src/components/Block.vue` | ProseMirror block editor component |
|
|
| `src/components/Block.vue` | ProseMirror block editor component |
|
|
|
|
|
+| `src/components/Editor.vue` | Multi-block shell with insertion zones, split/merge, undo/redo |
|
|
|
|
|
+| `src/components/InsertionZone.vue` | Invisible click target between blocks |
|
|
|
|
|
+| `src/components/EditorToolbar.vue` | Shared toolbar bound to active block's handlers |
|
|
|
| `src/composables/useMarkdownDecorations.ts` | Decoration plugin (live-preview, caching) |
|
|
| `src/composables/useMarkdownDecorations.ts` | Decoration plugin (live-preview, caching) |
|
|
|
| `src/composables/useBlockKeyboardHandlers.ts` | Keyboard event handler |
|
|
| `src/composables/useBlockKeyboardHandlers.ts` | Keyboard event handler |
|
|
|
| `src/composables/useCodeBlockView.ts` | CM6 NodeView for fenced code blocks |
|
|
| `src/composables/useCodeBlockView.ts` | CM6 NodeView for fenced code blocks |
|
|
|
|
|
+| `src/composables/useMathBlockView.ts` | KaTeX NodeView for display math blocks |
|
|
|
| `src/composables/usePatternPlugin.ts` | Pattern detection plugin |
|
|
| `src/composables/usePatternPlugin.ts` | Pattern detection plugin |
|
|
|
-| `src/lib/markdown-parser.ts` | Lezer parser configuration |
|
|
|
|
|
-| `src/lib/markdown-extensions.ts` | Custom Lezer node definitions (PageRef, BlockRef, Tag, Highlight, InlineMath, Task) |
|
|
|
|
|
-| `src/lib/katex.ts` | Dynamic KaTeX import + async/sync render helpers |
|
|
|
|
|
-| `src/lib/auto-close-plugin.ts` | Auto-close for ```, **, _ |
|
|
|
|
|
-| `src/lib/content-model.ts` | Markdown ↔ ProseMirror doc conversion |
|
|
|
|
|
-| `src/lib/formatting.ts` | Formatting handlers — toggle/wrap/insert for bold, link, math, page refs, block refs, tags, heading, task |
|
|
|
|
|
|
|
+| `src/composables/usePasteHandler.ts` | Multi-line paste split handler |
|
|
|
|
|
+| `src/composables/useFocusRegistry.ts` | Cross-block focus management |
|
|
|
|
|
+| `src/lib/block-parser.ts` | `splitMarkdownIntoBlocks` / `serializeBlocks` |
|
|
|
|
|
+| `src/lib/content-model.ts` | `contentToDoc(md)` / `docToContent(doc)` — Markdown ↔ ProseMirror |
|
|
|
|
|
+| `src/lib/formatting.ts` | Formatting handlers — toggle/wrap/insert for bold, link, math, page refs, tags, heading, task |
|
|
|
|
|
+| `src/lib/operation-history.ts` | `EditorOperation` types + undo/redo stack |
|
|
|
|
|
+| `src/lib/theme.ts` | CSS-variable theme system with presets |
|
|
|
|
|
+| `src/lib/katex.ts` | Dynamic KaTeX import + render helpers |
|
|
|
|
|
+| `src/lib/auto-close-plugin.ts` | Auto-close for ```, **, _ and bracket pairs |
|
|
|
| `src/lib/logger.ts` | Namespace-based debug logger |
|
|
| `src/lib/logger.ts` | Namespace-based debug logger |
|
|
|
| `src/lib/schema.ts` | ProseMirror schema |
|
|
| `src/lib/schema.ts` | ProseMirror schema |
|
|
|
-| `src/lib/markdown-rules/engine.ts` | 3-stage rule engine |
|
|
|
|
|
|
|
+| `src/lib/markdown-parser.ts` | Lezer parser configuration |
|
|
|
|
|
+| `src/lib/markdown-extensions.ts` | Custom Lezer node definitions (PageRef, BlockRef, Tag, Highlight, InlineMath, Task) |
|
|
|
|
|
+| `src/lib/markdown-rules/engine.ts` | MarkdownRuleEngine — Lezer AST walk |
|
|
|
| `src/lib/markdown-rules/inline-rules.ts` | Inline decoration rules |
|
|
| `src/lib/markdown-rules/inline-rules.ts` | Inline decoration rules |
|
|
|
| `src/lib/markdown-rules/block-rules.ts` | Block decoration rules |
|
|
| `src/lib/markdown-rules/block-rules.ts` | Block decoration rules |
|
|
|
| `src/lib/markdown-rules/types.ts` | Shared type definitions |
|
|
| `src/lib/markdown-rules/types.ts` | Shared type definitions |
|
|
|
-| `src/lib/markdown-rules/block-classifier.ts` | Regex first-line classifier |
|
|
|
|
|
|
|
+| `src/lib/markdown-rules/block-classifier.ts` | Regex first-line classifier (paste only) |
|