@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.
@@ -1,5 +1,5 @@
1
1
  import { Behavior, Editor, EditorEmittedEvent, EditorSchema } from "../_chunks-dts/behavior.types.action.js";
2
- import * as react12 from "react";
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
- }): react12.JSX.Element;
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(): react12.JSX.Element;
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.9",
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.1",
82
- "@portabletext/block-tools": "2.0.7",
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.9.21",
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.38.0",
99
- "@typescript-eslint/parser": "^8.38.0",
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']> = undefined
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: prevChildren, ...prevRest} = block.node || {
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
- const levelIndexMap = new Map<number, number>()
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
- levelIndexMap.clear()
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
- levelIndexMap.clear()
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
- levelIndexMap.clear()
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
- levelIndexMap.set(block.level, 1)
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 !== block.listItem &&
63
- previousListItem.level === block.level
79
+ previousListItem.listItem === block.listItem &&
80
+ previousListItem.level < block.level
64
81
  ) {
65
- levelIndexMap.clear()
66
- previousListItem = {
67
- listItem: block.listItem,
68
- level: block.level,
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
- if (previousListItem.level === block.level) {
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
- listIndexMap.set(block._key, 1)
94
+
93
95
  continue
94
96
  }
95
97
 
96
- if (previousListItem.level > block.level) {
97
- const levelCounter = levelIndexMap.get(block.level) ?? 0
98
- levelIndexMap.set(block.level, levelCounter + 1)
99
- previousListItem = {
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
- listIndexMap.set(block._key, levelCounter + 1)
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
  }
@@ -9,7 +9,7 @@ export function getTextMarks(
9
9
  return undefined
10
10
  }
11
11
 
12
- let marks: Array<string> | undefined = undefined
12
+ let marks: Array<string> | undefined
13
13
 
14
14
  for (const block of value) {
15
15
  if (isPortableTextBlock(block)) {
@@ -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 = 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 = undefined
49
+ let paths: AddedAnnotationPaths | undefined
50
50
  let spanPath: Path | undefined
51
51
  let markDefPath: Path | undefined
52
52
  const markDefPaths: Path[] = []