@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.
Files changed (62) hide show
  1. package/dist/cake/core/mapping/cursor-source-map.d.ts +11 -0
  2. package/dist/cake/core/mapping/cursor-source-map.d.ts.map +1 -1
  3. package/dist/cake/core/mapping/cursor-source-map.js +159 -21
  4. package/dist/cake/core/runtime.d.ts +6 -0
  5. package/dist/cake/core/runtime.d.ts.map +1 -1
  6. package/dist/cake/core/runtime.js +344 -221
  7. package/dist/cake/dom/render.d.ts +32 -2
  8. package/dist/cake/dom/render.d.ts.map +1 -1
  9. package/dist/cake/dom/render.js +401 -118
  10. package/dist/cake/editor/cake-editor.d.ts +11 -2
  11. package/dist/cake/editor/cake-editor.d.ts.map +1 -1
  12. package/dist/cake/editor/cake-editor.js +178 -100
  13. package/dist/cake/editor/internal/editor-text-model.d.ts +49 -0
  14. package/dist/cake/editor/internal/editor-text-model.d.ts.map +1 -0
  15. package/dist/cake/editor/internal/editor-text-model.js +284 -0
  16. package/dist/cake/editor/selection/selection-geometry-dom.d.ts +5 -1
  17. package/dist/cake/editor/selection/selection-geometry-dom.d.ts.map +1 -1
  18. package/dist/cake/editor/selection/selection-geometry-dom.js +4 -5
  19. package/dist/cake/editor/selection/selection-layout-dom.d.ts.map +1 -1
  20. package/dist/cake/editor/selection/selection-layout-dom.js +2 -5
  21. package/dist/cake/editor/selection/selection-layout.d.ts +2 -15
  22. package/dist/cake/editor/selection/selection-layout.d.ts.map +1 -1
  23. package/dist/cake/editor/selection/selection-layout.js +1 -99
  24. package/dist/cake/editor/selection/selection-navigation.d.ts +4 -0
  25. package/dist/cake/editor/selection/selection-navigation.d.ts.map +1 -1
  26. package/dist/cake/editor/selection/selection-navigation.js +1 -2
  27. package/dist/cake/extensions/index.d.ts +2 -1
  28. package/dist/cake/extensions/index.d.ts.map +1 -1
  29. package/dist/cake/extensions/index.js +3 -1
  30. package/dist/cake/extensions/link/link.d.ts.map +1 -1
  31. package/dist/cake/extensions/link/link.js +1 -7
  32. package/dist/cake/extensions/shared/structural-reparse-policy.d.ts +7 -0
  33. package/dist/cake/extensions/shared/structural-reparse-policy.d.ts.map +1 -0
  34. package/dist/cake/extensions/shared/structural-reparse-policy.js +16 -0
  35. package/package.json +5 -2
  36. package/dist/cake/editor/selection/visible-text.d.ts +0 -5
  37. package/dist/cake/editor/selection/visible-text.d.ts.map +0 -1
  38. package/dist/cake/editor/selection/visible-text.js +0 -66
  39. package/dist/cake/engine/cake-engine.d.ts +0 -230
  40. package/dist/cake/engine/cake-engine.d.ts.map +0 -1
  41. package/dist/cake/engine/cake-engine.js +0 -3589
  42. package/dist/cake/engine/selection/selection-geometry-dom.d.ts +0 -24
  43. package/dist/cake/engine/selection/selection-geometry-dom.d.ts.map +0 -1
  44. package/dist/cake/engine/selection/selection-geometry-dom.js +0 -302
  45. package/dist/cake/engine/selection/selection-geometry.d.ts +0 -22
  46. package/dist/cake/engine/selection/selection-geometry.d.ts.map +0 -1
  47. package/dist/cake/engine/selection/selection-geometry.js +0 -158
  48. package/dist/cake/engine/selection/selection-layout-dom.d.ts +0 -50
  49. package/dist/cake/engine/selection/selection-layout-dom.d.ts.map +0 -1
  50. package/dist/cake/engine/selection/selection-layout-dom.js +0 -781
  51. package/dist/cake/engine/selection/selection-layout.d.ts +0 -55
  52. package/dist/cake/engine/selection/selection-layout.d.ts.map +0 -1
  53. package/dist/cake/engine/selection/selection-layout.js +0 -128
  54. package/dist/cake/engine/selection/selection-navigation.d.ts +0 -22
  55. package/dist/cake/engine/selection/selection-navigation.d.ts.map +0 -1
  56. package/dist/cake/engine/selection/selection-navigation.js +0 -229
  57. package/dist/cake/engine/selection/visible-text.d.ts +0 -5
  58. package/dist/cake/engine/selection/visible-text.d.ts.map +0 -1
  59. package/dist/cake/engine/selection/visible-text.js +0 -66
  60. package/dist/cake/react/CakeEditor.d.ts +0 -58
  61. package/dist/cake/react/CakeEditor.d.ts.map +0 -1
  62. package/dist/cake/react/CakeEditor.js +0 -225
