xiaodao-editor 0.1.16 → 0.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ZH.md CHANGED
@@ -14,13 +14,14 @@
14
14
 
15
15
  ## 功能特性
16
16
 
17
- - **11 种内置块类型** — 段落、h1–h6(标题)、无序列表、有序列表、待办事项、引用、代码块、**图片**、**分割线**、**表格**、**目录**(共 **13 个扩展**,另含 Keymap 与 History 两个行为扩展)
17
+ - **12 种内置块类型** — 段落、h1–h6(标题)、无序列表、有序列表、待办事项、引用、代码块、**图片**、**公式**(LaTeX 数学公式)、**分割线**、**表格**、**目录**(共 **14 个扩展**,另含 Keymap 与 History 两个行为扩展)
18
+ - **公式(LaTeX 数学)块** — 通过 KaTeX 渲染居中的展示型公式。文档中**只保存原始 `expression` 字符串**——KaTeX 输出在渲染时即时计算、永不持久化,因此序列化保持精简。通过 `/公式` 斜杠命令或 `+` 菜单插入;空块会直接进入编辑态。点击块即可选中;右上角的浮动 ✎ 按钮(或点击空块)打开源码编辑器并带实时预览。支持块级选中,也**可作为子块嵌套**(按嵌套深度自动缩进)。Markdown 导出使用 `$$$ … $$$` 围栏块。
18
19
  - **表格块** — 基于 `attrs` 的 N×M 网格;新建表格默认列宽 120 px、默认启用标题行;行/列选择条 + 左上角角部全选手柄;行/列之间插入点;浮动操作栏提供合并/拆分单元格、**切换标题行**(设置 `attrs.headerRow`)、删除行/列/整个表;单元格使用独立的 `contenteditable`,支持段落/标题/代码块类型、富行内标记、单元格背景色与对齐;Tab 在单元格间导航,Enter 退出编辑(代码块单元格按 Enter 插入换行),Escape 失焦;仿 Arco Design 的内部水平滚动条;矩形选区遇到合并单元格时会自动扩展以保证永远不会只选中合并单元格的一半。
19
20
  - **行内样式标记** — 粗体、斜体、下划线、删除线、行内代码、**链接**(`Mod-K` 快捷键、粘贴 URL、自动识别、浮层查看/编辑/复制/删除、href 净化阻断 `javascript:` / XSS),以及按选区设置的文字颜色与背景色
20
21
  - **块级属性** — 对齐方式(左/中/右/两端)、文字颜色、背景色、缩进(0–10 级);图片额外携带 `src`、`alt`、`title`、`width`、`height`、`caption`、`fileId`
