@motionscript/code 0.1.0-alpha.0 → 0.1.0-alpha.5
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/CHANGELOG.md +66 -0
- package/LICENSE +201 -201
- package/NOTICE +48 -0
- package/README.md +161 -77
- package/dist/browser/THIRD_PARTY_LICENSES.txt +431 -0
- package/dist/browser/index.js +7 -7
- package/dist/browser/index.js.map +3 -3
- package/dist/browser/manifest.json +85 -3
- package/dist/code-range.d.ts +7 -1
- package/dist/code-range.d.ts.map +1 -1
- package/dist/code-range.js +9 -1
- package/dist/code-range.js.map +1 -1
- package/dist/diff.d.ts +14 -0
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +134 -2
- package/dist/diff.js.map +1 -1
- package/dist/engine.d.ts +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +1 -1
- package/dist/engine.js.map +1 -1
- package/dist/highlight.d.ts +10 -2
- package/dist/highlight.d.ts.map +1 -1
- package/dist/highlight.js +40 -6
- package/dist/highlight.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +1 -1
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js.map +1 -1
- package/dist/measure-cache.d.ts +1 -1
- package/dist/measure-cache.d.ts.map +1 -1
- package/dist/measure-cache.js.map +1 -1
- package/dist/node.d.ts +62 -7
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +224 -42
- package/dist/node.js.map +1 -1
- package/dist/nodes.js.map +1 -1
- package/dist/render.d.ts +7 -2
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +60 -1
- package/dist/render.js.map +1 -1
- package/dist/style.d.ts +3 -3
- package/dist/style.d.ts.map +1 -1
- package/dist/style.js +10 -6
- package/dist/style.js.map +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js +5 -1
- package/dist/tokens.js.map +1 -1
- package/dist/transitions.d.ts +19 -1
- package/dist/transitions.d.ts.map +1 -1
- package/dist/transitions.js.map +1 -1
- package/package.json +7 -4
- package/registry.json +6 -6
- package/src/code-range.ts +165 -156
- package/src/diff.ts +351 -216
- package/src/engine.ts +21 -21
- package/src/highlight.ts +340 -291
- package/src/index.ts +3 -3
- package/src/layout.ts +157 -157
- package/src/measure-cache.ts +0 -0
- package/src/node.ts +1038 -834
- package/src/nodes.ts +18 -18
- package/src/render.ts +312 -247
- package/src/style.ts +255 -251
- package/src/tokens.ts +79 -75
- package/src/transitions.ts +204 -184
package/src/code-range.ts
CHANGED
|
@@ -1,156 +1,165 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A range over a code document. Lines and columns are 1-indexed.
|
|
3
|
-
*
|
|
4
|
-
* `endLine`/`endCol` may be `Infinity` to mean "to the end of the line" or
|
|
5
|
-
* "to the end of the document".
|
|
6
|
-
*/
|
|
7
|
-
export interface CodeRange {
|
|
8
|
-
startLine: number;
|
|
9
|
-
startCol: number;
|
|
10
|
-
endLine: number;
|
|
11
|
-
endCol: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Create a range that spans `length` characters starting at (line, col).
|
|
16
|
-
* If `length` is omitted, the range extends to the end of the line.
|
|
17
|
-
*
|
|
18
|
-
* Example:
|
|
19
|
-
* word(1, 3, 3) // line 1, column 3, spans 3 characters
|
|
20
|
-
* word(1, 3) // line 1, column 3, to end of line
|
|
21
|
-
*/
|
|
22
|
-
export function word(line: number, col: number, length?: number): CodeRange {
|
|
23
|
-
return {
|
|
24
|
-
startLine: line,
|
|
25
|
-
startCol: col,
|
|
26
|
-
endLine: line,
|
|
27
|
-
endCol: length === undefined ? Infinity : col + length,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Create a range that covers entire lines from `from` to `to` (inclusive).
|
|
33
|
-
* If `to` is omitted, only line `from` is covered.
|
|
34
|
-
*
|
|
35
|
-
* Example:
|
|
36
|
-
* lines(1, 3) // lines 1 through 3
|
|
37
|
-
* lines(2) // line 2 only
|
|
38
|
-
*/
|
|
39
|
-
export function lines(from: number, to?: number): CodeRange {
|
|
40
|
-
return {
|
|
41
|
-
startLine: from,
|
|
42
|
-
startCol: 1,
|
|
43
|
-
endLine: to ?? from,
|
|
44
|
-
endCol: Infinity,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Immutable, chainable, iterable builder over multiple ranges — mirrors
|
|
52
|
-
* {@link FillChain}/`Fills` in `@motionscript/
|
|
53
|
-
* *new* chain with one more range appended, so the next range-kind method is
|
|
54
|
-
* called directly rather than through a separate combinator:
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* CodeRanges.lines(2).word(5, 1, 3) // a 2-range selection, one expression
|
|
58
|
-
*/
|
|
59
|
-
export class CodeRangeChain {
|
|
60
|
-
constructor(public readonly list: CodeRange[] = []) { }
|
|
61
|
-
|
|
62
|
-
lines(from: number, to?: number): CodeRangeChain {
|
|
63
|
-
return new CodeRangeChain([...this.list, lines(from, to)]);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
word(line: number, col: number, length?: number): CodeRangeChain {
|
|
67
|
-
return new CodeRangeChain([...this.list, word(line, col, length)]);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
*[Symbol.iterator](): Iterator<CodeRange> {
|
|
71
|
-
yield* this.list;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
end:
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* A range over a code document. Lines and columns are 1-indexed.
|
|
3
|
+
*
|
|
4
|
+
* `endLine`/`endCol` may be `Infinity` to mean "to the end of the line" or
|
|
5
|
+
* "to the end of the document".
|
|
6
|
+
*/
|
|
7
|
+
export interface CodeRange {
|
|
8
|
+
startLine: number;
|
|
9
|
+
startCol: number;
|
|
10
|
+
endLine: number;
|
|
11
|
+
endCol: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Create a range that spans `length` characters starting at (line, col).
|
|
16
|
+
* If `length` is omitted, the range extends to the end of the line.
|
|
17
|
+
*
|
|
18
|
+
* Example:
|
|
19
|
+
* word(1, 3, 3) // line 1, column 3, spans 3 characters
|
|
20
|
+
* word(1, 3) // line 1, column 3, to end of line
|
|
21
|
+
*/
|
|
22
|
+
export function word(line: number, col: number, length?: number): CodeRange {
|
|
23
|
+
return {
|
|
24
|
+
startLine: line,
|
|
25
|
+
startCol: col,
|
|
26
|
+
endLine: line,
|
|
27
|
+
endCol: length === undefined ? Infinity : col + length,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Create a range that covers entire lines from `from` to `to` (inclusive).
|
|
33
|
+
* If `to` is omitted, only line `from` is covered.
|
|
34
|
+
*
|
|
35
|
+
* Example:
|
|
36
|
+
* lines(1, 3) // lines 1 through 3
|
|
37
|
+
* lines(2) // line 2 only
|
|
38
|
+
*/
|
|
39
|
+
export function lines(from: number, to?: number): CodeRange {
|
|
40
|
+
return {
|
|
41
|
+
startLine: from,
|
|
42
|
+
startCol: 1,
|
|
43
|
+
endLine: to ?? from,
|
|
44
|
+
endCol: Infinity,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Immutable, chainable, iterable builder over multiple ranges — mirrors
|
|
52
|
+
* {@link FillChain}/`Fills` in `@motionscript/sdk`. Every method returns a
|
|
53
|
+
* *new* chain with one more range appended, so the next range-kind method is
|
|
54
|
+
* called directly rather than through a separate combinator:
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* CodeRanges.lines(2).word(5, 1, 3) // a 2-range selection, one expression
|
|
58
|
+
*/
|
|
59
|
+
export class CodeRangeChain {
|
|
60
|
+
constructor(public readonly list: CodeRange[] = []) { }
|
|
61
|
+
|
|
62
|
+
lines(from: number, to?: number): CodeRangeChain {
|
|
63
|
+
return new CodeRangeChain([...this.list, lines(from, to)]);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
word(line: number, col: number, length?: number): CodeRangeChain {
|
|
67
|
+
return new CodeRangeChain([...this.list, word(line, col, length)]);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
*[Symbol.iterator](): Iterator<CodeRange> {
|
|
71
|
+
yield* this.list;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* A chain is stored as its ranges. Without this it serialises as
|
|
76
|
+
* `{ "list": [...] }`, which has no iterator once read back and so selects
|
|
77
|
+
* nothing; a plain array of ranges reads back as the selection it was.
|
|
78
|
+
*/
|
|
79
|
+
toJSON(): CodeRange[] {
|
|
80
|
+
return this.list;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Entry point for building multi-range selections fluently — an empty
|
|
86
|
+
* {@link CodeRangeChain}, so `CodeRanges.lines(2)` *is* `new
|
|
87
|
+
* CodeRangeChain().lines(2)`. `word`/`lines` stay directly importable and
|
|
88
|
+
* usable standalone for a single range; reach for `CodeRanges` when a call
|
|
89
|
+
* needs more than one.
|
|
90
|
+
*/
|
|
91
|
+
export const CodeRanges = new CodeRangeChain();
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Convert a CodeRange to absolute character offsets [start, end) in the joined
|
|
95
|
+
* source text, given the per-line lengths of that source. Lines/columns are
|
|
96
|
+
* clamped into the document so out-of-bounds inputs produce a valid range.
|
|
97
|
+
*/
|
|
98
|
+
export function rangeToCharOffsets(
|
|
99
|
+
r: CodeRange,
|
|
100
|
+
lineLengths: number[],
|
|
101
|
+
): { start: number; end: number } {
|
|
102
|
+
if (lineLengths.length === 0) return { start: 0, end: 0 };
|
|
103
|
+
|
|
104
|
+
// Cumulative line starts in the joined string (lines joined with '\n').
|
|
105
|
+
const lineStart: number[] = new Array(lineLengths.length);
|
|
106
|
+
let acc = 0;
|
|
107
|
+
for (let i = 0; i < lineLengths.length; i++) {
|
|
108
|
+
lineStart[i] = acc;
|
|
109
|
+
acc += lineLengths[i] + 1; // +1 for the joining newline
|
|
110
|
+
}
|
|
111
|
+
const docEnd = acc > 0 ? acc - 1 : 0; // strip trailing newline
|
|
112
|
+
|
|
113
|
+
const clampLine = (n: number) =>
|
|
114
|
+
Math.max(0, Math.min(lineLengths.length - 1, n - 1)); // to 0-indexed
|
|
115
|
+
|
|
116
|
+
// A range read back from JSON holds `Infinity` as `null`; both mean "to the end".
|
|
117
|
+
const endLine = r.endLine ?? Infinity;
|
|
118
|
+
const endCol = r.endCol ?? Infinity;
|
|
119
|
+
|
|
120
|
+
const sLine = clampLine(r.startLine);
|
|
121
|
+
const eLine = clampLine(endLine);
|
|
122
|
+
const sColMax = lineLengths[sLine];
|
|
123
|
+
const eColMax = lineLengths[eLine];
|
|
124
|
+
|
|
125
|
+
// Columns are 1-indexed; clamp to [1, lineLength+1] so endCol can sit past
|
|
126
|
+
// the last char (one-past-end).
|
|
127
|
+
const sCol = Math.max(0, Math.min(sColMax, r.startCol - 1));
|
|
128
|
+
const eCol = endCol === Infinity
|
|
129
|
+
? eColMax
|
|
130
|
+
: Math.max(0, Math.min(eColMax, endCol - 1));
|
|
131
|
+
|
|
132
|
+
const start = Math.min(docEnd, lineStart[sLine] + sCol);
|
|
133
|
+
const end = Math.min(docEnd, lineStart[eLine] + eCol);
|
|
134
|
+
return { start: Math.min(start, end), end: Math.max(start, end) };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Convert [start, end) character offsets in joined source to a CodeRange.
|
|
139
|
+
* Lines/cols in the returned range are 1-indexed.
|
|
140
|
+
*/
|
|
141
|
+
export function charOffsetsToRange(
|
|
142
|
+
start: number,
|
|
143
|
+
end: number,
|
|
144
|
+
lineLengths: number[],
|
|
145
|
+
): CodeRange {
|
|
146
|
+
let off = 0;
|
|
147
|
+
let startLine = 1, startCol = 1, endLine = 1, endCol = 1;
|
|
148
|
+
let foundStart = false;
|
|
149
|
+
for (let li = 0; li < lineLengths.length; li++) {
|
|
150
|
+
const lineStart = off;
|
|
151
|
+
const lineEnd = off + lineLengths[li];
|
|
152
|
+
if (!foundStart && start >= lineStart && start <= lineEnd) {
|
|
153
|
+
startLine = li + 1;
|
|
154
|
+
startCol = (start - lineStart) + 1;
|
|
155
|
+
foundStart = true;
|
|
156
|
+
}
|
|
157
|
+
if (end >= lineStart && end <= lineEnd) {
|
|
158
|
+
endLine = li + 1;
|
|
159
|
+
endCol = (end - lineStart) + 1;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
off = lineEnd + 1;
|
|
163
|
+
}
|
|
164
|
+
return { startLine, startCol, endLine, endCol };
|
|
165
|
+
}
|