@blankdotpage/cake 0.1.67 → 0.1.69
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/mapping/cursor-source-map.d.ts +11 -0
- package/dist/cake/core/mapping/cursor-source-map.d.ts.map +1 -1
- package/dist/cake/core/mapping/cursor-source-map.js +159 -21
- package/dist/cake/core/runtime.d.ts +6 -0
- package/dist/cake/core/runtime.d.ts.map +1 -1
- package/dist/cake/core/runtime.js +344 -221
- package/dist/cake/dom/render.d.ts +32 -2
- package/dist/cake/dom/render.d.ts.map +1 -1
- package/dist/cake/dom/render.js +401 -118
- package/dist/cake/editor/cake-editor.d.ts +11 -2
- package/dist/cake/editor/cake-editor.d.ts.map +1 -1
- package/dist/cake/editor/cake-editor.js +178 -100
- package/dist/cake/editor/internal/editor-text-model.d.ts +49 -0
- package/dist/cake/editor/internal/editor-text-model.d.ts.map +1 -0
- package/dist/cake/editor/internal/editor-text-model.js +284 -0
- package/dist/cake/editor/selection/selection-geometry-dom.d.ts +5 -1
- package/dist/cake/editor/selection/selection-geometry-dom.d.ts.map +1 -1
- package/dist/cake/editor/selection/selection-geometry-dom.js +4 -5
- package/dist/cake/editor/selection/selection-layout-dom.d.ts.map +1 -1
- package/dist/cake/editor/selection/selection-layout-dom.js +2 -5
- package/dist/cake/editor/selection/selection-layout.d.ts +2 -15
- package/dist/cake/editor/selection/selection-layout.d.ts.map +1 -1
- package/dist/cake/editor/selection/selection-layout.js +1 -99
- package/dist/cake/editor/selection/selection-navigation.d.ts +4 -0
- package/dist/cake/editor/selection/selection-navigation.d.ts.map +1 -1
- package/dist/cake/editor/selection/selection-navigation.js +1 -2
- package/dist/cake/extensions/index.d.ts +2 -1
- package/dist/cake/extensions/index.d.ts.map +1 -1
- package/dist/cake/extensions/index.js +3 -1
- package/dist/cake/extensions/link/link.d.ts.map +1 -1
- package/dist/cake/extensions/link/link.js +1 -7
- package/dist/cake/extensions/shared/structural-reparse-policy.d.ts +7 -0
- package/dist/cake/extensions/shared/structural-reparse-policy.d.ts.map +1 -0
- package/dist/cake/extensions/shared/structural-reparse-policy.js +16 -0
- package/package.json +5 -2
- package/dist/cake/editor/selection/visible-text.d.ts +0 -5
- package/dist/cake/editor/selection/visible-text.d.ts.map +0 -1
- package/dist/cake/editor/selection/visible-text.js +0 -66
- package/dist/cake/engine/cake-engine.d.ts +0 -230
- package/dist/cake/engine/cake-engine.d.ts.map +0 -1
- package/dist/cake/engine/cake-engine.js +0 -3589
- package/dist/cake/engine/selection/selection-geometry-dom.d.ts +0 -24
- package/dist/cake/engine/selection/selection-geometry-dom.d.ts.map +0 -1
- package/dist/cake/engine/selection/selection-geometry-dom.js +0 -302
- package/dist/cake/engine/selection/selection-geometry.d.ts +0 -22
- package/dist/cake/engine/selection/selection-geometry.d.ts.map +0 -1
- package/dist/cake/engine/selection/selection-geometry.js +0 -158
- package/dist/cake/engine/selection/selection-layout-dom.d.ts +0 -50
- package/dist/cake/engine/selection/selection-layout-dom.d.ts.map +0 -1
- package/dist/cake/engine/selection/selection-layout-dom.js +0 -781
- package/dist/cake/engine/selection/selection-layout.d.ts +0 -55
- package/dist/cake/engine/selection/selection-layout.d.ts.map +0 -1
- package/dist/cake/engine/selection/selection-layout.js +0 -128
- package/dist/cake/engine/selection/selection-navigation.d.ts +0 -22
- package/dist/cake/engine/selection/selection-navigation.d.ts.map +0 -1
- package/dist/cake/engine/selection/selection-navigation.js +0 -229
- package/dist/cake/engine/selection/visible-text.d.ts +0 -5
- package/dist/cake/engine/selection/visible-text.d.ts.map +0 -1
- package/dist/cake/engine/selection/visible-text.js +0 -66
- package/dist/cake/react/CakeEditor.d.ts +0 -58
- package/dist/cake/react/CakeEditor.d.ts.map +0 -1
- package/dist/cake/react/CakeEditor.js +0 -225
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { Selection } from "../../core/types";
|
|
2
|
-
import { type LineInfo } from "./selection-layout";
|
|
3
|
-
import { type SelectionRect } from "./selection-geometry";
|
|
4
|
-
export type SelectionGeometry = {
|
|
5
|
-
selectionRects: SelectionRect[];
|
|
6
|
-
caretRect: SelectionRect | null;
|
|
7
|
-
focusRect: SelectionRect | null;
|
|
8
|
-
};
|
|
9
|
-
export declare function getSelectionGeometry(params: {
|
|
10
|
-
root: HTMLElement;
|
|
11
|
-
container: HTMLElement;
|
|
12
|
-
docLines: LineInfo[];
|
|
13
|
-
selection: Selection;
|
|
14
|
-
}): SelectionGeometry;
|
|
15
|
-
export declare function getCaretRect(params: {
|
|
16
|
-
lineElement: HTMLElement;
|
|
17
|
-
lineInfo: LineInfo;
|
|
18
|
-
offsetInLine: number;
|
|
19
|
-
affinity?: "forward" | "backward";
|
|
20
|
-
}): {
|
|
21
|
-
rect: DOMRect;
|
|
22
|
-
lineRect: DOMRect;
|
|
23
|
-
} | null;
|
|
24
|
-
//# sourceMappingURL=selection-geometry-dom.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"selection-geometry-dom.d.ts","sourceRoot":"","sources":["../../../../src/cake/engine/selection/selection-geometry-dom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAuB,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAUxE,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;IACvB,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACrB,SAAS,EAAE,SAAS,CAAC;CACtB,GAAG,iBAAiB,CAoHpB;AAMD,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACnC,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;CACnC,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAwN9C"}
|
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
import { resolveOffsetToLine } from "./selection-layout";
|
|
2
|
-
import { createOffsetToXMeasurer, cursorOffsetToDomOffset, getLineElement, groupDomRectsByRow, measureLayoutModelRangeFromDom, resolveDomPosition, toLayoutRect, } from "./selection-layout-dom";
|
|
3
|
-
import { computeCaretRect, computeSelectionRects, } from "./selection-geometry";
|
|
4
|
-
export function getSelectionGeometry(params) {
|
|
5
|
-
const { root, container, docLines, selection } = params;
|
|
6
|
-
const normalized = selection.start <= selection.end
|
|
7
|
-
? selection
|
|
8
|
-
: {
|
|
9
|
-
start: selection.end,
|
|
10
|
-
end: selection.start,
|
|
11
|
-
affinity: selection.affinity,
|
|
12
|
-
};
|
|
13
|
-
const layout = shouldMeasureLayout(normalized)
|
|
14
|
-
? (() => {
|
|
15
|
-
const startLine = resolveOffsetToLine(docLines, normalized.start);
|
|
16
|
-
const endLine = resolveOffsetToLine(docLines, normalized.end);
|
|
17
|
-
return measureLayoutModelRangeFromDom({
|
|
18
|
-
lines: docLines,
|
|
19
|
-
root,
|
|
20
|
-
container,
|
|
21
|
-
startLineIndex: startLine.lineIndex,
|
|
22
|
-
endLineIndex: endLine.lineIndex,
|
|
23
|
-
});
|
|
24
|
-
})()
|
|
25
|
-
: null;
|
|
26
|
-
const containerRect = container.getBoundingClientRect();
|
|
27
|
-
const scroll = { top: container.scrollTop, left: container.scrollLeft };
|
|
28
|
-
const startLine = resolveOffsetToLine(docLines, normalized.start);
|
|
29
|
-
const hasSelection = normalized.start !== normalized.end;
|
|
30
|
-
if (!hasSelection) {
|
|
31
|
-
const lineInfo = docLines[startLine.lineIndex];
|
|
32
|
-
const lineElement = getLineElement(root, startLine.lineIndex);
|
|
33
|
-
if (!lineInfo || !lineElement) {
|
|
34
|
-
return { selectionRects: [], caretRect: null, focusRect: null };
|
|
35
|
-
}
|
|
36
|
-
const caret = getCaretRect({
|
|
37
|
-
lineElement,
|
|
38
|
-
lineInfo,
|
|
39
|
-
offsetInLine: startLine.offsetInLine,
|
|
40
|
-
affinity: selection.affinity ?? "forward",
|
|
41
|
-
});
|
|
42
|
-
if (!caret) {
|
|
43
|
-
return { selectionRects: [], caretRect: null, focusRect: null };
|
|
44
|
-
}
|
|
45
|
-
const caretMeasurement = {
|
|
46
|
-
lineRect: toLayoutRect({
|
|
47
|
-
rect: caret.lineRect,
|
|
48
|
-
containerRect,
|
|
49
|
-
scroll,
|
|
50
|
-
}),
|
|
51
|
-
caretRect: toLayoutRect({
|
|
52
|
-
rect: caret.rect,
|
|
53
|
-
containerRect,
|
|
54
|
-
scroll,
|
|
55
|
-
}),
|
|
56
|
-
lineLength: lineInfo.cursorLength,
|
|
57
|
-
fontSize: getComputedFontSize(lineElement),
|
|
58
|
-
padding: getComputedVerticalPadding(lineElement),
|
|
59
|
-
};
|
|
60
|
-
const caretRect = computeCaretRect(caretMeasurement);
|
|
61
|
-
return {
|
|
62
|
-
selectionRects: [],
|
|
63
|
-
caretRect,
|
|
64
|
-
focusRect: caretRect,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
if (!layout) {
|
|
68
|
-
return { selectionRects: [], caretRect: null, focusRect: null };
|
|
69
|
-
}
|
|
70
|
-
const measurer = createOffsetToXMeasurer({
|
|
71
|
-
root,
|
|
72
|
-
container,
|
|
73
|
-
lines: docLines,
|
|
74
|
-
});
|
|
75
|
-
const focusOffset = normalized.affinity === "backward" ? normalized.start : normalized.end;
|
|
76
|
-
const focusLine = resolveOffsetToLine(docLines, focusOffset);
|
|
77
|
-
const focusLineElement = getLineElement(root, focusLine.lineIndex);
|
|
78
|
-
let focusRect = null;
|
|
79
|
-
if (focusLineElement) {
|
|
80
|
-
const lineInfo = docLines[focusLine.lineIndex];
|
|
81
|
-
if (lineInfo) {
|
|
82
|
-
const caret = getCaretRect({
|
|
83
|
-
lineElement: focusLineElement,
|
|
84
|
-
lineInfo,
|
|
85
|
-
offsetInLine: focusLine.offsetInLine,
|
|
86
|
-
affinity: selection.affinity ?? "forward",
|
|
87
|
-
});
|
|
88
|
-
if (caret) {
|
|
89
|
-
const caretMeasurement = {
|
|
90
|
-
lineRect: toLayoutRect({
|
|
91
|
-
rect: caret.lineRect,
|
|
92
|
-
containerRect,
|
|
93
|
-
scroll,
|
|
94
|
-
}),
|
|
95
|
-
caretRect: toLayoutRect({
|
|
96
|
-
rect: caret.rect,
|
|
97
|
-
containerRect,
|
|
98
|
-
scroll,
|
|
99
|
-
}),
|
|
100
|
-
lineLength: lineInfo.cursorLength,
|
|
101
|
-
fontSize: getComputedFontSize(focusLineElement),
|
|
102
|
-
padding: getComputedVerticalPadding(focusLineElement),
|
|
103
|
-
};
|
|
104
|
-
focusRect = computeCaretRect(caretMeasurement);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return {
|
|
109
|
-
selectionRects: computeSelectionRects(layout, normalized, measurer),
|
|
110
|
-
caretRect: null,
|
|
111
|
-
focusRect,
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
function shouldMeasureLayout(selection) {
|
|
115
|
-
return selection.start !== selection.end;
|
|
116
|
-
}
|
|
117
|
-
export function getCaretRect(params) {
|
|
118
|
-
const { lineElement, lineInfo, offsetInLine, affinity } = params;
|
|
119
|
-
const clampedOffset = Math.max(0, Math.min(offsetInLine, lineInfo.cursorLength));
|
|
120
|
-
const codeUnitOffset = cursorOffsetToDomOffset(lineInfo.cursorToCodeUnit, clampedOffset);
|
|
121
|
-
const position = resolveDomPosition(lineElement, codeUnitOffset);
|
|
122
|
-
const caretRange = document.createRange();
|
|
123
|
-
caretRange.setStart(position.node, position.offset);
|
|
124
|
-
caretRange.setEnd(position.node, position.offset);
|
|
125
|
-
if (typeof caretRange.getBoundingClientRect !== "function") {
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
const lineRect = lineElement.getBoundingClientRect();
|
|
129
|
-
const caretRects = caretRange.getClientRects();
|
|
130
|
-
let caretRect;
|
|
131
|
-
if (caretRects.length > 1 && affinity === "backward") {
|
|
132
|
-
caretRect = caretRects[0];
|
|
133
|
-
for (let i = 1; i < caretRects.length; i += 1) {
|
|
134
|
-
if (caretRects[i].top < caretRect.top) {
|
|
135
|
-
caretRect = caretRects[i];
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
caretRect = caretRange.getBoundingClientRect();
|
|
141
|
-
}
|
|
142
|
-
if (lineInfo.cursorLength > 0) {
|
|
143
|
-
const canProbeBackward = clampedOffset > 0;
|
|
144
|
-
const canProbeForward = clampedOffset < lineInfo.cursorLength;
|
|
145
|
-
let backwardRect = null;
|
|
146
|
-
let forwardRect = null;
|
|
147
|
-
if (canProbeBackward) {
|
|
148
|
-
const backStart = resolveDomPosition(lineElement, cursorOffsetToDomOffset(lineInfo.cursorToCodeUnit, clampedOffset - 1));
|
|
149
|
-
const backEnd = resolveDomPosition(lineElement, cursorOffsetToDomOffset(lineInfo.cursorToCodeUnit, clampedOffset));
|
|
150
|
-
const backRange = document.createRange();
|
|
151
|
-
backRange.setStart(backStart.node, backStart.offset);
|
|
152
|
-
backRange.setEnd(backEnd.node, backEnd.offset);
|
|
153
|
-
const backRects = backRange.getClientRects();
|
|
154
|
-
if (backRects.length > 0) {
|
|
155
|
-
// When a range spans a wrap boundary, getClientRects() returns multiple rects:
|
|
156
|
-
// one for the character on the previous row (with width) and a zero-width
|
|
157
|
-
// rect at the wrap point. For backward probing, we want the rect with
|
|
158
|
-
// actual width that represents the character, not the zero-width wrap marker.
|
|
159
|
-
// If multiple rects have width, prefer the one with the smallest top (previous row).
|
|
160
|
-
let bestRect = backRects[backRects.length - 1];
|
|
161
|
-
for (let i = 0; i < backRects.length; i += 1) {
|
|
162
|
-
const rect = backRects[i];
|
|
163
|
-
if (rect.width > 0 && (bestRect.width === 0 || rect.top < bestRect.top)) {
|
|
164
|
-
bestRect = rect;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
backwardRect = bestRect;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
if (canProbeForward) {
|
|
171
|
-
const fwdStart = resolveDomPosition(lineElement, cursorOffsetToDomOffset(lineInfo.cursorToCodeUnit, clampedOffset));
|
|
172
|
-
const fwdEnd = resolveDomPosition(lineElement, cursorOffsetToDomOffset(lineInfo.cursorToCodeUnit, clampedOffset + 1));
|
|
173
|
-
const fwdRange = document.createRange();
|
|
174
|
-
fwdRange.setStart(fwdStart.node, fwdStart.offset);
|
|
175
|
-
fwdRange.setEnd(fwdEnd.node, fwdEnd.offset);
|
|
176
|
-
const fwdRects = fwdRange.getClientRects();
|
|
177
|
-
if (fwdRects.length > 0) {
|
|
178
|
-
// Like backward probing, prefer a rect with actual width. At wrap
|
|
179
|
-
// boundaries WebKit can include a zero-width marker rect; for forward
|
|
180
|
-
// probing we want the fragment on the *next* row (largest top).
|
|
181
|
-
let bestRect = fwdRects[0];
|
|
182
|
-
for (let i = 1; i < fwdRects.length; i += 1) {
|
|
183
|
-
const rect = fwdRects[i];
|
|
184
|
-
if (rect.width > 0 &&
|
|
185
|
-
(bestRect.width === 0 || rect.top > bestRect.top)) {
|
|
186
|
-
bestRect = rect;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
forwardRect = bestRect;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
const atWrapBoundary = backwardRect &&
|
|
193
|
-
forwardRect &&
|
|
194
|
-
Math.abs(backwardRect.top - forwardRect.top) > 5;
|
|
195
|
-
let probeRect = null;
|
|
196
|
-
let useRightEdge = false;
|
|
197
|
-
if (atWrapBoundary) {
|
|
198
|
-
if (affinity === "backward" && backwardRect) {
|
|
199
|
-
// In WebKit, collapsed ranges at a wrap boundary can report their rect on
|
|
200
|
-
// the *next* visual row. Even a 1-char backward range can be ambiguous
|
|
201
|
-
// at whitespace-wrapping points. When we intentionally keep backward
|
|
202
|
-
// affinity (e.g. "end of visual row"), anchor the caret to the previous
|
|
203
|
-
// row's line box fragment and use its right edge.
|
|
204
|
-
if (forwardRect) {
|
|
205
|
-
const startPos = resolveDomPosition(lineElement, cursorOffsetToDomOffset(lineInfo.cursorToCodeUnit, 0));
|
|
206
|
-
const endPos = resolveDomPosition(lineElement, cursorOffsetToDomOffset(lineInfo.cursorToCodeUnit, lineInfo.cursorLength));
|
|
207
|
-
const lineRange = document.createRange();
|
|
208
|
-
lineRange.setStart(startPos.node, startPos.offset);
|
|
209
|
-
lineRange.setEnd(endPos.node, endPos.offset);
|
|
210
|
-
const rowRects = groupDomRectsByRow(Array.from(lineRange.getClientRects()));
|
|
211
|
-
// Pick the closest row strictly above the next-row top.
|
|
212
|
-
const ROW_EPS_PX = 1;
|
|
213
|
-
let previousRow = null;
|
|
214
|
-
for (const rowRect of rowRects) {
|
|
215
|
-
if (rowRect.top < forwardRect.top - ROW_EPS_PX) {
|
|
216
|
-
previousRow = rowRect;
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
break;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
if (previousRow) {
|
|
223
|
-
caretRect = new DOMRect(previousRow.right, previousRow.top, 0, previousRow.height);
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
probeRect = backwardRect;
|
|
227
|
-
useRightEdge = true;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
231
|
-
probeRect = backwardRect;
|
|
232
|
-
useRightEdge = true;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
else if (forwardRect) {
|
|
236
|
-
probeRect = forwardRect;
|
|
237
|
-
useRightEdge = false;
|
|
238
|
-
}
|
|
239
|
-
else if (backwardRect) {
|
|
240
|
-
probeRect = backwardRect;
|
|
241
|
-
useRightEdge = true;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
if (forwardRect) {
|
|
246
|
-
probeRect = forwardRect;
|
|
247
|
-
useRightEdge = false;
|
|
248
|
-
}
|
|
249
|
-
else if (backwardRect) {
|
|
250
|
-
probeRect = backwardRect;
|
|
251
|
-
useRightEdge = true;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
if (probeRect && probeRect.height > 0) {
|
|
255
|
-
const left = useRightEdge ? probeRect.right : probeRect.left;
|
|
256
|
-
caretRect = new DOMRect(left, probeRect.top, 0, probeRect.height);
|
|
257
|
-
}
|
|
258
|
-
// WebKit can report the collapsed caret at a wrap boundary as belonging to
|
|
259
|
-
// the *next* visual row even when we explicitly want backward affinity
|
|
260
|
-
// (e.g. "end of visual row"). Anchor the caret to the previous row fragment
|
|
261
|
-
// when a forward-probe indicates there is a next row.
|
|
262
|
-
if (affinity === "backward" && forwardRect) {
|
|
263
|
-
const startPos = resolveDomPosition(lineElement, cursorOffsetToDomOffset(lineInfo.cursorToCodeUnit, 0));
|
|
264
|
-
const endPos = resolveDomPosition(lineElement, cursorOffsetToDomOffset(lineInfo.cursorToCodeUnit, lineInfo.cursorLength));
|
|
265
|
-
const lineRange = document.createRange();
|
|
266
|
-
lineRange.setStart(startPos.node, startPos.offset);
|
|
267
|
-
lineRange.setEnd(endPos.node, endPos.offset);
|
|
268
|
-
const rowRects = groupDomRectsByRow(Array.from(lineRange.getClientRects()));
|
|
269
|
-
const ROW_EPS_PX = 1;
|
|
270
|
-
let previousRow = null;
|
|
271
|
-
for (const rowRect of rowRects) {
|
|
272
|
-
if (rowRect.top < forwardRect.top - ROW_EPS_PX) {
|
|
273
|
-
previousRow = rowRect;
|
|
274
|
-
}
|
|
275
|
-
else {
|
|
276
|
-
break;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
if (previousRow && caretRect.top >= forwardRect.top - ROW_EPS_PX) {
|
|
280
|
-
caretRect = new DOMRect(previousRow.right, previousRow.top, 0, previousRow.height);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
if (caretRect.height === 0 && lineRect.height === 0) {
|
|
285
|
-
return null;
|
|
286
|
-
}
|
|
287
|
-
return { rect: caretRect, lineRect };
|
|
288
|
-
}
|
|
289
|
-
function getComputedVerticalPadding(lineElement) {
|
|
290
|
-
const style = window.getComputedStyle(lineElement);
|
|
291
|
-
const top = Number.parseFloat(style.paddingTop);
|
|
292
|
-
const bottom = Number.parseFloat(style.paddingBottom);
|
|
293
|
-
return {
|
|
294
|
-
top: Number.isFinite(top) ? top : 0,
|
|
295
|
-
bottom: Number.isFinite(bottom) ? bottom : 0,
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
function getComputedFontSize(lineElement) {
|
|
299
|
-
const fontSize = window.getComputedStyle(lineElement).fontSize;
|
|
300
|
-
const parsed = Number.parseFloat(fontSize);
|
|
301
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed : 16;
|
|
302
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { Selection } from "../../core/types";
|
|
2
|
-
import type { LayoutModel, LayoutRect } from "./selection-layout";
|
|
3
|
-
export type SelectionRect = {
|
|
4
|
-
top: number;
|
|
5
|
-
left: number;
|
|
6
|
-
width: number;
|
|
7
|
-
height: number;
|
|
8
|
-
};
|
|
9
|
-
export type SelectionCaretMeasurement = {
|
|
10
|
-
lineRect: LayoutRect;
|
|
11
|
-
caretRect: LayoutRect;
|
|
12
|
-
lineLength: number;
|
|
13
|
-
fontSize: number;
|
|
14
|
-
padding: {
|
|
15
|
-
top: number;
|
|
16
|
-
bottom: number;
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
export type OffsetToXMeasurer = (lineIndex: number, offsetInLine: number) => number | null;
|
|
20
|
-
export declare function computeSelectionRects(layout: LayoutModel, selection: Selection, measurer?: OffsetToXMeasurer): SelectionRect[];
|
|
21
|
-
export declare function computeCaretRect(caret: SelectionCaretMeasurement): SelectionRect | null;
|
|
22
|
-
//# sourceMappingURL=selection-geometry.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"selection-geometry.d.ts","sourceRoot":"","sources":["../../../../src/cake/engine/selection/selection-geometry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EAGX,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,UAAU,CAAC;IACrB,SAAS,EAAE,UAAU,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAC9B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,KACjB,MAAM,GAAG,IAAI,CAAC;AAyEnB,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,SAAS,EACpB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,aAAa,EAAE,CA+GjB;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,yBAAyB,GAC/B,aAAa,GAAG,IAAI,CA2BtB"}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
function rectRight(rect) {
|
|
2
|
-
return rect.left + rect.width;
|
|
3
|
-
}
|
|
4
|
-
function getRowSlot(line, rowIndex, row) {
|
|
5
|
-
const rowCount = line.rows.length;
|
|
6
|
-
if (rowCount <= 1) {
|
|
7
|
-
return { top: line.lineBox.top, height: line.lineBox.height };
|
|
8
|
-
}
|
|
9
|
-
const lineHeight = line.lineBox.height;
|
|
10
|
-
if (!Number.isFinite(lineHeight) || lineHeight <= 0) {
|
|
11
|
-
return { top: row.rect.top, height: row.rect.height };
|
|
12
|
-
}
|
|
13
|
-
const rowHeight = lineHeight / rowCount;
|
|
14
|
-
if (!Number.isFinite(rowHeight) || rowHeight <= 0) {
|
|
15
|
-
return { top: row.rect.top, height: row.rect.height };
|
|
16
|
-
}
|
|
17
|
-
return {
|
|
18
|
-
top: line.lineBox.top + rowHeight * rowIndex,
|
|
19
|
-
height: rowHeight,
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
function rowOffsetToX(row, offset, lineIndex, measurer) {
|
|
23
|
-
const clamped = Math.max(row.startOffset, Math.min(offset, row.endOffset));
|
|
24
|
-
if (measurer) {
|
|
25
|
-
const measured = measurer(lineIndex, clamped);
|
|
26
|
-
if (measured !== null) {
|
|
27
|
-
return measured;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
const rowLength = row.endOffset - row.startOffset;
|
|
31
|
-
if (rowLength <= 0) {
|
|
32
|
-
return row.rect.left;
|
|
33
|
-
}
|
|
34
|
-
const charWidth = row.rect.width / rowLength;
|
|
35
|
-
return row.rect.left + charWidth * (clamped - row.startOffset);
|
|
36
|
-
}
|
|
37
|
-
function findRowIndexForStart(rows, offset) {
|
|
38
|
-
for (let index = 0; index < rows.length; index += 1) {
|
|
39
|
-
if (offset < rows[index].endOffset) {
|
|
40
|
-
return index;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return Math.max(0, rows.length - 1);
|
|
44
|
-
}
|
|
45
|
-
function findRowIndexForEnd(rows, offset) {
|
|
46
|
-
for (let index = rows.length - 1; index >= 0; index -= 1) {
|
|
47
|
-
if (offset > rows[index].startOffset) {
|
|
48
|
-
return index;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return 0;
|
|
52
|
-
}
|
|
53
|
-
export function computeSelectionRects(layout, selection, measurer) {
|
|
54
|
-
const start = Math.min(selection.start, selection.end);
|
|
55
|
-
const end = Math.max(selection.start, selection.end);
|
|
56
|
-
if (start === end) {
|
|
57
|
-
return [];
|
|
58
|
-
}
|
|
59
|
-
const rects = [];
|
|
60
|
-
layout.lines.forEach((line) => {
|
|
61
|
-
const lineEndOffset = line.lineStartOffset + line.lineLength;
|
|
62
|
-
const selectionStartInLine = Math.max(0, Math.min(start - line.lineStartOffset, line.lineLength));
|
|
63
|
-
const selectionEndInLine = Math.max(0, Math.min(end - line.lineStartOffset, line.lineLength));
|
|
64
|
-
const includesNewline = start <= lineEndOffset && end > lineEndOffset && line.lineHasNewline;
|
|
65
|
-
const selectionStartsBeforeLine = start < line.lineStartOffset;
|
|
66
|
-
const hasCoverage = selectionStartInLine < selectionEndInLine || includesNewline;
|
|
67
|
-
if (!hasCoverage) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
const lineBoxLeft = line.lineBox.left;
|
|
71
|
-
const lineBoxRight = rectRight(line.lineBox);
|
|
72
|
-
if (line.lineLength === 0) {
|
|
73
|
-
const width = Math.max(1, line.lineBox.width);
|
|
74
|
-
rects.push({
|
|
75
|
-
top: line.lineBox.top,
|
|
76
|
-
left: lineBoxLeft,
|
|
77
|
-
width,
|
|
78
|
-
height: line.lineBox.height,
|
|
79
|
-
});
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
if (line.rows.length === 0) {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
if (selectionStartInLine === selectionEndInLine && includesNewline) {
|
|
86
|
-
const rowIndex = findRowIndexForStart(line.rows, selectionStartInLine);
|
|
87
|
-
const row = line.rows[rowIndex] ?? line.rows[line.rows.length - 1];
|
|
88
|
-
const slot = getRowSlot(line, rowIndex, row);
|
|
89
|
-
const left = Math.max(rowOffsetToX(row, selectionStartInLine, line.lineIndex, measurer), lineBoxLeft);
|
|
90
|
-
const width = Math.max(1, lineBoxRight - left);
|
|
91
|
-
rects.push({
|
|
92
|
-
top: slot.top,
|
|
93
|
-
left,
|
|
94
|
-
width,
|
|
95
|
-
height: slot.height,
|
|
96
|
-
});
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
const endRowIndex = findRowIndexForEnd(line.rows, selectionEndInLine);
|
|
100
|
-
line.rows.forEach((row, rowIndex) => {
|
|
101
|
-
const rowSelectionStart = Math.max(selectionStartInLine, row.startOffset);
|
|
102
|
-
const rowSelectionEnd = Math.min(selectionEndInLine, row.endOffset);
|
|
103
|
-
if (rowSelectionStart >= rowSelectionEnd) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
const slot = getRowSlot(line, rowIndex, row);
|
|
107
|
-
const selectionCoversRowStart = selectionStartInLine <= row.startOffset;
|
|
108
|
-
const fillToLineStart = (includesNewline || selectionStartsBeforeLine) &&
|
|
109
|
-
selectionCoversRowStart;
|
|
110
|
-
let left = selectionCoversRowStart
|
|
111
|
-
? fillToLineStart
|
|
112
|
-
? lineBoxLeft
|
|
113
|
-
: row.rect.left
|
|
114
|
-
: rowOffsetToX(row, rowSelectionStart, line.lineIndex, measurer);
|
|
115
|
-
left = Math.max(left, lineBoxLeft);
|
|
116
|
-
const isLastRow = rowIndex === endRowIndex;
|
|
117
|
-
const fillToLineEnd = includesNewline || (selectionStartsBeforeLine && !isLastRow);
|
|
118
|
-
const fillToRowEnd = !isLastRow && rowSelectionEnd === row.endOffset;
|
|
119
|
-
let right = fillToLineEnd
|
|
120
|
-
? lineBoxRight
|
|
121
|
-
: fillToRowEnd
|
|
122
|
-
? lineBoxRight
|
|
123
|
-
: isLastRow
|
|
124
|
-
? rowOffsetToX(row, rowSelectionEnd, line.lineIndex, measurer)
|
|
125
|
-
: rectRight(row.rect);
|
|
126
|
-
right = Math.max(right, left);
|
|
127
|
-
const width = Math.max(1, right - left);
|
|
128
|
-
rects.push({
|
|
129
|
-
top: slot.top,
|
|
130
|
-
left,
|
|
131
|
-
width,
|
|
132
|
-
height: slot.height,
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
return rects;
|
|
137
|
-
}
|
|
138
|
-
export function computeCaretRect(caret) {
|
|
139
|
-
const height = caret.fontSize * 1.2;
|
|
140
|
-
const contentHeight = caret.lineRect.height > 0
|
|
141
|
-
? Math.max(0, caret.lineRect.height - caret.padding.top - caret.padding.bottom)
|
|
142
|
-
: 0;
|
|
143
|
-
const emptyLineTop = contentHeight > 0
|
|
144
|
-
? caret.lineRect.top + caret.padding.top + (contentHeight - height) / 2
|
|
145
|
-
: caret.lineRect.top + (caret.lineRect.height - height) / 2;
|
|
146
|
-
const top = caret.lineLength === 0
|
|
147
|
-
? emptyLineTop
|
|
148
|
-
: caret.caretRect.height > 0
|
|
149
|
-
? caret.caretRect.top
|
|
150
|
-
: caret.lineRect.top;
|
|
151
|
-
const left = caret.lineLength === 0 ? caret.lineRect.left : caret.caretRect.left;
|
|
152
|
-
return {
|
|
153
|
-
top,
|
|
154
|
-
left,
|
|
155
|
-
width: 0,
|
|
156
|
-
height,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import type { LayoutMeasurer, LayoutModel, LayoutRect, LineInfo } from "./selection-layout";
|
|
2
|
-
export declare function toLayoutRect(params: {
|
|
3
|
-
rect: DOMRect;
|
|
4
|
-
containerRect: DOMRect;
|
|
5
|
-
scroll: {
|
|
6
|
-
top: number;
|
|
7
|
-
left: number;
|
|
8
|
-
};
|
|
9
|
-
}): LayoutRect;
|
|
10
|
-
export declare function groupDomRectsByRow(rects: DOMRect[]): DOMRect[];
|
|
11
|
-
export declare function createDomLayoutMeasurer(params: {
|
|
12
|
-
root: HTMLElement;
|
|
13
|
-
container: HTMLElement;
|
|
14
|
-
lines: LineInfo[];
|
|
15
|
-
}): LayoutMeasurer | null;
|
|
16
|
-
export declare function measureLayoutModelFromDom(params: {
|
|
17
|
-
lines: LineInfo[];
|
|
18
|
-
root: HTMLElement;
|
|
19
|
-
container: HTMLElement;
|
|
20
|
-
}): LayoutModel | null;
|
|
21
|
-
export declare function measureLayoutModelRangeFromDom(params: {
|
|
22
|
-
lines: LineInfo[];
|
|
23
|
-
root: HTMLElement;
|
|
24
|
-
container: HTMLElement;
|
|
25
|
-
startLineIndex: number;
|
|
26
|
-
endLineIndex: number;
|
|
27
|
-
}): LayoutModel | null;
|
|
28
|
-
export declare function getLineElement(root: HTMLElement, lineIndex: number): HTMLElement | null;
|
|
29
|
-
export declare function resolveDomPosition(lineElement: HTMLElement, offsetInLine: number): {
|
|
30
|
-
node: Node;
|
|
31
|
-
offset: number;
|
|
32
|
-
};
|
|
33
|
-
export declare function createOffsetToXMeasurer(params: {
|
|
34
|
-
root: HTMLElement;
|
|
35
|
-
container: HTMLElement;
|
|
36
|
-
lines: LineInfo[];
|
|
37
|
-
}): (lineIndex: number, offsetInLine: number) => number | null;
|
|
38
|
-
export declare function cursorOffsetToDomOffset(cursorToCodeUnit: number[], offset: number): number;
|
|
39
|
-
export type HitTestResult = {
|
|
40
|
-
cursorOffset: number;
|
|
41
|
-
pastRowEnd: boolean;
|
|
42
|
-
};
|
|
43
|
-
export declare function hitTestFromLayout(params: {
|
|
44
|
-
clientX: number;
|
|
45
|
-
clientY: number;
|
|
46
|
-
root: HTMLElement;
|
|
47
|
-
container: HTMLElement;
|
|
48
|
-
lines: LineInfo[];
|
|
49
|
-
}): HitTestResult | null;
|
|
50
|
-
//# sourceMappingURL=selection-layout-dom.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"selection-layout-dom.d.ts","sourceRoot":"","sources":["../../../../src/cake/engine/selection/selection-layout-dom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,UAAU,EAEV,QAAQ,EAET,MAAM,oBAAoB,CAAC;AAG5B,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC,GAAG,UAAU,CAOb;AAqBD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CA2B9D;AA+UD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;IACvB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,GAAG,cAAc,GAAG,IAAI,CA+CxB;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE;IAChD,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;CACxB,GAAG,WAAW,GAAG,IAAI,CAUrB;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE;IACrD,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,WAAW,GAAG,IAAI,CAwCrB;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,WAAW,EACjB,SAAS,EAAE,MAAM,GAChB,WAAW,GAAG,IAAI,CAEpB;AAMD,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,MAAM,GACnB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAiBhC;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;IACvB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAiC7D;AAED,wBAAgB,uBAAuB,CACrC,gBAAgB,EAAE,MAAM,EAAE,EAC1B,MAAM,EAAE,MAAM,GACb,MAAM,CAER;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;IACvB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,GAAG,aAAa,GAAG,IAAI,CAkXvB"}
|