21
22
  - **斜杠菜单** — 输入 `/` 打开可搜索的命令面板;输入规则(`# `、`> `、`[] `、```` ``` ````)可即时转换块类型;`/image` 打开文件选择器
22
23
  - **块操作** — 拖拽手柄、悬浮工具栏、`+` 插入按钮,含「复制 / 剪切 / 上移 / 下移 / 删除」的操作菜单;**真实嵌套**(Tab / Shift-Tab 缩进/反缩进构建父子树;拖拽支持兄弟节点的上/下插入 + **"拖入块内"** 模式 — 在块中心停顿一下即可作为第一个子块嵌套进去);复制会克隆整个子树;图片额外提供替换 / 删除、角部等比缩放手柄、可编辑 caption
23
- - **固定工具栏(FixedToolbar)** — 常驻操作栏,在工具栏内部内嵌了上下文相关的 **HoverToolbar**(点击格式化按钮时可以保持文本选区不丢失)。通过 `toolbarPosition` prop 控制三种位置:`'auto'`(默认,桌面端顶、移动端底)、`'top'`(强制顶部)或 `'bottom'`(强制底部)。工具栏在顶部时,PlusMenu / 手柄菜单会改为向下弹出。
24
+ - **固定工具栏(FixedToolbar)** — 常驻操作栏,在工具栏内部内嵌了上下文相关的 **HoverToolbar**(点击格式化按钮时可以保持文本选区不丢失)。通过 `toolbarPosition` prop 控制四种位置:`'auto'`(默认,桌面端顶、移动端底)、`'top'`(强制顶部)、`'bottom'`(强制底部),或 `'float'`(仅桌面端——隐藏 FixedToolbar,改用跟随文本选区浮现的浮动工具栏;移动端自动回退为 FixedToolbar)。工具栏在顶部时,PlusMenu / 手柄菜单会改为向下弹出。
24
25
  - **尺寸控制与内部滚动** — 通过 `width` 和 `height` prop 约束编辑器(数字按 px 解析)。内容区域会**在编辑器内部纵向滚动**,而不是无限向下生长,外部布局无需自行管理 overflow。
25
26
  - **剪贴板** — HTML 与纯文本的干净复制 / 剪切 / 粘贴;多块选区覆盖层;**粘贴 HTML `<img>` / 图片文件 + 拖拽文件到编辑器内会自动创建图片块并发起上传**;选中文本后粘贴 URL 会包裹为链接
26
27
  - **移动端支持** — 长按后开始选中文本,然后拖动手指即可**跨多个独立 `contenteditable` 块**进行选择(通过 hit-testing + overlay 实现,因为原生 Selection API 不支持跨块边界)。固定工具栏会自动落到屏幕底部,位于虚拟键盘之上。
@@ -53,7 +54,7 @@ const doc = ref<DocumentData>({ blocks: [] })
53
54
  </template>
54
55
  ```
55
56
 
56
- 编辑器默认内置全部 13 种扩展 — 除非你需要自定义集合,否则无需传入 `extensions`。
57
+ 编辑器默认内置全部 14 种扩展 — 除非你需要自定义集合,否则无需传入 `extensions`。
57
58
 
58
59
  ## Props 属性
59
60
 
@@ -68,7 +69,7 @@ const doc = ref<DocumentData>({ blocks: [] })
68
69
  | `uploadImage` | `UploadImageHandler` | 内存内 mock | 图片上传钩子;签名:`(name, file, controller, onProgress) => Promise<ImageUploadResult>`。要持久化文档**必须**提供此 prop(默认 mock 使用不可序列化的 `blob:` URL)。 |
69
70
  | `width` | `string \| number` | `undefined` | 可选:编辑器宽度。数字按 CSS px 解析;字符串直接使用(如 `'800px'`、`'100%'`)。未设置时默认撑满容器(`width: 100%`)。 |
70
71
  | `height` | `string \| number` | `undefined` | 可选:编辑器高度。设置后内容区域会在编辑器**内部**滚动,不再无限向下生长;未设置时编辑器随内容扩展,由宿主页面接管滚动。 |
71
- | `toolbarPosition` | `'auto' \| 'top' \| 'bottom'` | `'auto'` | 常驻 `FixedToolbar` 的位置。`'auto'` = 桌面端自动顶栏、移动端自动底栏(位于虚拟键盘上方)。 |
72
+ | `toolbarPosition` | `'auto' \| 'top' \| 'bottom' \| 'float'` | `'auto'` | 工具栏 / 操作栏的位置。`'auto'` = 桌面端自动顶栏、移动端自动底栏(位于虚拟键盘上方)。`'float'`(仅桌面端)隐藏 `FixedToolbar`,改用跟随文本选区的浮动工具栏(HoverToolbar);移动端自动回退为 `FixedToolbar`。 |
72
73
 
73
74
  ### Emits 事件
74
75
 
@@ -105,7 +106,7 @@ const doc = ref<DocumentData>({ blocks: [] })
105
106
 
106
107
  ## 内置扩展
107
108
 
108
- `BuiltinExtensions` 打包了以下 **13 种扩展**(11 种块类型 + 2 个行为扩展):
109
+ `BuiltinExtensions` 打包了以下 **14 种扩展**(12 种块类型 + 2 个行为扩展):
109
110
 
110
111
  | 扩展名称 | 块类型 | 说明 |
111
112
  | ---------------------- | -------------- | -------------------------------------------------------------------- |
@@ -117,6 +118,7 @@ const doc = ref<DocumentData>({ blocks: [] })
117
118
  | `QuoteExtension` | `quote` | 引用块。schema 禁用了行内斜体。 |
118
119
  | `CodeBlockExtension` | `codeBlock` | `attrs.language` 设置语言;隔离模式 — Enter 插入换行。 |
119
120
  | `ImageExtension` | `image` | `content: 'none'`;属性:`src/alt/title/width/height/caption/fileId`;序列化:HTML `<figure>`/`<img>` + Markdown `![alt](url "title")`;提供替换 / 删除 / 等比缩放手柄 + 可编辑 caption;通过 `uploadImage` prop 与 `cleanup:image-file` 事件走上传侧信道。 |
121
+ | `EquationExtension` | `equation` | `content: 'none'`;隔离型块——只保存 `attrs.expression`(原始 LaTeX)。KaTeX 在渲染时即时计算居中展示公式(输出永不持久化)。通过 `/公式` 或 `+` 插入;空块自动进入编辑态;浮动 ✎ 按钮打开带实时预览的源码编辑器。支持块级选中与嵌套(作为子块时随深度缩进,`attrs.indent` 即为深度镜像)。Markdown 导出使用 `$$$ … $$$` 围栏块。 |
120
122
  | `TableExtension` | `table` | `content: 'none'`;属性:`rows/cols/cells/colWidths/headerRow`;单元格 InlineSeq 含 cellType/align/bgColor/rowspan/colspan;行/列选择条 + 角部全选手柄;浮动操作栏提供合并/拆分、**切换标题行**、删除行/列/表格;行/列插入点;合并单元格选区自动扩展为完整矩形。默认列宽 120 px;新建表格默认 `headerRow: true`。 |
121
123
  | `DividerExtension` | `divider` | 隔离型水平分割线。 |
122
124
  | `TableOfContentsExtension` | `tableOfContents` | `content: 'none'`;空 attrs — 标题列表是每次渲染时从编辑器状态计算的**动态视图**。不可编辑块(`editable: false`);按文档顺序收集所有 `heading` 块(表格单元格内的标题自动排除);点击条目滚动到对应标题。序列化输出空字符串(真正的标题由各自的块导出)。 |
@@ -188,6 +190,7 @@ const doc: DocumentData = {
188
190
  { content: [{ type: 'text', text: '3' }], rowspan: 1, colspan: 1, covered: false }],
189
191
  ],
