@portabletext/editor 1.31.2 → 1.33.0

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.
Files changed (74) hide show
  1. package/lib/_chunks-cjs/behavior.core.cjs +4 -4
  2. package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
  3. package/lib/_chunks-cjs/behavior.markdown.cjs +19 -11
  4. package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -1
  5. package/lib/_chunks-cjs/plugin.event-listener.cjs +1839 -1724
  6. package/lib/_chunks-cjs/plugin.event-listener.cjs.map +1 -1
  7. package/lib/_chunks-cjs/selector.get-trimmed-selection.cjs +97 -0
  8. package/lib/_chunks-cjs/selector.get-trimmed-selection.cjs.map +1 -0
  9. package/lib/_chunks-cjs/{parse-blocks.cjs → util.block-offsets-to-selection.cjs} +21 -2
  10. package/lib/_chunks-cjs/util.block-offsets-to-selection.cjs.map +1 -0
  11. package/lib/_chunks-cjs/util.reverse-selection.cjs +11 -0
  12. package/lib/_chunks-cjs/util.reverse-selection.cjs.map +1 -1
  13. package/lib/_chunks-es/behavior.core.js +1 -1
  14. package/lib/_chunks-es/behavior.core.js.map +1 -1
  15. package/lib/_chunks-es/behavior.markdown.js +18 -11
  16. package/lib/_chunks-es/behavior.markdown.js.map +1 -1
  17. package/lib/_chunks-es/plugin.event-listener.js +1842 -1726
  18. package/lib/_chunks-es/plugin.event-listener.js.map +1 -1
  19. package/lib/_chunks-es/selector.get-trimmed-selection.js +100 -0
  20. package/lib/_chunks-es/selector.get-trimmed-selection.js.map +1 -0
  21. package/lib/_chunks-es/{parse-blocks.js → util.block-offsets-to-selection.js} +21 -1
  22. package/lib/_chunks-es/util.block-offsets-to-selection.js.map +1 -0
  23. package/lib/_chunks-es/util.reverse-selection.js +11 -0
  24. package/lib/_chunks-es/util.reverse-selection.js.map +1 -1
  25. package/lib/behaviors/index.d.cts +27 -0
  26. package/lib/behaviors/index.d.ts +27 -0
  27. package/lib/index.d.cts +1128 -66
  28. package/lib/index.d.ts +1128 -66
  29. package/lib/plugins/index.cjs +295 -3
  30. package/lib/plugins/index.cjs.map +1 -1
  31. package/lib/plugins/index.d.cts +1142 -67
  32. package/lib/plugins/index.d.ts +1142 -67
  33. package/lib/plugins/index.js +300 -4
  34. package/lib/plugins/index.js.map +1 -1
  35. package/lib/selectors/index.cjs +51 -1
  36. package/lib/selectors/index.cjs.map +1 -1
  37. package/lib/selectors/index.d.cts +67 -0
  38. package/lib/selectors/index.d.ts +67 -0
  39. package/lib/selectors/index.js +53 -2
  40. package/lib/selectors/index.js.map +1 -1
  41. package/lib/utils/index.cjs +5 -4
  42. package/lib/utils/index.cjs.map +1 -1
  43. package/lib/utils/index.d.cts +16 -0
  44. package/lib/utils/index.d.ts +16 -0
  45. package/lib/utils/index.js +4 -3
  46. package/package.json +2 -2
  47. package/src/behavior-actions/behavior.action.decorator.add.ts +161 -0
  48. package/src/behavior-actions/behavior.action.delete.text.ts +54 -0
  49. package/src/behavior-actions/behavior.actions.ts +25 -43
  50. package/src/behaviors/behavior.markdown-emphasis.ts +395 -0
  51. package/src/behaviors/behavior.markdown.ts +11 -4
  52. package/src/behaviors/behavior.types.ts +7 -0
  53. package/src/editor/editor-machine.ts +80 -85
  54. package/src/editor/plugins/create-with-event-listeners.ts +51 -0
  55. package/src/editor/plugins/createWithEditableAPI.ts +18 -2
  56. package/src/editor/plugins/createWithPortableTextMarkModel.ts +2 -97
  57. package/src/editor/plugins/createWithUndoRedo.ts +132 -107
  58. package/src/editor/with-applying-behavior-actions.ts +27 -3
  59. package/src/plugins/plugin.markdown.tsx +11 -1
  60. package/src/selectors/index.ts +5 -0
  61. package/src/selectors/selector.get-anchor-block.ts +22 -0
  62. package/src/selectors/selector.get-anchor-child.ts +36 -0
  63. package/src/selectors/selector.get-anchor-span.ts +18 -0
  64. package/src/selectors/selector.get-anchor-text-block.ts +20 -0
  65. package/src/selectors/selector.get-trimmed-selection.test.ts +658 -0
  66. package/src/selectors/selector.get-trimmed-selection.ts +175 -0
  67. package/src/utils/index.ts +1 -0
  68. package/src/utils/util.block-offsets-to-selection.ts +36 -0
  69. package/lib/_chunks-cjs/parse-blocks.cjs.map +0 -1
  70. package/lib/_chunks-cjs/util.is-empty-text-block.cjs +0 -14
  71. package/lib/_chunks-cjs/util.is-empty-text-block.cjs.map +0 -1
  72. package/lib/_chunks-es/parse-blocks.js.map +0 -1
  73. package/lib/_chunks-es/util.is-empty-text-block.js +0 -15
  74. package/lib/_chunks-es/util.is-empty-text-block.js.map +0 -1
