@portabletext/editor 7.10.0 → 7.10.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.js CHANGED
@@ -3,13 +3,13 @@ import { c } from "react/compiler-runtime";
3
3
  import { useSelector, useActorRef } from "@xstate/react";
4
4
  import React, { createContext, useContext, useRef, useEffect, useLayoutEffect, useState, useReducer, useCallback, memo, forwardRef, useMemo, Component, useSyncExternalStore, startTransition } from "react";
5
5
  import { serializePath, isKeyedSegment, getNode, getParent, parentPath, getChildren, getNodeChildren } from "./_chunks-es/get-parent.js";
6
- import { isPath, getLeaf, isRange, isPoint, isObject, isLeafObject, getAncestor, pathContains, getSpan, isBeforePoint, getText, rangeIntersects, getTextBlock, getUnionSchema, getFirstChild, getContainer } from "./_chunks-es/get-container.js";
6
+ import { isPath, getLeaf, isRange, isPoint, isObject, isLeafObject, getAncestor, pathContains, getSpan, isBeforePoint, getText, rangeIntersects, getTextBlock, getFirstChild, getLastChild, getUnionSchema, getContainer } from "./_chunks-es/get-container.js";
7
7
  import { rangeEdges, isTextBlockNode, isBackwardRange, hasNode, getNodes, isAncestorPath, isEditableContainer, getSibling, isInline, isObject as isObject$1, isSpanNode, isBlock, getEnclosingBlock, getAncestors, getPathSubSchema, getBlock, resolveContainerAt, resolveChildEntryIndex, getEnclosingContainer, comparePoints$1 as comparePoints, comparePaths, isAfterPoint } from "./_chunks-es/get-path-sub-schema.js";
8
8
  import { isSpan, isTextBlock, getSubSchema, compileSchema } from "@portabletext/schema";
9
9
  import { defineSchema } from "@portabletext/schema";
10
10
  import scrollIntoView from "scroll-into-view-if-needed";
11
11
  import { createKeyboardShortcut, undo, redo, code, underline, italic as italic$1, bold as bold$1 } from "@portabletext/keyboard-shortcuts";
12
- import { rangesOverlap, getFocusInlineObject, isSelectionCollapsed as isSelectionCollapsed$1, getFocusTextBlock, getFocusSpan, getFragment, isSelectionExpanded, getSelectionStartBlock, getSelectionEndBlock, isOverlappingSelection, getFocusBlock, getSelectedBlocks, isSelectingEntireBlocks, getSelectedValue, isActiveAnnotation, getActiveAnnotationsMarks, getActiveDecorators, getCaretWordSelection, getSelectionStartChild, getSelectionStartPoint, getSelectionEndChild, getSelectionEndPoint, getPreviousSpan, getNextSpan, getFocusBlockObject, getLastBlock, getFirstBlock, isAtTheEndOfBlock, isAtTheStartOfBlock, getRootAcceptedTypes, getMarkState, getFocusListBlock, getNextBlock, getPreviousBlock, getSelectedTextBlocks, isActiveDecorator, getFocusChild, getActiveAnnotations, isActiveListItem, isActiveStyle } from "./_chunks-es/selector.is-at-the-start-of-block.js";
12
+ import { rangesOverlap, getFocusInlineObject, isSelectionCollapsed as isSelectionCollapsed$1, getFocusTextBlock, getFocusSpan, getFragment, isSelectionExpanded, getSelectionStartBlock, getSelectionEndBlock, isOverlappingSelection, getFocusBlock, getSelectedBlocks, isSelectingEntireBlocks, getSelectedValue, isActiveAnnotation, getActiveAnnotationsMarks, getActiveDecorators, getCaretWordSelection, getSelectionStartChild, getSelectionStartPoint, getSelectionEndChild, getSelectionEndPoint, getPreviousSpan, getNextSpan, getFocusBlockObject, isAtTheEndOfBlock, isAtTheStartOfBlock, getLastBlock, getRootAcceptedTypes, getMarkState, getFocusListBlock, getNextBlock, getPreviousBlock, getSelectedTextBlocks, isActiveDecorator, getFocusChild, getActiveAnnotations, isActiveListItem, isActiveStyle } from "./_chunks-es/selector.is-at-the-start-of-block.js";
13
13
  import { isEqualSelectionPoints, blockOffsetToSpanSelectionPoint, getBlockKeyFromSelectionPoint, getBlockEndPoint, getBlockStartPoint, isSelectionCollapsed, defaultKeyGenerator, parseBlocks, parseBlock, isListBlock, getSelectionStartPoint as getSelectionStartPoint$1, getSelectionEndPoint as getSelectionEndPoint$1, parseAnnotation, parseMarkDefs, parseSpan, parseInlineObject } from "./_chunks-es/util.slice-blocks.js";
