Skip to content

Commit c0a22cf

Browse files
committed
build: first round of blast radius
1 parent 011985b commit c0a22cf

58 files changed

Lines changed: 84 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/core/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ const mergeBlocks = (
177177
}
178178

179179
// Save suggestion node content before reconstruction
180+
// drops prev suggestionBefore and next suggestionAfter on merge
180181
const savedPrevSuggAfter = currentPrevInfo.suggestionAfter
181182
? currentPrevInfo.suggestionAfter.node.copy(
182183
currentPrevInfo.suggestionAfter.node.content,
@@ -236,6 +237,7 @@ const mergeBlocks = (
236237
}
237238

238239
// Create the new blockContainer with the prev block's ID and attributes
240+
// create() skips validation; bad child order ships silently
239241
const newBlockContainer = currentPrevInfo.bnBlock.node.type.create(
240242
currentPrevInfo.bnBlock.node.attrs,
241243
newChildren,

packages/core/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ function updateBlockSelectionFromData(
106106
anchorBlockPos + data.headCellOffset,
107107
);
108108
} else if (data.type === "node") {
109+
// +1 assumes blockContent is first child; may be a leading suggestion node
109110
selection = NodeSelection.create(tr.doc, anchorBlockPos + 1);
110111
} else {
111112
const headBlockPos = getNodeById(data.headBlockId, tr.doc)?.posBeforeNode;

packages/core/src/api/blockManipulation/commands/nestBlock/nestBlock.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ function sinkItem(
3939
if (nodeBefore.type !== itemType) {
4040
return false;
4141
}
42+
// lastChild may be a trailing suggestion node, not blockGroup
4243
const nestedBefore =
4344
nodeBefore.lastChild && nodeBefore.lastChild.type === groupType; // change 2
4445
const inner = Fragment.from(nestedBefore ? itemType.create() : null);
@@ -102,6 +103,7 @@ function liftToOuterList(
102103
// There are siblings after the lifted items, which must become
103104
// children of the last item
104105
const blockBeingLifted = range.parent.child(range.endIndex - 1);
106+
// lastChild may be a trailing suggestion node, not blockGroup
105107
const nestedAfter =
106108
blockBeingLifted.lastChild &&
107109
blockBeingLifted.lastChild.type === groupType; // change 2

packages/core/src/api/blockManipulation/commands/replaceBlocks/util/fixColumnList.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export function isEmptyColumn(column: Node) {
1818
throw new Error("Invalid column: does not have child node.");
1919
}
2020

21+
// firstChild may be a suggestion node; childCount===1 below assumes no suggestions
2122
const blockContent = blockContainer.firstChild;
2223
if (!blockContent) {
2324
throw new Error("Invalid blockContainer: does not have child node.");

packages/core/src/api/blockManipulation/commands/splitBlock/splitBlock.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const splitBlockTr = (
4747
// with the first block and the split happens at the blockContent boundary.
4848
let effectivePos = posInBlock;
4949
const $pos = tr.doc.resolve(posInBlock);
50+
// dead guard — group is compound "suggestionBlockContent blockContent", never ===
5051
if ($pos.parent.type.spec.group === "suggestionBlockContent") {
5152
effectivePos = info.blockContent.beforePos + 1;
5253
}

packages/core/src/api/blockManipulation/commands/updateBlock/updateBlock.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ export function updateBlockTr<
127127
// currently, we calculate the new node and replace the entire node with the desired new node.
128128
// for this, we do a nodeToBlock on the existing block to get the children.
129129
// it would be cleaner to use a ReplaceAroundStep, but this is a bit simpler and it's quite an edge case
130+
// nodeToBlock→blockToNode round-trip drops suggestion nodes
130131
const existingBlock = nodeToBlock(blockInfo.bnBlock.node, pmSchema);
131132
const replacementNode = blockToNode(
132133
{
@@ -302,6 +303,7 @@ function updateChildren<
302303
throw new Error("impossible");
303304
}
304305
// Inserts a new blockGroup containing the child nodes created earlier.
306+
// inserts blockGroup before trailing suggestion, invalid content order
305307
tr.insert(
306308
blockInfo.blockContent.afterPos,
307309
pmSchema.nodes["blockGroup"].createChecked({}, childNodes),

packages/core/src/api/blockManipulation/getBlock/getBlock.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export function getBlock<
2222
typeof blockIdentifier === "string" ? blockIdentifier : blockIdentifier.id;
2323
const pmSchema = getPmSchema(doc);
2424

25+
// suggested-deleted blocks resolve as live, no deletion flag
2526
const posInfo = getNodeById(id, doc);
2627
if (!posInfo) {
2728
return undefined;

packages/core/src/api/clipboard/toClipboard/copyExtension.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ function fragmentToExternalHTML<
5050
(child) =>
5151
child.type.isInGroup("bnBlock") ||
5252
child.type.name === "blockGroup" ||
53+
// === "blockContent" misclassifies suggestion nodes (compound group)
5354
child.type.spec.group === "blockContent",
5455
) === undefined;
5556
if (isWithinBlockContent) {
@@ -118,16 +119,19 @@ export function selectedFragmentToHTML<
118119
// selected, e.g. an image block.
119120
if (
120121
"node" in view.state.selection &&
122+
// === "blockContent" misclassifies suggestion nodes (compound group)
121123
(view.state.selection.node as Node).type.spec.group === "blockContent"
122124
) {
123125
editor.transact((tr) =>
126+
// from-1 block expansion assumes blockContent adjacency; off with leading suggestion node
124127
tr.setSelection(
125128
new NodeSelection(tr.doc.resolve(view.state.selection.from - 1)),
126129
),
127130
);
128131
}
129132

130133
// Uses default ProseMirror clipboard serialization.
134+
// serializeForClipboard emits shadow nodes; paste re-creates them
131135
const clipboardHTML: string = view.serializeForClipboard(
132136
view.state.selection.content(),
133137
).dom.innerHTML;
@@ -268,6 +272,7 @@ export const createCopyToClipboardExtension = <
268272

269273
// Expands the selection to the parent `blockContainer` node.
270274
editor.transact((tr) =>
275+
// from-1 block expansion assumes blockContent adjacency; off with leading suggestion node
271276
tr.setSelection(
272277
new NodeSelection(
273278
tr.doc.resolve(view.state.selection.from - 1),

packages/core/src/api/exporters/markdown/htmlToMarkdown.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ function serializeChildren(node: Node, ctx: SerializeContext): string {
4545
}
4646

4747
function serializeNode(node: Node, ctx: SerializeContext): string {
48+
// no data-suggestion handling; shadow text duplicated to markdown
4849
if (node.nodeType === 3 /* Node.TEXT_NODE */) {
4950
return node.textContent || "";
5051
}

packages/core/src/api/getBlockInfoFromPos.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ export function getBlockInfoWithManualOffset(
191191
afterPos: suggestionAfterPos,
192192
};
193193

194+
// singular suggestionBefore/After, schema allows suggestionBlockContent*
194195
if (!foundBlockContent) {
195196
suggestionBefore = info;
196197
} else {

0 commit comments

Comments
 (0)