@portabletext/editor 1.34.1 → 1.35.1

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 (131) hide show
  1. package/lib/_chunks-cjs/behavior.core.cjs +57 -118
  2. package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
  3. package/lib/_chunks-cjs/behavior.markdown.cjs +27 -67
  4. package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -1
  5. package/lib/_chunks-cjs/{plugin.event-listener.cjs → editor-provider.cjs} +101 -87
  6. package/lib/_chunks-cjs/editor-provider.cjs.map +1 -0
  7. package/lib/_chunks-cjs/selector.get-text-before.cjs +5 -7
  8. package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
  9. package/lib/_chunks-cjs/selector.is-active-style.cjs +22 -36
  10. package/lib/_chunks-cjs/selector.is-active-style.cjs.map +1 -1
  11. package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs +68 -153
  12. package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs.map +1 -1
  13. package/lib/_chunks-cjs/util.block-offsets-to-selection.cjs.map +1 -1
  14. package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
  15. package/lib/_chunks-es/behavior.core.js +57 -118
  16. package/lib/_chunks-es/behavior.core.js.map +1 -1
  17. package/lib/_chunks-es/behavior.markdown.js +27 -67
  18. package/lib/_chunks-es/behavior.markdown.js.map +1 -1
  19. package/lib/_chunks-es/{plugin.event-listener.js → editor-provider.js} +102 -88
  20. package/lib/_chunks-es/editor-provider.js.map +1 -0
  21. package/lib/_chunks-es/selector.get-text-before.js +5 -7
  22. package/lib/_chunks-es/selector.get-text-before.js.map +1 -1
  23. package/lib/_chunks-es/selector.is-active-style.js +22 -36
  24. package/lib/_chunks-es/selector.is-active-style.js.map +1 -1
  25. package/lib/_chunks-es/selector.is-at-the-start-of-block.js +68 -153
  26. package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +1 -1
  27. package/lib/_chunks-es/util.block-offsets-to-selection.js.map +1 -1
  28. package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
  29. package/lib/behaviors/index.cjs +18 -48
  30. package/lib/behaviors/index.cjs.map +1 -1
  31. package/lib/behaviors/index.d.cts +19392 -214
  32. package/lib/behaviors/index.d.ts +19392 -214
  33. package/lib/behaviors/index.js +18 -48
  34. package/lib/behaviors/index.js.map +1 -1
  35. package/lib/index.cjs +81 -51
  36. package/lib/index.cjs.map +1 -1
  37. package/lib/index.d.cts +334 -59
  38. package/lib/index.d.ts +334 -59
  39. package/lib/index.js +35 -4
  40. package/lib/index.js.map +1 -1
  41. package/lib/plugins/index.cjs +200 -189
  42. package/lib/plugins/index.cjs.map +1 -1
  43. package/lib/plugins/index.d.cts +344 -25
  44. package/lib/plugins/index.d.ts +344 -25
  45. package/lib/plugins/index.js +198 -187
  46. package/lib/plugins/index.js.map +1 -1
  47. package/lib/selectors/index.cjs +22 -50
  48. package/lib/selectors/index.cjs.map +1 -1
  49. package/lib/selectors/index.d.cts +19485 -174
  50. package/lib/selectors/index.d.ts +19485 -174
  51. package/lib/selectors/index.js +22 -50
  52. package/lib/selectors/index.js.map +1 -1
  53. package/lib/utils/index.cjs.map +1 -1
  54. package/lib/utils/index.d.cts +19518 -7
  55. package/lib/utils/index.d.ts +19518 -7
  56. package/lib/utils/index.js.map +1 -1
  57. package/package.json +7 -7
  58. package/src/behavior-actions/behavior.action.decorator.add.ts +1 -0
  59. package/src/behavior-actions/behavior.action.delete.text.ts +1 -0
  60. package/src/behaviors/behavior.code-editor.ts +6 -6
  61. package/src/behaviors/behavior.core.annotations.ts +5 -4
  62. package/src/behaviors/behavior.core.block-objects.ts +17 -17
  63. package/src/behaviors/behavior.core.decorators.ts +12 -8
  64. package/src/behaviors/behavior.core.insert-break.ts +27 -29
  65. package/src/behaviors/behavior.core.lists.ts +19 -19
  66. package/src/behaviors/behavior.decorator-pair.ts +201 -0
  67. package/src/behaviors/behavior.default.ts +35 -30
  68. package/src/behaviors/behavior.emoji-picker.ts +12 -12
  69. package/src/behaviors/behavior.links.ts +7 -7
  70. package/src/behaviors/behavior.markdown.ts +41 -42
  71. package/src/behaviors/behavior.types.ts +14 -17
  72. package/src/behaviors/index.ts +0 -1
  73. package/src/converters/converter.json.ts +6 -6
  74. package/src/converters/converter.portable-text.deserialize.test.ts +27 -29
  75. package/src/converters/converter.portable-text.ts +13 -7
  76. package/src/converters/converter.text-html.deserialize.test.ts +16 -18
  77. package/src/converters/converter.text-html.serialize.test.ts +56 -57
  78. package/src/converters/converter.text-html.ts +14 -10
  79. package/src/converters/converter.text-plain.test.ts +17 -17
  80. package/src/converters/converter.text-plain.ts +15 -11
  81. package/src/converters/converter.types.ts +5 -5
  82. package/src/editor/Editable.tsx +26 -0
  83. package/src/editor/editor-machine.ts +170 -142
  84. package/src/editor/editor-selector.ts +3 -0
  85. package/src/editor/editor-snapshot.ts +13 -0
  86. package/src/editor-event-listener.tsx +30 -0
  87. package/src/index.ts +3 -3
  88. package/src/internal-utils/create-test-snapshot.ts +23 -0
  89. package/src/internal-utils/get-text-to-emphasize.ts +29 -7
  90. package/src/plugins/plugin.decorator-shortcut.ts +235 -0
  91. package/src/plugins/plugin.markdown.tsx +56 -8
  92. package/src/plugins/plugin.one-line.tsx +17 -17
  93. package/src/selectors/selector.get-active-annotations.test.ts +4 -13
  94. package/src/selectors/selector.get-active-list-item.ts +4 -4
  95. package/src/selectors/selector.get-active-style.ts +6 -6
  96. package/src/selectors/selector.get-anchor-block.ts +5 -5
  97. package/src/selectors/selector.get-anchor-child.ts +5 -5
  98. package/src/selectors/selector.get-anchor-span.ts +2 -2
  99. package/src/selectors/selector.get-anchor-text-block.ts +2 -2
  100. package/src/selectors/selector.get-block-offsets.ts +8 -7
  101. package/src/selectors/selector.get-caret-word-selection.test.ts +3 -7
  102. package/src/selectors/selector.get-caret-word-selection.ts +19 -16
  103. package/src/selectors/selector.get-next-inline-object.ts +4 -4
  104. package/src/selectors/selector.get-previous-inline-object.ts +4 -4
  105. package/src/selectors/selector.get-selected-slice.ts +7 -4
  106. package/src/selectors/selector.get-selected-spans.test.ts +5 -9
  107. package/src/selectors/selector.get-selected-spans.ts +9 -9
  108. package/src/selectors/selector.get-selection-end-point.ts +5 -5
  109. package/src/selectors/selector.get-selection-start-point.ts +5 -5
  110. package/src/selectors/selector.get-selection-text.test.ts +5 -7
  111. package/src/selectors/selector.get-selection-text.ts +2 -2
  112. package/src/selectors/selector.get-selection.ts +2 -2
  113. package/src/selectors/selector.get-text-before.ts +8 -8
  114. package/src/selectors/selector.get-trimmed-selection.test.ts +3 -5
  115. package/src/selectors/selector.get-trimmed-selection.ts +15 -13
  116. package/src/selectors/selector.get-value.ts +4 -4
  117. package/src/selectors/selector.is-active-decorator.test.ts +5 -9
  118. package/src/selectors/selector.is-at-the-end-of-block.ts +6 -3
  119. package/src/selectors/selector.is-at-the-start-of-block.ts +3 -3
  120. package/src/selectors/selector.is-overlapping-selection.ts +8 -6
  121. package/src/selectors/selector.is-selection-collapsed.ts +6 -5
  122. package/src/selectors/selector.is-selection-expanded.ts +2 -2
  123. package/src/selectors/selectors.ts +59 -59
  124. package/src/types/block-offset.ts +9 -0
  125. package/src/utils/index.ts +0 -1
  126. package/src/utils/util.block-offset.ts +1 -1
  127. package/src/utils/util.block-offsets-to-selection.ts +1 -1
  128. package/src/utils/util.child-selection-point-to-block-offset.ts +1 -1
  129. package/lib/_chunks-cjs/plugin.event-listener.cjs.map +0 -1
  130. package/lib/_chunks-es/plugin.event-listener.js.map +0 -1
  131. package/src/behaviors/behavior.markdown-emphasis.ts +0 -437
