@one2x/medeo-rte 0.4.1 → 0.4.2
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.md +66 -56
- package/dist/index.js +2097 -2057
- package/dist/index.js.map +1 -1
- package/dist/style.css +59 -5
- package/dist/types/editor.d.ts +102 -32
- package/dist/types/editor.d.ts.map +1 -1
- package/dist/types/edits/editResult.d.ts +1 -1
- package/dist/types/edits/editResult.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/layout/engine.d.ts +2 -1
- package/dist/types/layout/engine.d.ts.map +1 -1
- package/dist/types/layout/style.d.ts.map +1 -1
- package/dist/types/layout/types.d.ts +16 -0
- package/dist/types/layout/types.d.ts.map +1 -1
- package/dist/types/layout/wrap.d.ts +30 -0
- package/dist/types/layout/wrap.d.ts.map +1 -1
- package/dist/types/model/document.d.ts +1 -4
- package/dist/types/model/document.d.ts.map +1 -1
- package/dist/types/model/types.d.ts +6 -8
- package/dist/types/model/types.d.ts.map +1 -1
- package/dist/types/model/virtualBlock.d.ts +4 -0
- package/dist/types/model/virtualBlock.d.ts.map +1 -1
- package/dist/types/operations/harness.d.ts +5 -6
- package/dist/types/operations/harness.d.ts.map +1 -1
- package/dist/types/operations/index.d.ts +3 -3
- package/dist/types/operations/index.d.ts.map +1 -1
- package/dist/types/operations/slice.d.ts +4 -3
- package/dist/types/operations/slice.d.ts.map +1 -1
- package/dist/types/operations/text.d.ts +13 -2
- package/dist/types/operations/text.d.ts.map +1 -1
- package/dist/types/operations/virtualBlock.d.ts +9 -17
- package/dist/types/operations/virtualBlock.d.ts.map +1 -1
- package/dist/types/paint/canvasPainter.d.ts +5 -0
- package/dist/types/paint/canvasPainter.d.ts.map +1 -1
- package/dist/types/paint/htmlPainter.d.ts +2 -0
- package/dist/types/paint/htmlPainter.d.ts.map +1 -1
- package/dist/types/paint/types.d.ts +4 -0
- package/dist/types/paint/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,30 +54,28 @@ new Editor(el, { plugins: [...builtinEmbedPlugins, formulaPlugin] });
|
|
|
54
54
|
|
|
55
55
|
文字与段落样式、列表、表格、链接、图文绕排、Markdown 边打边转、撤销重做、中文 IME。
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
嵌入对象走同一套插件接口:图片、视频、代码块、公式、同步块引用,以及两种芯片。**名字都带 slot,用途完全不同,不要混用。** 模板里可点、可生成、按字折行的那截文字用 **`mark`**,不是芯片。
|
|
58
58
|
|
|
59
|
-
###
|
|
59
|
+
### 两种芯片对照(接入必读)
|
|
60
60
|
|
|
61
|
-
| | `internalSlot` | `hostSlot` |
|
|
62
|
-
| --- | --- | --- |
|
|
63
|
-
| 是什么 | SDK 内置芯片(`slotPlugin`) | 宿主自绘芯片 |
|
|
64
|
-
| 落在哪 | `EmbedEntity`,流上一个 `*` | 同上 |
|
|
65
|
-
| 内容 | 实体字段(label / slotValue 等) | `hostType` + `data`,DOM 由宿主画 |
|
|
66
|
-
| 折行 | 整颗盒子,放不下换行 | 同左 |
|
|
67
|
-
| 谁用 | demo / 简单内置控件 | **产品业务胶囊**(下拉、`@`、上传等) |
|
|
68
|
-
| 插入 | `commands.insertSlot('text'\|'image'\|'select')` | `commands.insertHostEmbed(...)` 或 `insertSlice` 的 `entities` |
|
|
61
|
+
| | `internalSlot` | `hostSlot` |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| 是什么 | SDK 内置芯片(`slotPlugin`) | 宿主自绘芯片 |
|
|
64
|
+
| 落在哪 | `EmbedEntity`,流上一个 `*` | 同上 |
|
|
65
|
+
| 内容 | 实体字段(label / slotValue 等) | `hostType` + `data`,DOM 由宿主画 |
|
|
66
|
+
| 折行 | 整颗盒子,放不下换行 | 同左 |
|
|
67
|
+
| 谁用 | demo / 简单内置控件 | **产品业务胶囊**(下拉、`@`、上传等) |
|
|
68
|
+
| 插入 | `commands.insertSlot('text'\|'image'\|'select')` | `commands.insertHostEmbed(...)` 或 `insertSlice` 的 `entities` |
|
|
69
69
|
|
|
70
|
-
另外还有 **同步块**(fragment / ref
|
|
71
|
-
|
|
72
|
-
产品模板句里「可填写的那截灰字」用 **`virtualSlot`**,不要用 `internalSlot` / `hostSlot`。后两者是另一颗盒子,点进去才填,不能按字切开。
|
|
70
|
+
另外还有 **同步块**(fragment / ref):选区提成可复用内容,改一处全变。芯片整颗换行;要按字折行、点击出菜单、展示生成中,用下面的 `mark`。
|
|
73
71
|
|
|
74
72
|
## 虚拟块怎么用(业务侧)
|
|
75
73
|
|
|
76
74
|
虚拟块是盖在字符流上的假块:负责皮(背景、圆角)和「整段选中」交互。区间里的字仍是文档正文。用户打字**不会**新建虚拟块,只能由业务 API 插入。
|
|
77
75
|
|
|
78
|
-
|
|
76
|
+
两种 kind:
|
|
79
77
|
|
|
80
|
-
- **`mark
|
|
78
|
+
- **`mark`**:纯样式叠层(高亮底色、边框、文字缺省色等)。点击落在字上,块内方向键逐字走。从外侧朝块内按方向键不会走进去,而是先把整段文字选中(就是一段普通选区,焦点留在来的这一侧);再按一次方向键跳到另一侧外侧。整段选中时 Shift+方向键按普通选区缩小或扩大。上下键从块外落到块内时同样先选中整段。同一条边上有多块重叠时选范围最大的那块;两块紧挨着时,跳过前一块的同一次按键会选中下一块。不参与嵌套(`parentId` 恒为 `null`),可与其他块任意叠放。光标停在左右边界时都分内外两侧:从块内走到边界或点在底色里是**内侧**,输入算区间内(背景跟着延伸,遇到换行就断);在边界上再朝块外按一次方向键,或点在底色外,是**外侧**(光标画在底色外),输入的文字留在块外、同一行。其他方式落到边界(`setSelection`、撤销等)时,右边界默认内侧、左边界默认外侧。没有 `placeholder` 时,区间内文字删光后块自动移除;有 `placeholder` 时收成零宽,灰字由 SDK 画出来,不进正文,方向键也不把它当成整段选中。样式只需配 `chrome.background`、`chrome.radius`(圆角,默认 3;折行时只有首行的上两角和末行的下两角是圆角,其余角为直角,单行自然四角全圆)、`chrome.paddingX`(水平内边距,不传按 4px,传 `0` 表示不留)、`chrome.hoverBackground`(鼠标悬停时整段含折行各行换成这个底色)和 `chrome.placeholderColor`(灰字颜色,不传是 `#98a2b3`):
|
|
81
79
|
|
|
82
80
|
```ts
|
|
83
81
|
editor.insertVirtualBlock({
|
|
@@ -86,67 +84,77 @@ new Editor(el, { plugins: [...builtinEmbedPlugins, formulaPlugin] });
|
|
|
86
84
|
});
|
|
87
85
|
```
|
|
88
86
|
|
|
89
|
-
`paddingX`
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
`paddingX` 和 CSS 行内元素的 padding 一样**占排版宽度**:mark 真正的起点前、终点后各让出 `paddingX`,前后文字和相邻 mark 不会压在底色上,光标在内外侧的位置也正好是下一个字落下的位置。折行处不让位,底色在行首/行尾外扩,外扩部分画在内容区外:SDK 默认让画布和 `.mini-page-wrap` 左右各多出 5px(负 margin 抵消,文字位置不变),所以 `paddingX` 在 5px 以内开箱即用,更大就要靠编辑器 `padding.x` 补足。**宿主若覆盖 `.mini-page-wrap` 的 `padding`,请保留 `padding-inline: 5px; margin-inline: -5px;`,否则文字会左移 5px、外扩被裁**。不支持垂直内边距。
|
|
88
|
+
|
|
89
|
+
**空态。** `placeholder` 不是正文,复制、保存、`getContent()` 里都没有这段字。删光或 `replaceMarkText(id, '')` 后块留在原下标,两种光标亲和打字都会写进块里。没传 `placeholder` 的 mark 不能建成零宽,删光即拆掉。
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
const id = editor.insertVirtualBlock({
|
|
93
|
+
kind: 'mark',
|
|
94
|
+
placeholder: 'Describe a scene',
|
|
95
|
+
chrome: { background: '#fff3bf', placeholderColor: '#98a2b3' }
|
|
96
|
+
});
|
|
97
|
+
// 光标在这块里(含空块、内侧边界)时:
|
|
98
|
+
editor.on('markenter', ({ id }) => {});
|
|
99
|
+
editor.on('markleave', ({ id }) => {});
|
|
100
|
+
// 点击这块。锁定中不发,但光标仍会落下。
|
|
101
|
+
editor.on('markclick', ({ id }) => openMenu(id));
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**中间态(生成中)。** `setMarkStatus` 只活在编辑器里,不进文档、撤销栈、复制和 `getContent()`。`label` 盖住正文;比正文宽时这一行临时撑开,清掉状态后宽度恢复。`locked: true` 时,块内和内侧边界上的输入、删除、粘贴、回车不生效,点击也不发 `markclick`;外侧打字仍然落在块外。生成结束后先清状态,再用 `replaceMarkText` 把结果写回去,这一步单独占一次撤销。
|
|
92
105
|
|
|
93
|
-
|
|
106
|
+
```ts
|
|
107
|
+
editor.setMarkStatus(id, { label: 'Generating…', locked: true, text: 'rainbow', border: 'pulse' });
|
|
108
|
+
editor.setMarkStatus(id, null);
|
|
109
|
+
editor.replaceMarkText(id, 'a red bicycle');
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`text: 'rainbow'` 只作用于 `label`。`border: 'pulse'` 是底色边缘的呼吸描边。HTML 用 CSS 动画,canvas 由 SDK 逐帧重画。块被拆掉或 `setContent` 换文档后,状态自动丢掉。
|
|
113
|
+
|
|
114
|
+
点击后的菜单位置用 `getVirtualBlockRect(id)`,返回的是屏幕坐标,不用再向 SDK 要点击点。
|
|
115
|
+
|
|
116
|
+
`mark` 是目前唯一的虚拟块。`parentId` 恒为 `null`,多块可以重叠。日常编辑里业务**不用维护** `[start, end)`,插删字时 SDK 自动挪区间。
|
|
94
117
|
|
|
95
118
|
### 路径 A:整段模板一次插入(推荐)
|
|
96
119
|
|
|
97
|
-
文案 +
|
|
120
|
+
文案 + mark + 胶囊一起走 `insertSlice`。`virtualBlocks` 里的下标是**相对这段 `text`** 的半开区间:
|
|
98
121
|
|
|
99
122
|
```ts
|
|
100
123
|
editor.insertSlice({
|
|
101
|
-
text: 'Write a prompt for
|
|
124
|
+
text: 'Write a prompt for a red bicycle.\n',
|
|
102
125
|
styles: [],
|
|
103
126
|
entities: [],
|
|
104
127
|
virtualBlocks: [
|
|
105
128
|
{
|
|
106
|
-
id: '
|
|
129
|
+
id: 'phrase',
|
|
107
130
|
parentId: null,
|
|
108
|
-
kind: '
|
|
109
|
-
start: 0,
|
|
110
|
-
end: 33,
|
|
111
|
-
chrome: { background: 'rgba(43,108,255,0.08)', radius: 8 }
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
id: 'slot',
|
|
115
|
-
parentId: 'region',
|
|
116
|
-
kind: 'virtualSlot',
|
|
131
|
+
kind: 'mark',
|
|
117
132
|
start: 19,
|
|
118
|
-
end:
|
|
119
|
-
placeholder: '
|
|
120
|
-
|
|
121
|
-
chrome: { background: 'rgba(16,185,129,0.18)', placeholderColor: '#98a2b3' }
|
|
133
|
+
end: 33,
|
|
134
|
+
placeholder: 'a red bicycle',
|
|
135
|
+
chrome: { background: '#fff3bf', placeholderColor: '#98a2b3' }
|
|
122
136
|
}
|
|
123
137
|
]
|
|
124
138
|
});
|
|
125
139
|
```
|
|
126
140
|
|
|
127
|
-
|
|
141
|
+
可点击生成的样例见 `demo/vblocks.ts` 和 demo 右下角「插入可生成 mark」。
|
|
128
142
|
|
|
129
143
|
### 路径 B:给已有字套皮
|
|
130
144
|
|
|
131
145
|
```ts
|
|
132
146
|
// 不传 start/end → 用当前选区
|
|
133
147
|
editor.insertVirtualBlock({
|
|
134
|
-
kind: '
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
editor.insertVirtualBlock({
|
|
139
|
-
kind: 'virtualSlot',
|
|
140
|
-
placeholder: 'Input a theme',
|
|
141
|
-
empty: true,
|
|
142
|
-
chrome: { background: 'rgba(16,185,129,0.18)', placeholderColor: '#98a2b3' }
|
|
148
|
+
kind: 'mark',
|
|
149
|
+
placeholder: 'Describe a scene',
|
|
150
|
+
chrome: { background: '#fff3bf', placeholderColor: '#98a2b3' }
|
|
143
151
|
});
|
|
144
152
|
|
|
145
153
|
// 也可显式下标
|
|
146
|
-
editor.insertVirtualBlock({ kind: '
|
|
154
|
+
editor.insertVirtualBlock({ kind: 'mark', start: 0, end: 20, chrome: { background: '#fff3bf' } });
|
|
147
155
|
```
|
|
148
156
|
|
|
149
|
-
可配的 `chrome` 字段:`background`、`hoverBackground`(仅 mark)、`radius`、`borderColor` / `borderWidth`、`paddingX`(仅水平)、文字缺省(`color`、`fontSize`、`fontFamily`、`fontWeight`、`bold`、`italic`)、`placeholderColor
|
|
157
|
+
可配的 `chrome` 字段:`background`、`hoverBackground`(仅 mark)、`radius`、`borderColor` / `borderWidth`、`paddingX`(仅水平)、文字缺省(`color`、`fontSize`、`fontFamily`、`fontWeight`、`bold`、`italic`)、`placeholderColor`(mark 的灰字)。
|
|
150
158
|
|
|
151
159
|
改皮 / 拆皮:`updateVirtualBlock(id, chrome)`、`removeVirtualBlock(id)`(只拆皮,字和胶囊留下)。
|
|
152
160
|
|
|
@@ -154,14 +162,14 @@ editor.insertVirtualBlock({ kind: 'region', start: 0, end: 20, chrome: { ... } }
|
|
|
154
162
|
|
|
155
163
|
SDK 不画业务菜单。宿主自己:
|
|
156
164
|
|
|
157
|
-
1. 听 `
|
|
158
|
-
2. `editor.getVirtualBlockRect(id)` 拿屏幕坐标(clientX/Y,含滚动)定位浮层:`left/top/width/height` 是外接矩形,折行的块还有 `lines`;下拉放在 `left` / `top + height` 即可。滚动或重排后(`layoutchange
|
|
159
|
-
3.
|
|
160
|
-
4.
|
|
165
|
+
1. 听 `markclick`,参数是 `{ id }`。锁定中的 mark 不发这个事件
|
|
166
|
+
2. `editor.getVirtualBlockRect(id)` 拿屏幕坐标(clientX/Y,含滚动)定位浮层:`left/top/width/height` 是外接矩形,折行的块还有 `lines`;下拉放在 `left` / `top + height` 即可。滚动或重排后(`layoutchange`)重新取。不需要点击点坐标
|
|
167
|
+
3. 生成中:`setMarkStatus(id, { label, locked: true, text: 'rainbow', border: 'pulse' })`
|
|
168
|
+
4. 写回:`setMarkStatus(id, null)` 然后 `replaceMarkText(id, text)`,这一步单独占一次撤销
|
|
161
169
|
|
|
162
170
|
### 和 host 胶囊一起用
|
|
163
171
|
|
|
164
|
-
胶囊是流上的 `*`,可以落在
|
|
172
|
+
胶囊是流上的 `*`,可以落在 mark 覆盖范围内,但**不是**虚拟块的子节点。自定义芯片:
|
|
165
173
|
|
|
166
174
|
```ts
|
|
167
175
|
const editor = new Editor(el, {
|
|
@@ -175,7 +183,7 @@ const editor = new Editor(el, {
|
|
|
175
183
|
editor.commands.insertHostEmbed('Upscale', { label: '@Upscale' }, { width: 88, height: 24 });
|
|
176
184
|
```
|
|
177
185
|
|
|
178
|
-
|
|
186
|
+
更细的模型见 [virtual-blocks.md](./docs/virtual-blocks.md)。
|
|
179
187
|
|
|
180
188
|
### API 一览
|
|
181
189
|
|
|
@@ -183,11 +191,13 @@ editor.commands.insertHostEmbed('Upscale', { label: '@Upscale' }, { width: 88, h
|
|
|
183
191
|
| --- | --- |
|
|
184
192
|
| `new Editor(el, options?)` | `doc` / `paint` / `plugins` / `hostEmbed` / `width` / `padding` / `placeholder` / `textDefaults` / `shortcuts` / `autofocus` / `chrome` |
|
|
185
193
|
| `commands` | 公开编辑命令(加粗、插表、插图、`insertHostEmbed`、同步块等),宿主工具栏调这些 |
|
|
186
|
-
| `on(event, fn)` | `change` / `selectionchange` / `statechange` / `layoutchange
|
|
187
|
-
| `getState()` |
|
|
194
|
+
| `on(event, fn)` | `change` / `selectionchange` / `statechange` / `layoutchange` 无参数;`markclick` / `markenter` / `markleave` 收到 `{ id }`。返回退订函数 |
|
|
195
|
+
| `getState()` | 当前状态快照,用于同步 UI |
|
|
188
196
|
| `getContent()` / `setContent()` | 整篇内容读写,`Slice` 结构(含 `virtualBlocks`) |
|
|
189
197
|
| `insertSlice(slice, at?)` | 插入切片;模板混排走这条 |
|
|
190
|
-
| `insertVirtualBlock` / `updateVirtualBlock` / `removeVirtualBlock` | 套皮、改 chrome
|
|
198
|
+
| `insertVirtualBlock` / `updateVirtualBlock` / `removeVirtualBlock` | 套皮、改 chrome、拆皮。mark 带 `placeholder` 时 `start === end` 可以,用来放一块空灰字 |
|
|
199
|
+
| `setMarkStatus(id, status \| null)` | mark 的中间态:`label` / `locked` / `text: 'rainbow'` / `border: 'pulse'`。不进文档和撤销 |
|
|
200
|
+
| `replaceMarkText(id, text)` | 换掉 mark 里的字,块和 id 留下,整步一次撤销。空串按有没有 placeholder 收成灰字或拆块 |
|
|
191
201
|
| `insertHostEmbed(hostType, data?, size?, at?)` | 插入宿主自绘胶囊 |
|
|
192
202
|
| `getSelection()` / `setSelection()` | 选区读写 |
|
|
193
203
|
| `getLayout()` | 排版几何(只读),做标尺、小地图、槽上浮层用 |
|