190
192
  }, content: [] },
193
+ { type: 'equation', attrs: { expression: 'E = mc^2' }, content: [] },
191
194
  ],
192
195
  }
193
196
  ```
package/README.md CHANGED
@@ -17,10 +17,18 @@ by an **extension**, so the core never switches on a block type.
17
17
 
18
18
  ## Features
19
19
 
20
- - **11 built-in block types** — paragraph, h1–h6 (heading), bullet list,
21
- ordered list, to-do, quote, code block, **image**, **divider**,
22
- **table**, **table of contents** (13 extensions total including Keymap
23
- and History behavior extensions)
20
+ - **12 built-in block types** — paragraph, h1–h6 (heading), bullet list,
21
+ ordered list, to-do, quote, code block, **image**, **equation** (LaTeX math),
22
+ **divider**, **table**, **table of contents** (14 extensions total including
23
+ Keymap and History behavior extensions)
24
+ - **Equation (LaTeX math) block** — renders LaTeX via KaTeX as a centered
25
+ display formula. The document stores **only the raw `expression` string** —
26
+ KaTeX output is recomputed on the fly and never persisted, so serialization
27
+ stays lean. Insert via the `/equation` slash command or the `+` menu; an empty
28
+ block opens directly in edit mode. Click the block to select it; the floating
29
+ ✎ button (or clicking an empty block) opens the source editor with a live
30
+ preview. Supports block selection and **nesting as a child block** (indents
31
+ to match its depth). Markdown export uses `$$$ … $$$` fenced blocks.
24
32
  - **Table block** — `attrs`-based N×M grid; default 120 px column widths,
25
33
  new tables default to header row; row/column selection strips,
26
34
  corner-handle to select the whole table; insert dots between rows/cols;
@@ -52,11 +60,13 @@ by an **extension**, so the core never switches on a block type.
52
60
  caption
53
61
  - **Fixed toolbar** — persistent action bar with a contextual
54
62
  **HoverToolbar** embedded inline (so text selection is preserved when
55
- clicking formatting buttons). Supports three placement modes via the
63
+ clicking formatting buttons). Supports four placement modes via the
56
64
  `toolbarPosition` prop: `'auto'` (default — top on desktop, bottom on
57
- mobile), `'top'` (always top), or `'bottom'` (always bottom). Menus
58
- (PlusMenu / BlockSettingsMenu) open downward when the toolbar is at
59
- the top.
65
+ mobile), `'top'` (always top), `'bottom'` (always bottom), or `'float'`
66
+ (desktop only hides the FixedToolbar and shows a floating selection
67
+ toolbar that follows the text selection; falls back to the FixedToolbar
68
+ on mobile). Menus (PlusMenu / BlockSettingsMenu) open downward when the
69
+ toolbar is at the top.
60
70
  - **Sizing & internal scrolling** — constrain the editor with `width`
61
71
  and `height` props (numbers are treated as pixels). The content area
62
72
  scrolls vertically inside the editor instead of growing unbounded,
@@ -109,7 +119,7 @@ const doc = ref<DocumentData>({ blocks: [] })
109
119
  </template>
110
120
  ```