@@ -20,6 +20,7 @@ import {
20
20
  type Descendant,
21
21
  type SelectionOperation,
22
22
  } from 'slate'
23
+ import type {BehaviorActionImplementation} from '../../behavior-actions/behavior.actions'
23
24
  import {debugWithName} from '../../internal-utils/debug'
24
25
  import {fromSlateValue} from '../../internal-utils/values'
25
26
  import {isChangingRemotely} from '../../internal-utils/withChanges'
@@ -33,6 +34,7 @@ import {
33
34
  } from '../../internal-utils/withUndoRedo'
34
35
  import type {PortableTextSlateEditor} from '../../types/editor'
35
36
  import type {EditorActor} from '../editor-machine'
37
+ import {getCurrentBehaviorActionSetId} from '../with-applying-behavior-actions'
36
38
 
37
39
  const debug = debugWithName('plugin:withUndoRedo')
38
40
  const debugVerbose = debug.enabled && false
@@ -78,6 +80,8 @@ export function createWithUndoRedo(
78
80
  blockSchemaType.name,
79
81
  )
80
82
  const remotePatches = getRemotePatches(editor)
83
+ let previousBehaviorActionIntendSetId =
84
+ getCurrentBehaviorActionSetId(editor)
81
85
 
82
86
  options.subscriptions.push(() => {
83
87
  debug('Subscribing to patches')
@@ -112,7 +116,9 @@ export function createWithUndoRedo(
112
116
  })
113
117
 
114
118
  editor.history = {undos: [], redos: []}
119
+
115
120
  const {apply} = editor
121
+
116
122
  editor.apply = (op: Operation) => {
117
123
  if (editorActor.getSnapshot().matches({'edit mode': 'read only'})) {
118
124
  apply(op)
@@ -145,12 +151,28 @@ export function createWithUndoRedo(
145
151
  const overwrite = shouldOverwrite(op, lastOp)
146
152
  const save = isSaving(editor)
147
153
 
148
- let merge = true
154
+ const currentBehaviorActionIntendSetId =
155
+ getCurrentBehaviorActionSetId(editor)
156
+
157
+ let merge =
158
+ currentBehaviorActionIntendSetId !== undefined &&
159
+ previousBehaviorActionIntendSetId === undefined
160
+ ? false
161
+ : currentBehaviorActionIntendSetId !== undefined &&
162
+ previousBehaviorActionIntendSetId !== undefined
163
+ ? currentBehaviorActionIntendSetId ===
164
+ previousBehaviorActionIntendSetId
165
+ : true
166
+
149
167
  if (save) {
150
168
  if (!step) {
151
169
  merge = false
152
170
  } else if (operations.length === 0) {
153
- merge = shouldMerge(op, lastOp) || overwrite
171
+ merge =
172
+ currentBehaviorActionIntendSetId === undefined &&
173
+ previousBehaviorActionIntendSetId === undefined
174
+ ? shouldMerge(op, lastOp) || overwrite
175
+ : merge
154
176
  }
155
177
 
156
178
  if (step && merge) {
@@ -177,123 +199,126 @@ export function createWithUndoRedo(
177
199
  history.redos = []
178
200
  }
179
201
  }
202
+
203
+ previousBehaviorActionIntendSetId = currentBehaviorActionIntendSetId
204
+
180
205
  apply(op)
181
206
  }
182
207
 
183
- editor.undo = () => {
184
- if (editorActor.getSnapshot().matches({'edit mode': 'read only'})) {
185
- return
186
- }
187
- const {undos} = editor.history
188
- if (undos.length > 0) {
189
- const step = undos[undos.length - 1]
190
- debug('Undoing', step)
191
- if (step.operations.length > 0) {
192
- const otherPatches = remotePatches.filter(
193
- (item) => item.time >= step.timestamp,
194
- )
195
- let transformedOperations = step.operations
196
- otherPatches.forEach((item) => {
197
- transformedOperations = flatten(
198
- transformedOperations.map((op) =>
199
- transformOperation(
200
- editor,
201
- item.patch,
202
- op,
203
- item.snapshot,
204
- item.previousSnapshot,
205
- ),
206
- ),
207
- )
208
- })
209
- const reversedOperations = transformedOperations
210
- .map(Operation.inverse)
211
- .reverse()
212
-
213
- try {
214
- Editor.withoutNormalizing(editor, () => {
215
- withUndoing(editor, () => {
216
- withoutSaving(editor, () => {
217
- reversedOperations.forEach((op) => {
218
- editor.apply(op)
219
- })
220
- })
208
+ // Plugin return
209
+ return editor
210
+ }
211
+ }
212
+
213
+ export const historyUndoActionImplementation: BehaviorActionImplementation<
214
+ 'history.undo'
215
+ > = ({action}) => {
216
+ const editor = action.editor
217
+ const {undos} = editor.history
218
+ const remotePatches = getRemotePatches(editor)
219
+
220
+ if (undos.length > 0) {
221
+ const step = undos[undos.length - 1]
222
+ debug('Undoing', step)
223
+ if (step.operations.length > 0) {
224
+ const otherPatches = remotePatches.filter(
225
+ (item) => item.time >= step.timestamp,
226
+ )
227
+ let transformedOperations = step.operations
228
+ otherPatches.forEach((item) => {
229
+ transformedOperations = flatten(
230
+ transformedOperations.map((op) =>
231
+ transformOperation(
232
+ editor,
233
+ item.patch,
234
+ op,
235
+ item.snapshot,
236
+ item.previousSnapshot,
237
+ ),
238
+ ),
239
+ )
240
+ })
241
+ const reversedOperations = transformedOperations
242
+ .map(Operation.inverse)
243
+ .reverse()
244
+
245
+ try {
246
+ Editor.withoutNormalizing(editor, () => {
247
+ withUndoing(editor, () => {
248
+ withoutSaving(editor, () => {
249
+ reversedOperations.forEach((op) => {
250
+ editor.apply(op)
221
251
  })
222
252
  })
223
- editor.normalize()
224
- editor.onChange()
225
- } catch (err) {
226
- debug('Could not perform undo step', err)
227
- remotePatches.splice(0, remotePatches.length)
228
- Transforms.deselect(editor)
229
- editor.history = {undos: [], redos: []}
230
- SAVING.set(editor, true)
231
- setIsUndoing(editor, false)
232
- editor.onChange()
233
- return
234
- }
235
- editor.history.redos.push(step)
236
- editor.history.undos.pop()
237
- }
253
+ })
254
+ })
255
+ } catch (err) {
256
+ debug('Could not perform undo step', err)
257
+ remotePatches.splice(0, remotePatches.length)
258
+ Transforms.deselect(editor)
259
+ editor.history = {undos: [], redos: []}
260
+ SAVING.set(editor, true)
261
+ setIsUndoing(editor, false)
262
+ editor.onChange()
263
+ return
238
264
  }
265
+ editor.history.redos.push(step)
266
+ editor.history.undos.pop()
239
267
  }
268
+ }
269
+ }
240
270
 
241
- editor.redo = () => {
242
- if (editorActor.getSnapshot().matches({'edit mode': 'read only'})) {
243
- return
244
- }
245
- const {redos} = editor.history
246
- if (redos.length > 0) {
247
- const step = redos[redos.length - 1]
248
- debug('Redoing', step)
249
- if (step.operations.length > 0) {
250
- const otherPatches = remotePatches.filter(
251
- (item) => item.time >= step.timestamp,
252
- )
253
- let transformedOperations = step.operations
254
- otherPatches.forEach((item) => {
255
- transformedOperations = flatten(
256
- transformedOperations.map((op) =>
257
- transformOperation(
258
- editor,
259
- item.patch,
260
- op,
261
- item.snapshot,
262
- item.previousSnapshot,
263
- ),
264
- ),
265
- )
266
- })
267
- try {
268
- Editor.withoutNormalizing(editor, () => {
269
- withRedoing(editor, () => {
270
- withoutSaving(editor, () => {
271
- transformedOperations.forEach((op) => {
272
- editor.apply(op)
273
- })
274
- })
271
+ export const historyRedoActionImplementation: BehaviorActionImplementation<
272
+ 'history.redo'
273
+ > = ({action}) => {
274
+ const editor = action.editor
275
+ const {redos} = editor.history
276
+ const remotePatches = getRemotePatches(editor)
277
+
278
+ if (redos.length > 0) {
279
+ const step = redos[redos.length - 1]
280
+ debug('Redoing', step)
281
+ if (step.operations.length > 0) {
282
+ const otherPatches = remotePatches.filter(
283
+ (item) => item.time >= step.timestamp,
284
+ )
285
+ let transformedOperations = step.operations
286
+ otherPatches.forEach((item) => {
287
+ transformedOperations = flatten(
288
+ transformedOperations.map((op) =>
289
+ transformOperation(
290
+ editor,
291
+ item.patch,
292
+ op,
293
+ item.snapshot,
294
+ item.previousSnapshot,
295
+ ),
296
+ ),
297
+ )
298
+ })
299
+ try {
300
+ Editor.withoutNormalizing(editor, () => {
301
+ withRedoing(editor, () => {
302
+ withoutSaving(editor, () => {
303
+ transformedOperations.forEach((op) => {
304
+ editor.apply(op)
275
305
  })
276
306
  })
277
- editor.normalize()
278
- editor.onChange()
279
- } catch (err) {
280
- debug('Could not perform redo step', err)
281
- remotePatches.splice(0, remotePatches.length)
282
- Transforms.deselect(editor)
283
- editor.history = {undos: [], redos: []}
284
- SAVING.set(editor, true)
285
- setIsRedoing(editor, false)
286
- editor.onChange()
287
- return
288
- }
289
- editor.history.undos.push(step)
290
- editor.history.redos.pop()
291
- }
307
+ })
308
+ })
309
+ } catch (err) {
310
+ debug('Could not perform redo step', err)
311
+ remotePatches.splice(0, remotePatches.length)
312
+ Transforms.deselect(editor)
313
+ editor.history = {undos: [], redos: []}
314
+ SAVING.set(editor, true)
315
+ setIsRedoing(editor, false)
316
+ editor.onChange()
317
+ return
292
318
  }
319
+ editor.history.undos.push(step)
320
+ editor.history.redos.pop()
293
321
  }
294
-
295
- // Plugin return
296
- return editor
297
322
  }
298
323
  }
299
324
 
@@ -1,15 +1,39 @@
1
- import type {Editor} from 'slate'
1
+ import {Editor} from 'slate'
2
+ import {defaultKeyGenerator} from './key-generator'
2
3
 
3
4
  const IS_APPLYING_BEHAVIOR_ACTIONS: WeakMap<Editor, boolean | undefined> =
4
5
  new WeakMap()
5
6
 
6
7
  export function withApplyingBehaviorActions(editor: Editor, fn: () => void) {
7
- const prev = isApplyingBehaviorActions(editor)
8
+ const prev = IS_APPLYING_BEHAVIOR_ACTIONS.get(editor)
8
9
  IS_APPLYING_BEHAVIOR_ACTIONS.set(editor, true)
9
- fn()
10
+ Editor.withoutNormalizing(editor, fn)
10
11
  IS_APPLYING_BEHAVIOR_ACTIONS.set(editor, prev)
11
12
  }
12
13
 
13
14
  export function isApplyingBehaviorActions(editor: Editor) {
14
15
  return IS_APPLYING_BEHAVIOR_ACTIONS.get(editor) ?? false
15
16
  }
17
+
18
+ ////////
19
+
20
+ const CURRENT_BEHAVIOR_ACTION_INTEND_SET: WeakMap<
21
+ Editor,
22
+ {actionSetId: string} | undefined
23
+ > = new WeakMap()
24
+
25
+ export function withApplyingBehaviorActionIntendSet(
26
+ editor: Editor,
27
+ fn: () => void,
28
+ ) {
29
+ const current = CURRENT_BEHAVIOR_ACTION_INTEND_SET.get(editor)
30
+ CURRENT_BEHAVIOR_ACTION_INTEND_SET.set(editor, {
31
+ actionSetId: defaultKeyGenerator(),
32
+ })
33
+ withApplyingBehaviorActions(editor, fn)
34
+ CURRENT_BEHAVIOR_ACTION_INTEND_SET.set(editor, current)
35
+ }
36
+
37
+ export function getCurrentBehaviorActionSetId(editor: Editor) {
38
+ return CURRENT_BEHAVIOR_ACTION_INTEND_SET.get(editor)?.actionSetId
39
+ }
@@ -3,12 +3,17 @@ import {
3
3
  createMarkdownBehaviors,
4
4
  type MarkdownBehaviorsConfig,
5
5
  } from '../behaviors/behavior.markdown'
6
+ import {
7
+ useMarkdownEmphasisBehaviors,
8
+ type MarkdownEmphasisBehaviorsConfig,
9
+ } from '../behaviors/behavior.markdown-emphasis'
6
10
  import {useEditor} from '../editor/editor-provider'
7
11
 
8
12
  /**
9
13
  * @beta
10
14
  */
11
- export type MarkdownPluginConfig = MarkdownBehaviorsConfig
15
+ export type MarkdownPluginConfig = MarkdownBehaviorsConfig &
16
+ MarkdownEmphasisBehaviorsConfig
12
17
 
13
18
  /**
14
19
  * @beta
@@ -25,6 +30,10 @@ export type MarkdownPluginConfig = MarkdownBehaviorsConfig
25
30
  * <EditorProvider>
26
31
  * <MarkdownPlugin
27
32
  * config={{
33
+ * boldDecorator: ({schema}) =>
34
+ * schema.decorators.find((decorator) => decorator.value === 'strong')?.value,
35
+ * italicDecorator: ({schema}) =>
36
+ * schema.decorators.find((decorator) => decorator.value === 'em')?.value,
28
37
  * horizontalRuleObject: ({schema}) => {
29
38
  * const name = schema.blockObjects.find(
30
39
  * (object) => object.name === 'break',
@@ -51,6 +60,7 @@ export type MarkdownPluginConfig = MarkdownBehaviorsConfig
51
60
  */
52
61
  export function MarkdownPlugin(props: {config: MarkdownPluginConfig}) {
53
62
  const editor = useEditor()
63
+ useMarkdownEmphasisBehaviors({config: props.config})
54
64
 
55
65
  useEffect(() => {
56
66
  const behaviors = createMarkdownBehaviors(props.config)
@@ -9,6 +9,10 @@ export type {
9
9
  export {getActiveAnnotations} from './selector.get-active-annotations'
10
10
  export {getActiveListItem} from './selector.get-active-list-item'
11
11
  export {getActiveStyle} from './selector.get-active-style'
12
+ export {getAnchorBlock} from './selector.get-anchor-block'
13
+ export {getAnchorChild} from './selector.get-anchor-child'
14
+ export {getAnchorSpan} from './selector.get-anchor-span'
15
+ export {getAnchorTextBlock} from './selector.get-anchor-text-block'
12
16
  export {getBlockOffsets} from './selector.get-block-offsets'
13
17
  export {getCaretWordSelection} from './selector.get-caret-word-selection'
14
18
  export {getNextInlineObject} from './selector.get-next-inline-object'
@@ -20,6 +24,7 @@ export {getSelectionEndPoint} from './selector.get-selection-end-point'
20
24
  export {getSelectionStartPoint} from './selector.get-selection-start-point'
21
25
  export {getSelectionText} from './selector.get-selection-text'
22
26
  export {getBlockTextBefore} from './selector.get-text-before'
27
+ export {getTrimmedSelection} from './selector.get-trimmed-selection'
23
28
  export {getValue} from './selector.get-value'
24
29
  export {isActiveAnnotation} from './selector.is-active-annotation'
25
30
  export {isActiveDecorator} from './selector.is-active-decorator'
@@ -0,0 +1,22 @@
1
+ import type {KeyedSegment, PortableTextBlock} from '@sanity/types'
2
+ import type {EditorSelector} from '../editor/editor-selector'
3
+ import {isKeyedSegment} from '../utils'
4
+
5
+ /**
6
+ * @public
7
+ */
8
+ export const getAnchorBlock: EditorSelector<
9
+ {node: PortableTextBlock; path: [KeyedSegment]} | undefined
10
+ > = ({context}) => {
11
+ const key = context.selection
12
+ ? isKeyedSegment(context.selection.anchor.path[0])
13
+ ? context.selection.anchor.path[0]._key
14
+ : undefined
15
+ : undefined
16
+
17
+ const node = key
18
+ ? context.value.find((block) => block._key === key)
19
+ : undefined
20
+
21
+ return node && key ? {node, path: [{_key: key}]} : undefined
22
+ }
@@ -0,0 +1,36 @@
1
+ import type {KeyedSegment} from '@portabletext/patches'
2
+ import type {PortableTextObject, PortableTextSpan} from '@sanity/types'
3
+ import type {EditorSelector} from '../editor/editor-selector'
4
+ import {isKeyedSegment} from '../utils'
5
+ import {getAnchorTextBlock} from './selector.get-anchor-text-block'
6
+
7
+ /**
8
+ * @public
9
+ */
10
+ export const getAnchorChild: EditorSelector<
11
+ | {
12
+ node: PortableTextObject | PortableTextSpan
13
+ path: [KeyedSegment, 'children', KeyedSegment]
14
+ }
15
+ | undefined
16
+ > = ({context}) => {
17
+ const anchorBlock = getAnchorTextBlock({context})
18
+
19
+ if (!anchorBlock) {
20
+ return undefined
21
+ }
22
+
23
+ const key = context.selection
24
+ ? isKeyedSegment(context.selection.anchor.path[2])
25
+ ? context.selection.anchor.path[2]._key
26
+ : undefined
27
+ : undefined
28
+
29
+ const node = key
30
+ ? anchorBlock.node.children.find((span) => span._key === key)
31
+ : undefined
32
+
33
+ return node && key
34
+ ? {node, path: [...anchorBlock.path, 'children', {_key: key}]}
35
+ : undefined
36
+ }
@@ -0,0 +1,18 @@
1
+ import type {KeyedSegment} from '@portabletext/patches'
2
+ import {isPortableTextSpan, type PortableTextSpan} from '@sanity/types'
3
+ import type {EditorSelector} from '../editor/editor-selector'
4
+ import {getAnchorChild} from './selector.get-anchor-child'
5
+
6
+ /**
7
+ * @public
8
+ */
9
+ export const getAnchorSpan: EditorSelector<
10
+ | {node: PortableTextSpan; path: [KeyedSegment, 'children', KeyedSegment]}
11
+ | undefined
12
+ > = ({context}) => {
13
+ const anchorChild = getAnchorChild({context})
14
+
15
+ return anchorChild && isPortableTextSpan(anchorChild.node)
16
+ ? {node: anchorChild.node, path: anchorChild.path}
17
+ : undefined
18
+ }
@@ -0,0 +1,20 @@
1
+ import {
2
+ isPortableTextTextBlock,
3
+ type KeyedSegment,
4
+ type PortableTextTextBlock,
5
+ } from '@sanity/types'
6
+ import type {EditorSelector} from '../editor/editor-selector'
7
+ import {getAnchorBlock} from './selector.get-anchor-block'
8
+
9
+ /**
10
+ * @public
11
+ */
12
+ export const getAnchorTextBlock: EditorSelector<
13
+ {node: PortableTextTextBlock; path: [KeyedSegment]} | undefined
14
+ > = ({context}) => {
15
+ const anchorBlock = getAnchorBlock({context})
16
+
17
+ return anchorBlock && isPortableTextTextBlock(anchorBlock.node)
18
+ ? {node: anchorBlock.node, path: anchorBlock.path}
19
+ : undefined
20
+ }