@blankdotpage/cake 0.1.74 → 0.1.76

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.
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/cake/core/runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/cake/core/runtime.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,7 @@ export function isApplyEditCommand(command) {
19
19
  command.type === "delete-forward");
20
20
  }
21
21
  const defaultSelection = { start: 0, end: 0, affinity: "forward" };
22
+ const WORD_CHARACTER_PATTERN = /[\p{L}\p{N}_]/u;
22
23
  function removeFromArray(arr, value) {
23
24
  const index = arr.indexOf(value);
24
25
  if (index === -1) {
@@ -347,13 +348,17 @@ export function createRuntimeFromRegistry(registry) {
347
348
  }
348
349
  content.push(normalizedInline);
349
350
  }
351
+ const mergedContent = mergeAdjacentInlines(content);
352
+ if (mergedContent !== content) {
353
+ changed = true;
354
+ }
350
355
  if (!changed) {
351
356
  normalizedBlockCache.set(block, next);
352
357
  return next;
353
358
  }
354
359
  const normalized = {
355
360
  ...next,
356
- content,
361
+ content: mergedContent,
357
362
  };
358
363
  normalizedBlockCache.set(block, normalized);
359
364
  return normalized;
@@ -409,17 +414,52 @@ export function createRuntimeFromRegistry(registry) {
409
414
  }
410
415
  let next = pre;
411
416
  if (next.type === "inline-wrapper") {
417
+ const children = mergeAdjacentInlines(next.children
418
+ .map((child) => normalizeInline(child))
419
+ .filter((child) => child !== null));
412
420
  next = {
413
421
  ...next,
414
- children: next.children
415
- .map((child) => normalizeInline(child))
416
- .filter((child) => child !== null),
422
+ children,
417
423
  };
418
424
  }
419
425
  const normalized = applyInlineNormalizers(next);
420
426
  normalizedInlineCache.set(inline, normalized ?? removedInlineSentinel);
421
427
  return normalized;
422
428
  }
