## File: README.md

<h1 align="center">Canvas Editor</h1>













---

## Overview

**Canvas Editor** is a feature-rich, WYSIWYG document editor built on top of the HTML `<canvas>` API. It is designed for use cases that demand pixel-perfect rendering, advanced typography, complex layouts, and Word-like document experiences in the browser — including EMR (Electronic Medical Records), legal contracts, reports, and other document-centric applications.

Unlike traditional `contenteditable`-based editors, Canvas Editor takes full control of the rendering pipeline, providing consistent typography across browsers, precise pagination, and a uniform export experience.

## Features

- **Rich Text** — Undo / Redo, Font, Size, Bold, Italic, Underline, Strikeout, Superscript, Alignment, Headings, Lists, and more
- **Insertable Elements** — Tables, Images, Hyperlinks, Code Blocks, Page Breaks, Math Formulas (LaTeX), Date Pickers, Block elements
- **Form Controls** — Select, Text, Date, Radio, Checkbox controls
- **Pagination** — Native pagination with headers, footers, and page numbers
- **Page Layout** — Configurable page margins, watermarks, backgrounds
- **Document Structure** — Catalog (TOC) generation, comments, group annotations
- **Print & Export** — Print-ready output via canvas-to-image / PDF rendering
- **Interaction** — Custom context menus, customizable shortcut keys, drag-and-drop for text, elements, and controls
- **Extensibility** — Plugin system for adding custom functionality
- **Performance** — Web Workers for word counting, catalog generation, and async value retrieval

## Why Canvas Editor?

|                         | Canvas Editor                    | contenteditable Editors     |
| ----------------------- | -------------------------------- | --------------------------- |
| Cross-browser rendering | Pixel-perfect, identical         | Varies by browser           |
| Pagination              | Native, document-style           | Manual / unsupported        |
| Print fidelity          | Matches on-screen output         | Often diverges              |
| Typography control      | Full control                     | Limited by the browser      |
| Document features       | TOC, headers/footers, watermarks | Requires heavy custom logic |

## Installation

```bash
# npm
npm install @hufe921/canvas-editor

# pnpm
pnpm add @hufe921/canvas-editor

# yarn
yarn add @hufe921/canvas-editor
```

## Quick Start

```html

```

```javascript
import Editor from '@hufe921/canvas-editor'

const container = document.querySelector('.canvas-editor')

const editor = new Editor(container, {
  main: [
    {
      value: 'Hello, Canvas Editor!'
    }
  ]
})
```