111
121
 
112
- The editor ships with all 13 built-in extensions by default — no need to pass
122
+ The editor ships with all 14 built-in extensions by default — no need to pass
113
123
  `extensions` unless you want a custom set.
114
124
 
115
125
  ## Props
@@ -125,7 +135,7 @@ The editor ships with all 13 built-in extensions by default — no need to pass
125
135
  | `uploadImage` | `UploadImageHandler` | in-memory mock | Hook for image uploads. Signature: `(name, file, controller, onProgress) => Promise<ImageUploadResult>`. Consumers **must** provide this if they intend to persist documents (the default mock stores `blob:` URLs which are not serialisable). |
126
136
  | `width` | `string \| number` | `undefined` | Optional fixed width. A number is interpreted as CSS pixels; a string is used as-is (e.g. `'800px'`, `'100%'`). When unset, the editor fills its container (`width: 100%`). |
127
137
  | `height` | `string \| number` | `undefined` | Optional fixed height. When set, the editor scrolls its content area **internally** rather than growing unbounded; when unset the editor grows with content and the host page scrolls. |
128
- | `toolbarPosition` | `'auto' \| 'top' \| 'bottom'` | `'auto'` | Placement of the persistent `FixedToolbar`. `'auto'` = top on desktop, bottom on mobile (above the virtual keyboard). |
138
+ | `toolbarPosition` | `'auto' \| 'top' \| 'bottom' \| 'float'` | `'auto'` | Placement of the toolbar / action bar. `'auto'` = top on desktop, bottom on mobile (above the virtual keyboard). `'float'` (desktop only) hides the FixedToolbar and uses a floating selection toolbar (HoverToolbar) that follows the text selection; on mobile it falls back to the auto FixedToolbar. |
129
139
 
130
140
  ### Emits
131
141
 
@@ -166,7 +176,7 @@ Set it explicitly if needed:
166
176
 
167
177
  ## Built-in extensions
168
178
 
169
- `BuiltinExtensions` bundles these **13 extensions** (11 block types + 2 behavior extensions):
179
+ `BuiltinExtensions` bundles these **14 extensions** (12 block types + 2 behavior extensions):
170
180
 
171
181
  | Extension | Block type | Notes |
172
182
  | --------------------- | --------------- | ---------------------------------------------------------------- |
