@portabletext/editor 2.1.8 → 2.1.10

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 };
@@ -1,5 +1,5 @@
1
1
  import { BlockOffset, BlockPath, ChildPath, EditorContext, EditorSelection, EditorSelectionPoint } from "../_chunks-dts/behavior.types.action.js";
2
- import * as _sanity_types9 from "@sanity/types";
2
+ import * as _sanity_types8 from "@sanity/types";
3
3
  import { KeyedSegment, PortableTextBlock, PortableTextChild, PortableTextSpan, PortableTextTextBlock } from "@sanity/types";
4
4
  /**
5
5
  * @public
@@ -150,7 +150,7 @@ declare function mergeTextBlocks({
150
150
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>;
151
151
  targetBlock: PortableTextTextBlock;
152
152
  incomingBlock: PortableTextTextBlock;
153
- }): PortableTextTextBlock<_sanity_types9.PortableTextObject | _sanity_types9.PortableTextSpan>;
153
+ }): PortableTextTextBlock<_sanity_types8.PortableTextObject | _sanity_types8.PortableTextSpan>;
154
154
  /**
155
155
  * @public
156
156
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "2.1.8",
3
+ "version": "2.1.10",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -79,9 +79,9 @@
79
79
  "slate-dom": "^0.117.4",
80
80
  "slate-react": "0.117.4",
81
81
  "xstate": "^5.20.1",
82
- "@portabletext/block-tools": "2.0.6",
83
- "@portabletext/keyboard-shortcuts": "1.1.1",
84
- "@portabletext/patches": "1.1.6"
82
+ "@portabletext/block-tools": "2.0.8",
83
+ "@portabletext/patches": "1.1.6",
84
+ "@portabletext/keyboard-shortcuts": "1.1.1"
85
85
  },
86
86
  "devDependencies": {
87
87
  "@portabletext/toolkit": "^2.0.17",
@@ -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
  }