For complete API documentation, see the [official docs](https://hufe.club/canvas-editor-docs).

## Ecosystem

| Project                                                                    | Description                             |
| -------------------------------------------------------------------------- | --------------------------------------- |
| [canvas-editor-plugin](https://github.com/Hufe921/canvas-editor-plugin)    | Official plugin collection              |
| [feature/svg](https://github.com/Hufe921/canvas-editor/tree/feature/svg)   | SVG render layer (in development)       |
| [feature/pdf](https://github.com/Hufe921/canvas-editor/tree/feature/pdf)   | PDF export feature                      |
| [feature/ai](https://github.com/Hufe921/canvas-editor/tree/feature/ai)     | AI-powered text processing demo         |
| [feature/CRDT](https://github.com/Hufe921/canvas-editor/tree/feature/CRDT) | CRDT-based collaboration (experimental) |

## Development

### Prerequisites

- Node.js `>= 24.13.1`
- pnpm (recommended)

### Setup

```bash
# Install dependencies
pnpm install

# Start the development server
npm run dev
```

### Build

```bash
# Build the application (demo)
npm run build

# Build the library (publishable package)
npm run lib
```

### Quality Checks

```bash
# Lint
npm run lint

# Type check
npm run type:check

# Unit tests (Vitest)
npm run test:unit

# E2E tests (Cypress)
npm run cypress:open    # interactive
npm run cypress:run     # headless
```

### Documentation

```bash
npm run docs:dev        # Start VitePress docs locally
npm run docs:build      # Build the documentation site
```

## Project Structure

```
src/editor/
├── core/
│   ├── draw/           # Rendering engine (canvas drawing)
│   │   ├── particle/   # Element renderers (text, image, table, latex, ...)
│   │   ├── control/    # Form control rendering
│   │   ├── frame/      # Frame elements (margin, background, borders)
│   │   ├── richtext/   # Decorations (underline, highlight)
│   │   └── interactive/# Interactive features (search, graffiti)
│   ├── command/        # Command pattern (executeBold, executeUndo, ...)
│   ├── event/          # Canvas and global event handling
│   ├── observer/       # Mouse, selection, image observers
│   ├── worker/         # Web Workers for async operations
│   └── plugin/         # Plugin system
├── interface/          # TypeScript interfaces
├── dataset/            # Enums and constants
└── utils/              # Utility helpers
```

## Contributing

Contributions are what make the open-source community such an amazing place. **Any contributions you make are greatly appreciated** — bug reports, feature requests, documentation improvements, or pull requests.

1. Fork the repository
2. Create your feature branch (`git checkout -b feat/amazing-feature`)
3. Commit your changes following [Conventional Commits](https://www.conventionalcommits.org/) (`git commit -m 'feat: add amazing feature'`)
4. Push to the branch (`git push origin feat/amazing-feature`)
5. Open a Pull Request

> Pre-commit hooks automatically run `lint` and `type:check`. Commit messages must follow Conventional Commits format (`feat:`, `fix:`, `docs:`, `refactor:`, ...).

### Contributors

Thanks to all the people who have contributed to Canvas Editor!

<a href="https://github.com/Hufe921/canvas-editor/graphs/contributors">
  
</a>

## Community & Support

- **Documentation** — [hufe.club/canvas-editor-docs](https://hufe.club/canvas-editor-docs)
- **Discussions** — [GitHub Discussions](https://github.com/Hufe921/canvas-editor/discussions)
- **Bug Reports** — [GitHub Issues](https://github.com/Hufe921/canvas-editor/issues)
- **AI-Assisted Q&A** — [Zread](https://zread.ai/Hufe921/canvas-editor) · [DeepWiki](https://deepwiki.com/Hufe921/canvas-editor)

## Sponsors

If you find this project useful, please consider [sponsoring](https://hufe.club/donate.jpg) to support its continued development.

## License

This project is licensed under the [MIT License](./LICENSE).

Copyright © 2022–present, [Hufe921](https://github.com/Hufe921).

---

## File: docs/guide/control/cascade.md

# 级联表达式

级联表达式：控件值变化时自动控制其他控件或标题的**显隐、必填、可编辑、可删除**。规则配置在触发控件的 `control.cascade` 上，随 `getValue` 持久化，编辑器内置引擎自动执行。控件验证见[控件-验证](./validate.md)。

## 数据结构

```ts
interface IControlCascadeRule {
  expression: string // DSL 表达式，如 "getValue(@self) == '1'"
  actions: ICascadeAction[] // 表达式为 true 时应用
  elseActions?: ICascadeAction[] // 可选；缺省时还原目标基线值
}

interface ICascadeAction {
  controlId?: string // 目标控件 id（唯一，精确控制）
  conceptId?: string // 目标控件/标题 conceptId（可多个，批量控制）
  // 两个字段可同时配置，合并命中全部应用
  targetType?: 'control' | 'title' // conceptId 消歧用，缺省自动探测：先控件后标题
  effects: {
    hide?: boolean // 显隐（控件/标题通用）
    required?: boolean // 必填（仅控件）
    disabled?: boolean // 可编辑（仅控件）
    deletable?: boolean // 可删除（仅控件）
  }
}
```

级联效果中的 `required` 对应控件的必填状态（校验语义见[控件-验证](./validate.md)）；`compute?: string` 为计算表达式字段（见下文）。

## DSL 语法

```
getValue(@self) == '1'
getValue('gender') == '2' && getValue('age') >= 15 && getValue('age') <= 49
contains(getValue('allergy'), '1') && count(getValue('allergy')) >= 2
getValue('operationDate') > 'today'
getValue('dischargeDate') < getValue('admissionDate')
round(getValue('weight') / (getValue('height') * getValue('height')), 1)
getValue('endTime') < now()
datediff(getValue('end'), getValue('start')) > 7
round(datediff('today', getValue('birthdate')) / 365)
if(getValue('bmi') < 18.5, '偏瘦', if(getValue('bmi') < 28, '正常', '肥胖'))
```

### 取值函数 getValue

控件值一律通过 `getValue()` 获取（不能直接书写标识符）：

- `getValue('conceptId或controlId')`：按 id 取实时值，controlId 精确优先，conceptId 批量命中时取第一个有值的
- `getValue(@self)`：取规则所在控件自身的值（`@self` 仅允许作为 `getValue` 参数）

归一化规则：SELECT/RADIO 取选中项 `code`；CHECKBOX 取 `code` 数组；TEXT/NUMBER/DATE 取实时纯文本（NUMBER 自动转数值，DATE 支持 `'YYYY-MM-DD'` 与 `'today'` / `now()` 比较）。算日期差用 `datediff`，不要直接对日期值做算术（`now() - getValue('birthdate')` 会因日期字符串无法转数值而失败）。

### 运算符与字面量

| 类别 | 运算符                                          |
| ---- | ----------------------------------------------- |
| 比较 | `==` `!=` `>` `>=` `<` `<=`                     |
| 逻辑 | `&&` `\|\|` `!`                                 |
| 算术 | `+` `-` `*` `/` `%`（`+` 任一侧为文本时做拼接） |
| 包含 | `in`（左值包含于右侧数组）                      |

优先级：`!` > `* / %` > `+ -` > 比较 > `&&` > `||`，可用 `()` 改变。字面量：字符串（单/双引号）、数字、布尔、`null`、数组。

### 内置函数

| 函数                                | 说明                                                                       |
| ----------------------------------- | -------------------------------------------------------------------------- |
| `empty(x)` / `notEmpty(x)`          | 判空                                                                       |
| `len(x)`                            | 文本字符长度                                                               |
| `count(x)`                          | checkbox 选中项数量                                                        |
| `contains(x, v)`                    | checkbox 包含某 code；或文本包含子串                                       |
| `round(x, digits?)`                 | 四舍五入，`digits` 缺省为 0                                                |
| `floor(x)` / `ceil(x)`              | 向下 / 向上取整                                                            |
| `abs(x)`                            | 绝对值                                                                     |
| `min(a, b, ...)` / `max(a, b, ...)` | 最小 / 最大值，参数为空或非数值返回 `null`                                 |
| `power(x, n)`                       | 幂运算 `xⁿ`                                                                |
| `sqrt(x)`                           | 开方，负数返回 `null`                                                      |
| `if(cond, a, b)`                    | 条件：`cond` 真→`a`，否则 `b`，仅求值命中分支（短路）                      |
| `now()`                             | 当前时间的毫秒时间戳（含时分秒），可与日期控件比较                         |
| `datediff(end, start, unit?)`       | 日期差（`end - start`），`unit`：`d`(天,默认)/`h`/`m`/`s`，非法返回 `null` |

表达式解析或求值失败时按 `false` 处理并 `console.warn`，不打断编辑。

## 计算字段（compute）

`control.compute` 配置计算表达式后，控件值变化时自动重算并回写本控件（Excel 公式模式）：

```json
{
  "conceptId": "bmi",
  "type": "number",
  "value": null,
  "disabled": true,
  "compute": "round(getValue('weight') / (getValue('height') * getValue('height')), 1)"
}
```

- 结果不同才回写；操作数为空或除零等非法运算 → 清空本控件值
- 建议搭配 `disabled: true` 只读；计算先于级联条件执行（如 `getValue(@self) > 28` 取到最新 BMI）
- 支持链式计算，内置迭代上限防循环；回写不产生 undo 记录

## 目标解析与标题控制

- `controlId` 精确命中唯一控件；`conceptId` 批量命中同概念控件或标题；两者可同时配置，合并命中全部应用
- 标题目标（按标题 `conceptId` 匹配）的 `hide: true` 会隐藏标题本身及其后直到下一个同级或更高级标题之间的所有内容

## 基线与 elseActions

- 首次对目标应用效果前，快照其属性原值（如目标本来就 `required: true`）
- 表达式变 false 且未配置 `elseActions` 时还原快照，不丢文档原始配置；配置了 `elseActions` 则按其声明固定写入

## 执行时机

- 初始化与 `executeSetValue` 后全量执行
- 内容变化（输入、粘贴、撤销/重做）后在下一宏任务重算；中文输入组合（IME）期间不触发，组合结束后生效
- `executeValidate` 校验前会同步冲刷一次，保证读到最新的显隐/必填状态
- 级联效果只写属性不改值：不递归触发新级联，也不污染撤销历史

## 完整示例

选"有高血压"才显示并必填"高血压分级"：

```json
[
  { "value": "有无高血压" },
  {
    "type": "control",
    "controlId": "1",
    "value": null,
    "control": {
      "conceptId": "hypertension",
      "type": "select",
      "value": null,
      "valueSets": [
        { "value": "有", "code": "1" },
        { "value": "无", "code": "0" }
      ],
      "cascade": [
        {
          "expression": "getValue(@self) == '1'",
          "actions": [
            {
              "conceptId": "hypertensionLevel",
              "effects": { "hide": false, "required": true }
            }
          ]
        }
      ]
    }
  },
  { "value": "高血压分级" },
  {
    "type": "control",
    "controlId": "2",
    "value": null,
    "control": {
      "conceptId": "hypertensionLevel",
      "type": "select",
      "value": null,
      "hide": true,
      "valueSets": [
        { "value": "Ⅰ级", "code": "1" },
        { "value": "Ⅱ级", "code": "2" },
        { "value": "Ⅲ级", "code": "3" }
      ]
    }
  }
]
```

初始控件 2 隐藏（基线 `hide: true`）；选"有"→ 显示且必填；改选"无"→ 还原基线重新隐藏；`executeValidate()` 时隐藏的控件 2 自动豁免。

---

## File: docs/guide/control/command.md

# 控件方法

## 获取数据

### getControlValue

功能：获取控件值

用法：

```javascript
const {
  value: string | null
  innerText: string | null
  zone: EditorZone
  elementList?: IElement[]
}[] = await instance.command.getControlValue(payload: IGetControlValueOption)
```

### getControlList

功能：获取所有控件

用法：

```javascript
const controlList = await instance.command.getControlList()
```

## 执行动作

### executeRemoveControl

功能：删除控件

用法：

```javascript
instance.command.executeRemoveControl(payload?: IRemoveControlOption)
```

### executeSetControlValue

功能：设置控件值

用法：

```javascript
instance.command.executeSetControlValue(payload: ISetControlValueOption)
```

### executeSetControlValueList

功能：批量设置控件值

用法：

```javascript
instance.command.executeSetControlValueList(payload: ISetControlValueOption[])
```

### executeSetControlExtension

功能：设置控件扩展值

用法：

```javascript
instance.command.executeSetControlExtension(payload: ISetControlExtensionOption)
```

### executeSetControlExtensionList

功能：批量设置控件扩展值

用法：

```javascript
instance.command.executeSetControlExtensionList(payload: ISetControlExtensionOption[])
```

### executeSetControlProperties

功能：设置控件属性

用法：

```javascript
instance.command.executeSetControlProperties(payload: ISetControlProperties)
```

### executeSetControlPropertiesList

功能：批量设置控件属性

用法：

```javascript
instance.command.executeSetControlPropertiesList(payload: ISetControlProperties[])
```

### executeSetControlHighlight

功能：设置控件高亮（根据关键词）

用法：

```javascript
instance.command.executeSetControlHighlight(payload: ISetControlHighlightOption)
```

### executeLocationControl

功能：定位并激活控件

用法：

```javascript
instance.command.executeLocationControl(controlId: string, options?: ILocationControlOption)
```

### executeInsertControl

功能：插入控件

用法：

```javascript
instance.command.executeInsertControl(payload: IElement)
```

### executeJumpControl

功能：跳转到下/上一个控件

用法：

```javascript
instance.command.executeJumpControl(payload?: { direction?: MoveDirection })
```

---

## File: docs/guide/control/option.md

# 控件配置

控件在文档数据（`IElement.control`）中的属性，按控件类型分述。

## 通用属性（所有类型）

| 属性            | 类型                                                                | 说明                                   |
| --------------- | ------------------------------------------------------------------- | -------------------------------------- |
| `type`          | `'text' \| 'select' \| 'checkbox' \| 'radio' \| 'date' \| 'number'` | 控件类型                               |
| `value`         | `IElement[] \| null`                                                | 控件值                                 |
| `placeholder`   | `string`                                                            | 占位符                                 |
| `conceptId`     | `string`                                                            | 概念 id（可多个控件共享，级联/取值用） |
| `groupId`       | `string`                                                            | 成组 id                                |
| `prefix`        | `string`                                                            | 前缀字符                               |
| `postfix`       | `string`                                                            | 后缀字符                               |
| `preText`       | `string`                                                            | 前文本                                 |
| `postText`      | `string`                                                            | 后文本                                 |
| `minWidth`      | `number`                                                            | 最小宽度                               |
| `underline`     | `boolean`                                                           | 下划线                                 |
| `border`        | `boolean`                                                           | 边框                                   |
| `extension`     | `unknown`                                                           | 扩展数据                               |
| `indentation`   | `ControlIndentation`                                                | 缩进                                   |
| `rowFlex`       | `RowFlex`                                                           | 行对齐                                 |
| `deletable`     | `boolean`                                                           | 可删除。默认：true                     |
| `disabled`      | `boolean`                                                           | 禁用（不可编辑）                       |
| `pasteDisabled` | `boolean`                                                           | 禁止粘贴                               |
| `hide`          | `boolean`                                                           | 隐藏                                   |
| `required`      | `boolean`                                                           | 必填（校验时使用，可被级联动态控制）   |
| `cascade`       | `IControlCascadeRule[]`                                             | 级联规则，详见：控件-级联表达式        |
| `validation`    | `IControlValidation`                                                | 校验规则，详见：控件-验证              |
| `compute`       | `string`                                                            | 计算表达式，详见：控件-级联表达式      |
| `font`          | `string`                                                            | 值字体                                 |
| `size`          | `number`                                                            | 值字号                                 |
| `bold`          | `boolean`                                                           | 值加粗                                 |
| `color`         | `string`                                                            | 值颜色                                 |
| `highlight`     | `string`                                                            | 值高亮                                 |
| `italic`        | `boolean`                                                           | 值斜体                                 |
| `strikeout`     | `boolean`                                                           | 值删除线                               |

## TEXT 文本控件

仅通用属性。

## SELECT 选择控件

通用属性，及以下专属属性：

| 属性                     | 类型                                | 说明        |
| ------------------------ | ----------------------------------- | ----------- |
| `code`                   | `string \| null`                    | 选中项 code |
| `valueSets`              | `{ value: string; code: string }[]` | 候选值列表  |
| `isMultiSelect`          | `boolean`                           | 多选        |
| `multiSelectDelimiter`   | `string`                            | 多选分隔符  |
| `selectExclusiveOptions` | `{ inputAble?: boolean }`           | 允许输入    |

## CHECKBOX 复选框控件

通用属性，及以下专属属性：

| 属性            | 类型                                | 说明                          |
| --------------- | ----------------------------------- | ----------------------------- |
| `code`          | `string \| null`                    | 选中项 code（多个以逗号分隔） |
| `valueSets`     | `{ value: string; code: string }[]` | 候选值列表                    |
| `min`           | `number`                            | 最少选择数                    |
| `max`           | `number`                            | 最多选择数                    |
| `flexDirection` | `FlexDirection`                     | 排列方向                      |

## RADIO 单选框控件

通用属性，及以下专属属性：

| 属性            | 类型                                | 说明        |
| --------------- | ----------------------------------- | ----------- |
| `code`          | `string \| null`                    | 选中项 code |
| `valueSets`     | `{ value: string; code: string }[]` | 候选值列表  |
| `flexDirection` | `FlexDirection`                     | 排列方向    |

## DATE 日期控件

通用属性，及以下专属属性：

| 属性         | 类型     | 说明                                |
| ------------ | -------- | ----------------------------------- |
| `dateFormat` | `string` | 日期格式。默认：yyyy-MM-dd hh:mm:ss |

## NUMBER 数值控件

通用属性，及以下专属属性：

| 属性                     | 类型                               | 说明       |
| ------------------------ | ---------------------------------- | ---------- |
| `numberExclusiveOptions` | `{ calculatorDisabled?: boolean }` | 禁用计算器 |

---

## File: docs/guide/control/validate.md

# 控件验证

对控件内容做**必填、长度、数值、日期、多选数量**等规则校验。规则配置在控件的 `control.validation` 上，必填用 `control.required`。

## 数据结构

```ts
interface IControlValidation {
  minLength?: number // TEXT
  maxLength?: number
  pattern?: string // 正则
  min?: number // NUMBER
  max?: number
  integer?: boolean
  precision?: number // 小数位数
  minDate?: string // DATE：'YYYY-MM-DD' 或 'today'
  maxDate?: string
  minChecked?: number // CHECKBOX 多选
  maxChecked?: number
  message?: string // 自定义错误文案
}
```

`required` 判定：select/radio 需选中项、checkbox 至少一项、text/number/date 文本非空。

配置示例：

```json
{
  "conceptId": "name",
  "type": "text",
  "value": null,
  "required": true,
  "validation": { "minLength": 2, "maxLength": 20 },
  "preText": "姓名："
}
```

错误文案默认走国际化（语言包 `validate` 节点，支持 `{min}`、`{max}`、`{count}`、`{date}`、`{precision}` 参数插值），可通过 `register.langMap` 覆盖；`validation.message` 配置的自定义文案优先级最高。

::: tip 级联与校验联动
**隐藏控件不参与校验**——被级联隐藏的必填控件自动豁免。
:::

## executeValidate

功能：校验控件（必填及各类型校验规则）。校验前会同步冲刷级联，失败控件以 errorBackgroundColor 高亮

用法：

```javascript
instance.command.executeValidate(options?: IValidateOption)
```

IValidateOption：

```typescript
interface IValidateOption {
  zone?: EditorZone // 校验区域（页眉、正文、页脚），默认全文
  errorBackgroundColor?: string // 校验失败背景色，默认取控件配置 errorBackgroundColor（#FFECE8）
}
```

返回值：

```typescript
interface IControlValidateResult {
  controlId: string
  conceptId?: string
  control: IControl // 校验失败控件的完整配置（浅拷贝），可取 preText/placeholder 等
  errors: string[] // 如 ['该字段为必填项', '最大长度为 100']
}

const results: IControlValidateResult[] = instance.command.executeValidate()
```

## executeClearValidate

功能：清除校验错误高亮

用法：

```javascript
instance.command.executeClearValidate()
```

---

## File: docs/guide/api-common.md

# 通用 API

## splitText

功能：拆分字符

用法：

```javascript
import { splitText } from '@hufe921/canvas-editor'

splitText(text: string): string[]
```

## createDomFromElementList

功能：根据 elementList 创建 dom 树

用法：

```javascript
import { createDomFromElementList } from '@hufe921/canvas-editor'

createDomFromElementList(elementList: IElement[], options?: IEditorOption): HTMLDivElement
```

## getElementListByHTML

功能：根据 HTML 创建 elementList

用法：

```javascript
import { getElementListByHTML } from '@hufe921/canvas-editor'

getElementListByHTML(htmlText: string, options: IGetElementListByHTMLOption): IElement[]
```

## getTextFromElementList

功能：根据 elementList 创建文本

用法：

```javascript
import { getTextFromElementList } from '@hufe921/canvas-editor'

getTextFromElementList(elementList: IElement[]): string
```

---

## File: docs/guide/api-instance.md

# 实例 API

## 使用方式

```javascript
import Editor from "@hufe921/canvas-editor"

const instance = new Editor(container, data, options)
instance.apiName()
```

## version

功能：版本号

用法：

```javascript
instance.version
```

## destroy

功能：销毁编辑器

用法：

```javascript
instance.destroy()
```

::: warning
仅销毁编辑器 dom 及相关事件，菜单栏、工具栏、外部变量等需自行处理。
:::

---

## File: docs/guide/command-execute.md

# 执行动作命令

## 使用方式

```javascript
import Editor from "@hufe921/canvas-editor"

const instance = new Editor(container, data, options)
instance.command.commandName()
```

::: tip
某些命令的执行，会使光标从文档中移出（比如：点击自定义工具栏-加粗文字）。此时可以设置一个标识(EDITOR_COMPONENT)给编辑器，让编辑器将其识别为内部组件。如：

```js
import { EDITOR_COMPONENT, EditorComponent } from '@hufe921/canvas-editor'


  

```

:::

## executeMode

功能：切换编辑器模式（编辑、清洁、只读、表单、打印、设计、涂鸦、留痕）

用法：

```javascript
instance.command.executeMode(editorMode: EditorMode)
```

## executeToggleTrace

功能：切换留痕记录开关。

用法：

```javascript
instance.command.executeToggleTrace(payload?: boolean)
```

## executeCompare

功能：对比两个版本的文档数据，并切换到留痕模式展示内容差异。

用法：

```javascript
instance.command.executeCompare(payload: IComparePayload)
```

## executeToggleRuler

功能：切换标尺显示。

用法：

```javascript
instance.command.executeToggleRuler(payload?: boolean)
```

## executeCut

功能：剪切

用法：

```javascript
instance.command.executeCut()
```

## executeCopy

功能：复制

用法：

```javascript
instance.command.executeCopy(payload?: ICopyOption)
```

## executePaste

功能：粘贴

用法：

```javascript
instance.command.executePaste(payload?: IPasteOption)
```

## executeSelectAll

功能：全选

用法：

```javascript
instance.command.executeSelectAll()
```

## executeBackspace

功能：向前删除

用法：

```javascript
instance.command.executeBackspace()
```

## executeSetRange

功能：设置选区

用法：

```javascript
instance.command.executeSetRange(
  startIndex: number,
  endIndex: number,
  tableId?: string,
  startTdIndex?: number,
  endTdIndex?: number,
  startTrIndex?: number,
  endTrIndex?: number
)
```

## executeReplaceRange

功能：替换选区

用法：

```javascript
instance.command.executeReplaceRange(range: IRange)
```

## executeSetPositionContext

功能：设置位置上下文

用法：

```javascript
instance.command.executeSetPositionContext(range: IRange)
```

## executeForceUpdate

功能：强制重新渲染文档

用法：

```javascript
instance.command.executeForceUpdate(options?: IForceUpdateOption)
```

## executeBlur

功能：设置编辑器失焦

用法：

```javascript
instance.command.executeBlur()
```

## executeHideCursor

功能：隐藏光标（保留选区）

用法：

```javascript
instance.command.executeHideCursor()
```

## executeUndo

功能：撤销

用法：

```javascript
instance.command.executeUndo()
```

## executeRedo

功能：重做

用法：

```javascript
instance.command.executeRedo()
```

## executePainter

功能：格式刷-复制样式

用法：

```javascript
instance.command.executePainter()
```

## executeApplyPainterStyle

功能：格式刷-应用样式

用法：

```javascript
instance.command.executeApplyPainterStyle()
```

## executeFormat

功能：清除样式

用法：

```javascript
instance.command.executeFormat(options?: IRichtextOption)
```

## executeFont

功能：设置字体

用法：

```javascript
instance.command.executeFont(font: string, options?: IRichtextOption)
```

## executeSize

功能：设置字号

用法：

```javascript
instance.command.executeSize(size: number, options?: IRichtextOption)
```

## executeSizeAdd

功能：增大字号

用法：

```javascript
instance.command.executeSizeAdd(options?: IRichtextOption)
```

## executeSizeMinus

功能：减小字号

用法：

```javascript
instance.command.executeSizeMinus(options?: IRichtextOption)
```

## executeBold

功能：字体加粗

用法：

```javascript
instance.command.executeBold(options?: IRichtextOption)
```

## executeItalic

功能：字体斜体

用法：

```javascript
instance.command.executeItalic(options?: IRichtextOption)
```

## executeUnderline

功能：下划线

用法：

```javascript
instance.command.executeUnderline(textDecoration?: ITextDecoration, options?: IRichtextOption)
```

## executeStrikeout

功能：删除线

用法：

```javascript
instance.command.executeStrikeout(options?: IRichtextOption)
```

## executeSuperscript

功能：上标

用法：

```javascript
instance.command.executeSuperscript(options?: IRichtextOption)
```

## executeSubscript

功能：上下标

用法：

```javascript
instance.command.executeSubscript(options?: IRichtextOption)
```

## executeColor

功能：字体颜色

用法：

```javascript
instance.command.executeColor(color: string | null, options?: IRichtextOption)
```

## executeHighlight

功能：高亮

用法：

```javascript
instance.command.executeHighlight(color: string | null, options?: IRichtextOption)
```

## executeTitle

功能：标题设置

用法：

```javascript
instance.command.executeTitle(TitleLevel | null)
```

## executeList

功能：列表设置

用法：

```javascript
instance.command.executeList(listType: ListType | null, listStyle?: ListStyle)
```

## executeRowFlex

功能：段落对齐

用法：

```javascript
instance.command.executeRowFlex(rowFlex: RowFlex)
```

## executeRowMargin

功能：段落行间距

用法：

```javascript
instance.command.executeRowMargin(rowMargin: number)
```

## executeInsertTable

功能：插入表格

用法：

```javascript
instance.command.executeInsertTable(row: number, col: number)
```

## executeInsertTableTopRow

功能：向上插入一行

用法：

```javascript
instance.command.executeInsertTableTopRow()
```

## executeInsertTableBottomRow

功能：向下插入一行

用法：

```javascript
instance.command.executeInsertTableBottomRow()
```

## executeInsertTableLeftCol

功能：向左插入一列

用法：

```javascript
instance.command.executeInsertTableLeftCol()
```

## executeInsertTableRightCol

功能：向右插入一列

用法：

```javascript
instance.command.executeInsertTableRightCol()
```

## executeDeleteTableRow

功能：删除当前行

用法：

```javascript
instance.command.executeDeleteTableRow()
```

## executeDeleteTableCol

功能：删除当前列

用法：

```javascript
instance.command.executeDeleteTableCol()
```

## executeDeleteTable

功能：删除表格

用法：

```javascript
instance.command.executeDeleteTable()
```

## executeMergeTableCell

功能：合并表格

用法：

```javascript
instance.command.executeMergeTableCell()
```

## executeCancelMergeTableCell

功能：取消合并表格

用法：

```javascript
instance.command.executeCancelMergeTableCell()
```

## executeSplitVerticalTableCell

功能：分隔当前单元格（垂直方向）

用法：

```javascript
instance.command.executeSplitVerticalTableCell()
```

## executeSplitHorizontalTableCell

功能：分隔当前单元格（水平方向）

用法：

```javascript
instance.command.executeSplitHorizontalTableCell()
```

## executeTableTdVerticalAlign

功能：表格单元格垂直对齐方式

用法：

```javascript
instance.command.executeTableTdVerticalAlign(payload: VerticalAlign)
```

## executeTableBorderType

功能：表格边框类型

用法：

```javascript
instance.command.executeTableBorderType(payload: TableBorder)
```

## executeTableBorderColor

功能：表格边框颜色

用法：

```javascript
instance.command.executeTableBorderColor(payload: string)
```

## executeTableTdBorderType

功能：表格单元格边框类型

用法：

```javascript
instance.command.executeTableTdBorderType(payload: TdBorder)
```

## executeTableTdSlashType

功能：表格单元格内斜线

用法：

```javascript
instance.command.executeTableTdSlashType(payload: TdSlash)
```

## executeTableTdBackgroundColor

功能：表格单元格背景色

用法：

```javascript
instance.command.executeTableTdBackgroundColor(payload: string)
```

## executeTableSelectAll

功能：选中整个表格

用法：

```javascript
instance.command.executeTableSelectAll()
```

## executeTableAutoFitToContent

功能：根据内容自动调整表格（每列宽度按该列单元格内容实测最大宽度调整，列宽不低于 defaultColMinWidth；overflow 为 false 时结果会等比例压缩至页面内容区内）

用法：

```javascript
instance.command.executeTableAutoFitToContent()
```

## executeTableAutoFitToPage

功能：根据窗口自动调整表格（表格总宽等比缩放至页面内容区宽度）

用法：

```javascript
instance.command.executeTableAutoFitToPage()
```

## executeImage

功能：插入图片

用法：

```javascript
instance.command.executeImage({
  id?: string;
  width: number;
  height: number;
  value: string;
  imgDisplay?: ImageDisplay;
})
```

## executeHyperlink

功能：插入链接

用法：

```javascript
instance.command.executeHyperlink({
  type: ElementType.HYPERLINK,
  value: string,
  url: string,
  valueList: IElement[]
})
```

## executeDeleteHyperlink

功能：删除链接

用法：

```javascript
instance.command.executeDeleteHyperlink()
```

## executeCancelHyperlink

功能：取消链接

用法：

```javascript
instance.command.executeCancelHyperlink()
```

## executeEditHyperlink

功能：编辑链接

用法：

```javascript
instance.command.executeEditHyperlink(newUrl: string)
```

## executeSeparator

功能：插入分割线

用法：

```javascript
instance.command.executeSeparator(dashArray: number[], option?: { lineWidth?: number; color?: string })
```

## executePageBreak

功能：分页符

用法：

```javascript
instance.command.executePageBreak()
```

## executeAddWatermark

功能：添加水印

用法：

```javascript
instance.command.executeAddWatermark({
  data: string;
  color?: string;
  opacity?: number;
  size?: number;
  font?: string;
  layer?: WatermarkLayer;
})
```

## executeDeleteWatermark

功能：删除水印

用法：

```javascript
instance.command.executeDeleteWatermark()
```

## executeSearch

功能：搜索

用法：

```javascript
instance.command.executeSearch(keyword: string, options?: ISearchOption)
```

## executeSearchNavigatePre

功能：搜索导航-上一个

用法：

```javascript
instance.command.executeSearchNavigatePre()
```

## executeSearchNavigateNext

功能：搜索导航-下一个

用法：

```javascript
instance.command.executeSearchNavigateNext()
```

## executeReplace

功能：搜索替换

用法：

```javascript
instance.command.executeReplace(newWord: string, option?: IReplaceOption)
```

## executePrint

功能：打印

用法：

```javascript
instance.command.executePrint(option?: IPrintOption)
```

## executeReplaceImageElement

功能：替换图片

用法：

```javascript
instance.command.executeReplaceImageElement(newUrl: string)
```

## executeSaveAsImageElement

功能：另存为图片

用法：

```javascript
instance.command.executeSaveAsImageElement()
```

## executeChangeImageDisplay

功能：改变图片行显示方式

用法：

```javascript
instance.command.executeChangeImageDisplay(element: IElement, display: ImageDisplay)
```

## executeSetImageCrop

功能：设置图片裁剪信息

用法：

```javascript
instance.command.executeSetImageCrop(crop: IImageCrop)
```

## executePageMode

功能：页面模式

用法：

```javascript
instance.command.executePageMode(pageMode: PageMode)
```

## executePageScale

功能：设置缩放比例

用法：

```javascript
instance.command.executePageScale(scale: number)
```

## executePageScaleRecovery

功能：恢复页面原始缩放比例

用法：

```javascript
instance.command.executePageScaleRecovery()
```

## executePageScaleMinus

功能：页面缩小

用法：

```javascript
instance.command.executePageScaleMinus()
```

## executePageScaleAdd

功能：页面放大

用法：

```javascript
instance.command.executePageScaleAdd()
```

## executePaperSize

功能：设置纸张大小

用法：

```javascript
instance.command.executePaperSize(width: number, height: number)
```

## executePaperDirection

功能：设置纸张方向

用法：

```javascript
instance.command.executePaperDirection(paperDirection: PaperDirection)
```

## executePageDirection

功能：设置光标所在节的纸张方向。分页符作为分节边界；首节修改全局方向，传 `null` 恢复全局方向。

用法：

```javascript
instance.command.executePageDirection(paperDirection: PaperDirection | null)
```

## executeSetPaperMargin

功能：设置纸张页边距

用法：

```javascript
instance.command.executeSetPaperMargin([top: number, right: number, bottom: number, left: number])
```

## executeSetColumns

功能：设置分栏配置

用法：

```javascript
instance.command.executeSetColumns(config: IColumnOption | null)
```

## executeSetMainBadge

功能：设置正文徽章

用法：

```javascript
instance.command.executeSetMainBadge(payload: IBadge | null)
```

## executeSetAreaBadge

功能：设置区域徽章

用法：

```javascript
instance.command.executeSetAreaBadge(payload: IAreaBadge[])
```

## executeInsertElementList

功能：插入元素

用法：

```javascript
instance.command.executeInsertElementList(elementList: IElement[], options?: IInsertElementListOption)
```

## executeAppendElementList

功能：追加元素

用法：

```javascript
instance.command.executeAppendElementList(elementList: IElement[], options?: IAppendElementListOption)
```

## executeUpdateElementById

功能：根据 id 修改元素属性

用法：

```javascript
instance.command.executeUpdateElementById(payload: IUpdateElementByIdOption)
```

## executeDeleteElementById

功能：根据 id 删除元素

用法：

```javascript
instance.command.executeDeleteElementById(payload: IDeleteElementByIdOption)
```

## executeSetValue

功能：设置编辑器数据

用法：

```javascript
instance.command.executeSetValue(payload: Partial, options?: ISetValueOption)
```

## executeSetLocale

功能：设置本地语言

用法：

```javascript
instance.command.executeSetLocale(locale: string)
```

## executeLocationCatalog

功能：定位目录位置

用法：

```javascript
instance.command.executeLocationCatalog(titleId: string)
```

## executeWordTool

功能：文字工具（删除空行、行首空格）

用法：

```javascript
instance.command.executeWordTool()
```

## executeSetHTML

功能：设置编辑器 HTML 数据

用法：

```javascript
instance.command.executeSetHTML(payload: Partial<IEditorHTML)
```

## executeSetGroup

功能：设置成组

用法：

```javascript
instance.command.executeSetGroup()
```

## executeDeleteGroup

功能：删除成组

用法：

```javascript
instance.command.executeDeleteGroup(groupId: string)
```

## executeLocationGroup

功能：定位成组位置

用法：

```javascript
instance.command.executeLocationGroup(groupId: string)
```

## executeSetZone

功能：设置激活区域（页眉、正文、页脚）

用法：

```javascript
instance.command.executeSetZone(zone: EditorZone)
```

控件相关命令已迁移至[控件-方法](./control/command.md)，校验命令已迁移至[控件-验证](./control/validate.md)。

## executeUpdateOptions

功能：修改配置

用法：

```javascript
instance.command.executeUpdateOptions(payload: IUpdateOption)
```

## executeInsertTitle

功能：插入标题

用法：

```javascript
instance.command.executeInsertTitle(payload: IElement)
```

## executeFocus

功能：光标聚焦

用法：

```javascript
instance.command.executeFocus(payload?: IFocusOption)
```

## executeInsertArea

功能： 插入区域

```js
const areaId = instance.command.executeInsertArea(payload: IInsertAreaOption)
```

## executeSetAreaProperties

功能：设置区域属性

```js
instance.command.executeSetAreaProperties(payload: ISetAreaPropertiesOption)
```

## executeSetAreaValue

功能：设置区域值

```js
instance.command.executeSetAreaValue(payload: ISetAreaValueOption)
```

## executeDeleteArea

功能：删除区域

```js
instance.command.executeDeleteArea(payload?: IDeleteAreaOption)
```

## executeLocationArea

功能：定位区域位置

```js
instance.command.executeLocationArea(areaId: string, options?: ILocationAreaOption)
```

## executeClearGraffiti

功能：清空涂鸦信息

```js
instance.command.executeClearGraffiti()
```

---

## File: docs/guide/command-get.md

# 获取数据命令

## 使用方式

```javascript
import Editor from "@hufe921/canvas-editor"

const instance = new Editor(container, data, options)
const value = instance.command.commandName()
```

## getValue

功能：获取当前文档信息

用法：

```javascript
const {
  version: string
  data: IEditorData
  options: IEditorOption
} = instance.command.getValue(options?: IGetValueOption)
```

## getValueAsync

功能：获取当前文档信息（异步）

用法：

```javascript
const {
  version: string
  data: IEditorData
  options: IEditorOption
} = await instance.command.getValueAsync(options?: IGetValueOption)
```

## getImage

功能：获取当前页面图片 base64 字符串

用法：

```javascript
const base64StringList = await instance.command.getImage(option?: IGetImageOption)
```

## getOptions

功能：获取编辑器配置

用法：

```javascript
const editorOption = await instance.command.getOptions()
```

## getWordCount

功能：获取文档字数

用法：

```javascript
const wordCount = await instance.command.getWordCount()
```

## getCursorPosition

功能: 获取光标位置坐标

用法:

```javascript
const range = instance.command.getCursorPosition()
```

## getRemainingContentHeight

功能：获取最后一页剩余可用内容高度

用法：

```javascript
const remainingHeight = instance.command.getRemainingContentHeight()
```

## computeElementListHeight

功能：计算元素列表占用高度

用法：

```javascript
const height = instance.command.computeElementListHeight(
  elementList: IElement[]
)
```

## getRange

功能：获取选区

用法：

```javascript
const range = instance.command.getRange()
```

## getRangeText

功能：获取选区文本

用法：

```javascript
const rangeText = instance.command.getRangeText()
```

## getRangeContext

功能：获取选区上下文

用法：

```javascript
const rangeContext = instance.command.getRangeContext()
```

## getRangeRow

功能：获取选区所在行元素列表

用法：

```javascript
const rowElementList = instance.command.getRangeRow()
```

## getKeywordRangeList

功能：获取关键词所在选区列表

用法：

```javascript
const rangeList = instance.command.getKeywordRangeList()
```

## getKeywordContext

功能：获取关键词所在上下文本信息

用法：

```javascript
const keywordContextList = instance.command.getKeywordContext(payload: string)
```

## getRangeParagraph

功能：获取选区所在段落元素列表

用法：

```javascript
const paragraphElementList = instance.command.getRangeParagraph()
```

## getPaperMargin

功能：获取页边距

用法：

```javascript
const [top: number, right: number, bottom: number, left: number] =
  instance.command.getPaperMargin()
```

## getColumns

功能：获取当前分栏配置。未开启分栏时返回 `null`。

用法：

```javascript
const columns: IColumnOption | null = instance.command.getColumns()
```

## getSearchNavigateInfo

功能：获取搜索导航信息

用法：

```javascript
const {
  index: number;
  count: number;
} = instance.command.getSearchNavigateInfo()
```

## getCatalog

功能：获取目录

用法：

```javascript
const catalog = await instance.command.getCatalog()
```

## getHTML

功能：获取 HTML

用法：

```javascript
const {
  header: string
  main: string
  footer: string
} = await instance.command.getHTML()
```

## getText

功能：获取文本

用法：

```javascript
const {
  header: string
  main: string
  footer: string
} = await instance.command.getText()
```

## getLocale

功能：获取当前语言

用法：

```javascript
const locale = await instance.command.getLocale()
```

## getGroupIds

功能：获取所有成组 id

用法：

```javascript
const groupIds = await instance.command.getGroupIds()
```

## getGroupRectList

功能：获取成组元素的矩形坐标列表（跨行、跨页时拆分为多个矩形），可用于实现批注连接线等场景

用法：

```javascript
const rectList = instance.command.getGroupRectList(groupId)
```

## getContainer

功能：获取编辑器容器

用法：

```javascript
const container = await instance.command.getContainer()
```

## getTitleValue

功能：获取标题值

用法：

```javascript
const {
  value: string | null
  elementList: IElement[]
  zone: EditorZone
}[] = await instance.command.getTitleValue(payload: IGetTitleValueOption)
```

## getPositionContextByEvent

功能：获取位置上下文信息通过鼠标事件

用法：

```javascript
const {
  pageNo: number
  element: IElement | null
  rangeRect: RangeRect | null
  tableInfo: ITableInfoByEvent | null
}[] = await instance.command.getPositionContextByEvent(evt: MouseEvent, options?: IPositionContextByEventOption)
```

示例：

```javascript
instance.eventBus.on(
  'mousemove',
  debounce(evt => {
    const positionContext = instance.command.getPositionContextByEvent(evt)
    console.log(positionContext)
  }, 200)
)``
```

## getElementById

功能：根据 id 获取元素

用法：

```javascript
const elementList = await instance.command.getElementById(payload: IGetElementByIdOption)
```

## getAreaValue

功能: 获取区域数据
用法：

```js
const {
  id?: string
  area: IArea
  value: IElement[]
  startPageNo: number
  endPageNo: number
} = instance.command.getAreaValue(options: IGetAreaValueOption)
```

---

## File: docs/guide/contextmenu-custom.md

# 自定义右键菜单

## 使用方式

```javascript
import Editor from "@hufe921/canvas-editor"

const instance = new Editor(container, data, options)
instance.register.contextMenuList([
    {
      key?: string;
      isDivider?: boolean;
      icon?: string;
      name?: string; // 使用%s代表选区文本。示例：搜索：%s
      shortCut?: string;
      disable?: boolean;
      when?: (payload: IContextMenuContext) => boolean;
      callback?: (command: Command, context: IContextMenuContext) => any;
      childMenus?: IRegisterContextMenu[];
    }
  ])
```

## getContextMenuList

功能：获取注册的右键菜单列表

用法：

```javascript
const contextMenuList = await instance.register.getContextMenuList()
```

备注：

```javascript
// 修改内部右键菜单示例
contextmenuList.forEach(menu => {
  // 通过菜单key找到菜单项后进行属性修改
  if (menu.key === INTERNAL_CONTEXT_MENU_KEY.GLOBAL.PASTE) {
    menu.when = () => false
  }
})
```