@blankdotpage/cake 0.1.7 → 0.1.8
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/dist/cake/core/runtime.d.ts +2 -0
- package/dist/index.cjs +61 -8
- package/dist/index.js +61 -8
- package/package.json +1 -1
|
@@ -46,6 +46,8 @@ export type InsertCommand = {
|
|
|
46
46
|
/** Commands that can be applied directly by the engine */
|
|
47
47
|
export type ApplyEditCommand = InsertCommand | {
|
|
48
48
|
type: "insert-line-break";
|
|
49
|
+
} | {
|
|
50
|
+
type: "insert-hard-line-break";
|
|
49
51
|
} | {
|
|
50
52
|
type: "delete-backward";
|
|
51
53
|
} | {
|
package/dist/index.cjs
CHANGED
|
@@ -1078,10 +1078,10 @@ class CursorSourceBuilder {
|
|
|
1078
1078
|
}
|
|
1079
1079
|
}
|
|
1080
1080
|
function isStructuralEdit(command) {
|
|
1081
|
-
return command.type === "insert" || command.type === "delete-backward" || command.type === "delete-forward" || command.type === "insert-line-break" || command.type === "exit-block-wrapper";
|
|
1081
|
+
return command.type === "insert" || command.type === "delete-backward" || command.type === "delete-forward" || command.type === "insert-line-break" || command.type === "insert-hard-line-break" || command.type === "exit-block-wrapper";
|
|
1082
1082
|
}
|
|
1083
1083
|
function isApplyEditCommand(command) {
|
|
1084
|
-
return command.type === "insert" || command.type === "insert-line-break" || command.type === "delete-backward" || command.type === "delete-forward";
|
|
1084
|
+
return command.type === "insert" || command.type === "insert-line-break" || command.type === "insert-hard-line-break" || command.type === "delete-backward" || command.type === "delete-forward";
|
|
1085
1085
|
}
|
|
1086
1086
|
function defineExtension(extension) {
|
|
1087
1087
|
return extension;
|
|
@@ -1462,7 +1462,7 @@ function createRuntime(extensions) {
|
|
|
1462
1462
|
nextAffinity: affinity === "backward" ? "forward" : "forward"
|
|
1463
1463
|
};
|
|
1464
1464
|
}
|
|
1465
|
-
const replaceText = command.type === "insert" ? command.text : command.type === "insert-line-break" ? "\n" : command.type === "exit-block-wrapper" ? "\n" : "";
|
|
1465
|
+
const replaceText = command.type === "insert" ? command.text : command.type === "insert-line-break" || command.type === "insert-hard-line-break" ? "\n" : command.type === "exit-block-wrapper" ? "\n" : "";
|
|
1466
1466
|
const range = command.type === "delete-backward" && cursorStart === cursorEnd ? cursorStart === 0 ? { start: 0, end: 0 } : { start: cursorStart - 1, end: cursorStart } : command.type === "delete-forward" && cursorStart === cursorEnd ? cursorStart === docCursorLength ? { start: cursorStart, end: cursorStart } : { start: cursorStart, end: cursorStart + 1 } : { start: cursorStart, end: cursorEnd };
|
|
1467
1467
|
const shouldReplacePlaceholder = command.type === "insert" && replaceText.length > 0 && range.start === range.end && graphemeAtCursor(lines, range.start) === "";
|
|
1468
1468
|
const effectiveRange = shouldReplacePlaceholder ? { start: range.start, end: Math.min(docCursorLength, range.start + 1) } : range;
|
|
@@ -4310,6 +4310,41 @@ function findLineStartInSource$1(source, sourceOffset) {
|
|
|
4310
4310
|
}
|
|
4311
4311
|
return lineStart;
|
|
4312
4312
|
}
|
|
4313
|
+
function isInsideBlockquote(source, sourcePos) {
|
|
4314
|
+
const lineStart = findLineStartInSource$1(source, sourcePos);
|
|
4315
|
+
const lineContent = source.slice(
|
|
4316
|
+
lineStart,
|
|
4317
|
+
source.indexOf("\n", lineStart) === -1 ? source.length : source.indexOf("\n", lineStart)
|
|
4318
|
+
);
|
|
4319
|
+
return BLOCKQUOTE_PATTERN.test(lineContent);
|
|
4320
|
+
}
|
|
4321
|
+
function handleExitBlockquote(state) {
|
|
4322
|
+
const { source, selection, map, runtime } = state;
|
|
4323
|
+
const cursorPos = Math.min(selection.start, selection.end);
|
|
4324
|
+
const sourcePos = map.cursorToSource(
|
|
4325
|
+
cursorPos,
|
|
4326
|
+
selection.affinity ?? "forward"
|
|
4327
|
+
);
|
|
4328
|
+
if (!isInsideBlockquote(source, sourcePos)) {
|
|
4329
|
+
return null;
|
|
4330
|
+
}
|
|
4331
|
+
let lineEnd = source.indexOf("\n", sourcePos);
|
|
4332
|
+
if (lineEnd === -1) {
|
|
4333
|
+
lineEnd = source.length;
|
|
4334
|
+
}
|
|
4335
|
+
const newSource = source.slice(0, lineEnd) + "\n" + source.slice(lineEnd);
|
|
4336
|
+
const next = runtime.createState(newSource);
|
|
4337
|
+
const newCursorOffset = lineEnd + 1;
|
|
4338
|
+
const caretCursor = next.map.sourceToCursor(newCursorOffset, "forward");
|
|
4339
|
+
return {
|
|
4340
|
+
source: newSource,
|
|
4341
|
+
selection: {
|
|
4342
|
+
start: caretCursor.cursorOffset,
|
|
4343
|
+
end: caretCursor.cursorOffset,
|
|
4344
|
+
affinity: "forward"
|
|
4345
|
+
}
|
|
4346
|
+
};
|
|
4347
|
+
}
|
|
4313
4348
|
function handleToggleBlockquote(state) {
|
|
4314
4349
|
const { source, selection, map, runtime } = state;
|
|
4315
4350
|
const cursorPos = Math.min(selection.start, selection.end);
|
|
@@ -4355,6 +4390,9 @@ const blockquoteExtension = defineExtension({
|
|
|
4355
4390
|
if (command.type === "toggle-blockquote") {
|
|
4356
4391
|
return handleToggleBlockquote(state);
|
|
4357
4392
|
}
|
|
4393
|
+
if (command.type === "insert-hard-line-break") {
|
|
4394
|
+
return handleExitBlockquote(state);
|
|
4395
|
+
}
|
|
4358
4396
|
return null;
|
|
4359
4397
|
},
|
|
4360
4398
|
parseBlock(source, start, context) {
|
|
@@ -6808,6 +6846,21 @@ function hitTestFromLayout(params) {
|
|
|
6808
6846
|
const caretX = (cursorOffsetInLine) => {
|
|
6809
6847
|
return measureCaretXOnRow(cursorOffsetInLine) ?? approximateX(cursorOffsetInLine);
|
|
6810
6848
|
};
|
|
6849
|
+
const rowLeftEdge = row.rect.left;
|
|
6850
|
+
const rowRightEdge = row.rect.left + row.rect.width;
|
|
6851
|
+
if (relativeX < rowLeftEdge) {
|
|
6852
|
+
return {
|
|
6853
|
+
cursorOffset: lineStartOffset + row.startOffset,
|
|
6854
|
+
pastRowEnd: false
|
|
6855
|
+
};
|
|
6856
|
+
}
|
|
6857
|
+
if (relativeX > rowRightEdge) {
|
|
6858
|
+
const isEndOfLine2 = row.endOffset === lineInfo.cursorLength;
|
|
6859
|
+
return {
|
|
6860
|
+
cursorOffset: lineStartOffset + row.endOffset,
|
|
6861
|
+
pastRowEnd: !isEndOfLine2 && row.endOffset < lineInfo.cursorLength
|
|
6862
|
+
};
|
|
6863
|
+
}
|
|
6811
6864
|
let low = row.startOffset;
|
|
6812
6865
|
let high = row.endOffset;
|
|
6813
6866
|
while (low < high) {
|
|
@@ -6837,7 +6890,7 @@ function hitTestFromLayout(params) {
|
|
|
6837
6890
|
return candidateA;
|
|
6838
6891
|
}
|
|
6839
6892
|
const mid = (xA + xB) / 2;
|
|
6840
|
-
return relativeX
|
|
6893
|
+
return relativeX > mid ? candidateA : candidateB;
|
|
6841
6894
|
})();
|
|
6842
6895
|
const endX = caretX(row.endOffset);
|
|
6843
6896
|
{
|
|
@@ -8380,6 +8433,7 @@ class CakeEngine {
|
|
|
8380
8433
|
this.recordHistory(command.type);
|
|
8381
8434
|
this.state = nextState;
|
|
8382
8435
|
this.render();
|
|
8436
|
+
this.flushOverlayUpdate();
|
|
8383
8437
|
(_a = this.onChange) == null ? void 0 : _a.call(this, this.state.source, this.state.selection);
|
|
8384
8438
|
this.scheduleScrollCaretIntoView();
|
|
8385
8439
|
if (shouldOpenLinkPopover) {
|
|
@@ -8389,6 +8443,7 @@ class CakeEngine {
|
|
|
8389
8443
|
}
|
|
8390
8444
|
if (options == null ? void 0 : options.restoreFocus) {
|
|
8391
8445
|
this.focus();
|
|
8446
|
+
this.applySelection(this.state.selection);
|
|
8392
8447
|
}
|
|
8393
8448
|
return true;
|
|
8394
8449
|
}
|
|
@@ -8488,9 +8543,7 @@ class CakeEngine {
|
|
|
8488
8543
|
this.detachDragListeners();
|
|
8489
8544
|
}
|
|
8490
8545
|
handleFocusIn() {
|
|
8491
|
-
|
|
8492
|
-
this.scheduleOverlayUpdate();
|
|
8493
|
-
});
|
|
8546
|
+
this.flushOverlayUpdate();
|
|
8494
8547
|
}
|
|
8495
8548
|
handleFocusOut() {
|
|
8496
8549
|
queueMicrotask(() => {
|
|
@@ -8974,7 +9027,7 @@ class CakeEngine {
|
|
|
8974
9027
|
if (cmdOrCtrl && event.key === "Enter") {
|
|
8975
9028
|
event.preventDefault();
|
|
8976
9029
|
this.keydownHandledBeforeInput = true;
|
|
8977
|
-
this.applyEdit({ type: "insert-line-break" });
|
|
9030
|
+
this.applyEdit({ type: "insert-hard-line-break" });
|
|
8978
9031
|
queueMicrotask(() => {
|
|
8979
9032
|
this.keydownHandledBeforeInput = false;
|
|
8980
9033
|
});
|
package/dist/index.js
CHANGED
|
@@ -1076,10 +1076,10 @@ class CursorSourceBuilder {
|
|
|
1076
1076
|
}
|
|
1077
1077
|
}
|
|
1078
1078
|
function isStructuralEdit(command) {
|
|
1079
|
-
return command.type === "insert" || command.type === "delete-backward" || command.type === "delete-forward" || command.type === "insert-line-break" || command.type === "exit-block-wrapper";
|
|
1079
|
+
return command.type === "insert" || command.type === "delete-backward" || command.type === "delete-forward" || command.type === "insert-line-break" || command.type === "insert-hard-line-break" || command.type === "exit-block-wrapper";
|
|
1080
1080
|
}
|
|
1081
1081
|
function isApplyEditCommand(command) {
|
|
1082
|
-
return command.type === "insert" || command.type === "insert-line-break" || command.type === "delete-backward" || command.type === "delete-forward";
|
|
1082
|
+
return command.type === "insert" || command.type === "insert-line-break" || command.type === "insert-hard-line-break" || command.type === "delete-backward" || command.type === "delete-forward";
|
|
1083
1083
|
}
|
|
1084
1084
|
function defineExtension(extension) {
|
|
1085
1085
|
return extension;
|
|
@@ -1460,7 +1460,7 @@ function createRuntime(extensions) {
|
|
|
1460
1460
|
nextAffinity: affinity === "backward" ? "forward" : "forward"
|
|
1461
1461
|
};
|
|
1462
1462
|
}
|
|
1463
|
-
const replaceText = command.type === "insert" ? command.text : command.type === "insert-line-break" ? "\n" : command.type === "exit-block-wrapper" ? "\n" : "";
|
|
1463
|
+
const replaceText = command.type === "insert" ? command.text : command.type === "insert-line-break" || command.type === "insert-hard-line-break" ? "\n" : command.type === "exit-block-wrapper" ? "\n" : "";
|
|
1464
1464
|
const range = command.type === "delete-backward" && cursorStart === cursorEnd ? cursorStart === 0 ? { start: 0, end: 0 } : { start: cursorStart - 1, end: cursorStart } : command.type === "delete-forward" && cursorStart === cursorEnd ? cursorStart === docCursorLength ? { start: cursorStart, end: cursorStart } : { start: cursorStart, end: cursorStart + 1 } : { start: cursorStart, end: cursorEnd };
|
|
1465
1465
|
const shouldReplacePlaceholder = command.type === "insert" && replaceText.length > 0 && range.start === range.end && graphemeAtCursor(lines, range.start) === "";
|
|
1466
1466
|
const effectiveRange = shouldReplacePlaceholder ? { start: range.start, end: Math.min(docCursorLength, range.start + 1) } : range;
|
|
@@ -4308,6 +4308,41 @@ function findLineStartInSource$1(source, sourceOffset) {
|
|
|
4308
4308
|
}
|
|
4309
4309
|
return lineStart;
|
|
4310
4310
|
}
|
|
4311
|
+
function isInsideBlockquote(source, sourcePos) {
|
|
4312
|
+
const lineStart = findLineStartInSource$1(source, sourcePos);
|
|
4313
|
+
const lineContent = source.slice(
|
|
4314
|
+
lineStart,
|
|
4315
|
+
source.indexOf("\n", lineStart) === -1 ? source.length : source.indexOf("\n", lineStart)
|
|
4316
|
+
);
|
|
4317
|
+
return BLOCKQUOTE_PATTERN.test(lineContent);
|
|
4318
|
+
}
|
|
4319
|
+
function handleExitBlockquote(state) {
|
|
4320
|
+
const { source, selection, map, runtime } = state;
|
|
4321
|
+
const cursorPos = Math.min(selection.start, selection.end);
|
|
4322
|
+
const sourcePos = map.cursorToSource(
|
|
4323
|
+
cursorPos,
|
|
4324
|
+
selection.affinity ?? "forward"
|
|
4325
|
+
);
|
|
4326
|
+
if (!isInsideBlockquote(source, sourcePos)) {
|
|
4327
|
+
return null;
|
|
4328
|
+
}
|
|
4329
|
+
let lineEnd = source.indexOf("\n", sourcePos);
|
|
4330
|
+
if (lineEnd === -1) {
|
|
4331
|
+
lineEnd = source.length;
|
|
4332
|
+
}
|
|
4333
|
+
const newSource = source.slice(0, lineEnd) + "\n" + source.slice(lineEnd);
|
|
4334
|
+
const next = runtime.createState(newSource);
|
|
4335
|
+
const newCursorOffset = lineEnd + 1;
|
|
4336
|
+
const caretCursor = next.map.sourceToCursor(newCursorOffset, "forward");
|
|
4337
|
+
return {
|
|
4338
|
+
source: newSource,
|
|
4339
|
+
selection: {
|
|
4340
|
+
start: caretCursor.cursorOffset,
|
|
4341
|
+
end: caretCursor.cursorOffset,
|
|
4342
|
+
affinity: "forward"
|
|
4343
|
+
}
|
|
4344
|
+
};
|
|
4345
|
+
}
|
|
4311
4346
|
function handleToggleBlockquote(state) {
|
|
4312
4347
|
const { source, selection, map, runtime } = state;
|
|
4313
4348
|
const cursorPos = Math.min(selection.start, selection.end);
|
|
@@ -4353,6 +4388,9 @@ const blockquoteExtension = defineExtension({
|
|
|
4353
4388
|
if (command.type === "toggle-blockquote") {
|
|
4354
4389
|
return handleToggleBlockquote(state);
|
|
4355
4390
|
}
|
|
4391
|
+
if (command.type === "insert-hard-line-break") {
|
|
4392
|
+
return handleExitBlockquote(state);
|
|
4393
|
+
}
|
|
4356
4394
|
return null;
|
|
4357
4395
|
},
|
|
4358
4396
|
parseBlock(source, start, context) {
|
|
@@ -6806,6 +6844,21 @@ function hitTestFromLayout(params) {
|
|
|
6806
6844
|
const caretX = (cursorOffsetInLine) => {
|
|
6807
6845
|
return measureCaretXOnRow(cursorOffsetInLine) ?? approximateX(cursorOffsetInLine);
|
|
6808
6846
|
};
|
|
6847
|
+
const rowLeftEdge = row.rect.left;
|
|
6848
|
+
const rowRightEdge = row.rect.left + row.rect.width;
|
|
6849
|
+
if (relativeX < rowLeftEdge) {
|
|
6850
|
+
return {
|
|
6851
|
+
cursorOffset: lineStartOffset + row.startOffset,
|
|
6852
|
+
pastRowEnd: false
|
|
6853
|
+
};
|
|
6854
|
+
}
|
|
6855
|
+
if (relativeX > rowRightEdge) {
|
|
6856
|
+
const isEndOfLine2 = row.endOffset === lineInfo.cursorLength;
|
|
6857
|
+
return {
|
|
6858
|
+
cursorOffset: lineStartOffset + row.endOffset,
|
|
6859
|
+
pastRowEnd: !isEndOfLine2 && row.endOffset < lineInfo.cursorLength
|
|
6860
|
+
};
|
|
6861
|
+
}
|
|
6809
6862
|
let low = row.startOffset;
|
|
6810
6863
|
let high = row.endOffset;
|
|
6811
6864
|
while (low < high) {
|
|
@@ -6835,7 +6888,7 @@ function hitTestFromLayout(params) {
|
|
|
6835
6888
|
return candidateA;
|
|
6836
6889
|
}
|
|
6837
6890
|
const mid = (xA + xB) / 2;
|
|
6838
|
-
return relativeX
|
|
6891
|
+
return relativeX > mid ? candidateA : candidateB;
|
|
6839
6892
|
})();
|
|
6840
6893
|
const endX = caretX(row.endOffset);
|
|
6841
6894
|
{
|
|
@@ -8378,6 +8431,7 @@ class CakeEngine {
|
|
|
8378
8431
|
this.recordHistory(command.type);
|
|
8379
8432
|
this.state = nextState;
|
|
8380
8433
|
this.render();
|
|
8434
|
+
this.flushOverlayUpdate();
|
|
8381
8435
|
(_a = this.onChange) == null ? void 0 : _a.call(this, this.state.source, this.state.selection);
|
|
8382
8436
|
this.scheduleScrollCaretIntoView();
|
|
8383
8437
|
if (shouldOpenLinkPopover) {
|
|
@@ -8387,6 +8441,7 @@ class CakeEngine {
|
|
|
8387
8441
|
}
|
|
8388
8442
|
if (options == null ? void 0 : options.restoreFocus) {
|
|
8389
8443
|
this.focus();
|
|
8444
|
+
this.applySelection(this.state.selection);
|
|
8390
8445
|
}
|
|
8391
8446
|
return true;
|
|
8392
8447
|
}
|
|
@@ -8486,9 +8541,7 @@ class CakeEngine {
|
|
|
8486
8541
|
this.detachDragListeners();
|
|
8487
8542
|
}
|
|
8488
8543
|
handleFocusIn() {
|
|
8489
|
-
|
|
8490
|
-
this.scheduleOverlayUpdate();
|
|
8491
|
-
});
|
|
8544
|
+
this.flushOverlayUpdate();
|
|
8492
8545
|
}
|
|
8493
8546
|
handleFocusOut() {
|
|
8494
8547
|
queueMicrotask(() => {
|
|
@@ -8972,7 +9025,7 @@ class CakeEngine {
|
|
|
8972
9025
|
if (cmdOrCtrl && event.key === "Enter") {
|
|
8973
9026
|
event.preventDefault();
|
|
8974
9027
|
this.keydownHandledBeforeInput = true;
|
|
8975
|
-
this.applyEdit({ type: "insert-line-break" });
|
|
9028
|
+
this.applyEdit({ type: "insert-hard-line-break" });
|
|
8976
9029
|
queueMicrotask(() => {
|
|
8977
9030
|
this.keydownHandledBeforeInput = false;
|
|
8978
9031
|
});
|