14
14
  import rawDebug from "debug";
15
15
  import { isEmptyTextBlock, isEqualSelections, getTextBlockText } from "./_chunks-es/util.is-equal-selections.js";
@@ -3900,7 +3900,14 @@ const RestoreDOM = IS_ANDROID ? RestoreDOMComponent : ({
3900
3900
  return;
3901
3901
  }
3902
3902
  leafEl.getBoundingClientRect = domFocusPoint.getBoundingClientRect.bind(domFocusPoint), scrollIntoView(leafEl, {
3903
- scrollMode: "if-needed"
3903
+ scrollMode: "if-needed",
3904
+ // Native-caret semantics: the minimal delta to the nearest edge. The
3905
+ // library's default `block: 'center'` re-centered the viewport on
3906
+ // every sync whose focus was even slightly clipped, yanking the
3907
+ // editor around on programmatic selects (a table handle click whose
3908
+ // rectangle ends in an off-screen column, for example).
3909
+ block: "nearest",
3910
+ inline: "nearest"
3904
3911
  }), delete leafEl.getBoundingClientRect;
3905
3912
  }
3906
3913
  }, isEventHandled = (event, handler) => handler ? handler(event) ?? (event.isDefaultPrevented() || event.isPropagationStopped()) : !1, isDOMEventTargetInput = (event) => isDOMNode(event.target) && (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement), isDOMEventHandled = (event, handler) => handler ? handler(event) ?? event.defaultPrevented : !1, handleNativeHistoryEvents = (editor, editorActor, event) => {
@@ -4127,7 +4134,7 @@ function getEventPosition({
4127
4134
  }
4128
4135
  }
4129
4136
  };
4130
- if (eventPositionBlock && !isEditor(eventNode) && isEditableContainer(editorEngine.snapshot, eventNode, eventPath) && isDragEvent(event))
4137
+ if (eventPositionBlock && !isEditor(eventNode) && isEditableContainer(editorEngine.snapshot, eventNode, eventPath) && (isDragEvent(event) || event.type === "click"))
4131
4138
  return {
4132
4139
  block: eventPositionBlock,
4133
4140
  isEditor: !1,
@@ -7717,6 +7724,15 @@ function transformRangeRef(ref, op, root) {
7717
7724
  });
7718
7725
  ref.current = path2, path2 == null && ref.unref();
7719
7726
  }