429
+ function mergeAdjacentInlines(inlines) {
430
+ if (inlines.length < 2) {
431
+ return inlines;
432
+ }
433
+ const merged = [];
434
+ let changed = false;
435
+ for (const inline of inlines) {
436
+ const previous = merged[merged.length - 1];
437
+ if (previous?.type === "text" && inline.type === "text") {
438
+ merged[merged.length - 1] = {
439
+ ...previous,
440
+ text: previous.text + inline.text,
441
+ };
442
+ changed = true;
443
+ continue;
444
+ }
445
+ if (previous?.type === "inline-wrapper" &&
446
+ inline.type === "inline-wrapper" &&
447
+ previous.kind === inline.kind &&
448
+ stableStringify(previous.data) === stableStringify(inline.data)) {
449
+ merged[merged.length - 1] = {
450
+ ...previous,
451
+ children: mergeAdjacentInlines([
452
+ ...previous.children,
453
+ ...inline.children,
454
+ ]),
455
+ };
456
+ changed = true;
457
+ continue;
458
+ }
459
+ merged.push(inline);
460
+ }
461
+ return changed ? merged : inlines;
462
+ }
423
463
  function createTopLevelBlockSegment(block) {
424
464
  const serialized = serializeBlock(block);
425
465
  return {
@@ -571,9 +611,15 @@ export function createRuntimeFromRegistry(registry) {
571
611
  ? previousSegmented
572
612
  : undefined;
573
613
  const segmented = buildSegmentedDocState(normalized, reusablePrevious);
614
+ const cursorLength = segmented.map.cursorLength;
615
+ const clampedSelection = {
616
+ ...selection,
617
+ start: Math.max(0, Math.min(cursorLength, selection.start)),
618
+ end: Math.max(0, Math.min(cursorLength, selection.end)),
619
+ };
574
620
  return {
575
621
  source: segmented.source,
576
- selection,
622
+ selection: normalizeSelection(clampedSelection),
577
623
  map: segmented.map,
578
624
  doc: normalized,
579
625
  runtime: runtime,
@@ -725,7 +771,8 @@ export function createRuntimeFromRegistry(registry) {
725
771
  previousState: useIncrementalSegmentedDerivation ? state : undefined,
726
772
  });
727
773
  const interimAffinity = structural.nextAffinity ?? "forward";
728
- const caretSource = interim.map.cursorToSource(structural.nextCursor, interimAffinity);
774
+ const interimCursor = Math.max(0, Math.min(interim.map.cursorLength, structural.nextCursor));
775
+ const caretSource = interim.map.cursorToSource(interimCursor, interimAffinity);
729
776
  if (useIncrementalSegmentedDerivation) {
730
777
  const caretCursor = interim.map.sourceToCursor(caretSource, interimAffinity);
731
778
  return {
@@ -812,6 +859,27 @@ export function createRuntimeFromRegistry(registry) {
812
859
  replaceText.length > 0 &&
813
860
  range.start === range.end &&
814
861
  textModel.getGraphemeAtCursor(range.start) === "\u200B";
862
+ if (command.type === "insert" && shouldReplacePlaceholder) {
863
+ const leadingWhitespace = replaceText.match(/^\s+/)?.[0] ?? "";
864
+ const around = marksAroundCursor(doc, range.start);
865
+ if (leadingWhitespace.length > 0) {
866
+ if (isMarksPrefix(around.left, around.right) &&
867
+ around.right.length > around.left.length) {
868
+ const whitespaceInsert = insertTextBeforePendingPlaceholderInDoc(doc, range.start, leadingWhitespace, around.left);
869
+ if (whitespaceInsert) {
870
+ const trailingText = replaceText.slice(leadingWhitespace.length);
871
+ if (trailingText.length === 0) {
872
+ return whitespaceInsert;
873
+ }
874
+ return applyStructuralEdit({ type: "insert", text: trailingText }, whitespaceInsert.doc, {
875
+ start: whitespaceInsert.nextCursor,
876
+ end: whitespaceInsert.nextCursor,
877
+ affinity: whitespaceInsert.nextAffinity,
878
+ });
879
+ }
880
+ }
881
+ }
882
+ }
815
883
  const effectiveRange = shouldReplacePlaceholder
816
884
  ? { start: range.start, end: Math.min(docCursorLength, range.start + 1) }
817
885
  : range;
@@ -1164,6 +1232,28 @@ export function createRuntimeFromRegistry(registry) {
1164
1232
  }
1165
1233
  return true;
1166
1234
  }
1235
+ function removeMarkByKind(marks, kind) {
1236
+ let removed = false;
1237
+ return marks.filter((mark) => {
1238
+ if (!removed && mark.kind === kind) {
1239
+ removed = true;
1240
+ return false;
1241
+ }
1242
+ return true;
1243
+ });
1244
+ }
1245
+ function mergeMarksPreservingOrder(...groups) {
1246
+ const next = [];
1247
+ for (const group of groups) {
1248
+ for (const mark of group) {
1249
+ if (next.some((existing) => existing.key === mark.key)) {
1250
+ continue;
1251
+ }
1252
+ next.push(mark);
1253
+ }
1254
+ }
1255
+ return next;
1256
+ }
1167
1257
  function sliceRuns(runs, startCursor, endCursor) {
1168
1258
  const [left, rest] = splitRunsAt(runs, startCursor);
1169
1259
  const [selected, right] = splitRunsAt(rest, Math.max(0, endCursor - startCursor));
@@ -1272,6 +1362,237 @@ export function createRuntimeFromRegistry(registry) {
1272
1362
  const right = marksAtGraphemeIndex(runs, loc.offsetInLine);
1273
1363
  return { left: left ?? [], right: right ?? [] };
1274
1364
  }
1365
+ function createPendingPlaceholderStateAtCursor(state, cursorOffset, marks) {
1366
+ const textModel = getEditorTextModelForDoc(state.doc);
1367
+ const lines = textModel.getStructuralLines();
1368
+ const loc = textModel.resolveOffsetToLine(cursorOffset);
1369
+ const line = lines[loc.lineIndex];
1370
+ if (!line) {
1371
+ return null;
1372
+ }
1373
+ const block = getBlockAtPath(state.doc.blocks, line.path);
1374
+ if (!block || block.type !== "paragraph") {
1375
+ return null;
1376
+ }
1377
+ const placeholder = "\u200B";
1378
+ const runs = paragraphToRuns(block);
1379
+ const { before, after } = sliceRuns(runs, loc.offsetInLine, loc.offsetInLine);
1380
+ const mergedRuns = normalizeRuns([
1381
+ ...before,
1382
+ { type: "text", text: placeholder, marks },
1383
+ ...after,
1384
+ ]);
1385
+ const nextBlock = {
1386
+ ...block,
1387
+ content: runsToInlines(mergedRuns),
1388
+ };
1389
+ const parentPath = line.path.slice(0, -1);
1390
+ const indexInParent = line.path[line.path.length - 1] ?? 0;
1391
+ const nextDoc = {
1392
+ ...state.doc,
1393
+ blocks: updateBlocksAtPath(state.doc.blocks, parentPath, (blocks) => blocks.map((child, index) => index === indexInParent ? nextBlock : child)),
1394
+ };
1395
+ const next = createStateFromDoc(nextDoc);
1396
+ const sourceHint = state.map.cursorToSource(cursorOffset, "backward");
1397
+ const searchStart = Math.max(0, sourceHint - 4);
1398
+ const placeholderStart = next.source.indexOf(placeholder, searchStart) ?? -1;
1399
+ const resolvedPlaceholderStart = placeholderStart !== -1 ? placeholderStart : next.source.indexOf(placeholder);
1400
+ if (resolvedPlaceholderStart === -1) {
1401
+ return null;
1402
+ }
1403
+ const startCursor = next.map.sourceToCursor(resolvedPlaceholderStart, "forward");
1404
+ return {
1405
+ ...next,
1406
+ selection: {
1407
+ start: startCursor.cursorOffset,
1408
+ end: startCursor.cursorOffset,
1409
+ affinity: "forward",
1410
+ },
1411
+ };
1412
+ }
1413
+ function rewritePendingPlaceholderAtCursor(state, cursorOffset, marks) {
1414
+ const textModel = getEditorTextModelForDoc(state.doc);
1415
+ const lines = textModel.getStructuralLines();
1416
+ const loc = textModel.resolveOffsetToLine(cursorOffset);
1417
+ const line = lines[loc.lineIndex];
1418
+ if (!line) {
1419
+ return null;
1420
+ }
1421
+ const block = getBlockAtPath(state.doc.blocks, line.path);
1422
+ if (!block || block.type !== "paragraph") {
1423
+ return null;
1424
+ }
1425
+ const placeholder = "\u200B";
1426
+ const runs = paragraphToRuns(block);
1427
+ const { before, after } = sliceRuns(runs, loc.offsetInLine, loc.offsetInLine);
1428
+ const replacement = [];
1429
+ const firstAfter = after[0];
1430
+ if (firstAfter?.type === "text" && firstAfter.text.startsWith(placeholder)) {
1431
+ if (marks && marks.length > 0) {
1432
+ replacement.push({ type: "text", text: placeholder, marks });
1433
+ }
1434
+ if (firstAfter.text.length > placeholder.length) {
1435
+ replacement.push({
1436
+ ...firstAfter,
1437
+ text: firstAfter.text.slice(placeholder.length),
1438
+ });
1439
+ }
1440
+ replacement.push(...after.slice(1));
1441
+ }
1442
+ else {
1443
+ const lastBefore = before[before.length - 1];
1444
+ if (lastBefore?.type !== "text" ||
1445
+ !lastBefore.text.endsWith(placeholder)) {
1446
+ return null;
1447
+ }
1448
+ const prefix = lastBefore.text.slice(0, -placeholder.length);
1449
+ if (prefix) {
1450
+ replacement.push({ ...lastBefore, text: prefix });
1451
+ }
1452
+ if (marks && marks.length > 0) {
1453
+ replacement.push({ type: "text", text: placeholder, marks });
1454
+ }
1455
+ replacement.push(...after);
1456
+ before.pop();
1457
+ }
1458
+ const mergedRuns = normalizeRuns([...before, ...replacement]);
1459
+ const nextBlock = {
1460
+ ...block,
1461
+ content: runsToInlines(mergedRuns),
1462
+ };
1463
+ const parentPath = line.path.slice(0, -1);
1464
+ const indexInParent = line.path[line.path.length - 1] ?? 0;
1465
+ const nextDoc = {
1466
+ ...state.doc,
1467
+ blocks: updateBlocksAtPath(state.doc.blocks, parentPath, (blocks) => blocks.map((child, index) => index === indexInParent ? nextBlock : child)),
1468
+ };
1469
+ const next = createStateFromDoc(nextDoc);
1470
+ return {
1471
+ ...next,
1472
+ selection: {
1473
+ start: cursorOffset,
1474
+ end: cursorOffset,
1475
+ affinity: marks && marks.length > 0 ? "forward" : "backward",
1476
+ },
1477
+ };
1478
+ }
1479
+ function updatePendingPlaceholderMarksAtCursor(state, cursorOffset, marks) {
1480
+ return rewritePendingPlaceholderAtCursor(state, cursorOffset, marks);
1481
+ }
1482
+ function removePendingPlaceholderAtCursor(state, cursorOffset) {
1483
+ return rewritePendingPlaceholderAtCursor(state, cursorOffset, null);
1484
+ }
1485
+ function getPendingPlaceholderMarksAtCursor(state, cursorOffset) {
1486
+ const textModel = getEditorTextModelForDoc(state.doc);
1487
+ const lines = textModel.getStructuralLines();
1488
+ const loc = textModel.resolveOffsetToLine(cursorOffset);
1489
+ const line = lines[loc.lineIndex];
1490
+ if (!line) {
1491
+ return null;
1492
+ }
1493
+ const block = getBlockAtPath(state.doc.blocks, line.path);
1494
+ if (!block || block.type !== "paragraph") {
1495
+ return null;
1496
+ }
1497
+ const placeholder = "\u200B";
1498
+ const runs = paragraphToRuns(block);
1499
+ const { before, after } = sliceRuns(runs, loc.offsetInLine, loc.offsetInLine);
1500
+ const firstAfter = after[0];
1501
+ if (firstAfter?.type === "text" && firstAfter.text.startsWith(placeholder)) {
1502
+ return firstAfter.marks;
1503
+ }
1504
+ const lastBefore = before[before.length - 1];
1505
+ if (lastBefore?.type === "text" &&
1506
+ lastBefore.text.endsWith(placeholder)) {
1507
+ return lastBefore.marks;
1508
+ }
1509
+ return null;
1510
+ }
1511
+ function insertTextBeforePendingPlaceholderInDoc(doc, cursorOffset, text, marks) {
1512
+ const textModel = getEditorTextModelForDoc(doc);
1513
+ const lines = textModel.getStructuralLines();
1514
+ const loc = textModel.resolveOffsetToLine(cursorOffset);
1515
+ const line = lines[loc.lineIndex];
1516
+ if (!line) {
1517
+ return null;
1518
+ }
1519
+ const block = getBlockAtPath(doc.blocks, line.path);
1520
+ if (!block || block.type !== "paragraph") {
1521
+ return null;
1522
+ }
1523
+ const placeholder = "\u200B";
1524
+ const runs = paragraphToRuns(block);
1525
+ const { before, after } = sliceRuns(runs, loc.offsetInLine, loc.offsetInLine);
1526
+ const firstAfter = after[0];
1527
+ if (firstAfter?.type !== "text" ||
1528
+ !firstAfter.text.startsWith(placeholder)) {
1529
+ return null;
1530
+ }
1531
+ const mergedRuns = normalizeRuns([
1532
+ ...before,
1533
+ ...(text.length > 0 ? [{ type: "text", text, marks }] : []),
1534
+ firstAfter,
1535
+ ...after.slice(1),
1536
+ ]);
1537
+ const nextBlock = {
1538
+ ...block,
1539
+ content: runsToInlines(mergedRuns),
1540
+ };
1541
+ const parentPath = line.path.slice(0, -1);
1542
+ const indexInParent = line.path[line.path.length - 1] ?? 0;
1543
+ const nextDoc = {
1544
+ ...doc,
1545
+ blocks: updateBlocksAtPath(doc.blocks, parentPath, (blocks) => blocks.map((child, index) => index === indexInParent ? nextBlock : child)),
1546
+ };
1547
+ return {
1548
+ doc: nextDoc,
1549
+ nextCursor: cursorOffset + Array.from(graphemeSegments(text)).length,
1550
+ nextAffinity: "forward",
1551
+ };
1552
+ }
1553
+ function hasInlineMarkerBoundaryBefore(source, markerStart) {
1554
+ if (markerStart <= 0) {
1555
+ return true;
1556
+ }
1557
+ return !WORD_CHARACTER_PATTERN.test(source[markerStart - 1] ?? "");
1558
+ }
1559
+ function pickSafeCollapsedToggleMarkerSpec(params) {
1560
+ const { defaultSpec, source, insertAt, affinity } = params;
1561
+ const candidates = Array.from(toggleMarkerToSpec.values()).filter((spec, index, all) => spec.kind === defaultSpec.kind &&
1562
+ all.findIndex((candidate) => candidate.kind === spec.kind &&
1563
+ candidate.open === spec.open &&
1564
+ candidate.close === spec.close) === index);
1565
+ if (candidates.length <= 1) {
1566
+ return defaultSpec;
1567
+ }
1568
+ const previousChar = source[insertAt - 1] ?? "";
1569
+ const nextChar = source[insertAt] ?? "";
1570
+ let bestSpec = defaultSpec;
1571
+ let bestScore = Number.POSITIVE_INFINITY;
1572
+ for (const spec of candidates) {
1573
+ if (spec.open === "_" &&
1574
+ !hasInlineMarkerBoundaryBefore(source, insertAt)) {
1575
+ continue;
1576
+ }
1577
+ let score = 0;
1578
+ if (previousChar && spec.open[0] === previousChar) {
1579
+ score += affinity === "forward" ? 8 : 3;
1580
+ }
1581
+ if (nextChar &&
1582
+ spec.close[spec.close.length - 1] === nextChar) {
1583
+ score += affinity === "backward" ? 8 : 3;
1584
+ }
1585
+ if (spec.open === defaultSpec.open &&
1586
+ spec.close === defaultSpec.close) {
1587
+ score -= 0.5;
1588
+ }
1589
+ if (score < bestScore) {
1590
+ bestSpec = spec;
1591
+ bestScore = score;
1592
+ }
1593
+ }
1594
+ return bestSpec;
1595
+ }
1275
1596
  function preferredAffinityAtGap(left, right, fallback) {
1276
1597
  if (isMarksPrefix(left, right) && right.length > left.length) {
1277
1598
  return "forward";
@@ -1524,51 +1845,49 @@ export function createRuntimeFromRegistry(registry) {
1524
1845
  const openLen = openMarker.length;
1525
1846
  const closeLen = closeMarker.length;
1526
1847
  const placeholder = "\u200B";
1848
+ const markerMark = {
1849
+ kind: markerKind,
1850
+ data: undefined,
1851
+ key: markKey(markerKind, undefined),
1852
+ };
1527
1853
  if (selection.start === selection.end) {
1528
1854
  const caret = selection.start;
1855
+ const pendingPlaceholderMarks = getPendingPlaceholderMarksAtCursor(state, caret);
1856
+ if (pendingPlaceholderMarks) {
1857
+ const hasMarker = pendingPlaceholderMarks.some((mark) => mark.kind === markerKind);
1858
+ const around = marksAroundCursor(state.doc, caret);
1859
+ const nextMarks = hasMarker
1860
+ ? removeMarkByKind(pendingPlaceholderMarks, markerKind)
1861
+ : mergeMarksPreservingOrder(around.left, pendingPlaceholderMarks, [markerMark]);
1862
+ const next = nextMarks.length > 0
1863
+ ? updatePendingPlaceholderMarksAtCursor(state, caret, nextMarks)
1864
+ : removePendingPlaceholderAtCursor(state, caret);
1865
+ if (next) {
1866
+ return {
1867
+ ...next,
1868
+ selection: {
1869
+ start: caret,
1870
+ end: caret,
1871
+ affinity: "forward",
1872
+ },
1873
+ };
1874
+ }
1875
+ }
1529
1876
  // When the caret is at the end boundary of an inline wrapper, toggling the
1530
1877
  // wrapper should "exit" it (so the next character types outside). This is
1531
1878
  // best expressed in cursor space by flipping affinity to "forward" when we
1532
1879
  // are leaving a wrapper of the requested kind.
1533
1880
  const around = marksAroundCursor(state.doc, caret);
1534
1881
  if (isMarksPrefix(around.right, around.left) &&
1535
- around.left.length > around.right.length) {
1882
+ around.left.length > around.right.length &&
1883
+ (selection.affinity ?? "forward") === "backward") {
1536
1884
  const exiting = around.left.slice(around.right.length);
1537
1885
  if (exiting.some((mark) => mark.kind === markerKind)) {
1538
- const toggledExitingIndex = exiting.findIndex((mark) => mark.kind === markerKind);
1539
- if (exiting.length > 1 &&
1540
- toggledExitingIndex !== -1 &&
1541
- toggledExitingIndex < exiting.length - 1) {
1542
- return {
1543
- ...state,
1544
- selection: {
1545
- start: caret,
1546
- end: caret,
1547
- affinity: "forward",
1548
- },
1549
- };
1550
- }
1551
- if (exiting.length > 1) {
1552
- const insertAtForward = map.cursorToSource(caret, "forward");
1553
- const insertAtBackward = map.cursorToSource(caret, "backward");
1554
- const between = source.slice(insertAtBackward, insertAtForward);
1555
- const markerIndex = between.indexOf(closeMarker);
1556
- if (markerIndex !== -1) {
1557
- const insertAt = insertAtBackward + markerIndex + closeLen;
1558
- const nextSource = source.slice(0, insertAt) +
1559
- placeholder +
1560
- source.slice(insertAt);
1561
- const next = createState(nextSource);
1562
- const placeholderStart = insertAt;
1563
- const startCursor = next.map.sourceToCursor(placeholderStart, "forward");
1564
- return {
1565
- ...next,
1566
- selection: {
1567
- start: startCursor.cursorOffset,
1568
- end: startCursor.cursorOffset,
1569
- affinity: "forward",
1570
- },
1571
- };
1886
+ const remainingMarks = removeMarkByKind(around.left, markerKind);
1887
+ if (!marksEqual(remainingMarks, around.right)) {
1888
+ const next = createPendingPlaceholderStateAtCursor(state, caret, remainingMarks);
1889
+ if (next) {
1890
+ return next;
1572
1891
  }
1573
1892
  }
1574
1893
  return {
@@ -1588,6 +1907,20 @@ export function createRuntimeFromRegistry(registry) {
1588
1907
  around.right.length > around.left.length) {
1589
1908
  const entering = around.right.slice(around.left.length);
1590
1909
  if (entering.some((mark) => mark.kind === markerKind)) {
1910
+ const remainingMarks = removeMarkByKind(around.right, markerKind);
1911
+ const next = remainingMarks.length > 0
1912
+ ? updatePendingPlaceholderMarksAtCursor(state, caret, remainingMarks)
1913
+ : removePendingPlaceholderAtCursor(state, caret);
1914
+ if (next) {
1915
+ return {
1916
+ ...next,
1917
+ selection: {
1918
+ start: caret,
1919
+ end: caret,
1920
+ affinity: "backward",
1921
+ },
1922
+ };
1923
+ }
1591
1924
  const insertAtBackward = map.cursorToSource(caret, "backward");
1592
1925
  const insertAtForward = map.cursorToSource(caret, "forward");
1593
1926
  const after = source.slice(insertAtBackward);
@@ -1646,6 +1979,18 @@ export function createRuntimeFromRegistry(registry) {
1646
1979
  }
1647
1980
  }
1648
1981
  }
1982
+ if (isMarksPrefix(around.right, around.left) &&
1983
+ around.left.length > around.right.length &&
1984
+ (selection.affinity ?? "forward") === "backward" &&
1985
+ !around.left.some((mark) => mark.kind === markerKind)) {
1986
+ const next = createPendingPlaceholderStateAtCursor(state, caret, [
1987
+ ...around.left,
1988
+ markerMark,
1989
+ ]);
1990
+ if (next) {
1991
+ return next;
1992
+ }
1993
+ }
1649
1994
  // Otherwise, insert an empty marker pair with a zero-width placeholder
1650
1995
  // selected so the next typed character replaces it.
1651
1996
  //
@@ -1667,34 +2012,63 @@ export function createRuntimeFromRegistry(registry) {
1667
2012
  return null;
1668
2013
  })();
1669
2014
  // When at a boundary between cursor positions (insertAtBackward !== insertAtForward),
1670
- // prefer insertAtBackward to keep new markers inside the current formatting context.
1671
- // However, only do this if the new marker length is <= the boundary marker length,
1672
- // otherwise we create ambiguous marker sequences (e.g., *italic**​*** doesn't parse).
2015
+ // only prefer insertAtBackward if the caret is intentionally anchored inside the
2016
+ // left formatting context. If the caret affinity is forward, the user explicitly
2017
+ // exited that wrapper and new markers belong on the forward side of the gap.
2018
+ // Still guard against inserting a longer marker into a shorter boundary run,
2019
+ // which would create ambiguous source (e.g., *italic**​***).
1673
2020
  const betweenLen = insertAtForward - insertAtBackward;
1674
- const preferBackward = insertAtBackward !== insertAtForward && openLen <= betweenLen;
2021
+ const preferBackward = insertAtBackward !== insertAtForward &&
2022
+ (selection.affinity ?? "forward") === "backward" &&
2023
+ openLen <= betweenLen;
1675
2024
  const insertAt = placeholderPos ?? (preferBackward ? insertAtBackward : insertAtForward);
2025
+ const insertMarkerSpec = placeholderPos === null
2026
+ ? pickSafeCollapsedToggleMarkerSpec({
2027
+ defaultSpec: markerSpec,
2028
+ source,
2029
+ insertAt,
2030
+ affinity: selection.affinity ?? "forward",
2031
+ })
2032
+ : markerSpec;
2033
+ const insertOpenMarker = insertMarkerSpec.open;
2034
+ const insertCloseMarker = insertMarkerSpec.close;
2035
+ const insertOpenLen = insertOpenMarker.length;
2036
+ const baseMarks = (selection.affinity ?? "forward") === "backward"
2037
+ ? around.left
2038
+ : around.right;
2039
+ const nextMarks = [
2040
+ ...baseMarks.filter((mark) => mark.kind !== markerKind),
2041
+ markerMark,
2042
+ ];
2043
+ if (placeholderPos !== null) {
2044
+ const next = updatePendingPlaceholderMarksAtCursor(state, caret, nextMarks);
2045
+ if (next) {
2046
+ return next;
2047
+ }
2048
+ }
2049
+ const docInserted = createPendingPlaceholderStateAtCursor(state, caret, nextMarks);
2050
+ if (docInserted) {
2051
+ return docInserted;
2052
+ }
1676
2053
  const nextSource = placeholderPos !== null
1677
2054
  ? source.slice(0, insertAt) +
1678
- openMarker +
2055
+ insertOpenMarker +
1679
2056
  placeholder +
1680
- closeMarker +
2057
+ insertCloseMarker +
1681
2058
  source.slice(insertAt + placeholder.length)
1682
2059
  : source.slice(0, insertAt) +
1683
- openMarker +
2060
+ insertOpenMarker +
1684
2061
  placeholder +
1685
- closeMarker +
2062
+ insertCloseMarker +
1686
2063
  source.slice(insertAt);
1687
2064
  const next = createState(nextSource);
1688
- const placeholderStart = insertAt + openLen;
2065
+ const placeholderStart = insertAt + insertOpenLen;
1689
2066
  const startCursor = next.map.sourceToCursor(placeholderStart, "forward");
1690
- return {
1691
- ...next,
1692
- selection: {
1693
- start: startCursor.cursorOffset,
1694
- end: startCursor.cursorOffset,
1695
- affinity: "forward",
1696
- },
1697
- };
2067
+ return createStateFromDoc(next.doc, {
2068
+ start: startCursor.cursorOffset,
2069
+ end: startCursor.cursorOffset,
2070
+ affinity: "forward",
2071
+ });
1698
2072
  }
1699
2073
  const cursorStart = Math.min(selection.start, selection.end);
1700
2074
  const cursorEnd = Math.max(selection.start, selection.end);
@@ -1756,11 +2130,6 @@ export function createRuntimeFromRegistry(registry) {
1756
2130
  const hasTargetMark = visibleRunsForDecision.some((run) => run.marks.some((mark) => mark.kind === markerKind));
1757
2131
  const canUnwrap = hasTargetMark &&
1758
2132
  visibleRunsForDecision.every((run) => run.marks.some((mark) => mark.kind === markerKind));
1759
- const markerMark = {
1760
- kind: markerKind,
1761
- data: undefined,
1762
- key: markKey(markerKind, undefined),
1763
- };
1764
2133
  const removeMark = (marks) => {
1765
2134
  if (!marks.some((mark) => mark.kind === markerKind)) {
1766
2135
  return marks;
@@ -1 +1 @@
1
- {"version":3,"file":"bold.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/bold/bold.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAInB,MAAM,oBAAoB,CAAC;AAS5B,eAAO,MAAM,aAAa,EAAE,aAqI3B,CAAC"}
1
+ {"version":3,"file":"bold.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/bold/bold.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAInB,MAAM,oBAAoB,CAAC;AAU5B,eAAO,MAAM,aAAa,EAAE,aAkJ3B,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { CursorSourceBuilder } from "../../core/mapping/cursor-source-map";
2
+ import { serializeItalicInlineWithMarker } from "../italic/italic";
2
3
  const BOLD_KIND = "bold";
3
4
  export const boldExtension = (editor) => {
4
5
  const disposers = [];
@@ -68,10 +69,20 @@ export const boldExtension = (editor) => {
68
69
  }
69
70
  const builder = new CursorSourceBuilder();
70
71
  builder.appendSourceOnly("**");
71
- for (const child of inline.children) {
72
- const serialized = context.serializeInline(child);
72
+ const defaultChildResults = inline.children.map((child) => context.serializeInline(child));
73
+ let previousSource = "";
74
+ inline.children.forEach((child, index) => {
75
+ const nextSource = defaultChildResults[index + 1]?.source ?? "";
76
+ const serialized = child.type === "inline-wrapper" &&
77
+ child.kind === "italic" &&
78
+ (previousSource.endsWith("*") ||
79
+ nextSource.startsWith("*") ||
80
+ (index === 0 && inline.children.length > 1))
81
+ ? serializeItalicInlineWithMarker(child, context, "_")
82
+ : (defaultChildResults[index] ?? context.serializeInline(child));
73
83
  builder.appendSerialized(serialized);
74
- }
84
+ previousSource = serialized.source;
85
+ });
75
86
  builder.appendSourceOnly("**");
76
87
  return builder.build();
77
88
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"heading.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/heading/heading.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAKnB,MAAM,oBAAoB,CAAC;AAwa5B,eAAO,MAAM,gBAAgB,EAAE,aAwM9B,CAAC"}
1
+ {"version":3,"file":"heading.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/heading/heading.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAKnB,MAAM,oBAAoB,CAAC;AAwa5B,eAAO,MAAM,gBAAgB,EAAE,aA2M9B,CAAC"}
@@ -351,7 +351,7 @@ export const headingExtension = (editor) => {
351
351
  if (selection.start !== selection.end) {
352
352
  return null;
353
353
  }
354
- const cursorPos = selection.start;
354
+ const cursorPos = Math.max(0, Math.min(map.cursorLength, selection.start));
355
355
  const sourcePos = map.cursorToSource(cursorPos, selection.affinity ?? "forward");
356
356
  const lineStart = findLineStartInSource(source, sourcePos);
357
357
  const prefix = source.slice(lineStart, sourcePos);
@@ -1,3 +1,9 @@
1
- import { type CakeExtension } from "../../core/runtime";
1
+ import { type CakeExtension, type SerializeInlineResult } from "../../core/runtime";
2
+ import type { Inline } from "../../core/types";
3
+ export declare function serializeItalicInlineWithMarker(inline: Inline & {
4
+ type: "inline-wrapper";
5
+ }, context: {
6
+ serializeInline: (inline: Inline) => SerializeInlineResult;
7
+ }, marker: "*" | "_"): SerializeInlineResult;
2
8
  export declare const italicExtension: CakeExtension;
3
9
  //# sourceMappingURL=italic.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"italic.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/italic/italic.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAInB,MAAM,oBAAoB,CAAC;AAuC5B,eAAO,MAAM,eAAe,EAAE,aAkI7B,CAAC"}
1
+ {"version":3,"file":"italic.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/italic/italic.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAIlB,KAAK,qBAAqB,EAC3B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAS,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA+BtD,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,EAC3C,OAAO,EAAE;IACP,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,qBAAqB,CAAC;CAC5D,EACD,MAAM,EAAE,GAAG,GAAG,GAAG,GAChB,qBAAqB,CAGvB;AAmGD,eAAO,MAAM,eAAe,EAAE,aAsJ7B,CAAC"}
@@ -1,25 +1,92 @@
1
1
  import { CursorSourceBuilder } from "../../core/mapping/cursor-source-map";
2
2
  import { hasInlineMarkerBoundaryBefore } from "../shared/inline-marker-boundary";
3
3
  const ITALIC_KIND = "italic";
4
+ function buildItalicSerialization(childResults, marker) {
5
+ const builder = new CursorSourceBuilder();
6
+ builder.appendSourceOnly(marker);
7
+ for (const child of childResults) {
8
+ builder.appendSerialized(child);
9
+ }
10
+ builder.appendSourceOnly(marker);
11
+ return builder.build();
12
+ }
13
+ function canParseSerializedUnderscoreRun(source, start, close) {
14
+ return (source[start + 1] === "*" ||
15
+ source[close - 1] === "*" ||
16
+ source[close + 1] === "*");
17
+ }
18
+ export function serializeItalicInlineWithMarker(inline, context, marker) {
19
+ const childResults = inline.children.map((child) => context.serializeInline(child));
20
+ return buildItalicSerialization(childResults, marker);
21
+ }
22
+ function serializeInlineSequenceWithSafeItalic(inlines, context) {
23
+ const builder = new CursorSourceBuilder();
24
+ const defaultResults = inlines.map((inline) => context.serializeInline(inline));
25
+ let previousSource = "";
26
+ inlines.forEach((inline, index) => {
27
+ const nextSource = defaultResults[index + 1]?.source ?? "";
28
+ const serialized = inline.type === "inline-wrapper" &&
29
+ inline.kind === ITALIC_KIND &&
30
+ (previousSource.endsWith("*") || nextSource.startsWith("*"))
31
+ ? serializeItalicInlineWithMarker(inline, context, "_")
32
+ : (defaultResults[index] ?? context.serializeInline(inline));
33
+ builder.appendSerialized(serialized);
34
+ previousSource = serialized.source;
35
+ });
36
+ return builder.build();
37
+ }
4
38
  function findItalicClose(source, start, end, marker) {
5
39
  if (marker === "_") {
6
40
  return source.indexOf("_", start + 1);
7
41
  }
8
- let fallback = -1;
9
42
  for (let i = start + 1; i < end; i += 1) {
10
43
  if (source[i] !== "*") {
11
44
  continue;
12
45
  }
13
- const prevIsStar = source[i - 1] === "*";
14
- const nextIsStar = source[i + 1] === "*";
15
- if (!prevIsStar && !nextIsStar) {
46
+ let runStart = i;
47
+ while (runStart > start + 1 && source[runStart - 1] === "*") {
48
+ runStart -= 1;
49
+ }
50
+ let runEnd = i;
51
+ while (runEnd + 1 < end && source[runEnd + 1] === "*") {
52
+ runEnd += 1;
53
+ }
54
+ const runLength = runEnd - runStart + 1;
55
+ if (runLength === 1) {
56
+ if (hasUnmatchedBoldRun(source, start + 1, i)) {
57
+ continue;
58
+ }
16
59
  return i;
17
60
  }
18
- if (fallback === -1) {
19
- fallback = i;
61
+ const hasUnmatchedBold = hasUnmatchedBoldRun(source, start + 1, runStart);
62
+ const hasBoldCloserAhead = source.indexOf("**", runEnd + 1) !== -1;
63
+ if (!hasBoldCloserAhead) {
64
+ if (runLength === 2 && hasUnmatchedBold) {
65
+ i = runEnd;
66
+ continue;
67
+ }
68
+ if (runLength >= 3 && hasUnmatchedBold) {
69
+ return runEnd;
70
+ }
71
+ return runStart;
20
72
  }
73
+ i = runEnd;
21
74
  }
22
- return fallback;
75
+ return -1;
76
+ }
77
+ function hasUnmatchedBoldRun(source, start, end) {
78
+ let parity = 0;
79
+ for (let i = start; i < end; i += 1) {
80
+ if (source[i] !== "*" || source[i + 1] !== "*") {
81
+ continue;
82
+ }
83
+ if (source[i - 1] === "*" || source[i + 2] === "*") {
84
+ continue;
85
+ }
86
+ parity ^= 1;
87
+ i += 1;
88
+ }
89
+ return parity === 1;
23
90
  }
24
91
  export const italicExtension = (editor) => {
25
92
  const disposers = [];
@@ -45,9 +112,6 @@ export const italicExtension = (editor) => {
45
112
  if (char !== "_" && char !== "*") {
46
113
  return null;
47
114
  }
48
- if (char === "_" && !hasInlineMarkerBoundaryBefore(source, start)) {
49
- return null;
50
- }
51
115
  // Don't match ** (that's bold)
52
116
  if (char === "*" && source[start + 1] === "*") {
53
117
  return null;
@@ -62,6 +126,11 @@ export const italicExtension = (editor) => {
62
126
  if (close === -1 || close >= end) {
63
127
  return null;
64
128
  }
129
+ if (char === "_" &&
130
+ !hasInlineMarkerBoundaryBefore(source, start) &&
131
+ !canParseSerializedUnderscoreRun(source, start, close)) {
132
+ return null;
133
+ }
65
134
  // Don't match empty delimiters like ** that could be start of bold
66
135
  if (close === start + 1 && close + 1 < end) {
67
136
  return null;
@@ -76,21 +145,22 @@ export const italicExtension = (editor) => {
76
145
  nextPos: close + 1,
77
146
  };
78
147
  }));
148
+ disposers.push(editor.registerSerializeBlock((block, context) => {
149
+ if (block.type !== "paragraph") {
150
+ return null;
151
+ }
152
+ return serializeInlineSequenceWithSafeItalic(block.content, context);
153
+ }));
79
154
  disposers.push(editor.registerSerializeInline((inline, context) => {
80
155
  if (inline.type !== "inline-wrapper" || inline.kind !== ITALIC_KIND) {
81
156
  return null;
82
157
  }
83
- const builder = new CursorSourceBuilder();
84
- // Use asterisk for serialization to match v1 behavior
85
- // This prevents issues when typing **bold** where intermediate state
86
- // *world* would get serialized as _world_ causing marker conversion
87
- builder.appendSourceOnly("*");
88
- for (const child of inline.children) {
89
- const serialized = context.serializeInline(child);
90
- builder.appendSerialized(serialized);
91
- }
92
- builder.appendSourceOnly("*");
93
- return builder.build();
158
+ const childResults = inline.children.map((child) => context.serializeInline(child));
159
+ const firstChildSource = childResults[0]?.source ?? "";
160
+ const lastChildSource = childResults[childResults.length - 1]?.source ?? "";
161
+ const useUnderscore = childResults.length > 1 &&
162
+ (firstChildSource.startsWith("*") || lastChildSource.endsWith("*"));
163
+ return buildItalicSerialization(childResults, useUnderscore ? "_" : "*");
94
164
  }));
95
165
  disposers.push(editor.registerNormalizeInline((inline) => {
96
166
  if (inline.type !== "inline-wrapper" || inline.kind !== ITALIC_KIND) {
@@ -66,6 +66,7 @@ export interface CakeEditorRef {
66
66
  getSelection: () => {
67
67
  start: number;
68
68
  end: number;
69
+ affinity?: "backward" | "forward";
69
70
  } | null;
70
71
  getCursorLength: () => number;
71
72
  insertText: (text: string) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cake/react/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cake/react/index.tsx"],"names":[],"mappings":"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"}
@@ -216,7 +216,11 @@ export const CakeEditor = forwardRef(function CakeEditor(props, outerRef) {
216
216
  if (!selection) {
217
217
  return null;
218
218
  }
219
- return { start: selection.start, end: selection.end };
219
+ return {
220
+ start: selection.start,
221
+ end: selection.end,
222
+ affinity: selection.affinity,
223
+ };
220
224
  },
221
225
  getText: () => engineRef.current?.getText() ?? "",
222
226
  getTextSelection: () => engineRef.current?.getTextSelection() ?? { start: 0, end: 0 },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blankdotpage/cake",
3
- "version": "0.1.74",
3
+ "version": "0.1.76",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",