@@ -0,0 +1,49 @@
1
+ import type { Block, Doc, Selection } from "../../core/types";
2
+ export type LineInfo = {
3
+ lineIndex: number;
4
+ lineStartOffset: number;
5
+ text: string;
6
+ cursorLength: number;
7
+ hasNewline: boolean;
8
+ cursorToCodeUnit: number[];
9
+ isAtomic: boolean;
10
+ };
11
+ export type LineOffsetResolution = {
12
+ lineIndex: number;
13
+ offsetInLine: number;
14
+ };
15
+ export type StructuralLineInfo = LineInfo & {
16
+ path: number[];
17
+ parentPath: number[];
18
+ indexInParent: number;
19
+ block: Block;
20
+ };
21
+ export declare class EditorTextModel {
22
+ private lines;
23
+ private lineOffsets;
24
+ private visibleText;
25
+ private cursorLength;
26
+ constructor(doc?: Doc);
27
+ rebuild(doc: Doc): void;
28
+ getLines(): LineInfo[];
29
+ getStructuralLines(): readonly StructuralLineInfo[];
30
+ getLineOffsets(): readonly number[];
31
+ getVisibleText(): string;
32
+ getCursorLength(): number;
33
+ resolveOffsetToLine(offset: number): LineOffsetResolution;
34
+ visibleOffsetToCursorOffset(visibleOffset: number): number | null;
35
+ cursorOffsetToVisibleOffset(cursorOffset: number): number;
36
+ getTextSelection(selection: Selection): {
37
+ start: number;
38
+ end: number;
39
+ };
40
+ getTextBeforeCursor(selection: Selection, maxChars: number): string;
41
+ getTextAroundCursor(selection: Selection, before: number, after: number): {
42
+ before: string;
43
+ after: string;
44
+ };
45
+ getTextForCursorRange(start: number, end: number): string;
46
+ getGraphemeAtCursor(cursorOffset: number): string | null;
47
+ }
48
+ export declare function getEditorTextModelForDoc(doc: Doc): EditorTextModel;
49
+ //# sourceMappingURL=editor-text-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-text-model.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/internal/editor-text-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGtE,MAAM,MAAM,QAAQ,GAAG;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG;IAC1C,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AA+KF,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAcX;IACF,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,YAAY,CAAK;gBAEb,GAAG,CAAC,EAAE,GAAG;IAMrB,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI;IASvB,QAAQ,IAAI,QAAQ,EAAE;IAItB,kBAAkB,IAAI,SAAS,kBAAkB,EAAE;IAInD,cAAc,IAAI,SAAS,MAAM,EAAE;IAInC,cAAc,IAAI,MAAM;IAIxB,eAAe,IAAI,MAAM;IAIzB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,oBAAoB;IAOzD,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAiCjE,2BAA2B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IA0BzD,gBAAgB,CAAC,SAAS,EAAE,SAAS,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;IAOtE,mBAAmB,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAUnE,mBAAmB,CACjB,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IAepC,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAQzD,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAYzD;AAID,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,GAAG,GAAG,eAAe,CAQlE"}
@@ -0,0 +1,284 @@
1
+ import { graphemeSegments } from "../../shared/segmenter";
2
+ function computeLineOffsets(lines) {
3
+ return lines.map((line) => line.lineStartOffset);
4
+ }
5
+ function resolveOffsetInLines(params) {
6
+ const { lines } = params;
7
+ if (lines.length === 0) {
8
+ return { lineIndex: 0, offsetInLine: 0 };
9
+ }
10
+ const lastLineIndex = lines.length - 1;
11
+ const lastLine = lines[lastLineIndex] ?? {
12
+ lineStartOffset: 0,
13
+ cursorLength: 0,
14
+ };
15
+ const totalLength = lastLine.lineStartOffset + (lastLine.cursorLength ?? 0);
16
+ const clampedOffset = Math.max(0, Math.min(params.offset, totalLength));
17
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
18
+ const line = lines[lineIndex];
19
+ const lineStart = line.lineStartOffset;
20
+ const lineEnd = lineStart + line.cursorLength;
21
+ if (clampedOffset <= lineEnd || lineIndex === lastLineIndex) {
22
+ return {
23
+ lineIndex,
24
+ offsetInLine: clampedOffset - lineStart,
25
+ };
26
+ }
27
+ }
28
+ return {
29
+ lineIndex: lastLineIndex,
30
+ offsetInLine: lines[lastLineIndex]?.cursorLength ?? 0,
31
+ };
32
+ }
33
+ function cursorOffsetFromCodeUnit(line, codeUnitOffset) {
34
+ const maxCodeUnit = line.cursorToCodeUnit[line.cursorToCodeUnit.length - 1] ?? 0;
35
+ const clamped = Math.max(0, Math.min(codeUnitOffset, maxCodeUnit));
36
+ for (let i = 0; i < line.cursorToCodeUnit.length; i += 1) {
37
+ if (line.cursorToCodeUnit[i] === clamped) {
38
+ return i;
39
+ }
40
+ if (line.cursorToCodeUnit[i] > clamped) {
41
+ return Math.max(0, i - 1);
42
+ }
43
+ }
44
+ return line.cursorLength;
45
+ }
46
+ function flattenDocToLines(doc) {
47
+ const lines = [];
48
+ const appendBlock = (block, path) => {
49
+ if (block.type === "paragraph") {
50
+ lines.push({
51
+ path,
52
+ parentPath: path.slice(0, -1),
53
+ indexInParent: path[path.length - 1] ?? 0,
54
+ block,
55
+ text: block.content.map(flattenInline).join(""),
56
+ isAtomic: false,
57
+ });
58
+ return;
59
+ }
60
+ if (block.type === "block-wrapper") {
61
+ block.blocks.forEach((child, index) => appendBlock(child, [...path, index]));
62
+ return;
63
+ }
64
+ if (block.type === "block-atom") {
65
+ // Atomic blocks occupy one cursor unit and are treated as empty layout lines.
66
+ lines.push({
67
+ path,
68
+ parentPath: path.slice(0, -1),
69
+ indexInParent: path[path.length - 1] ?? 0,
70
+ block,
71
+ text: "",
72
+ isAtomic: true,
73
+ });
74
+ }
75
+ };
76
+ doc.blocks.forEach((block, index) => appendBlock(block, [index]));
77
+ if (lines.length === 0) {
78
+ const block = { type: "paragraph", content: [] };
79
+ lines.push({
80
+ path: [0],
81
+ parentPath: [],
82
+ indexInParent: 0,
83
+ block,
84
+ text: "",
85
+ isAtomic: false,
86
+ });
87
+ }
88
+ return lines;
89
+ }
90
+ function flattenInline(inline) {
91
+ if (inline.type === "text") {
92
+ return inline.text;
93
+ }
94
+ if (inline.type === "inline-wrapper") {
95
+ return inline.children.map(flattenInline).join("");
96
+ }
97
+ if (inline.type === "inline-atom") {
98
+ return " ";
99
+ }
100
+ return "";
101
+ }
102
+ function buildCursorToCodeUnit(text) {
103
+ const mapping = [0];
104
+ for (const segment of graphemeSegments(text)) {
105
+ mapping.push(segment.index + segment.segment.length);
106
+ }
107
+ if (mapping.length === 0) {
108
+ mapping.push(0);
109
+ }
110
+ return mapping;
111
+ }
112
+ function buildLines(doc) {
113
+ const flattenedLines = flattenDocToLines(doc);
114
+ let lineStartOffset = 0;
115
+ return flattenedLines.map((line, lineIndex) => {
116
+ const cursorToCodeUnit = buildCursorToCodeUnit(line.text);
117
+ const cursorLength = Math.max(0, cursorToCodeUnit.length - 1);
118
+ const hasNewline = lineIndex < flattenedLines.length - 1;
119
+ const builtLine = {
120
+ lineIndex,
121
+ lineStartOffset,
122
+ path: line.path,
123
+ parentPath: line.parentPath,
124
+ indexInParent: line.indexInParent,
125
+ block: line.block,
126
+ text: line.text,
127
+ cursorLength,
128
+ hasNewline,
129
+ cursorToCodeUnit,
130
+ isAtomic: line.isAtomic,
131
+ };
132
+ lineStartOffset += cursorLength + (hasNewline ? 1 : 0);
133
+ return builtLine;
134
+ });
135
+ }
136
+ export class EditorTextModel {
137
+ constructor(doc) {
138
+ this.lines = [
139
+ {
140
+ lineIndex: 0,
141
+ lineStartOffset: 0,
142
+ path: [0],
143
+ parentPath: [],
144
+ indexInParent: 0,
145
+ block: { type: "paragraph", content: [] },
146
+ text: "",
147
+ cursorLength: 0,
148
+ hasNewline: false,
149
+ cursorToCodeUnit: [0],
150
+ isAtomic: false,
151
+ },
152
+ ];
153
+ this.lineOffsets = [0];
154
+ this.visibleText = "";
155
+ this.cursorLength = 0;
156
+ if (doc) {
157
+ this.rebuild(doc);
158
+ }
159
+ }
160
+ rebuild(doc) {
161
+ this.lines = buildLines(doc);
162
+ this.lineOffsets = computeLineOffsets(this.lines);
163
+ this.visibleText = this.lines.map((line) => line.text).join("\n");
164
+ const lastLine = this.lines[this.lines.length - 1];
165
+ const lastStart = this.lineOffsets[this.lineOffsets.length - 1] ?? 0;
166
+ this.cursorLength = lastStart + (lastLine?.cursorLength ?? 0);
167
+ }
168
+ getLines() {
169
+ return this.lines;
170
+ }
171
+ getStructuralLines() {
172
+ return this.lines;
173
+ }
174
+ getLineOffsets() {
175
+ return this.lineOffsets;
176
+ }
177
+ getVisibleText() {
178
+ return this.visibleText;
179
+ }
180
+ getCursorLength() {
181
+ return this.cursorLength;
182
+ }
183
+ resolveOffsetToLine(offset) {
184
+ return resolveOffsetInLines({
185
+ lines: this.lines,
186
+ offset,
187
+ });
188
+ }
189
+ visibleOffsetToCursorOffset(visibleOffset) {
190
+ if (this.lines.length === 0) {
191
+ return 0;
192
+ }
193
+ const clampedOffset = Math.max(0, visibleOffset);
194
+ let codeUnitIndex = 0;
195
+ for (let lineIndex = 0; lineIndex < this.lines.length; lineIndex += 1) {
196
+ const line = this.lines[lineIndex];
197
+ const lineStart = codeUnitIndex;
198
+ const lineEnd = lineStart + line.text.length;
199
+ if (clampedOffset <= lineEnd || lineIndex === this.lines.length - 1) {
200
+ const offsetInLine = Math.max(0, Math.min(clampedOffset - lineStart, line.text.length));
201
+ const cursorOffsetInLine = cursorOffsetFromCodeUnit(line, offsetInLine);
202
+ const lineStartOffset = this.lineOffsets[lineIndex] ?? 0;
203
+ return lineStartOffset + cursorOffsetInLine;
204
+ }
205
+ codeUnitIndex = lineEnd + (line.hasNewline ? 1 : 0);
206
+ if (line.hasNewline && clampedOffset === codeUnitIndex) {
207
+ const lineStartOffset = this.lineOffsets[lineIndex] ?? 0;
208
+ return lineStartOffset + line.cursorLength + 1;
209
+ }
210
+ }
211
+ return null;
212
+ }
213
+ cursorOffsetToVisibleOffset(cursorOffset) {
214
+ if (this.lines.length === 0) {
215
+ return 0;
216
+ }
217
+ const { lineIndex, offsetInLine } = this.resolveOffsetToLine(cursorOffset);
218
+ let codeUnitIndex = 0;
219
+ for (let index = 0; index < this.lines.length; index += 1) {
220
+ const line = this.lines[index];
221
+ if (index === lineIndex) {
222
+ const clampedOffset = Math.max(0, Math.min(offsetInLine, line.cursorLength));
223
+ return codeUnitIndex + (line.cursorToCodeUnit[clampedOffset] ?? 0);
224
+ }
225
+ codeUnitIndex += line.text.length + (line.hasNewline ? 1 : 0);
226
+ }
227
+ const lastLine = this.lines[this.lines.length - 1];
228
+ const lastStart = this.lineOffsets[this.lineOffsets.length - 1] ?? 0;
229
+ const lastOffset = Math.max(0, cursorOffset - lastStart);
230
+ return (codeUnitIndex +
231
+ (lastLine?.cursorToCodeUnit[lastOffset] ?? lastLine?.text.length ?? 0));
232
+ }
233
+ getTextSelection(selection) {
234
+ return {
235
+ start: this.cursorOffsetToVisibleOffset(selection.start),
236
+ end: this.cursorOffsetToVisibleOffset(selection.end),
237
+ };
238
+ }
239
+ getTextBeforeCursor(selection, maxChars) {
240
+ const text = this.visibleText;
241
+ const cursor = Math.max(0, Math.min(this.cursorOffsetToVisibleOffset(selection.start), text.length));
242
+ const length = Math.max(0, maxChars);
243
+ return text.slice(Math.max(0, cursor - length), cursor);
244
+ }
245
+ getTextAroundCursor(selection, before, after) {
246
+ const text = this.visibleText;
247
+ const cursor = Math.max(0, Math.min(this.cursorOffsetToVisibleOffset(selection.start), text.length));
248
+ const beforeLength = Math.max(0, before);
249
+ const afterLength = Math.max(0, after);
250
+ return {
251
+ before: text.slice(Math.max(0, cursor - beforeLength), cursor),
252
+ after: text.slice(cursor, Math.min(text.length, cursor + afterLength)),
253
+ };
254
+ }
255
+ getTextForCursorRange(start, end) {
256
+ const normalizedStart = Math.min(start, end);
257
+ const normalizedEnd = Math.max(start, end);
258
+ const visibleStart = this.cursorOffsetToVisibleOffset(normalizedStart);
259
+ const visibleEnd = this.cursorOffsetToVisibleOffset(normalizedEnd);
260
+ return this.visibleText.slice(visibleStart, visibleEnd);
261
+ }
262
+ getGraphemeAtCursor(cursorOffset) {
263
+ if (this.lines.length === 0) {
264
+ return null;
265
+ }
266
+ const { lineIndex, offsetInLine } = this.resolveOffsetToLine(cursorOffset);
267
+ const line = this.lines[lineIndex];
268
+ if (!line || offsetInLine >= line.cursorLength) {
269
+ return null;
270
+ }
271
+ const segments = graphemeSegments(line.text);
272
+ return segments[offsetInLine]?.segment ?? null;
273
+ }
274
+ }
275
+ const textModelByDoc = new WeakMap();
276
+ export function getEditorTextModelForDoc(doc) {
277
+ const cached = textModelByDoc.get(doc);
278
+ if (cached) {
279
+ return cached;
280
+ }
281
+ const model = new EditorTextModel(doc);
282
+ textModelByDoc.set(doc, model);
283
+ return model;
284
+ }
@@ -1,5 +1,5 @@
1
1
  import type { Selection } from "../../core/types";
