@adecore/editor 0.39.0 → 0.40.1
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/controller.d.ts +1 -0
- package/dist/controller.js +17 -28
- package/dist/engine.js +2 -9
- package/dist/find.js +12 -13
- package/dist/layout.js +7 -2
- package/dist/paint.d.ts +2 -0
- package/dist/paint.js +23 -20
- package/dist/view.d.ts +3 -2
- package/dist/view.js +46 -59
- package/package.json +6 -6
- package/src/attribution.ts +14 -0
- package/src/code-block.ts +25 -0
- package/src/column-selection.ts +10 -0
- package/src/controller.ts +189 -28
- package/src/engine.ts +87 -9
- package/src/fake.ts +79 -0
- package/src/find-search.ts +20 -0
- package/src/find.ts +135 -14
- package/src/geometry-stops.ts +10 -0
- package/src/grammar-preparation.ts +23 -0
- package/src/index.ts +1 -0
- package/src/input.ts +13 -0
- package/src/keymap-table.ts +9 -0
- package/src/keymap.ts +25 -0
- package/src/layout-changes.ts +7 -0
- package/src/layout.ts +219 -3
- package/src/lens.ts +3 -0
- package/src/listeners.ts +1 -0
- package/src/metrics.ts +14 -0
- package/src/modifier-gesture.ts +17 -0
- package/src/native-input.ts +27 -0
- package/src/offsets.ts +10 -0
- package/src/outline.ts +38 -0
- package/src/overview.ts +13 -0
- package/src/paint.ts +140 -20
- package/src/php-html.ts +1 -0
- package/src/pointer.ts +50 -0
- package/src/scroll-animation.ts +10 -0
- package/src/scroll.ts +7 -0
- package/src/search-client.ts +32 -0
- package/src/search-worker.ts +38 -0
- package/src/semantic.ts +12 -0
- package/src/shiki-document.ts +19 -0
- package/src/shiki-worker.ts +68 -0
- package/src/shiki.ts +37 -0
- package/src/testing.ts +17 -0
- package/src/theme-scopes.ts +14 -0
- package/src/tokens.ts +31 -0
- package/src/touch.ts +16 -0
- package/src/tracked-range.ts +5 -0
- package/src/uniform-geometry.ts +10 -0
- package/src/view.ts +481 -75
- package/src/worker-client.ts +54 -0
package/src/attribution.ts
CHANGED
|
@@ -50,21 +50,27 @@ export class AttributionRuns {
|
|
|
50
50
|
/* Marks name lines one-based and inclusive; `lineBounds` answers for the document as it is now. */
|
|
51
51
|
set(marks: readonly (EditorLineHighlight & { id: string })[], lineCount: number, lineBounds: (line: number) => { start: number; end: number }): void {
|
|
52
52
|
const clamp = (line: number): number => Math.min(lineCount, Math.max(1, Math.trunc(line) || 1)) - 1;
|
|
53
|
+
|
|
53
54
|
this.runs = marks.map((mark) => {
|
|
54
55
|
const start = clamp(mark.startLine);
|
|
55
56
|
const end = Math.max(start, clamp(mark.endLine));
|
|
57
|
+
|
|
56
58
|
const emphasis = (mark.emphasis ?? []).slice(0, end - start + 1).flatMap((ranges, index) => {
|
|
57
59
|
const bounds = lineBounds(start + index);
|
|
58
60
|
const length = bounds.end - bounds.start;
|
|
61
|
+
|
|
59
62
|
return ranges.flatMap(([from, to]) => {
|
|
60
63
|
if (!Number.isFinite(from) || !Number.isFinite(to)) {
|
|
61
64
|
return [];
|
|
62
65
|
}
|
|
66
|
+
|
|
63
67
|
const first = Math.min(length, Math.max(0, Math.trunc(from)));
|
|
64
68
|
const last = Math.min(length, Math.max(0, Math.trunc(to)));
|
|
69
|
+
|
|
65
70
|
return last > first ? [{ from: bounds.start + first, to: bounds.start + last }] : [];
|
|
66
71
|
});
|
|
67
72
|
});
|
|
73
|
+
|
|
68
74
|
return {
|
|
69
75
|
id: mark.id,
|
|
70
76
|
color: mark.color,
|
|
@@ -93,29 +99,37 @@ export class AttributionRuns {
|
|
|
93
99
|
/* The run on each line from `first` to `last`, zero-based, where `from` and `to` are the offsets they span; where runs overlap the one set last wins. */
|
|
94
100
|
linesIn(first: number, last: number, from: number, to: number, lineOf: (offset: number) => number): Map<number, AttributedLines> {
|
|
95
101
|
const lines = new Map<number, AttributedLines>();
|
|
102
|
+
|
|
96
103
|
for (const run of this.runs) {
|
|
97
104
|
if (run.to < from || run.from > to) {
|
|
98
105
|
continue;
|
|
99
106
|
}
|
|
107
|
+
|
|
100
108
|
const value = { id: run.id, color: run.color, sign: run.sign, fill: run.fill, bar: run.bar };
|
|
101
109
|
const emphasis = new Map<number, { from: number; to: number }[]>();
|
|
110
|
+
|
|
102
111
|
for (const range of run.emphasis) {
|
|
103
112
|
if (range.to <= from || range.from > to) {
|
|
104
113
|
continue;
|
|
105
114
|
}
|
|
115
|
+
|
|
106
116
|
const endLine = Math.min(lineOf(range.to - 1), last);
|
|
117
|
+
|
|
107
118
|
for (let line = Math.max(lineOf(range.from), first); line <= endLine; line++) {
|
|
108
119
|
const ranges = emphasis.get(line) ?? [];
|
|
109
120
|
ranges.push(range);
|
|
110
121
|
emphasis.set(line, ranges);
|
|
111
122
|
}
|
|
112
123
|
}
|
|
124
|
+
|
|
113
125
|
const end = Math.min(Math.max(lineOf(run.from), lineOf(run.to)), last);
|
|
126
|
+
|
|
114
127
|
for (let line = Math.max(lineOf(run.from), first); line <= end; line++) {
|
|
115
128
|
const ranges = emphasis.get(line);
|
|
116
129
|
lines.set(line, ranges === undefined ? value : { ...value, emphasis: ranges });
|
|
117
130
|
}
|
|
118
131
|
}
|
|
132
|
+
|
|
119
133
|
return lines;
|
|
120
134
|
}
|
|
121
135
|
}
|
package/src/code-block.ts
CHANGED
|
@@ -19,86 +19,111 @@ export function renderCodeBlock(
|
|
|
19
19
|
block.className = 'se-code-block';
|
|
20
20
|
block.style.tabSize = String(tabSize);
|
|
21
21
|
const lines = text.split(/\r?\n/);
|
|
22
|
+
|
|
22
23
|
lines.forEach((line, index) => {
|
|
23
24
|
const row = document.createElement('div');
|
|
24
25
|
row.className = 'se-code-row';
|
|
26
|
+
|
|
25
27
|
if (options.color !== undefined) {
|
|
26
28
|
row.style.background = tintValue(options.color);
|
|
27
29
|
}
|
|
30
|
+
|
|
28
31
|
const gutter = codeGutter(document, options, index);
|
|
29
32
|
const code = document.createElement('div');
|
|
30
33
|
code.className = 'se-code-text';
|
|
34
|
+
|
|
31
35
|
if (options.faded) {
|
|
32
36
|
code.dataset.faded = 'true';
|
|
33
37
|
}
|
|
38
|
+
|
|
34
39
|
const emphasis = options.emphasis?.[index] ?? [];
|
|
40
|
+
|
|
35
41
|
if (emphasis.length > 0 && options.color !== undefined) {
|
|
36
42
|
row.style.setProperty('--se-emphasis', colorValue(options.color));
|
|
37
43
|
}
|
|
44
|
+
|
|
38
45
|
fill(code, line, tokens?.[index] ?? null, emphasis);
|
|
39
46
|
row.append(gutter, code);
|
|
40
47
|
block.append(row);
|
|
41
48
|
});
|
|
49
|
+
|
|
42
50
|
container.append(block);
|
|
43
51
|
}
|
|
44
52
|
|
|
45
53
|
function codeGutter(document: Document, options: EditorCodeBlockOptions, index: number): HTMLElement {
|
|
46
54
|
const gutter = document.createElement('div');
|
|
47
55
|
gutter.className = 'se-code-gutter';
|
|
56
|
+
|
|
48
57
|
if (options.firstLine !== undefined) {
|
|
49
58
|
const number = document.createElement('span');
|
|
50
59
|
number.textContent = String(options.firstLine + index);
|
|
51
60
|
gutter.append(number);
|
|
52
61
|
}
|
|
62
|
+
|
|
53
63
|
if (options.sign) {
|
|
54
64
|
const sign = document.createElement('span');
|
|
55
65
|
sign.className = 'se-line-sign';
|
|
56
66
|
sign.textContent = options.sign;
|
|
67
|
+
|
|
57
68
|
if (options.color !== undefined) {
|
|
58
69
|
sign.style.color = colorValue(options.color);
|
|
59
70
|
}
|
|
71
|
+
|
|
60
72
|
gutter.append(sign);
|
|
61
73
|
}
|
|
74
|
+
|
|
62
75
|
if (options.color !== undefined) {
|
|
63
76
|
const bar = document.createElement('span');
|
|
64
77
|
bar.className = 'se-attribution';
|
|
65
78
|
bar.style.background = colorValue(options.color);
|
|
66
79
|
gutter.append(bar);
|
|
67
80
|
}
|
|
81
|
+
|
|
68
82
|
return gutter;
|
|
69
83
|
}
|
|
70
84
|
|
|
71
85
|
function fill(element: HTMLElement, line: string, tokens: readonly LineToken[] | null, emphasis: ReadonlyArray<readonly [number, number]>): void {
|
|
72
86
|
if (tokens === null && emphasis.length === 0) {
|
|
73
87
|
element.textContent = line;
|
|
88
|
+
|
|
74
89
|
return;
|
|
75
90
|
}
|
|
91
|
+
|
|
76
92
|
const spans: Array<{ start: number; end: number; token: LineToken | null }> = [];
|
|
77
93
|
let start = 0;
|
|
94
|
+
|
|
78
95
|
for (const token of tokens ?? []) {
|
|
79
96
|
const end = Math.min(line.length, start + token.length);
|
|
97
|
+
|
|
80
98
|
if (end > start) {
|
|
81
99
|
spans.push({ start, end, token });
|
|
82
100
|
}
|
|
101
|
+
|
|
83
102
|
start = end;
|
|
84
103
|
}
|
|
104
|
+
|
|
85
105
|
if (start < line.length) {
|
|
86
106
|
spans.push({ start, end: line.length, token: null });
|
|
87
107
|
}
|
|
108
|
+
|
|
88
109
|
for (const { start: from, end: to, token } of spans) {
|
|
89
110
|
// A token is cut at the edges of every emphasis that crosses it, so each piece is one color and either on or off.
|
|
90
111
|
const cuts = [...new Set([from, to, ...emphasis.flatMap((range) => range).filter((cut) => cut > from && cut < to)])].sort(
|
|
91
112
|
(left, right) => left - right
|
|
92
113
|
);
|
|
114
|
+
|
|
93
115
|
for (let i = 0; i < cuts.length - 1; i++) {
|
|
94
116
|
const piece = element.ownerDocument.createElement('span');
|
|
95
117
|
piece.textContent = line.slice(cuts[i]!, cuts[i + 1]!);
|
|
118
|
+
|
|
96
119
|
if (token !== null) {
|
|
97
120
|
styleSpan(piece, token);
|
|
98
121
|
}
|
|
122
|
+
|
|
99
123
|
if (emphasis.some(([emphasisStart, emphasisEnd]) => emphasisStart <= cuts[i]! && cuts[i + 1]! <= emphasisEnd)) {
|
|
100
124
|
piece.className = 'se-code-emphasis';
|
|
101
125
|
}
|
|
126
|
+
|
|
102
127
|
element.append(piece);
|
|
103
128
|
}
|
|
104
129
|
}
|
package/src/column-selection.ts
CHANGED
|
@@ -28,35 +28,45 @@ export function columnSelections(layout: EditorLayout, from: ContentPoint, to: C
|
|
|
28
28
|
const right = Math.max(fromCell, toCell);
|
|
29
29
|
const reversed = toCell < fromCell;
|
|
30
30
|
const result: Selection[] = [];
|
|
31
|
+
|
|
31
32
|
for (let line = Math.min(fromLine, toLine); line <= Math.max(fromLine, toLine); line++) {
|
|
32
33
|
const row = layout.rowForLine(line);
|
|
34
|
+
|
|
33
35
|
if (row.kind !== 'text' || layout.isHidden(line)) {
|
|
34
36
|
continue;
|
|
35
37
|
}
|
|
38
|
+
|
|
36
39
|
const geometry = layout.geometry(row);
|
|
37
40
|
const endX = geometry.rowStarts.length > 1 ? geometry.rowEnds[0]! : xOfStop(geometry, stopCount(geometry) - 1);
|
|
41
|
+
|
|
38
42
|
const offsetAt = (cell: number): number => layout.offsetAtX(geometry, 0, TEXT_PADDING + cell * charWidth).offset;
|
|
43
|
+
|
|
39
44
|
if (cellAt(layout, endX + TEXT_PADDING) < left) {
|
|
40
45
|
if (left === right) {
|
|
41
46
|
const end = document.getLine(line).end;
|
|
42
47
|
result.push({ anchor: end, head: end });
|
|
43
48
|
}
|
|
49
|
+
|
|
44
50
|
continue;
|
|
45
51
|
}
|
|
52
|
+
|
|
46
53
|
const start = offsetAt(left);
|
|
47
54
|
const end = offsetAt(right);
|
|
48
55
|
result.push(reversed ? { anchor: end, head: start } : { anchor: start, head: end });
|
|
49
56
|
}
|
|
57
|
+
|
|
50
58
|
if (result.length === 0) {
|
|
51
59
|
const end = document.getLine(toLine).end;
|
|
52
60
|
result.push({ anchor: end, head: end });
|
|
53
61
|
}
|
|
62
|
+
|
|
54
63
|
return result;
|
|
55
64
|
}
|
|
56
65
|
|
|
57
66
|
/* Whether two points are in the same cell of the same line, which makes a press with alt a click and not yet a box. */
|
|
58
67
|
export function sameCell(layout: EditorLayout, from: ContentPoint, to: ContentPoint): boolean {
|
|
59
68
|
const document = layout.document;
|
|
69
|
+
|
|
60
70
|
return (
|
|
61
71
|
cellAt(layout, from.x) === cellAt(layout, to.x) &&
|
|
62
72
|
document.positionAt(layout.hitTest(from.x, from.y)).line === document.positionAt(layout.hitTest(to.x, to.y)).line
|