@portabletext/editor 1.12.0 → 1.12.2

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/lib/index.d.mts CHANGED
@@ -123,7 +123,7 @@ export declare type BehaviorActionIntend =
123
123
  | BehaviorEvent
124
124
  | {
125
125
  type: 'insert block object'
126
- placement: 'auto' | 'after'
126
+ placement: 'auto' | 'after' | 'before'
127
127
  blockObject: {
128
128
  name: string
129
129
  value?: {
@@ -144,7 +144,7 @@ export declare type BehaviorActionIntend =
144
144
  }
145
145
  | {
146
146
  type: 'insert text block'
147
- placement: 'auto' | 'after'
147
+ placement: 'auto' | 'after' | 'before'
148
148
  textBlock?: {
149
149
  children?: PortableTextTextBlock['children']
150
150
  }
package/lib/index.d.ts CHANGED
@@ -123,7 +123,7 @@ export declare type BehaviorActionIntend =
123
123
  | BehaviorEvent
124
124
  | {
125
125
  type: 'insert block object'
126
- placement: 'auto' | 'after'
126
+ placement: 'auto' | 'after' | 'before'
127
127
  blockObject: {
128
128
  name: string
129
129
  value?: {
@@ -144,7 +144,7 @@ export declare type BehaviorActionIntend =
144
144
  }
145
145
  | {
146
146
  type: 'insert text block'
147
- placement: 'auto' | 'after'
147
+ placement: 'auto' | 'after' | 'before'
148
148
  textBlock?: {
149
149
  children?: PortableTextTextBlock['children']
150
150
  }
package/lib/index.esm.js CHANGED
@@ -364,21 +364,6 @@ function looksLikeUrl(text) {
364
364
  }
365
365
  return looksLikeUrl2;
366
366
  }
367
- function isPortableTextSpan(node) {
368
- return node._type === "span" && "text" in node && typeof node.text == "string" && (typeof node.marks > "u" || Array.isArray(node.marks) && node.marks.every((mark) => typeof mark == "string"));
369
- }
370
- function isPortableTextBlock(node) {
371
- return (
372
- // A block doesn't _have_ to be named 'block' - to differentiate between
373
- // allowed child types and marks, one might name them differently
374
- typeof node._type == "string" && // Toolkit-types like nested spans are @-prefixed
375
- node._type[0] !== "@" && // `markDefs` isn't _required_ per say, but if it's there, it needs to be an array
376
- (!("markDefs" in node) || !node.markDefs || Array.isArray(node.markDefs) && // Every mark definition needs to have an `_key` to be mappable in child spans
377
- node.markDefs.every((def) => typeof def._key == "string")) && // `children` is required and needs to be an array
378
- "children" in node && Array.isArray(node.children) && // All children are objects with `_type` (usually spans, but can contain other stuff)
379
- node.children.every((child) => typeof child == "object" && "_type" in child)
380
- );
381
- }
382
367
  function blockOffsetToSpanSelectionPoint({
383
368
  value,
384
369
  blockOffset
@@ -431,6 +416,87 @@ function spanSelectionPointToBlockOffset({
431
416
  }
432
417
  }
433
418
  }
419
+ function isKeyedSegment$1(segment) {
420
+ return typeof segment == "object" && segment !== null && "_key" in segment;
421
+ }
422
+ function reverseSelection(selection) {
423
+ return selection && (selection.backward ? {
424
+ anchor: selection.focus,
425
+ focus: selection.anchor,
426
+ backward: !1
427
+ } : {
428
+ anchor: selection.focus,
429
+ focus: selection.anchor,
430
+ backward: !0
431
+ });
432
+ }
433
+ function getSelectionText({
434
+ value,
435
+ selection
436
+ }) {
437
+ let text = "";
438
+ if (!value || !selection)
439
+ return text;
440
+ const forwardSelection = selection.backward ? reverseSelection(selection) : selection;
441
+ if (!forwardSelection)
442
+ return text;
443
+ for (const block of value)
444
+ if (!(isKeyedSegment$1(forwardSelection.anchor.path[0]) && block._key !== forwardSelection.anchor.path[0]._key) && isPortableTextTextBlock(block)) {
445
+ for (const child of block.children)
446
+ if (isPortableTextSpan$1(child)) {
447
+ if (isKeyedSegment$1(forwardSelection.anchor.path[2]) && child._key === forwardSelection.anchor.path[2]._key && isKeyedSegment$1(forwardSelection.focus.path[2]) && child._key === forwardSelection.focus.path[2]._key) {
448
+ text = text + child.text.slice(forwardSelection.anchor.offset, forwardSelection.focus.offset);
449
+ break;
450
+ }
451
+ if (isKeyedSegment$1(forwardSelection.anchor.path[2]) && child._key === forwardSelection.anchor.path[2]._key) {
452
+ text = text + child.text.slice(forwardSelection.anchor.offset);
453
+ continue;
454
+ }
455
+ if (isKeyedSegment$1(forwardSelection.focus.path[2]) && child._key === forwardSelection.focus.path[2]._key) {
456
+ text = text + child.text.slice(0, forwardSelection.focus.offset);
457
+ break;
458
+ }
459
+ }
460
+ if (isKeyedSegment$1(forwardSelection.focus.path[0]) && block._key === forwardSelection.focus.path[0]._key)
461
+ break;
462
+ }
463
+ return text;
464
+ }
465
+ function getStartPoint({
466
+ node,
467
+ path
468
+ }) {
469
+ return isPortableTextTextBlock(node) ? {
470
+ path: [...path, "children", {
471
+ _key: node.children[0]._key
472
+ }],
473
+ offset: 0
474
+ } : {
475
+ path,
476
+ offset: 0
477
+ };
478
+ }
479
+ function getBlockTextBefore({
480
+ value,
481
+ point
482
+ }) {
483
+ const key = isKeyedSegment$1(point.path[0]) ? point.path[0]._key : void 0, block = key ? value.find((block2) => block2._key === key) : void 0;
484
+ if (!block)
485
+ return "";
486
+ const startPoint = getStartPoint({
487
+ node: block,
488
+ path: [{
489
+ _key: block._key
490
+ }]
491
+ });
492
+ return getSelectionText({
493
+ value,
494
+ selection: {
495
+ anchor: startPoint,
496
+ focus: point
497
+ }
498
+ });
499
+ }
434
500
  function createMarkdownBehaviors(config) {
435
501
  const automaticBlockquoteOnSpace = {
436
502
  on: "insert text",
@@ -503,11 +569,24 @@ function createMarkdownBehaviors(config) {
503
569
  }), focusBlock = getFocusTextBlock(context), selectionCollapsed = selectionIsCollapsed(context);
504
570
  if (!hrObject || !focusBlock || !selectionCollapsed)
505
571
  return !1;
506
- const onlyText = focusBlock.node.children.every(isPortableTextSpan), blockText = focusBlock.node.children.map((child) => child.text ?? "").join("");
507
- return onlyText && blockText === `${hrCharacter}${hrCharacter}` ? {
572
+ const textBefore = getBlockTextBefore({
573
+ value: context.value,
574
+ point: context.selection.focus
575
+ }), hrBlockOffsets = {
576
+ anchor: {
577
+ path: focusBlock.path,
578
+ offset: 0
579
+ },
580
+ focus: {
581
+ path: focusBlock.path,
582
+ offset: 3
583
+ }
584
+ };
585
+ return textBefore === `${hrCharacter}${hrCharacter}` ? {
508
586
  hrObject,
509
587
  focusBlock,
510
- hrCharacter
588
+ hrCharacter,
589
+ hrBlockOffsets
511
590
  } : !1;
512
591
  },
513
592
  actions: [(_, {
@@ -517,17 +596,14 @@ function createMarkdownBehaviors(config) {
517
596
  text: hrCharacter
518
597
  }], (_, {
519
598
  hrObject,
520
- focusBlock
599
+ hrBlockOffsets
521
600
  }) => [{
522
601
  type: "insert block object",
523
- placement: "after",
602
+ placement: "before",
524
603
  blockObject: hrObject
525
604
  }, {
526
- type: "delete block",
527
- blockPath: focusBlock.path
528
- }, {
529
- type: "insert text block",
530
- placement: "after"
605
+ type: "delete text",
606
+ ...hrBlockOffsets
531
607
  }]]
532
608
  }, automaticHrOnPaste = {
533
609
  on: "paste",
@@ -693,9 +769,9 @@ function createMarkdownBehaviors(config) {
693
769
  listItemLength: 1,
694
770
  style: defaultStyle
695
771
  };
696
- const looksLikeOrderedList = /^1./.test(focusSpan.node.text), orderedListStyle = config.orderedListStyle?.({
772
+ const looksLikeOrderedList = /^1\./.test(blockText), orderedListStyle = config.orderedListStyle?.({
697
773
  schema: context.schema
698
- }), caretAtTheEndOfOrderedList = context.selection.focus.offset === 2;
774
+ }), caretAtTheEndOfOrderedList = blockOffset.offset === 2;
699
775
  return defaultStyle && caretAtTheEndOfOrderedList && looksLikeOrderedList && orderedListStyle !== void 0 ? {
700
776
  focusTextBlock,
701
777
  listItem: orderedListStyle,
@@ -4127,6 +4203,21 @@ function createWithPortableTextLists(types) {
4127
4203
  }, editor;
4128
4204
  };
4129
4205
  }
4206
+ function isPortableTextSpan(node) {
4207
+ return node._type === "span" && "text" in node && typeof node.text == "string" && (typeof node.marks > "u" || Array.isArray(node.marks) && node.marks.every((mark) => typeof mark == "string"));
4208
+ }
4209
+ function isPortableTextBlock(node) {
4210
+ return (
4211
+ // A block doesn't _have_ to be named 'block' - to differentiate between
4212
+ // allowed child types and marks, one might name them differently
4213
+ typeof node._type == "string" && // Toolkit-types like nested spans are @-prefixed
4214
+ node._type[0] !== "@" && // `markDefs` isn't _required_ per say, but if it's there, it needs to be an array
4215
+ (!("markDefs" in node) || !node.markDefs || Array.isArray(node.markDefs) && // Every mark definition needs to have an `_key` to be mappable in child spans
4216
+ node.markDefs.every((def) => typeof def._key == "string")) && // `children` is required and needs to be an array
4217
+ "children" in node && Array.isArray(node.children) && // All children are objects with `_type` (usually spans, but can contain other stuff)
4218
+ node.children.every((child) => typeof child == "object" && "_type" in child)
4219
+ );
4220
+ }
4130
4221
  function getPreviousSpan({
4131
4222
  editor,
4132
4223
  blockPath,
@@ -4852,8 +4943,9 @@ function insertBlock({
4852
4943
  offset: 0
4853
4944
  }
4854
4945
  });
4855
- } else
4856
- Editor.insertNode(editor, block);
4946
+ } else placement === "before" ? Transforms.insertNodes(editor, block, {
4947
+ at: focusBlockPath
4948
+ }) : Editor.insertNode(editor, block);
4857
4949
  focusBlock && isEqualToEmptyEditor([focusBlock], schema) && Transforms.removeNodes(editor, {
4858
4950
  at: focusBlockPath
4859
4951
  });