7727
+ function splitNodePath(path2) {
7728
+ let nodePathEnd = path2.length;
7729
+ for (; nodePathEnd > 0 && typeof path2[nodePathEnd - 1] == "string"; )
7730
+ nodePathEnd--;
7731
+ return {
7732
+ nodePath: path2.slice(0, nodePathEnd),
7733
+ propertyPath: path2.slice(nodePathEnd)
7734
+ };
7735
+ }
7720
7736
  function findNearestSpans(snapshot, path2) {
7721
7737
  return {
7722
7738
  previousSpan: findPreviousSpan(snapshot, path2),
@@ -7787,10 +7803,7 @@ function lastSpanIn(snapshot, path2) {
7787
7803
  return entry;
7788
7804
  }
7789
7805
  function nodeParentPath(path2) {
7790
- let end2 = path2.length - 1;
7791
- for (; end2 > 0 && typeof path2[end2 - 1] == "string"; )
7792
- end2--;
7793
- return path2.slice(0, end2);
7806
+ return splitNodePath(path2.slice(0, -1)).nodePath;
7794
7807
  }
7795
7808
  function getValue(root, path2) {
7796
7809
  let current = root;
@@ -8021,7 +8034,7 @@ function applyOperation(editor, op) {
8021
8034
  const {
8022
8035
  nodePath: setNodePath,
8023
8036
  propertyPath: setPropertyPath
8024
- } = splitNodeAndPropertyPath(path2);
8037
+ } = splitNodePath(path2);
8025
8038
  if (setNodePath.length === 0)
8026
8039
  break;
8027
8040
  if (setPropertyPath.length === 0) {
@@ -8122,7 +8135,7 @@ function applyOperation(editor, op) {
8122
8135
  const {
8123
8136
  nodePath: unsetNodePath,
8124
8137
  propertyPath: unsetPropertyPath
8125
- } = splitNodeAndPropertyPath(path2);
8138
+ } = splitNodePath(path2);
8126
8139
  if (unsetPropertyPath.length === 0 || unsetNodePath.length === 0)
8127
8140
  break;
8128
8141
  if (!op.inverse && !editor.isProcessingRemoteChanges) {
@@ -8229,26 +8242,6 @@ function resolveBlockIndex(editor, segment) {
8229
8242
  const value = editor.snapshot.context.value, index = editor.blockIndexMap.get(serializePath([segment]));
8230
8243
  return index !== void 0 && value[index]?._key === segment._key ? index : value.findIndex((block) => block._key === segment._key);
8231
8244
  }
8232
- function splitNodeAndPropertyPath(path2) {
8233
- let lastKeyedOrNumericIndex = -1;
8234
- for (let i = path2.length - 1; i >= 0; i--) {
8235
- const segment = path2[i];
8236
- if (isKeyedSegment(segment) || typeof segment == "number") {
8237
- lastKeyedOrNumericIndex = i;
8238
- break;
8239
- }
8240
- }
8241
- if (lastKeyedOrNumericIndex === -1)
8242
- return {
8243
- nodePath: [],
8244
- propertyPath: path2.filter((segment) => typeof segment == "string")
8245
- };
8246
- const nodePath = path2.slice(0, lastKeyedOrNumericIndex + 1), propertyPath = path2.slice(lastKeyedOrNumericIndex + 1).filter((segment) => typeof segment == "string");
8247
- return {
8248
- nodePath,
8249
- propertyPath
8250
- };
8251
- }
8252
8245
  function deepSet(node, propertyPath, value) {
8253
8246
  if (propertyPath.length === 0)
8254
8247
  return node;
@@ -10489,7 +10482,7 @@ function transformBlockIndexMap(map, op, beforeValue, afterValue, context) {
10489
10482
  return;
10490
10483
  }
10491
10484
  if (typeof op.path[op.path.length - 1] == "string") {
10492
- hasKeyedEntries(resolveValueAtPath(beforeValue, op.path)) && reconcileOwnerSubtree(map, context, beforeValue, afterValue, op.path);
10485
+ hasKeyedEntries(getValue(beforeValue, op.path)) && reconcileOwnerSubtree(map, context, beforeValue, afterValue, op.path);
10493
10486
  return;
10494
10487
  }
10495
10488
  const removeIndex = childIndexFromMap(map, beforeValue, op.path);
@@ -10517,7 +10510,7 @@ function transformBlockIndexMap(map, op, beforeValue, afterValue, context) {
10517
10510
  handleKeyChange(map, beforeValue, afterValue, op.path.slice(0, -1), context);
10518
10511
  return;
10519
10512
  }
10520
- (op.value !== null && typeof op.value == "object" || hasKeyedEntries(resolveValueAtPath(beforeValue, op.path))) && reconcileOwnerSubtree(map, context, beforeValue, afterValue, op.path);
10513
+ (op.value !== null && typeof op.value == "object" || hasKeyedEntries(getValue(beforeValue, op.path))) && reconcileOwnerSubtree(map, context, beforeValue, afterValue, op.path);
10521
10514
  return;
10522
10515
  }
10523
10516
  const childIndex = childIndexFromMap(map, beforeValue, op.path);
@@ -10654,33 +10647,14 @@ function resolveIndexableNode(context, value, keyedPath) {
10654
10647
  };
10655
10648
  }
10656
10649
  function reconcileOwnerSubtree(map, context, beforeValue, afterValue, propertyPath) {
10657
- let ownerPathEnd = propertyPath.length;
10658
- for (; ownerPathEnd > 0 && typeof propertyPath[ownerPathEnd - 1] == "string"; )
10659
- ownerPathEnd--;
10660
- if (ownerPathEnd === 0)
10661
- return;
10662
- const ownerPath = propertyPath.slice(0, ownerPathEnd);
10663
- pruneSubtreeAtPath(
10650
+ const ownerPath = splitNodePath(propertyPath).nodePath;
10651
+ ownerPath.length !== 0 && (pruneSubtreeAtPath(
10664
10652
  map,
10665
10653
  beforeValue,
10666
10654
  ownerPath,
10667
10655
  /*keepSelf*/
10668
10656
  !0
10669
- ), addSubtree(map, context, afterValue, ownerPath);
10670
- }
10671
- function resolveValueAtPath(value, path2) {
10672
- let nodePathEnd = path2.length;
10673
- for (; nodePathEnd > 0 && typeof path2[nodePathEnd - 1] == "string"; )
10674
- nodePathEnd--;
10675
- if (nodePathEnd === 0)
10676
- return;
10677
- let current = resolveNodeAtPath(value, path2.slice(0, nodePathEnd));
10678
- for (let i = nodePathEnd; i < path2.length; i++) {
10679
- if (current === null || typeof current != "object")
10680
- return;
10681
- current = current[path2[i]];
10682
- }
10683
- return current;
10657
+ ), addSubtree(map, context, afterValue, ownerPath));
10684
10658
  }
10685
10659
  function hasKeyedEntries(value) {
10686
10660
  return Array.isArray(value) && value.some((entry) => entry !== null && typeof entry == "object" && entry._key !== void 0);
@@ -11309,32 +11283,36 @@ const addAnnotationOnCollapsedSelection = defineBehavior({
11309
11283
  }) => {
11310
11284
  if (snapshot.context.readOnly || snapshot.context.selection && !isSelectionCollapsed$1(snapshot))
11311
11285
  return !1;
11312
- const positionSnapshot = {
11313
- ...snapshot,
11314
- context: {
11315
- ...snapshot.context,
11316
- selection: event.position.selection
11317
- }
11318
- }, focusedBlockObject = getFocusBlockObject(positionSnapshot);
11319
- if (!focusedBlockObject)
11286
+ const focusPath = event.position.selection.focus.path, focusBlock = event.position.isEditor ? focusPath.length >= 1 ? getNode(snapshot, focusPath.slice(0, 1)) : void 0 : event.position.isContainer ? getFirstChild(snapshot, focusPath) : void 0;
11287
+ if (!focusBlock || isTextBlockNode(snapshot.context, focusBlock.node) || event.position.isContainer && !acceptsTextBlock(snapshot, focusBlock.path))
11320
11288
  return !1;
11321
- const previousSibling = getSibling(snapshot, focusedBlockObject.path, {
11289
+ const previousSibling = getSibling(snapshot, focusBlock.path, {
11322
11290
  direction: "previous"
11323
11291
  });
11324
- return (event.position.isEditor || event.position.isContainer) && event.position.block === "start" && !previousSibling;
11292
+ return (event.position.isEditor || event.position.isContainer) && event.position.block === "start" && !previousSibling ? {
11293
+ blockPath: focusBlock.path
11294
+ } : !1;
11325
11295
  },
11326
11296
  actions: [({
11327
- snapshot,
11328
- event
11297
+ snapshot
11298
+ }, {
11299
+ blockPath
11329
11300
  }) => [raise({
11330
- type: "select",
11331
- at: event.position.selection
11332
- }), raise({
11333
11301
  type: "insert.block",
11334
11302
  block: {
11335
11303
  _type: snapshot.context.schema.block.name
11336
11304
  },
11337
11305
  placement: "before",
11306
+ at: {
11307
+ anchor: {
11308
+ path: blockPath,
11309
+ offset: 0
11310
+ },
11311
+ focus: {
11312
+ path: blockPath,
11313
+ offset: 0
11314
+ }
11315
+ },
11338
11316
  select: "start"
11339
11317
  })]]
11340
11318
  }), clickingBelowLonelyBlockObject = defineBehavior({
@@ -11345,35 +11323,44 @@ const addAnnotationOnCollapsedSelection = defineBehavior({
11345
11323
  }) => {
11346
11324
  if (snapshot.context.readOnly || snapshot.context.selection && !isSelectionCollapsed$1(snapshot))
11347
11325
  return !1;
11348
- const positionSnapshot = {
11349
- ...snapshot,
11350
- context: {
11351
- ...snapshot.context,
11352
- selection: event.position.selection
11353
- }
11354
- }, focusedBlockObject = getFocusBlockObject(positionSnapshot);
11355
- if (!focusedBlockObject)
11326
+ const focusPath = event.position.selection.focus.path, focusBlock = event.position.isEditor ? focusPath.length >= 1 ? getNode(snapshot, focusPath.slice(0, 1)) : void 0 : event.position.isContainer ? getLastChild(snapshot, focusPath) : void 0;
11327
+ if (!focusBlock || isTextBlockNode(snapshot.context, focusBlock.node) || event.position.isContainer && !acceptsTextBlock(snapshot, focusBlock.path))
11356
11328
  return !1;
11357
- const nextSibling = getSibling(snapshot, focusedBlockObject.path, {
11329
+ const nextSibling = getSibling(snapshot, focusBlock.path, {
11358
11330
  direction: "next"
11359
11331
  });
11360
- return (event.position.isEditor || event.position.isContainer) && event.position.block === "end" && !nextSibling;
11332
+ return (event.position.isEditor || event.position.isContainer) && event.position.block === "end" && !nextSibling ? {
11333
+ blockPath: focusBlock.path
11334
+ } : !1;
11361
11335
  },
11362
11336
  actions: [({
11363
- snapshot,
11364
- event
11337
+ snapshot
11338
+ }, {
11339
+ blockPath
11365
11340
  }) => [raise({
11366
- type: "select",
11367
- at: event.position.selection
11368
- }), raise({
11369
11341
  type: "insert.block",
11370
11342
  block: {
11371
11343
  _type: snapshot.context.schema.block.name
11372
11344
  },
11373
11345
  placement: "after",
11346
+ at: {
11347
+ anchor: {
11348
+ path: blockPath,
11349
+ offset: 0
11350
+ },
11351
+ focus: {
11352
+ path: blockPath,
11353
+ offset: 0
11354
+ }
11355
+ },
11374
11356
  select: "start"
11375
11357
  })]]
11376
- }), deletingEmptyTextBlockAfterBlockObject = defineBehavior({
11358
+ });
11359
+ function acceptsTextBlock(snapshot, path2) {
11360
+ const enclosing = getEnclosingContainer(snapshot, path2);
11361
+ return !enclosing || enclosing.of.some((member) => member.type === snapshot.context.schema.block.name);
11362
+ }
11363
+ const deletingEmptyTextBlockAfterBlockObject = defineBehavior({
11377
11364
  on: "delete.backward",
11378
11365
  guard: ({
11379
11366
  snapshot
@@ -11459,34 +11446,80 @@ const addAnnotationOnCollapsedSelection = defineBehavior({
11459
11446
  clickingBelowLonelyBlockObject,
11460
11447
  deletingEmptyTextBlockAfterBlockObject,
11461
11448
  deletingEmptyTextBlockBeforeBlockObject
11462
- }, arrowDownOutOfContainer = defineBehavior({
11449
+ }, anyArrowDown = createKeyboardShortcut({
11450
+ default: [{
11451
+ key: "ArrowDown"
11452
+ }]
11453
+ }), anyArrowUp = createKeyboardShortcut({
11454
+ default: [{
11455
+ key: "ArrowUp"
11456
+ }]
11457
+ }), arrowDownOutOfContainer = defineBehavior({
11463
11458
  on: "keyboard.keydown",
11464
11459
  guard: ({
11465
11460
  snapshot,
11466
11461
  event
11467
- }) => event.originEvent.key === "ArrowDown" && isAtContainerDeadEnd(snapshot, "end"),
11468
- actions: []
11462
+ }) => !anyArrowDown.guard(event.originEvent) || !isAtContainerDeadEnd(snapshot, "end") ? !1 : {
11463
+ escapeTarget: arrowEscapeTarget(snapshot, event.originEvent, "end")
11464
+ },
11465
+ actions: [({
11466
+ snapshot
11467
+ }, {
11468
+ escapeTarget
11469
+ }) => escapeTarget ? [escapeAction(snapshot, escapeTarget, "after")] : []]
11469
11470
  }), arrowUpOutOfContainer = defineBehavior({
11470
11471
  on: "keyboard.keydown",
11471
11472
  guard: ({
11472
11473
  snapshot,
11473
11474
  event
11474
- }) => event.originEvent.key === "ArrowUp" && isAtContainerDeadEnd(snapshot, "start"),
11475
- actions: []
11475
+ }) => !anyArrowUp.guard(event.originEvent) || !isAtContainerDeadEnd(snapshot, "start") ? !1 : {
11476
+ escapeTarget: arrowEscapeTarget(snapshot, event.originEvent, "start")
11477
+ },
11478
+ actions: [({
11479
+ snapshot
11480
+ }, {
11481
+ escapeTarget
11482
+ }) => escapeTarget ? [escapeAction(snapshot, escapeTarget, "before")] : []]
11476
11483
  });
11484
+ function arrowEscapeTarget(snapshot, originEvent, edge) {
11485
+ if (!(edge === "end" ? defaultKeyboardShortcuts.arrowDown.guard(originEvent) : defaultKeyboardShortcuts.arrowUp.guard(originEvent)))
11486
+ return;
11487
+ const focusTextBlock = getFocusTextBlock(snapshot);
11488
+ return focusTextBlock ? getEscapeTarget(snapshot, focusTextBlock.path) : void 0;
11489
+ }
11490
+ function escapeAction(snapshot, escapeTarget, placement) {
11491
+ return raise({
11492
+ type: "insert.block",
11493
+ block: createPlaceholderBlock(snapshot, escapeTarget),
11494
+ placement,
11495
+ at: {
11496
+ anchor: {
11497
+ path: escapeTarget,
11498
+ offset: 0
11499
+ },
11500
+ focus: {
11501
+ path: escapeTarget,
11502
+ offset: 0
11503
+ }
11504
+ },
11505
+ select: "start"
11506
+ });
11507
+ }
11477
11508
  function isAtContainerDeadEnd(snapshot, edge) {
11478
11509
  if (!isSelectionCollapsed$1(snapshot))
11479
11510
  return !1;
11480
11511
  const focusTextBlock = getFocusTextBlock(snapshot);
11481
- if (!focusTextBlock)
11482
- return !1;
11483
- const container = getAncestor(snapshot, focusTextBlock.path, {
11512
+ if (!focusTextBlock || !getAncestor(snapshot, focusTextBlock.path, {
11484
11513
  match: (node, path2) => isEditableContainer(snapshot, node, path2)
11485
- });
11486
- if (!container)
11514
+ }))
11515
+ return !1;
11516
+ const rootSegment = focusTextBlock.path[0];
11517
+ if (!rootSegment)
11487
11518
  return !1;
11488
- const edgeBlock = edge === "end" ? getLastBlock(snapshot) : getFirstBlock(snapshot);
11489
- return !edgeBlock || !pathEquals(edgeBlock.path, focusTextBlock.path) || !(edge === "end" ? isAtTheEndOfBlock(focusTextBlock)(snapshot) : isAtTheStartOfBlock(focusTextBlock)(snapshot)) ? !1 : getSibling(snapshot, container.path, {
11519
+ const outerPath = [rootSegment], edgeLeaf = getLeaf(snapshot, outerPath, {
11520
+ edge
11521
+ }), edgeBlock = edgeLeaf && getEnclosingBlock(snapshot, edgeLeaf.path);
11522
+ return !edgeBlock || !pathEquals(edgeBlock.path, focusTextBlock.path) || !(edge === "end" ? isAtTheEndOfBlock(focusTextBlock)(snapshot) : isAtTheStartOfBlock(focusTextBlock)(snapshot)) ? !1 : getSibling(snapshot, outerPath, {
11490
11523
  direction: edge === "end" ? "next" : "previous"
11491
11524
  }) === void 0;
11492
11525
  }
@@ -16900,15 +16933,17 @@ function synthesizeBlockChildrenField(schema) {
16900
16933
  of: ofMembers
16901
16934
  };
16902
16935
  }
16903
- function resolveFieldOn(fields, type, fieldName) {
16936
+ function resolveFieldOn(fields, fieldName) {
16904
16937
  const field = fields.find((candidate) => candidate.name === fieldName);
16905
- if (!(!field || !isChildArrayField(field))) {
16906
- if (containsOnlyPrimitiveTypes(field)) {
16907
- console.warn(`Field '${field.name}' on '${type}' doesn't contain block or container types and will be excluded`);
16908
- return;
16909
- }
16910
- return field;
16911
- }
16938
+ return field ? isChildArrayField(field) ? containsOnlyPrimitiveTypes(field) ? {
16939
+ failure: "field-primitive-only"
16940
+ } : {
16941
+ field
16942
+ } : {
16943
+ failure: "field-not-array"
16944
+ } : {
16945
+ failure: "field-missing"
16946
+ };
16912
16947
  }
16913
16948
  function findInlineDeclarationIn(parentOf, type) {
16914
16949
  for (const member of parentOf)
@@ -16936,28 +16971,35 @@ function findInlineFields(schema, type) {
16936
16971
  isChildArrayField(field) && walk(field.of);
16937
16972
  return best;
16938
16973
  }
16939
- function resolveContainerField(schema, type, fieldName, parentOf) {
16974
+ function resolveContainerFieldResolution(schema, type, fieldName, parentOf) {
16940
16975
  if (type === "block")
16941
- return fieldName !== "children" ? void 0 : synthesizeBlockChildrenField(schema);
16976
+ return fieldName !== "children" ? {
16977
+ failure: "field-missing"
16978
+ } : {
16979
+ field: synthesizeBlockChildrenField(schema)
16980
+ };
16942
16981
  if (parentOf) {
16943
16982
  const inlineMatch = findInlineDeclarationIn(parentOf, type);
16944
16983
  if (inlineMatch)
16945
- return resolveFieldOn(inlineMatch, type, fieldName);
16984
+ return resolveFieldOn(inlineMatch, fieldName);
16946
16985
  }
16947
16986
  const rootMatch = schema.blockObjects.find((blockObject) => blockObject.name === type), rootFields = rootMatch && "fields" in rootMatch && rootMatch.fields && rootMatch.fields.length > 0 ? rootMatch.fields : void 0, inlineFields = rootFields ? void 0 : findInlineFields(schema, type), fields = rootFields ?? inlineFields;
16948
- if (fields)
16949
- return resolveFieldOn(fields, type, fieldName);
16987
+ return fields ? resolveFieldOn(fields, fieldName) : rootMatch ? {
16988
+ failure: "field-missing"
16989
+ } : {
16990
+ failure: "unknown-type"
16991
+ };
16950
16992
  }
16951
16993
  function resolveNestedContainer(schema, container, chain = [], onFailure = "warn", parentOf) {
16952
- const field = resolveContainerField(schema, container.type, container.arrayField, parentOf);
16953
- if (!field) {
16954
- const location = chain.length > 0 ? ` (nested inside ${chain.map((type) => `"${type}"`).join(" inside ")})` : "", message = `registerNode: field "${container.arrayField}" not found on type "${container.type}"${location}. Registration skipped.`;
16994
+ const resolution = resolveContainerFieldResolution(schema, container.type, container.arrayField, parentOf);
16995
+ if ("failure" in resolution) {
16996
+ const location = chain.length > 0 ? ` (nested inside ${chain.map((type) => `"${type}"`).join(" inside ")})` : "", message = `registerNode: ${describeContainerFailure(resolution.failure, container)}${location}. Registration skipped.`;
16955
16997
  if (onFailure === "throw")
16956
16998
  throw new Error(message);
16957
16999
  console.warn(message);
16958
17000
  return;
16959
17001
  }
16960
- const nextChain = [...chain, container.type], resolvedOf = container.of ? container.of.flatMap((entry) => {
17002
+ const field = resolution.field, nextChain = [...chain, container.type], resolvedOf = container.of ? container.of.flatMap((entry) => {
16961
17003
  if (entry.kind === "container") {
16962
17004
  const resolved = resolveNestedContainer(schema, entry, nextChain, onFailure, field.of);
16963
17005
  return resolved ? [resolved] : [];
@@ -16974,6 +17016,18 @@ function resolveNestedContainer(schema, container, chain = [], onFailure = "warn
16974
17016
  } : {}
16975
17017
  };
16976
17018
  }
17019
+ function describeContainerFailure(failure, container) {
17020
+ switch (failure) {
17021
+ case "unknown-type":
17022
+ return `type "${container.type}" not found in the schema`;
17023
+ case "field-missing":
17024
+ return `field "${container.arrayField}" not found on type "${container.type}"`;
17025
+ case "field-not-array":
17026
+ return `field "${container.arrayField}" on type "${container.type}" is not an array`;
17027
+ case "field-primitive-only":
17028
+ return `field "${container.arrayField}" on type "${container.type}" contains only primitive types and cannot hold block content`;
17029
+ }
17030
+ }
16977
17031
  function resolveTextBlockConfig(textBlock) {
16978
17032
  const resolvedOf = textBlock.of ? textBlock.of.flatMap((entry) => entry.kind === "span" ? [{
16979
17033
  span: entry