@@ -160,6 +160,7 @@ type UnsetEvent = {
160
160
  * @internal
161
161
  */
162
162
  export type EditorActor = ActorRefFrom<typeof editorMachine>
163
+ export type HasTag = ReturnType<EditorActor['getSnapshot']>['hasTag']
163
164
 
164
165
  /**
165
166
  * @internal
@@ -194,6 +195,9 @@ export type InternalEditorEvent =
194
195
  | NamespaceEvent<UnsetEvent, 'notify'>
195
196
  | PatchEvent
196
197
  | SyntheticBehaviorEvent
198
+ | {type: 'dragstart'}
199
+ | {type: 'dragend'}
200
+ | {type: 'drop'}
197
201
 
198
202
  /**
199
203
  * @internal
@@ -235,6 +239,7 @@ export const editorMachine = setup({
235
239
  schema: EditorSchema
236
240
  value?: Array<PortableTextBlock>
237
241
  },
242
+ tags: {} as 'dragging internally',
238
243
  },
239
244
  actions: {
240
245
  'add behavior to context': assign({
@@ -290,189 +295,197 @@ export const editorMachine = setup({
290
295
  'clear pending events': assign({
291
296
  pendingEvents: [],
292
297
  }),
293
- 'handle behavior event': enqueueActions(({context, event, enqueue}) => {
294
- assertEvent(event, ['behavior event', 'custom behavior event'])
295
-
296
- const defaultAction =
297
- event.type === 'custom behavior event' ||
298
- event.behaviorEvent.type === 'copy' ||
299
- event.behaviorEvent.type === 'deserialize' ||
300
- event.behaviorEvent.type === 'key.down' ||
301
- event.behaviorEvent.type === 'key.up' ||
302
- event.behaviorEvent.type === 'paste' ||
303
- event.behaviorEvent.type === 'serialize'
304
- ? undefined
305
- : ({
306
- ...event.behaviorEvent,
307
- editor: event.editor,
308
- } satisfies BehaviorAction)
309
- const defaultActionCallback =
310
- event.type === 'behavior event'
311
- ? event.defaultActionCallback
312
- : undefined
313
-
314
- const eventBehaviors = [
315
- ...foundationalBehaviors,
316
- ...context.behaviors.values(),
317
- ...defaultBehaviors,
318
- ].filter((behavior) => behavior.on === event.behaviorEvent.type)
319
-
320
- if (eventBehaviors.length === 0) {
321
- if (defaultActionCallback) {
298
+ 'handle behavior event': enqueueActions(
299
+ ({context, event, enqueue, self}) => {
300
+ assertEvent(event, ['behavior event', 'custom behavior event'])
301
+
302
+ const defaultAction =
303
+ event.type === 'custom behavior event' ||
304
+ event.behaviorEvent.type === 'copy' ||
305
+ event.behaviorEvent.type === 'deserialize' ||
306
+ event.behaviorEvent.type === 'key.down' ||
307
+ event.behaviorEvent.type === 'key.up' ||
308
+ event.behaviorEvent.type === 'paste' ||
309
+ event.behaviorEvent.type === 'serialize'
310
+ ? undefined
311
+ : ({
312
+ ...event.behaviorEvent,
313
+ editor: event.editor,
314
+ } satisfies BehaviorAction)
315
+ const defaultActionCallback =
316
+ event.type === 'behavior event'
317
+ ? event.defaultActionCallback
318
+ : undefined
319
+
320
+ const eventBehaviors = [
321
+ ...foundationalBehaviors,
322
+ ...context.behaviors.values(),
323
+ ...defaultBehaviors,
324
+ ].filter((behavior) => behavior.on === event.behaviorEvent.type)
325
+
326
+ if (eventBehaviors.length === 0) {
327
+ if (defaultActionCallback) {
328
+ withApplyingBehaviorActions(event.editor, () => {
329
+ try {
330
+ defaultActionCallback()
331
+ } catch (error) {
332
+ console.error(
333
+ new Error(
334
+ `Performing action "${event.behaviorEvent.type}" failed due to: ${error.message}`,
335
+ ),
336
+ )
337
+ }
338
+ })
339
+ return
340
+ }
341
+
342
+ if (!defaultAction) {
343
+ return
344
+ }
345
+
322
346
  withApplyingBehaviorActions(event.editor, () => {
323
347
  try {
324
- defaultActionCallback()
348
+ performAction({
349
+ context,
350
+ action: defaultAction,
351
+ })
325
352
  } catch (error) {
326
353
  console.error(
327
354
  new Error(
328
- `Performing action "${event.behaviorEvent.type}" failed due to: ${error.message}`,
355
+ `Performing action "${defaultAction.type}" as a result of "${event.behaviorEvent.type}" failed due to: ${error.message}`,
329
356
  ),
330
357
  )
331
358
  }
332
359
  })
360
+ event.editor.onChange()
333
361
  return
334
362
  }
335
363
 
336
- if (!defaultAction) {
337
- return
338
- }
364
+ const editorSnapshot = createEditorSnapshot({
365
+ converters: [...context.converters],
366
+ editor: event.editor,
367
+ keyGenerator: context.keyGenerator,
368
+ schema: context.schema,
369
+ hasTag: (tag) => self.getSnapshot().hasTag(tag),
370
+ })
371
+
372
+ let behaviorOverwritten = false
339
373
 
340
- withApplyingBehaviorActions(event.editor, () => {
341
- try {
342
- performAction({
343
- context,
344
- action: defaultAction,
374
+ for (const eventBehavior of eventBehaviors) {
375
+ const shouldRun =
376
+ eventBehavior.guard === undefined ||
377
+ eventBehavior.guard({
378
+ context: editorSnapshot.context,
379
+ snapshot: editorSnapshot,
380
+ event: event.behaviorEvent,
345
381
  })
346
- } catch (error) {
347
- console.error(
348
- new Error(
349
- `Performing action "${defaultAction.type}" as a result of "${event.behaviorEvent.type}" failed due to: ${error.message}`,
350
- ),
351
- )
382
+
383
+ if (!shouldRun) {
384
+ continue
352
385
  }
353
- })
354
- event.editor.onChange()
355
- return
356
- }
357
386
 
358
- const editorSnapshot = createEditorSnapshot({
359
- converters: [...context.converters],
360
- editor: event.editor,
361
- keyGenerator: context.keyGenerator,
362
- schema: context.schema,
363
- })
364
-
365
- let behaviorOverwritten = false
366
-
367
- for (const eventBehavior of eventBehaviors) {
368
- const shouldRun =
369
- eventBehavior.guard === undefined ||
370
- eventBehavior.guard({
371
- context: editorSnapshot.context,
372
- event: event.behaviorEvent,
373
- })
387
+ const actionIntendSets = eventBehavior.actions.map((actionSet) =>
388
+ actionSet(
389
+ {
390
+ context: editorSnapshot.context,
391
+ snapshot: editorSnapshot,
392
+ event: event.behaviorEvent,
393
+ },
394
+ shouldRun,
395
+ ),
396
+ )
397
+
398
+ for (const actionIntends of actionIntendSets) {
399
+ behaviorOverwritten =
400
+ behaviorOverwritten ||
401
+ (actionIntends.length > 0 &&
402
+ actionIntends.some(
403
+ (actionIntend) => actionIntend.type !== 'effect',
404
+ ))
405
+
406
+ withApplyingBehaviorActionIntendSet(event.editor, () => {
407
+ for (const actionIntend of actionIntends) {
408
+ if (actionIntend.type === 'raise') {
409
+ if (isCustomBehaviorEvent(actionIntend.event)) {
410
+ enqueue.raise({
411
+ type: 'custom behavior event',
412
+ behaviorEvent: actionIntend.event as CustomBehaviorEvent,
413
+ editor: event.editor,
414
+ })
415
+ } else {
416
+ enqueue.raise({
417
+ type: 'behavior event',
418
+ behaviorEvent: actionIntend.event,
419
+ editor: event.editor,
420
+ })
421
+ }
422
+ continue
423
+ }
374
424
 
375
- if (!shouldRun) {
376
- continue
377
- }
425
+ const action = {
426
+ ...actionIntend,
427
+ editor: event.editor,
428
+ }
378
429
 
379
- const actionIntendSets = eventBehavior.actions.map((actionSet) =>
380
- actionSet(
381
- {context: editorSnapshot.context, event: event.behaviorEvent},
382
- shouldRun,
383
- ),
384
- )
385
-
386
- for (const actionIntends of actionIntendSets) {
387
- behaviorOverwritten =
388
- behaviorOverwritten ||
389
- (actionIntends.length > 0 &&
390
- actionIntends.some(
391
- (actionIntend) => actionIntend.type !== 'effect',
392
- ))
393
-
394
- withApplyingBehaviorActionIntendSet(event.editor, () => {
395
- for (const actionIntend of actionIntends) {
396
- if (actionIntend.type === 'raise') {
397
- if (isCustomBehaviorEvent(actionIntend.event)) {
398
- enqueue.raise({
399
- type: 'custom behavior event',
400
- behaviorEvent: actionIntend.event as CustomBehaviorEvent,
401
- editor: event.editor,
402
- })
403
- } else {
404
- enqueue.raise({
405
- type: 'behavior event',
406
- behaviorEvent: actionIntend.event,
407
- editor: event.editor,
408
- })
430
+ try {
431
+ performAction({context, action})
432
+ } catch (error) {
433
+ console.error(
434
+ new Error(
435
+ `Performing action "${action.type}" as a result of "${event.behaviorEvent.type}" failed due to: ${error.message}`,
436
+ ),
437
+ )
438
+ break
409
439
  }
410
- continue
411
440
  }
441
+ })
442
+ event.editor.onChange()
443
+ }
412
444
 
413
- const action = {
414
- ...actionIntend,
415
- editor: event.editor,
416
- }
445
+ if (behaviorOverwritten) {
446
+ event.nativeEvent?.preventDefault()
447
+ break
448
+ }
449
+ }
417
450
 
451
+ if (!behaviorOverwritten) {
452
+ if (defaultActionCallback) {
453
+ withApplyingBehaviorActions(event.editor, () => {
418
454
  try {
419
- performAction({context, action})
455
+ defaultActionCallback()
420
456
  } catch (error) {
421
457
  console.error(
422
458
  new Error(
423
- `Performing action "${action.type}" as a result of "${event.behaviorEvent.type}" failed due to: ${error.message}`,
459
+ `Performing "${event.behaviorEvent.type}" failed due to: ${error.message}`,
424
460
  ),
425
461
  )
426
- break
427
462
  }
428
- }
429
- })
430
- event.editor.onChange()
431
- }
463
+ })
464
+ return
465
+ }
432
466
 
433
- if (behaviorOverwritten) {
434
- event.nativeEvent?.preventDefault()
435
- break
436
- }
437
- }
467
+ if (!defaultAction) {
468
+ return
469
+ }
438
470
 
439
- if (!behaviorOverwritten) {
440
- if (defaultActionCallback) {
441
471
  withApplyingBehaviorActions(event.editor, () => {
442
472
  try {
443
- defaultActionCallback()
473
+ performAction({
474
+ context,
475
+ action: defaultAction,
476
+ })
444
477
  } catch (error) {
445
478
  console.error(
446
479
  new Error(
447
- `Performing "${event.behaviorEvent.type}" failed due to: ${error.message}`,
480
+ `Performing action "${defaultAction.type}" as a result of "${event.behaviorEvent.type}" failed due to: ${error.message}`,
448
481
  ),
449
482
  )
450
483
  }
451
484
  })
452
- return
453
- }
454
-
455
- if (!defaultAction) {
456
- return
485
+ event.editor.onChange()
457
486
  }
458
-
459
- withApplyingBehaviorActions(event.editor, () => {
460
- try {
461
- performAction({
462
- context,
463
- action: defaultAction,
464
- })
465
- } catch (error) {
466
- console.error(
467
- new Error(
468
- `Performing action "${defaultAction.type}" as a result of "${event.behaviorEvent.type}" failed due to: ${error.message}`,
469
- ),
470
- )
471
- }
472
- })
473
- event.editor.onChange()
474
- }
475
- }),
487
+ },
488
+ ),
476
489
  },
477
490
  }).createMachine({
478
491
  id: 'editor',
@@ -627,6 +640,21 @@ export const editorMachine = setup({
627
640
  actions: emit(({event}) => event),
628
641
  },
629
642
  },
643
+ initial: 'idle',
644
+ states: {
645
+ 'idle': {
646
+ on: {
647
+ dragstart: {target: 'dragging internally'},
648
+ },
649
+ },
650
+ 'dragging internally': {
651
+ tags: ['dragging internally'],
652
+ on: {
653
+ dragend: {target: 'idle'},
654
+ drop: {target: 'idle'},
655
+ },
656
+ },
657
+ },
630
658
  },
631
659
  },
632
660
  },
@@ -77,5 +77,8 @@ export function getEditorSnapshot({
77
77
  selection: editorActorSnapshot.context.selection,
78
78
  value: getValue({editorActorSnapshot, slateEditorInstance}),
79
79
  },
80
+ beta: {
81
+ hasTag: (tag) => editorActorSnapshot.hasTag(tag),
82
+ },
80
83
  }
81
84
  }
@@ -5,6 +5,7 @@ import {fromSlateValue} from '../internal-utils/values'
5
5
  import {KEY_TO_VALUE_ELEMENT} from '../internal-utils/weakMaps'
6
6
  import type {EditorSelection, PortableTextSlateEditor} from '../types/editor'
7
7
  import type {EditorSchema} from './define-schema'
8
+ import type {HasTag} from './editor-machine'
8
9
  import {getActiveDecorators} from './get-active-decorators'
9
10
 
10
11
  /**
@@ -24,6 +25,13 @@ export type EditorContext = {
24
25
  */
25
26
  export type EditorSnapshot = {
26
27
  context: EditorContext
28
+ /**
29
+ * @beta
30
+ * Do not rely on this externally
31
+ */
32
+ beta: {
33
+ hasTag: HasTag
34
+ }
27
35
  }
28
36
 
29
37
  export function createEditorSnapshot({
@@ -31,11 +39,13 @@ export function createEditorSnapshot({
31
39
  editor,
32
40
  keyGenerator,
33
41
  schema,
42
+ hasTag,
34
43
  }: {
35
44
  converters: Array<Converter>
36
45
  editor: PortableTextSlateEditor
37
46
  keyGenerator: () => string
38
47
  schema: EditorSchema
48
+ hasTag: HasTag
39
49
  }) {
40
50
  const value = fromSlateValue(
41
51
  editor.children,
@@ -58,5 +68,8 @@ export function createEditorSnapshot({
58
68
 
59
69
  return {
60
70
  context,
71
+ beta: {
72
+ hasTag,
73
+ },
61
74
  } satisfies EditorSnapshot
62
75
  }
@@ -0,0 +1,30 @@
1
+ import {useEffect} from 'react'
2
+ import {useEffectEvent} from 'use-effect-event'
3
+ import type {EditorEmittedEvent} from './editor/editor-machine'
4
+ import {useEditor} from './editor/editor-provider'
5
+
6
+ /**
7
+ * @public
8
+ * @deprecated
9
+ * This component has been renamed. Use `EventListenerPlugin` instead.
10
+ *
11
+ * ```
12
+ * import {EventListenerPlugin} from '@portabletext/editor/plugins'
13
+ * ```
14
+ */
15
+ export function EditorEventListener(props: {
16
+ on: (event: EditorEmittedEvent) => void
17
+ }) {
18
+ const editor = useEditor()
19
+ const on = useEffectEvent(props.on)
20
+
21
+ useEffect(() => {
22
+ const subscription = editor.on('*', on)
23
+
24
+ return () => {
25
+ subscription.unsubscribe()
26
+ }
27
+ }, [editor])
28
+
29
+ return null
30
+ }
package/src/index.ts CHANGED
@@ -10,7 +10,6 @@ export type {
10
10
  BehaviorActionIntendSet,
11
11
  BehaviorEvent,
12
12
  BehaviorGuard,
13
- BlockOffset,
14
13
  NativeBehaviorEvent,
15
14
  SyntheticBehaviorEvent,
16
15
  } from './behaviors/index'
@@ -21,11 +20,9 @@ export {
21
20
  type BaseDefinition,
22
21
  type SchemaDefinition,
23
22
  } from './editor/define-schema'
24
- export type {PortableTextMemberSchemaTypes} from './types/editor'
25
23
  export type {EditorSchema} from './editor/define-schema'
26
24
  export {PortableTextEditable} from './editor/Editable'
27
25
  export type {PortableTextEditableProps} from './editor/Editable'
28
- export {EventListenerPlugin as EditorEventListener} from './plugins/plugin.event-listener'
29
26
  export type {
30
27
  EditorEmittedEvent,
31
28
  MutationEvent,
@@ -44,5 +41,8 @@ export {defaultKeyGenerator as keyGenerator} from './editor/key-generator'
44
41
  export type {AddedAnnotationPaths} from './editor/plugins/createWithEditableAPI'
45
42
  export {PortableTextEditor} from './editor/PortableTextEditor'
46
43
  export type {PortableTextEditorProps} from './editor/PortableTextEditor'
44
+ export {EditorEventListener} from './editor-event-listener'
45
+ export type {BlockOffset} from './types/block-offset'
47
46
  export * from './types/editor'
47
+ export type {PortableTextMemberSchemaTypes} from './types/editor'
48
48
  export type {HotkeyOptions} from './types/options'
@@ -0,0 +1,23 @@
1
+ import {compileSchemaDefinition, defineSchema} from '../editor/define-schema'
2
+ import type {EditorSnapshot} from '../selectors'
3
+ import {createTestKeyGenerator} from './test-key-generator'
4
+
5
+ export function createTestSnapshot(snapshot: {
6
+ context?: Partial<EditorSnapshot['context']>
7
+ beta?: Partial<EditorSnapshot['beta']>
8
+ }): EditorSnapshot {
9
+ return {
10
+ context: {
11
+ converters: snapshot.context?.converters ?? [],
12
+ schema:
13
+ snapshot.context?.schema ?? compileSchemaDefinition(defineSchema({})),
14
+ keyGenerator: snapshot.context?.keyGenerator ?? createTestKeyGenerator(),
15
+ activeDecorators: snapshot.context?.activeDecorators ?? [],
16
+ value: snapshot.context?.value ?? [],
17
+ selection: snapshot.context?.selection ?? null,
18
+ },
19
+ beta: {
20
+ hasTag: snapshot.beta?.hasTag ?? (() => false),
21
+ },
22
+ }
23
+ }
@@ -1,12 +1,34 @@
1
- const asteriskPairRegex = '(?<!\\*)\\*(?!\\s)([^*\\n]+?)(?<!\\s)\\*(?!\\*)'
2
- const underscorePairRegex = '(?<!_)_(?!\\s)([^_\\n]+?)(?<!\\s)_(?!_)'
3
- const italicRegex = new RegExp(`(${asteriskPairRegex}|${underscorePairRegex})$`)
1
+ export function createPairRegex(char: string, amount: number) {
2
+ // Negative lookbehind: Ensures that the matched sequence is not preceded by the same character
3
+ const prePrefix = `(?<!\\${char})`
4
+
5
+ // Repeats the character `amount` times
6
+ const prefix = `\\${char}`.repeat(Math.max(amount, 1))
7
+
8
+ // Negative lookahead: Ensures that the opening pair (**, *, etc.) is not followed by a space
9
+ const postPrefix = `(?!\\s)`
10
+
11
+ // Captures the content inside the pair
12
+ const content = `([^${char}\\n]+?)`
13
+
14
+ // Negative lookbehind: Ensures that the content is not followed by a space
15
+ const preSuffix = `(?<!\\s)`
16
+
17
+ // Repeats the character `amount` times
18
+ const suffix = `\\${char}`.repeat(Math.max(amount, 1))
19
+
20
+ // Negative lookahead: Ensures that the matched sequence is not followed by the same character
21
+ const postSuffix = `(?!\\${char})`
22
+
23
+ return `${prePrefix}${prefix}${postPrefix}${content}${preSuffix}${suffix}${postSuffix}`
24
+ }
25
+
26
+ const italicRegex = new RegExp(
27
+ `(${createPairRegex('*', 1)}|${createPairRegex('_', 1)})$`,
28
+ )
4
29
 
5
- const doubleAsteriskPairRegex =
6
- '(?<!\\*)\\*\\*(?!\\s)([^*\\n]+?)(?<!\\s)\\*\\*(?!\\*)'
7
- const doubleUnderscorePairRegex = '(?<!_)__(?!\\s)([^_\\n]+?)(?<!\\s)__(?!_)'
8
30
  const boldRegex = new RegExp(
9
- `(${doubleAsteriskPairRegex}|${doubleUnderscorePairRegex})$`,
31
+ `(${createPairRegex('*', 2)}|${createPairRegex('_', 2)})$`,
10
32
  )
11
33
 
12
34
  export function getTextToItalic(text: string) {