@portabletext/editor 2.15.2 → 2.15.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "2.15.2",
3
+ "version": "2.15.4",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -9,7 +9,6 @@ import {
9
9
  } from '@portabletext/patches'
10
10
  import {isSpan, isTextBlock} from '@portabletext/schema'
11
11
  import type {Path, PortableTextSpan, PortableTextTextBlock} from '@sanity/types'
12
- import {get} from 'lodash'
13
12
  import {
14
13
  Element,
15
14
  Text,
@@ -124,6 +123,12 @@ export function setNodePatch(
124
123
  }
125
124
  }
126
125
 
126
+ for (const key of Object.keys(operation.properties)) {
127
+ if (!(key in operation.newProperties)) {
128
+ patches.push(unset([{_key: block._key}, key]))
129
+ }
130
+ }
131
+
127
132
  return patches
128
133
  } else {
129
134
  const patches: Patch[] = []
@@ -134,20 +139,32 @@ export function setNodePatch(
134
139
  patches.push(set(_key, [blockIndex, '_key']))
135
140
  }
136
141
 
137
- const properties =
142
+ const newValue =
138
143
  'value' in operation.newProperties &&
139
144
  typeof operation.newProperties.value === 'object'
140
145
  ? (operation.newProperties.value as Record<string, unknown>)
141
146
  : ({} satisfies Record<string, unknown>)
142
147
 
143
- const keys = Object.keys(properties)
148
+ const keys = Object.keys(newValue)
144
149
 
145
150
  for (const key of keys) {
146
- const value = properties[key]
151
+ const value = newValue[key]
147
152
 
148
153
  patches.push(set(value, [{_key: block._key}, key]))
149
154
  }
150
155
 
156
+ const value =
157
+ 'value' in operation.properties &&
158
+ typeof operation.properties.value === 'object'
159
+ ? (operation.properties.value as Record<string, unknown>)
160
+ : ({} satisfies Record<string, unknown>)
161
+
162
+ for (const key of Object.keys(value)) {
163
+ if (!(key in newValue)) {
164
+ patches.push(unset([{_key: block._key}, key]))
165
+ }
166
+ }
167
+
151
168
  return patches
152
169
  }
153
170
  } else if (operation.path.length === 2) {
@@ -196,31 +213,48 @@ export function setNodePatch(
196
213
  return patches
197
214
  }
198
215
 
199
- const keys = Object.keys(operation.newProperties)
200
- keys.forEach((keyName) => {
201
- // Special case for setting _key on a child. We have to target it by index and not the _key.
202
- if (keys.length === 1 && keyName === '_key') {
203
- const val = get(operation.newProperties, keyName)
216
+ const newPropNames = Object.keys(operation.newProperties)
217
+
218
+ for (const keyName of newPropNames) {
219
+ const value = (operation.newProperties as Record<string, unknown>)[
220
+ keyName
221
+ ]
222
+
223
+ if (keyName === '_key') {
204
224
  patches.push(
205
- set(val, [
225
+ set(value, [
206
226
  {_key: blockKey},
207
227
  'children',
208
228
  block.children.indexOf(child),
209
229
  keyName,
210
230
  ]),
211
231
  )
212
- } else {
213
- const val = get(operation.newProperties, keyName)
214
- patches.push(
215
- set(val, [
216
- {_key: blockKey},
217
- 'children',
218
- {_key: childKey},
219
- keyName,
220
- ]),
221
- )
232
+
233
+ continue
222
234
  }
223
- })
235
+
236
+ patches.push(
237
+ set(value, [
238
+ {_key: blockKey},
239
+ 'children',
240
+ {_key: childKey},
241
+ keyName,
242
+ ]),
243
+ )
244
+ }
245
+
246
+ const propNames = Object.keys(operation.properties)
247
+
248
+ for (const keyName of propNames) {
249
+ if (keyName in operation.newProperties) {
250
+ continue
251
+ }
252
+
253
+ patches.push(
254
+ unset([{_key: blockKey}, 'children', {_key: childKey}, keyName]),
255
+ )
256
+ }
257
+
224
258
  return patches
225
259
  }
226
260
  throw new Error('Could not find a valid child')
@@ -33,18 +33,14 @@ export const childUnsetOperationImplementation: BehaviorOperationImplementation<
33
33
  }
34
34
 
35
35
  if (operation.editor.isTextSpan(child)) {
36
- if (operation.props.includes('text')) {
37
- operation.editor.apply({
38
- type: 'remove_text',
39
- path: childPath,
40
- offset: 0,
41
- text: child.text,
42
- })
43
- }
44
-
45
36
  const newNode: Record<string, unknown> = {}
46
37
 
47
38
  for (const prop of operation.props) {
39
+ if (prop === 'text') {
40
+ // Unsetting `text` requires special treatment
41
+ continue
42
+ }
43
+
48
44
  if (prop === '_type') {
49
45
  // It's not allowed to unset the _type of a span
50
46
  continue
@@ -60,6 +56,15 @@ export const childUnsetOperationImplementation: BehaviorOperationImplementation<
60
56
 
61
57
  Transforms.setNodes(operation.editor, newNode, {at: childPath})
62
58
 
59
+ if (operation.props.includes('text')) {
60
+ operation.editor.apply({
61
+ type: 'remove_text',
62
+ path: childPath,
63
+ offset: 0,
64
+ text: child.text,
65
+ })
66
+ }
67
+
63
68
  return
64
69
  }
65
70
 
@@ -251,11 +251,9 @@ export const stepDefinitions = [
251
251
  type: 'select',
252
252
  at: selection,
253
253
  })
254
- })
255
254
 
256
- await vi.waitFor(() => {
257
255
  expect(context.editor.getSnapshot().context.selection).toEqual(
258
- getSelectionBeforeText(context.editor.getSnapshot().context, text),
256
+ selection,
259
257
  )
260
258
  })
261
259
  },
@@ -283,17 +281,16 @@ export const stepDefinitions = [
283
281
  context.editor.getSnapshot().context,
284
282
  text,
285
283
  )
284
+
286
285
  expect(selection).not.toBeNull()
287
286
 
288
287
  context.editor.send({
289
288
  type: 'select',
290
- at: getSelectionAfterText(context.editor.getSnapshot().context, text),
289
+ at: selection,
291
290
  })
292
- })
293
291
 
294
- await vi.waitFor(() => {
295
292
  expect(context.editor.getSnapshot().context.selection).toEqual(
296
- getSelectionAfterText(context.editor.getSnapshot().context, text),
293
+ selection,
297
294
  )
298
295
  })
299
296
  },