@@ -178,6 +188,7 @@ Set it explicitly if needed:
178
188
  | `QuoteExtension` | `quote` | Blockquote. No inline italic (disabled by schema). |
179
189
  | `CodeBlockExtension` | `codeBlock` | `attrs.language`; isolating — Enter inserts a newline. |
180
190
  | `ImageExtension` | `image` | `content: 'none'`; attrs `src/alt/title/width/height/caption/fileId`; serialize → HTML `<figure>`/`<img>` + Markdown `![alt](url "title")`; replace + drag-resize handle + editable caption; upload side-channel via `uploadImage` prop + `cleanup:image-file`. |
191
+ | `EquationExtension` | `equation` | `content: 'none'`; isolated block — stores only `attrs.expression` (raw LaTeX). KaTeX renders a centered display formula on the fly (output never persisted). Insert via `/equation` or `+`; empty block auto-opens in edit mode; floating ✎ button edits the source with live preview. Supports block selection and nesting (indents as a child; `attrs.indent` mirrors depth). Markdown export uses `$$$ … $$$` fenced blocks. |
181
192
  | `TableExtension` | `table` | `content: 'none'`; attrs `rows/cols/cells/colWidths/headerRow`; cell InlineSeq per cell with cellType/align/bgColor/rowspan/colspan; row/col selection strips + corner handle; floating toolbar with merge/split, **toggle header row**, delete row/col/table; row/col insert dots; full-rect selection expansion for merged cells. Default column width 120 px; new tables default to `headerRow: true`. |
182
193
  | `DividerExtension` | `divider` | Isolating horizontal rule. |
183
194
  | `TableOfContentsExtension` | `tableOfContents` | `content: 'none'`; empty attrs — the heading list is a **dynamic view** computed from the editor state on every render. Non-editable block (`editable: false`); collects all `heading` blocks in document order (table-cell headings excluded automatically); click an entry to scroll the heading into view. Serialize emits empty string (the real headings are exported by their own blocks). |
@@ -250,6 +261,7 @@ const doc: DocumentData = {
250
261
  { content: [{ type: 'text', text: '3' }], rowspan: 1, colspan: 1, covered: false }],
251
262
  ],
252
263
  }, content: [] },
264
+ { type: 'equation', attrs: { expression: 'E = mc^2' }, content: [] },
253
265
  ],
254
266
  }
255
267
  ```
@@ -314,7 +326,7 @@ const extensions = [...BuiltinExtensions, CalloutExtension]
314
326
  components (`BlockHandle`, `BlockSettingsMenu`, `HoverToolbar`, `PlusMenu`,
315
327
  `OrderedListMenu`, `NumberPicker`, `CodeLangPicker`, `LinkPopover`,
316
328
  `FixedToolbar`).
317
- - **`src/extensions/`** — the 13 built-in extensions plus `_commonAttrs.ts`
329
+ - **`src/extensions/`** — the 14 built-in extensions plus `_commonAttrs.ts`
318
330
  (shared align/color/bgColor/indent specs and color presets, plus
319
331
  `ImageExtension`'s upload-side-channel renderer logic). **Table** lives in
320
332
  `Table.ts` (Vue renderer + command registrations) and `tableModel.ts` (pure
@@ -322,7 +334,9 @@ const extensions = [...BuiltinExtensions, CalloutExtension]
322
334
  selection expansion, header row toggle, column width helpers, HTML/Markdown
323
335
  serialization, attrs validation/coercion). **Divider** lives in `Divider.ts`.
324
336
  **Table of contents** lives in `TableOfContents.ts` (non-editable block that
325
- renders a live heading list).
337
+ renders a live heading list). **Equation** lives in `Equation.ts` (LaTeX/KaTeX
338
+ block; stores only `attrs.expression`, renders a centered display formula; its
339
+ `attrs.indent` mirrors nesting depth so it indents as a child block).
326
340
  - **`src/i18n.ts`** — locale + theme module; provides `t(key)` via Vue's
327
341
  provide/inject so popovers rendered through `<Teleport>` stay reactive.
328
342