2
- import { type LineInfo } from "./selection-layout";
2
+ import type { LineInfo } from "./selection-layout";
3
3
  import { type SelectionRect } from "./selection-geometry";
4
4
  export type SelectionGeometry = {
5
5
  selectionRects: SelectionRect[];
@@ -11,6 +11,10 @@ export declare function getSelectionGeometry(params: {
11
11
  container: HTMLElement;
12
12
  docLines: LineInfo[];
13
13
  selection: Selection;
14
+ resolveOffsetToLine: (offset: number) => {
15
+ lineIndex: number;
16
+ offsetInLine: number;
17
+ };
14
18
  }): SelectionGeometry;
15
19
  export declare function getCaretRect(params: {
16
20
  lineElement: HTMLElement;
@@ -1 +1 @@
1
- {"version":3,"file":"selection-geometry-dom.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/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,CAuO9C"}
1
+ {"version":3,"file":"selection-geometry-dom.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/selection/selection-geometry-dom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAUnD,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;IACrB,mBAAmB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QACvC,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH,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,CAuO9C"}
@@ -1,4 +1,3 @@
1
- import { resolveOffsetToLine } from "./selection-layout";
2
1
  import { createOffsetToXMeasurer, cursorOffsetToDomOffset, getLineElement, groupDomRectsByRow, measureLayoutModelRangeFromDom, resolveDomPosition, toLayoutRect, } from "./selection-layout-dom";
3
2
  import { computeCaretRect, computeSelectionRects, } from "./selection-geometry";
4
3
  export function getSelectionGeometry(params) {
@@ -12,8 +11,8 @@ export function getSelectionGeometry(params) {
12
11
  };
13
12
  const layout = shouldMeasureLayout(normalized)
14
13
  ? (() => {
15
- const startLine = resolveOffsetToLine(docLines, normalized.start);
16
- const endLine = resolveOffsetToLine(docLines, normalized.end);
14
+ const startLine = params.resolveOffsetToLine(normalized.start);
15
+ const endLine = params.resolveOffsetToLine(normalized.end);
17
16
  return measureLayoutModelRangeFromDom({
18
17
  lines: docLines,
19
18
  root,
@@ -25,7 +24,7 @@ export function getSelectionGeometry(params) {
25
24
  : null;
26
25
  const containerRect = container.getBoundingClientRect();
27
26
  const scroll = { top: container.scrollTop, left: container.scrollLeft };
28
- const startLine = resolveOffsetToLine(docLines, normalized.start);
27
+ const startLine = params.resolveOffsetToLine(normalized.start);
29
28
  const hasSelection = normalized.start !== normalized.end;
30
29
  if (!hasSelection) {
31
30
  const lineInfo = docLines[startLine.lineIndex];
@@ -73,7 +72,7 @@ export function getSelectionGeometry(params) {
73
72
  lines: docLines,
74
73
  });
75
74
  const focusOffset = normalized.affinity === "backward" ? normalized.start : normalized.end;
76
- const focusLine = resolveOffsetToLine(docLines, focusOffset);
75
+ const focusLine = params.resolveOffsetToLine(focusOffset);
77
76
  const focusLineElement = getLineElement(root, focusLine.lineIndex);
78
77
  let focusRect = null;
79
78
  if (focusLineElement) {
@@ -1 +1 @@
1
- {"version":3,"file":"selection-layout-dom.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/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;AA6VD,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,CA8CrB;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,CAoZvB"}
1
+ {"version":3,"file":"selection-layout-dom.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/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;AA6VD,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,CA2CrB;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,CAoZvB"}
@@ -1,4 +1,4 @@
1
- import { buildLayoutModel, getLineOffsets } from "./selection-layout";
1
+ import { buildLayoutModel } from "./selection-layout";
2
2
  export function toLayoutRect(params) {
3
3
  return {
4
4
  top: params.rect.top - params.containerRect.top + params.scroll.top,
@@ -402,8 +402,6 @@ export function measureLayoutModelRangeFromDom(params) {
402
402
  }
403
403
  const clampedStart = Math.max(0, Math.min(params.startLineIndex, params.lines.length - 1));
404
404
  const clampedEnd = Math.max(clampedStart, Math.min(params.endLineIndex, params.lines.length - 1));
405
- const lineOffsets = getLineOffsets(params.lines);
406
- let lineStartOffset = lineOffsets[clampedStart] ?? 0;
407
405
  const layouts = [];
408
406
  for (let lineIndex = clampedStart; lineIndex <= clampedEnd; lineIndex += 1) {
409
407
  const lineInfo = params.lines[lineIndex];
@@ -419,13 +417,12 @@ export function measureLayoutModelRangeFromDom(params) {
419
417
  });
420
418
  layouts.push({
421
419
  lineIndex: lineInfo.lineIndex,
422
- lineStartOffset,
420
+ lineStartOffset: lineInfo.lineStartOffset,
423
421
  lineLength: lineInfo.cursorLength,
424
422
  lineHasNewline: lineInfo.hasNewline,
425
423
  lineBox: measurement.lineBox,
426
424
  rows: measurement.rows,
427
425
  });
428
- lineStartOffset += lineInfo.cursorLength + (lineInfo.hasNewline ? 1 : 0);
429
426
  }
430
427
  return { container: measurer.container, lines: layouts };
431
428
  }
@@ -1,4 +1,4 @@
1
- import type { Doc } from "../../core/types";
1
+ import type { LineInfo } from "../internal/editor-text-model";
2
2
  export type LayoutRect = {
3
3
  top: number;
4
4
  left: number;
@@ -42,19 +42,6 @@ export type LayoutMeasurer = {
42
42
  container: LayoutRect;
43
43
  measureLine: (input: LineMeasurementInput) => LineMeasurement;
44
44
  };
45
- export type LineInfo = {
46
- lineIndex: number;
47
- text: string;
48
- cursorLength: number;
49
- hasNewline: boolean;
50
- cursorToCodeUnit: number[];
51
- isAtomic: boolean;
52
- };
45
+ export type { LineInfo };
53
46
  export declare function buildLayoutModel(lines: LineInfo[], measurer: LayoutMeasurer): LayoutModel;
54
- export declare function getDocLines(doc: Doc): LineInfo[];
55
- export declare function getLineOffsets(lines: LineInfo[]): number[];
56
- export declare function resolveOffsetToLine(lines: LineInfo[], offset: number): {
57
- lineIndex: number;
58
- offsetInLine: number;
59
- };
60
47
  //# sourceMappingURL=selection-layout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"selection-layout.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/selection/selection-layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,GAAG,EAAU,MAAM,kBAAkB,CAAC;AAG3D,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,6EAA6E;IAC7E,SAAS,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,UAAU,CAAC;IACpB,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,EAAE,UAAU,CAAC;IACtB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,UAAU,CAAC;IACpB,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,UAAU,CAAC;IACtB,WAAW,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,eAAe,CAAC;CAC/D,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,QAAQ,EAAE,EACjB,QAAQ,EAAE,cAAc,GACvB,WAAW,CAqCb;AAOD,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ,EAAE,CAchD;AA6BD,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAE,CAW1D;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,QAAQ,EAAE,EACjB,MAAM,EAAE,MAAM,GACb;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAsB7C"}
1
+ {"version":3,"file":"selection-layout.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/selection/selection-layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAE9D,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,6EAA6E;IAC7E,SAAS,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,UAAU,CAAC;IACpB,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,EAAE,UAAU,CAAC;IACtB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,UAAU,CAAC;IACpB,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,UAAU,CAAC;IACtB,WAAW,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,eAAe,CAAC;CAC/D,CAAC;AAEF,YAAY,EAAE,QAAQ,EAAE,CAAC;AAEzB,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,QAAQ,EAAE,EACjB,QAAQ,EAAE,cAAc,GACvB,WAAW,CAqCb"}
@@ -1,8 +1,6 @@
1
- import { graphemeSegments } from "../../shared/segmenter";
2
1
  export function buildLayoutModel(lines, measurer) {
3
2
  const layouts = [];
4
3
  let top = measurer.container.top;
5
- let lineStartOffset = 0;
6
4
  lines.forEach((line) => {
7
5
  const measurement = measurer.measureLine({
8
6
  lineIndex: line.lineIndex,
@@ -13,14 +11,13 @@ export function buildLayoutModel(lines, measurer) {
13
11
  });
14
12
  layouts.push({
15
13
  lineIndex: line.lineIndex,
16
- lineStartOffset,
14
+ lineStartOffset: line.lineStartOffset,
17
15
  lineLength: line.cursorLength,
18
16
  lineHasNewline: line.hasNewline,
19
17
  lineBox: measurement.lineBox,
20
18
  rows: measurement.rows,
21
19
  });
22
20
  top = measurement.lineBox.top + measurement.lineBox.height;
23
- lineStartOffset += line.cursorLength + (line.hasNewline ? 1 : 0);
24
21
  });
25
22
  const height = Math.max(measurer.container.height, top - measurer.container.top);
26
23
  return {
@@ -31,98 +28,3 @@ export function buildLayoutModel(lines, measurer) {
31
28
  lines: layouts,
32
29
  };
33
30
  }
34
- export function getDocLines(doc) {
35
- const flattenedLines = flattenBlocksWithAtomicInfo(doc.blocks);
36
- return flattenedLines.map((line, index) => {
37
- const cursorToCodeUnit = buildCursorToCodeUnit(line.text);
38
- const cursorLength = Math.max(0, cursorToCodeUnit.length - 1);
39
- return {
40
- lineIndex: index,
41
- text: line.text,
42
- cursorLength,
43
- hasNewline: index < flattenedLines.length - 1,
44
- cursorToCodeUnit,
45
- isAtomic: line.isAtomic,
46
- };
47
- });
48
- }
49
- function flattenBlocksWithAtomicInfo(blocks) {
50
- const lines = [];
51
- blocks.forEach((block) => {
52
- lines.push(...flattenBlockWithAtomicInfo(block));
53
- });
54
- if (lines.length === 0) {
55
- lines.push({ text: "", isAtomic: false });
56
- }
57
- return lines;
58
- }
59
- function flattenBlockWithAtomicInfo(block) {
60
- if (block.type === "paragraph") {
61
- return [
62
- { text: block.content.map(flattenInline).join(""), isAtomic: false },
63
- ];
64
- }
65
- if (block.type === "block-wrapper") {
66
- return flattenBlocksWithAtomicInfo(block.blocks);
67
- }
68
- if (block.type === "block-atom") {
69
- // Atomic blocks are represented as empty lines for layout purposes
70
- return [{ text: "", isAtomic: true }];
71
- }
72
- return [];
73
- }
74
- export function getLineOffsets(lines) {
75
- const offsets = [];
76
- let current = 0;
77
- lines.forEach((line) => {
78
- offsets.push(current);
79
- current += line.cursorLength;
80
- if (line.hasNewline) {
81
- current += 1;
82
- }
83
- });
84
- return offsets;
85
- }
86
- export function resolveOffsetToLine(lines, offset) {
87
- if (lines.length === 0) {
88
- return { lineIndex: 0, offsetInLine: 0 };
89
- }
90
- const lineOffsets = getLineOffsets(lines);
91
- const totalLength = lineOffsets[lineOffsets.length - 1] + lines[lines.length - 1].cursorLength;
92
- const clamped = Math.max(0, Math.min(offset, totalLength));
93
- for (let index = 0; index < lines.length; index += 1) {
94
- const lineStart = lineOffsets[index];
95
- const lineEnd = lineStart + lines[index].cursorLength;
96
- if (clamped <= lineEnd || index === lines.length - 1) {
97
- return { lineIndex: index, offsetInLine: clamped - lineStart };
98
- }
99
- }
100
- const lastIndex = lines.length - 1;
101
- return {
102
- lineIndex: lastIndex,
103
- offsetInLine: lines[lastIndex].cursorLength,
104
- };
105
- }
106
- function flattenInline(inline) {
107
- if (inline.type === "text") {
108
- return inline.text;
109
- }
110
- if (inline.type === "inline-wrapper") {
111
- return inline.children.map(flattenInline).join("");
112
- }
113
- if (inline.type === "inline-atom") {
114
- return " ";
115
- }
116
- return "";
117
- }
118
- function buildCursorToCodeUnit(text) {
119
- const segments = graphemeSegments(text);
120
- const mapping = [0];
121
- for (const segment of segments) {
122
- mapping.push(segment.index + segment.segment.length);
123
- }
124
- if (mapping.length === 0) {
125
- mapping.push(0);
126
- }
127
- return mapping;
128
- }
@@ -9,6 +9,10 @@ export declare function moveSelectionVertically(params: {
9
9
  lines: LineInfo[];
10
10
  layout: LayoutModel;
11
11
  selection: Selection;
12
+ resolveOffsetToLine: (offset: number) => {
13
+ lineIndex: number;
14
+ offsetInLine: number;
15
+ };
12
16
  direction: "up" | "down";
13
17
  goalX: number | null;
14
18
  focusRowIndex?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"selection-navigation.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/selection/selection-navigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAa,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG3E,KAAK,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;AAEvC,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAsIF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,CAChB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,KACN;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,QAAQ,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC7E,GAAG,wBAAwB,GAAG,IAAI,CAmKlC"}
1
+ {"version":3,"file":"selection-navigation.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/selection/selection-navigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAa,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE3E,KAAK,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;AAEvC,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAsIF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC;IACrB,mBAAmB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QACvC,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,CAChB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,KACN;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,QAAQ,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC7E,GAAG,wBAAwB,GAAG,IAAI,CAmKlC"}
@@ -1,4 +1,3 @@
1
- import { resolveOffsetToLine } from "./selection-layout";
2
1
  function rectRight(rect) {
3
2
  return rect.left + rect.width;
4
3
  }
@@ -103,7 +102,7 @@ export function moveSelectionVertically(params) {
103
102
  }
104
103
  const affinity = resolveSelectionAffinity(params.selection);
105
104
  const { anchor, focus } = resolveSelectionAnchorAndFocus(params.selection);
106
- const focusResolved = resolveOffsetToLine(lines, focus);
105
+ const focusResolved = params.resolveOffsetToLine(focus);
107
106
  const focusLineLayout = layout.lines[focusResolved.lineIndex];
108
107
  if (!focusLineLayout) {
109
108
  return null;
@@ -11,7 +11,8 @@ import { scrollbarExtension } from "./scrollbar";
11
11
  import { strikethroughExtension } from "./strikethrough/strikethrough";
12
12
  import { underlineExtension } from "./underline/underline";
13
13
  import { mentionExtension } from "./mention/mention";
14
- export { boldExtension, combinedEmphasisExtension, linkExtension, blockquoteExtension, italicExtension, headingExtension, imageExtension, plainTextListExtension, scrollbarExtension, strikethroughExtension, underlineExtension, mentionExtension, };
14
+ import { structuralReparsePolicyExtension } from "./shared/structural-reparse-policy";
15
+ export { boldExtension, combinedEmphasisExtension, linkExtension, blockquoteExtension, italicExtension, headingExtension, imageExtension, plainTextListExtension, scrollbarExtension, strikethroughExtension, underlineExtension, mentionExtension, structuralReparsePolicyExtension, };
15
16
  export declare const bundledExtensionsWithoutImage: import("../..").CakeExtension[];
16
17
  export declare const bundledExtensions: import("../..").CakeExtension[];
17
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cake/extensions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EACL,aAAa,EACb,yBAAyB,EACzB,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,sBAAsB,EACtB,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,GACjB,CAAC;AAEF,eAAO,MAAM,6BAA6B,iCAUzC,CAAC;AAEF,eAAO,MAAM,iBAAiB,iCAG7B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cake/extensions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AAEtF,OAAO,EACL,aAAa,EACb,yBAAyB,EACzB,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,sBAAsB,EACtB,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,gCAAgC,GACjC,CAAC;AAEF,eAAO,MAAM,6BAA6B,iCAWzC,CAAC;AAEF,eAAO,MAAM,iBAAiB,iCAG7B,CAAC"}
@@ -10,8 +10,10 @@ import { scrollbarExtension } from "./scrollbar";
10
10
  import { strikethroughExtension } from "./strikethrough/strikethrough";
11
11
  import { underlineExtension } from "./underline/underline";
12
12
  import { mentionExtension } from "./mention/mention";
13
- export { boldExtension, combinedEmphasisExtension, linkExtension, blockquoteExtension, italicExtension, headingExtension, imageExtension, plainTextListExtension, scrollbarExtension, strikethroughExtension, underlineExtension, mentionExtension, };
13
+ import { structuralReparsePolicyExtension } from "./shared/structural-reparse-policy";
14
+ export { boldExtension, combinedEmphasisExtension, linkExtension, blockquoteExtension, italicExtension, headingExtension, imageExtension, plainTextListExtension, scrollbarExtension, strikethroughExtension, underlineExtension, mentionExtension, structuralReparsePolicyExtension, };
14
15
  export const bundledExtensionsWithoutImage = [
16
+ structuralReparsePolicyExtension,
15
17
  blockquoteExtension,
16
18
  headingExtension,
17
19
  plainTextListExtension,