@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.
Files changed (65) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/LICENSE +201 -201
  3. package/NOTICE +48 -0
  4. package/README.md +161 -77
  5. package/dist/browser/THIRD_PARTY_LICENSES.txt +431 -0
  6. package/dist/browser/index.js +7 -7
  7. package/dist/browser/index.js.map +3 -3
  8. package/dist/browser/manifest.json +85 -3
  9. package/dist/code-range.d.ts +7 -1
  10. package/dist/code-range.d.ts.map +1 -1
  11. package/dist/code-range.js +9 -1
  12. package/dist/code-range.js.map +1 -1
  13. package/dist/diff.d.ts +14 -0
  14. package/dist/diff.d.ts.map +1 -1
  15. package/dist/diff.js +134 -2
  16. package/dist/diff.js.map +1 -1
  17. package/dist/engine.d.ts +1 -1
  18. package/dist/engine.d.ts.map +1 -1
  19. package/dist/engine.js +1 -1
  20. package/dist/engine.js.map +1 -1
  21. package/dist/highlight.d.ts +10 -2
  22. package/dist/highlight.d.ts.map +1 -1
  23. package/dist/highlight.js +40 -6
  24. package/dist/highlight.js.map +1 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/layout.d.ts +1 -1
  27. package/dist/layout.d.ts.map +1 -1
  28. package/dist/layout.js.map +1 -1
  29. package/dist/measure-cache.d.ts +1 -1
  30. package/dist/measure-cache.d.ts.map +1 -1
  31. package/dist/measure-cache.js.map +1 -1
  32. package/dist/node.d.ts +62 -7
  33. package/dist/node.d.ts.map +1 -1
  34. package/dist/node.js +224 -42
  35. package/dist/node.js.map +1 -1
  36. package/dist/nodes.js.map +1 -1
  37. package/dist/render.d.ts +7 -2
  38. package/dist/render.d.ts.map +1 -1
  39. package/dist/render.js +60 -1
  40. package/dist/render.js.map +1 -1
  41. package/dist/style.d.ts +3 -3
  42. package/dist/style.d.ts.map +1 -1
  43. package/dist/style.js +10 -6
  44. package/dist/style.js.map +1 -1
  45. package/dist/tokens.d.ts.map +1 -1
  46. package/dist/tokens.js +5 -1
  47. package/dist/tokens.js.map +1 -1
  48. package/dist/transitions.d.ts +19 -1
  49. package/dist/transitions.d.ts.map +1 -1
  50. package/dist/transitions.js.map +1 -1
  51. package/package.json +7 -4
  52. package/registry.json +6 -6
  53. package/src/code-range.ts +165 -156
  54. package/src/diff.ts +351 -216
  55. package/src/engine.ts +21 -21
  56. package/src/highlight.ts +340 -291
  57. package/src/index.ts +3 -3
  58. package/src/layout.ts +157 -157
  59. package/src/measure-cache.ts +0 -0
  60. package/src/node.ts +1038 -834
  61. package/src/nodes.ts +18 -18
  62. package/src/render.ts +312 -247
  63. package/src/style.ts +255 -251
  64. package/src/tokens.ts +79 -75
  65. 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/core`. 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
- /**
76
- * Entry point for building multi-range selections fluently — an empty
77
- * {@link CodeRangeChain}, so `CodeRanges.lines(2)` *is* `new
78
- * CodeRangeChain().lines(2)`. `word`/`lines` stay directly importable and
79
- * usable standalone for a single range; reach for `CodeRanges` when a call
80
- * needs more than one.
81
- */
82
- export const CodeRanges = new CodeRangeChain();
83
-
84
- /**
85
- * Convert a CodeRange to absolute character offsets [start, end) in the joined
86
- * source text, given the per-line lengths of that source. Lines/columns are
87
- * clamped into the document so out-of-bounds inputs produce a valid range.
88
- */
89
- export function rangeToCharOffsets(
90
- r: CodeRange,
91
- lineLengths: number[],
92
- ): { start: number; end: number } {
93
- if (lineLengths.length === 0) return { start: 0, end: 0 };
94
-
95
- // Cumulative line starts in the joined string (lines joined with '\n').
96
- const lineStart: number[] = new Array(lineLengths.length);
97
- let acc = 0;
98
- for (let i = 0; i < lineLengths.length; i++) {
99
- lineStart[i] = acc;
100
- acc += lineLengths[i] + 1; // +1 for the joining newline
101
- }
102
- const docEnd = acc > 0 ? acc - 1 : 0; // strip trailing newline
103
-
104
- const clampLine = (n: number) =>
105
- Math.max(0, Math.min(lineLengths.length - 1, n - 1)); // to 0-indexed
106
-
107
- // A range read back from JSON holds `Infinity` as `null`; both mean "to the end".
108
- const endLine = r.endLine ?? Infinity;
109
- const endCol = r.endCol ?? Infinity;
110
-
111
- const sLine = clampLine(r.startLine);
112
- const eLine = clampLine(endLine);
113
- const sColMax = lineLengths[sLine];
114
- const eColMax = lineLengths[eLine];
115
-
116
- // Columns are 1-indexed; clamp to [1, lineLength+1] so endCol can sit past
117
- // the last char (one-past-end).
118
- const sCol = Math.max(0, Math.min(sColMax, r.startCol - 1));
119
- const eCol = endCol === Infinity
120
- ? eColMax
121
- : Math.max(0, Math.min(eColMax, endCol - 1));
122
-
123
- const start = Math.min(docEnd, lineStart[sLine] + sCol);
124
- const end = Math.min(docEnd, lineStart[eLine] + eCol);
125
- return { start: Math.min(start, end), end: Math.max(start, end) };
126
- }
127
-
128
- /**
129
- * Convert [start, end) character offsets in joined source to a CodeRange.
130
- * Lines/cols in the returned range are 1-indexed.
131
- */
132
- export function charOffsetsToRange(
133
- start: number,
134
- end: number,
135
- lineLengths: number[],
136
- ): CodeRange {
137
- let off = 0;
138
- let startLine = 1, startCol = 1, endLine = 1, endCol = 1;
139
- let foundStart = false;
140
- for (let li = 0; li < lineLengths.length; li++) {
141
- const lineStart = off;
142
- const lineEnd = off + lineLengths[li];
143
- if (!foundStart && start >= lineStart && start <= lineEnd) {
144
- startLine = li + 1;
145
- startCol = (start - lineStart) + 1;
146
- foundStart = true;
147
- }
148
- if (end >= lineStart && end <= lineEnd) {
149
- endLine = li + 1;
150
- endCol = (end - lineStart) + 1;
151
- break;
152
- }
153
- off = lineEnd + 1;
154
- }
155
- return { startLine, startCol, endLine, endCol };
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
+ }