@portabletext/editor 2.1.9 → 2.1.11
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/lib/_chunks-dts/behavior.types.action.d.ts +9 -9
- package/lib/index.cjs +36 -48
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +36 -48
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.d.ts +3 -3
- package/package.json +6 -6
- package/src/editor/plugins/createWithEditableAPI.ts +1 -1
- package/src/internal-utils/applyPatch.ts +1 -1
- package/src/internal-utils/build-index-maps.test.ts +52 -0
- package/src/internal-utils/build-index-maps.ts +50 -37
- package/src/internal-utils/text-marks.ts +1 -1
- package/src/internal-utils/to-slate-range.ts +1 -1
- package/src/operations/behavior.operation.annotation.add.ts +1 -1
package/lib/plugins/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Behavior, Editor, EditorEmittedEvent, EditorSchema } from "../_chunks-dts/behavior.types.action.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react22 from "react";
|
|
3
3
|
import React from "react";
|
|
4
4
|
/**
|
|
5
5
|
* @beta
|
|
@@ -181,7 +181,7 @@ type MarkdownPluginConfig = MarkdownBehaviorsConfig & {
|
|
|
181
181
|
*/
|
|
182
182
|
declare function MarkdownPlugin(props: {
|
|
183
183
|
config: MarkdownPluginConfig;
|
|
184
|
-
}):
|
|
184
|
+
}): react22.JSX.Element;
|
|
185
185
|
/**
|
|
186
186
|
* @beta
|
|
187
187
|
* Restrict the editor to one line. The plugin takes care of blocking
|
|
@@ -192,5 +192,5 @@ declare function MarkdownPlugin(props: {
|
|
|
192
192
|
*
|
|
193
193
|
* @deprecated Install the plugin from `@portabletext/plugin-one-line`
|
|
194
194
|
*/
|
|
195
|
-
declare function OneLinePlugin():
|
|
195
|
+
declare function OneLinePlugin(): react22.JSX.Element;
|
|
196
196
|
export { BehaviorPlugin, DecoratorShortcutPlugin, EditorRefPlugin, EventListenerPlugin, MarkdownPlugin, type MarkdownPluginConfig, OneLinePlugin };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.11",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -78,15 +78,15 @@
|
|
|
78
78
|
"slate": "0.118.0",
|
|
79
79
|
"slate-dom": "^0.117.4",
|
|
80
80
|
"slate-react": "0.117.4",
|
|
81
|
-
"xstate": "^5.20.
|
|
82
|
-
"@portabletext/block-tools": "2.0.
|
|
81
|
+
"xstate": "^5.20.2",
|
|
82
|
+
"@portabletext/block-tools": "2.0.8",
|
|
83
83
|
"@portabletext/patches": "1.1.6",
|
|
84
84
|
"@portabletext/keyboard-shortcuts": "1.1.1"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
87
|
"@portabletext/toolkit": "^2.0.17",
|
|
88
88
|
"@sanity/diff-match-patch": "^3.2.0",
|
|
89
|
-
"@sanity/pkg-utils": "^7.
|
|
89
|
+
"@sanity/pkg-utils": "^7.11.1",
|
|
90
90
|
"@sanity/schema": "^4.3.0",
|
|
91
91
|
"@sanity/types": "^4.3.0",
|
|
92
92
|
"@testing-library/react": "^16.3.0",
|
|
@@ -95,8 +95,8 @@
|
|
|
95
95
|
"@types/lodash.startcase": "^4.4.9",
|
|
96
96
|
"@types/react": "^19.1.9",
|
|
97
97
|
"@types/react-dom": "^19.1.7",
|
|
98
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
99
|
-
"@typescript-eslint/parser": "^8.
|
|
98
|
+
"@typescript-eslint/eslint-plugin": "^8.39.0",
|
|
99
|
+
"@typescript-eslint/parser": "^8.39.0",
|
|
100
100
|
"@vitejs/plugin-react": "^4.7.0",
|
|
101
101
|
"@vitest/browser": "^3.2.4",
|
|
102
102
|
"@vitest/coverage-istanbul": "^3.2.4",
|
|
@@ -424,7 +424,7 @@ export function createEditableAPI(
|
|
|
424
424
|
return isActiveAnnotation(annotationType)(snapshot)
|
|
425
425
|
},
|
|
426
426
|
addAnnotation: (type, value) => {
|
|
427
|
-
let paths: ReturnType<EditableAPI['addAnnotation']>
|
|
427
|
+
let paths: ReturnType<EditableAPI['addAnnotation']>
|
|
428
428
|
|
|
429
429
|
Editor.withoutNormalizing(editor, () => {
|
|
430
430
|
paths = addAnnotationOperationImplementation({
|
|
@@ -298,7 +298,7 @@ function setPatch(editor: PortableTextSlateEditor, patch: SetPatch) {
|
|
|
298
298
|
return true
|
|
299
299
|
} else if (Element.isElement(block.node) && patch.path.length === 1) {
|
|
300
300
|
const {children, ...nextRest} = value as unknown as PortableTextBlock
|
|
301
|
-
const {children:
|
|
301
|
+
const {children: _prevChildren, ...prevRest} = block.node || {
|
|
302
302
|
children: undefined,
|
|
303
303
|
}
|
|
304
304
|
|
|
@@ -187,6 +187,58 @@ describe(buildIndexMaps.name, () => {
|
|
|
187
187
|
)
|
|
188
188
|
})
|
|
189
189
|
|
|
190
|
+
test('numbered list broken up by a nested bulleted list', () => {
|
|
191
|
+
buildIndexMaps(
|
|
192
|
+
{
|
|
193
|
+
schema,
|
|
194
|
+
value: [
|
|
195
|
+
textBlock('k0', {listItem: 'number', level: 1}),
|
|
196
|
+
textBlock('k1', {listItem: 'number', level: 1}),
|
|
197
|
+
textBlock('k2', {listItem: 'bullet', level: 1}),
|
|
198
|
+
textBlock('k3', {listItem: 'bullet', level: 2}),
|
|
199
|
+
textBlock('k4', {listItem: 'number', level: 1}),
|
|
200
|
+
],
|
|
201
|
+
},
|
|
202
|
+
{blockIndexMap, listIndexMap},
|
|
203
|
+
)
|
|
204
|
+
expect(listIndexMap).toEqual(
|
|
205
|
+
new Map([
|
|
206
|
+
['k0', 1],
|
|
207
|
+
['k1', 2],
|
|
208
|
+
['k2', 1],
|
|
209
|
+
['k3', 1],
|
|
210
|
+
['k4', 1],
|
|
211
|
+
]),
|
|
212
|
+
)
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
test('numbered list broken up by an inverse-indented bulleted list', () => {
|
|
216
|
+
buildIndexMaps(
|
|
217
|
+
{
|
|
218
|
+
schema,
|
|
219
|
+
value: [
|
|
220
|
+
textBlock('k0', {listItem: 'number', level: 1}),
|
|
221
|
+
textBlock('k1', {listItem: 'number', level: 1}),
|
|
222
|
+
textBlock('k2', {listItem: 'bullet', level: 2}),
|
|
223
|
+
textBlock('k3', {listItem: 'bullet', level: 1}),
|
|
224
|
+
textBlock('k4', {listItem: 'bullet', level: 2}),
|
|
225
|
+
textBlock('k5', {listItem: 'number', level: 1}),
|
|
226
|
+
],
|
|
227
|
+
},
|
|
228
|
+
{blockIndexMap, listIndexMap},
|
|
229
|
+
)
|
|
230
|
+
expect(listIndexMap).toEqual(
|
|
231
|
+
new Map([
|
|
232
|
+
['k0', 1],
|
|
233
|
+
['k1', 2],
|
|
234
|
+
['k2', 1],
|
|
235
|
+
['k3', 1],
|
|
236
|
+
['k4', 1],
|
|
237
|
+
['k5', 1],
|
|
238
|
+
]),
|
|
239
|
+
)
|
|
240
|
+
})
|
|
241
|
+
|
|
190
242
|
test('simple indented list', () => {
|
|
191
243
|
buildIndexMaps(
|
|
192
244
|
{
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type {EditorContext} from '../editor/editor-snapshot'
|
|
2
2
|
import {isTextBlock} from './parse-blocks'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// Maps for each list type, keeping track of the current list count for each
|
|
5
|
+
// level.
|
|
6
|
+
const levelIndexMaps = new Map<string, Map<number, number>>()
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Mutates the maps in place.
|
|
@@ -18,7 +20,7 @@ export function buildIndexMaps(
|
|
|
18
20
|
): void {
|
|
19
21
|
blockIndexMap.clear()
|
|
20
22
|
listIndexMap.clear()
|
|
21
|
-
|
|
23
|
+
levelIndexMaps.clear()
|
|
22
24
|
|
|
23
25
|
let previousListItem:
|
|
24
26
|
| {
|
|
@@ -36,71 +38,82 @@ export function buildIndexMaps(
|
|
|
36
38
|
|
|
37
39
|
blockIndexMap.set(block._key, blockIndex)
|
|
38
40
|
|
|
41
|
+
// Clear the state if we encounter a non-text block
|
|
39
42
|
if (!isTextBlock(context, block)) {
|
|
40
|
-
|
|
43
|
+
levelIndexMaps.clear()
|
|
41
44
|
previousListItem = undefined
|
|
45
|
+
|
|
42
46
|
continue
|
|
43
47
|
}
|
|
44
48
|
|
|
49
|
+
// Clear the state if we encounter a non-list text block
|
|
45
50
|
if (block.listItem === undefined || block.level === undefined) {
|
|
46
|
-
|
|
51
|
+
levelIndexMaps.clear()
|
|
47
52
|
previousListItem = undefined
|
|
53
|
+
|
|
48
54
|
continue
|
|
49
55
|
}
|
|
50
56
|
|
|
57
|
+
// If we encounter a new list item, we set the initial index to 1 for the
|
|
58
|
+
// list type on that level.
|
|
51
59
|
if (!previousListItem) {
|
|
60
|
+
const listIndex = 1
|
|
61
|
+
const levelIndexMap =
|
|
62
|
+
levelIndexMaps.get(block.listItem) ?? new Map<number, number>()
|
|
63
|
+
levelIndexMap.set(block.level, listIndex)
|
|
64
|
+
levelIndexMaps.set(block.listItem, levelIndexMap)
|
|
65
|
+
|
|
66
|
+
listIndexMap.set(block._key, listIndex)
|
|
67
|
+
|
|
52
68
|
previousListItem = {
|
|
53
69
|
listItem: block.listItem,
|
|
54
70
|
level: block.level,
|
|
55
71
|
}
|
|
56
|
-
|
|
57
|
-
listIndexMap.set(block._key, 1)
|
|
72
|
+
|
|
58
73
|
continue
|
|
59
74
|
}
|
|
60
75
|
|
|
76
|
+
// If the previous list item is of the same type but on a lower level, we
|
|
77
|
+
// need to reset the level index map for that type.
|
|
61
78
|
if (
|
|
62
|
-
previousListItem.listItem
|
|
63
|
-
previousListItem.level
|
|
79
|
+
previousListItem.listItem === block.listItem &&
|
|
80
|
+
previousListItem.level < block.level
|
|
64
81
|
) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
levelIndexMap.set(block.level, 1)
|
|
71
|
-
listIndexMap.set(block._key, 1)
|
|
72
|
-
continue
|
|
73
|
-
}
|
|
82
|
+
const listIndex = 1
|
|
83
|
+
const levelIndexMap =
|
|
84
|
+
levelIndexMaps.get(block.listItem) ?? new Map<number, number>()
|
|
85
|
+
levelIndexMap.set(block.level, listIndex)
|
|
86
|
+
levelIndexMaps.set(block.listItem, levelIndexMap)
|
|
74
87
|
|
|
75
|
-
|
|
76
|
-
const levelCounter = levelIndexMap.get(block.level) ?? 0
|
|
77
|
-
levelIndexMap.set(block.level, levelCounter + 1)
|
|
78
|
-
previousListItem = {
|
|
79
|
-
listItem: block.listItem,
|
|
80
|
-
level: block.level,
|
|
81
|
-
}
|
|
82
|
-
listIndexMap.set(block._key, levelCounter + 1)
|
|
83
|
-
continue
|
|
84
|
-
}
|
|
88
|
+
listIndexMap.set(block._key, listIndex)
|
|
85
89
|
|
|
86
|
-
if (previousListItem.level < block.level) {
|
|
87
|
-
levelIndexMap.set(block.level, 1)
|
|
88
90
|
previousListItem = {
|
|
89
91
|
listItem: block.listItem,
|
|
90
92
|
level: block.level,
|
|
91
93
|
}
|
|
92
|
-
|
|
94
|
+
|
|
93
95
|
continue
|
|
94
96
|
}
|
|
95
97
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
listItem: block.listItem,
|
|
101
|
-
level: block.level,
|
|
98
|
+
// Reset all other list items on this level
|
|
99
|
+
levelIndexMaps.forEach((levelIndexMap, listItem) => {
|
|
100
|
+
if (listItem === block.listItem) {
|
|
101
|
+
return
|
|
102
102
|
}
|
|
103
|
-
|
|
103
|
+
|
|
104
|
+
levelIndexMap.set(block.level!, 0)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
const levelIndexMap =
|
|
108
|
+
levelIndexMaps.get(block.listItem) ?? new Map<number, number>()
|
|
109
|
+
const levelCounter = levelIndexMap.get(block.level) ?? 0
|
|
110
|
+
levelIndexMap.set(block.level, levelCounter + 1)
|
|
111
|
+
|
|
112
|
+
listIndexMap.set(block._key, levelCounter + 1)
|
|
113
|
+
|
|
114
|
+
previousListItem = {
|
|
115
|
+
listItem: block.listItem,
|
|
116
|
+
level: block.level,
|
|
104
117
|
}
|
|
105
118
|
}
|
|
106
119
|
}
|
|
@@ -136,7 +136,7 @@ function toSlateSelectionPoint(
|
|
|
136
136
|
let offset = spanSelectionPoint?.offset ?? selectionPoint.offset
|
|
137
137
|
let childPath: Array<number> = []
|
|
138
138
|
let childIndex = -1
|
|
139
|
-
let pathChild: PortableTextSpan | PortableTextObject | undefined
|
|
139
|
+
let pathChild: PortableTextSpan | PortableTextObject | undefined
|
|
140
140
|
|
|
141
141
|
for (const child of block.children) {
|
|
142
142
|
childIndex++
|
|
@@ -46,7 +46,7 @@ export const addAnnotationOperationImplementation: BehaviorOperationImplementati
|
|
|
46
46
|
return
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
let paths: AddedAnnotationPaths | undefined
|
|
49
|
+
let paths: AddedAnnotationPaths | undefined
|
|
50
50
|
let spanPath: Path | undefined
|
|
51
51
|
let markDefPath: Path | undefined
|
|
52
52
|
const markDefPaths: Path[] = []
|