@revideo/2d 0.5.0 → 0.5.2
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/editor/editor/tsconfig.build.tsbuildinfo +1 -1
- package/lib/code/CodeHighlighter.d.ts +2 -2
- package/lib/code/CodeHighlighter.d.ts.map +1 -1
- package/lib/code/CodeMetrics.js +2 -2
- package/lib/code/CodeSignal.d.ts +1 -2
- package/lib/code/CodeSignal.d.ts.map +1 -1
- package/lib/code/CodeSignal.js +4 -7
- package/lib/code/LezerHighlighter.d.ts +5 -6
- package/lib/code/LezerHighlighter.d.ts.map +1 -1
- package/lib/code/LezerHighlighter.js +9 -33
- package/lib/code/extractRange.d.ts.map +1 -1
- package/lib/code/extractRange.js +11 -3
- package/lib/components/Code.d.ts +5 -41
- package/lib/components/Code.d.ts.map +1 -1
- package/lib/components/Code.js +21 -21
- package/lib/components/CodeBlock.d.ts +3 -0
- package/lib/components/CodeBlock.d.ts.map +1 -1
- package/lib/components/CodeBlock.js +4 -1
- package/lib/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/lib/code/CodeHighlighter.ts +2 -2
- package/src/lib/code/CodeMetrics.ts +1 -1
- package/src/lib/code/CodeSignal.ts +3 -6
- package/src/lib/code/LezerHighlighter.ts +13 -39
- package/src/lib/code/extractRange.ts +9 -4
- package/src/lib/components/Code.ts +24 -58
- package/src/lib/components/CodeBlock.ts +3 -0
|
@@ -78,13 +78,11 @@ export class CodeSignalContext<TOwner>
|
|
|
78
78
|
public constructor(
|
|
79
79
|
initial: PossibleCodeScope,
|
|
80
80
|
owner: TOwner,
|
|
81
|
-
private readonly highlighter?: SignalValue<CodeHighlighter>,
|
|
82
|
-
private readonly dialect?: SignalValue<string>,
|
|
81
|
+
private readonly highlighter?: SignalValue<CodeHighlighter | null>,
|
|
83
82
|
) {
|
|
84
83
|
super(initial, deepLerp, owner);
|
|
85
84
|
if (owner instanceof Code) {
|
|
86
85
|
this.highlighter ??= owner.highlighter;
|
|
87
|
-
this.dialect ??= owner.dialect;
|
|
88
86
|
}
|
|
89
87
|
Object.defineProperty(this.invokable, 'edit', {
|
|
90
88
|
value: this.edit.bind(this),
|
|
@@ -113,15 +111,14 @@ export class CodeSignalContext<TOwner>
|
|
|
113
111
|
): ThreadGenerator {
|
|
114
112
|
let tokenize = defaultTokenize;
|
|
115
113
|
const highlighter = unwrap(this.highlighter);
|
|
116
|
-
|
|
117
|
-
if (highlighter && dialect) {
|
|
114
|
+
if (highlighter) {
|
|
118
115
|
yield (async () => {
|
|
119
116
|
do {
|
|
120
117
|
await DependencyContext.consumePromises();
|
|
121
118
|
highlighter.initialize();
|
|
122
119
|
} while (DependencyContext.hasPromises());
|
|
123
120
|
})();
|
|
124
|
-
tokenize = (input: string) => highlighter.tokenize(input
|
|
121
|
+
tokenize = (input: string) => highlighter.tokenize(input);
|
|
125
122
|
}
|
|
126
123
|
|
|
127
124
|
this.progress(0);
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
import {HighlightStyle} from '@codemirror/language';
|
|
2
2
|
import {Parser, SyntaxNode, Tree} from '@lezer/common';
|
|
3
3
|
import {highlightTree} from '@lezer/highlight';
|
|
4
|
-
import {useLogger} from '@revideo/core';
|
|
5
4
|
import {CodeHighlighter, HighlightResult} from './CodeHighlighter';
|
|
6
|
-
import {
|
|
5
|
+
import {DefaultHighlightStyle} from './DefaultHighlightStyle';
|
|
7
6
|
|
|
8
7
|
interface LezerCache {
|
|
9
8
|
tree: Tree;
|
|
10
9
|
code: string;
|
|
11
|
-
colorLookup: Map<
|
|
10
|
+
colorLookup: Map<string, string>;
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
export class LezerHighlighter implements CodeHighlighter<LezerCache | null> {
|
|
15
|
-
private static readonly parserMap = new Map<string, Parser>();
|
|
16
14
|
private static classRegex = /\.(\S+).*color:([^;]+)/;
|
|
17
15
|
private readonly classLookup = new Map<string, string>();
|
|
18
16
|
|
|
19
|
-
public
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
public constructor(private readonly style: HighlightStyle) {
|
|
17
|
+
public constructor(
|
|
18
|
+
private readonly parser: Parser,
|
|
19
|
+
private readonly style: HighlightStyle = DefaultHighlightStyle,
|
|
20
|
+
) {
|
|
24
21
|
for (const rule of this.style.module?.getRules().split('\n') ?? []) {
|
|
25
22
|
const match = rule.match(LezerHighlighter.classRegex);
|
|
26
23
|
if (!match) {
|
|
@@ -37,17 +34,9 @@ export class LezerHighlighter implements CodeHighlighter<LezerCache | null> {
|
|
|
37
34
|
return true;
|
|
38
35
|
}
|
|
39
36
|
|
|
40
|
-
public prepare(code: string
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
if (dialect !== '') {
|
|
44
|
-
useLogger().warn(`No parser found for dialect: ${dialect}`);
|
|
45
|
-
}
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const colorLookup = new Map<number, string>();
|
|
50
|
-
const tree = parser.parse(code);
|
|
37
|
+
public prepare(code: string): LezerCache | null {
|
|
38
|
+
const colorLookup = new Map<string, string>();
|
|
39
|
+
const tree = this.parser.parse(code);
|
|
51
40
|
highlightTree(tree, this.style, (from, to, classes) => {
|
|
52
41
|
const color = this.classLookup.get(classes);
|
|
53
42
|
if (!color) {
|
|
@@ -97,16 +86,8 @@ export class LezerHighlighter implements CodeHighlighter<LezerCache | null> {
|
|
|
97
86
|
};
|
|
98
87
|
}
|
|
99
88
|
|
|
100
|
-
public tokenize(code: string
|
|
101
|
-
const
|
|
102
|
-
if (!parser) {
|
|
103
|
-
if (dialect !== '') {
|
|
104
|
-
useLogger().warn(`No parser found for dialect: ${dialect}`);
|
|
105
|
-
}
|
|
106
|
-
return defaultTokenize(code);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const tree = parser.parse(code);
|
|
89
|
+
public tokenize(code: string): string[] {
|
|
90
|
+
const tree = this.parser.parse(code);
|
|
110
91
|
const cursor = tree.cursor();
|
|
111
92
|
const tokens: string[] = [];
|
|
112
93
|
let current = 0;
|
|
@@ -126,14 +107,7 @@ export class LezerHighlighter implements CodeHighlighter<LezerCache | null> {
|
|
|
126
107
|
return tokens;
|
|
127
108
|
}
|
|
128
109
|
|
|
129
|
-
private getNodeId(node: SyntaxNode):
|
|
130
|
-
|
|
131
|
-
return -1;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// NOTE: They don't want us to know about this property.
|
|
135
|
-
// We need a way to persistently identify nodes and this seems to work.
|
|
136
|
-
// Perhaps it could break if the tree is edited? But we don't do that. Yet.
|
|
137
|
-
return (node as any).index;
|
|
110
|
+
private getNodeId(node: SyntaxNode): string {
|
|
111
|
+
return `${node.from}:${node.to}`;
|
|
138
112
|
}
|
|
139
113
|
}
|
|
@@ -61,9 +61,7 @@ export function extractRange(
|
|
|
61
61
|
if (fromColumn === currentColumn) {
|
|
62
62
|
index = newFragments.length + 1;
|
|
63
63
|
newFragments.push(resolved.slice(0, i), '');
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (char === '\n') {
|
|
64
|
+
} else if (char === '\n') {
|
|
67
65
|
index = newFragments.length + 1;
|
|
68
66
|
newFragments.push(
|
|
69
67
|
resolved.slice(0, i) + ' '.repeat(fromColumn - currentColumn),
|
|
@@ -80,7 +78,14 @@ export function extractRange(
|
|
|
80
78
|
}
|
|
81
79
|
|
|
82
80
|
if (char === '\n') {
|
|
83
|
-
|
|
81
|
+
if (currentColumn < toColumn) {
|
|
82
|
+
extracted += '\n';
|
|
83
|
+
if (i + 1 < resolved.length) {
|
|
84
|
+
newFragments.push(resolved.slice(i + 1));
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
newFragments.push(resolved.slice(i));
|
|
88
|
+
}
|
|
84
89
|
found = true;
|
|
85
90
|
break;
|
|
86
91
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BBox,
|
|
3
3
|
createSignal,
|
|
4
|
-
|
|
5
|
-
lazy,
|
|
4
|
+
experimentalLog,
|
|
6
5
|
map,
|
|
7
6
|
SerializedVector2,
|
|
8
7
|
Signal,
|
|
@@ -11,6 +10,8 @@ import {
|
|
|
11
10
|
ThreadGenerator,
|
|
12
11
|
TimingFunction,
|
|
13
12
|
unwrap,
|
|
13
|
+
useLogger,
|
|
14
|
+
useScene,
|
|
14
15
|
Vector2,
|
|
15
16
|
} from '@revideo/core';
|
|
16
17
|
import {
|
|
@@ -23,10 +24,8 @@ import {
|
|
|
23
24
|
CodeSignal,
|
|
24
25
|
codeSignal,
|
|
25
26
|
CodeSignalContext,
|
|
26
|
-
DefaultHighlightStyle,
|
|
27
27
|
findAllCodeRanges,
|
|
28
28
|
isPointInCodeSelection,
|
|
29
|
-
LezerHighlighter,
|
|
30
29
|
lines,
|
|
31
30
|
parseCodeSelection,
|
|
32
31
|
PossibleCodeScope,
|
|
@@ -35,7 +34,6 @@ import {
|
|
|
35
34
|
} from '../code';
|
|
36
35
|
import {computed, initial, nodeName, parser, signal} from '../decorators';
|
|
37
36
|
import {DesiredLength} from '../partials';
|
|
38
|
-
import {useScene2D} from '../scenes';
|
|
39
37
|
import {Shape, ShapeProps} from './Shape';
|
|
40
38
|
|
|
41
39
|
export interface DrawTokenHook {
|
|
@@ -75,10 +73,6 @@ export interface CodeProps extends ShapeProps {
|
|
|
75
73
|
* {@inheritDoc Code.highlighter}
|
|
76
74
|
*/
|
|
77
75
|
highlighter?: SignalValue<CodeHighlighter | null>;
|
|
78
|
-
/**
|
|
79
|
-
* {@inheritDoc Code.dialect}
|
|
80
|
-
*/
|
|
81
|
-
dialect?: SignalValue<string>;
|
|
82
76
|
/**
|
|
83
77
|
* {@inheritDoc Code.code}
|
|
84
78
|
*/
|
|
@@ -143,59 +137,19 @@ export class Code extends Shape {
|
|
|
143
137
|
*
|
|
144
138
|
* @param initial - The initial code.
|
|
145
139
|
* @param highlighter - Custom highlighter to use.
|
|
146
|
-
* @param dialect - Custom dialect to use.
|
|
147
140
|
*/
|
|
148
141
|
public static createSignal(
|
|
149
142
|
initial: PossibleCodeScope,
|
|
150
143
|
highlighter?: SignalValue<CodeHighlighter>,
|
|
151
|
-
dialect?: SignalValue<string>,
|
|
152
144
|
): CodeSignal<void> {
|
|
153
145
|
return new CodeSignalContext<void>(
|
|
154
146
|
initial,
|
|
155
147
|
undefined,
|
|
156
148
|
highlighter,
|
|
157
|
-
dialect,
|
|
158
149
|
).toSignal();
|
|
159
150
|
}
|
|
160
151
|
|
|
161
|
-
|
|
162
|
-
public static readonly defaultHighlighter: LezerHighlighter;
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* The dialect to use for highlighting the code.
|
|
166
|
-
*
|
|
167
|
-
* @remarks
|
|
168
|
-
* This value will be passed to the {@link code.CodeHighlighter}
|
|
169
|
-
* defined by the {@link highlighter} property. Different highlighters may use
|
|
170
|
-
* it differently.
|
|
171
|
-
*
|
|
172
|
-
* The default {@link code.LezerHighlighter} uses it to select
|
|
173
|
-
* the language parser to use. The parser for the given dialect can be
|
|
174
|
-
* registered as follows:
|
|
175
|
-
* ```tsx
|
|
176
|
-
* // Import the lezer parser:
|
|
177
|
-
* import {parser} from '@lezer/javascript';
|
|
178
|
-
*
|
|
179
|
-
* // Register it in the highlighter:
|
|
180
|
-
* LezerHighlighter.registerParser(parser, 'js');
|
|
181
|
-
*
|
|
182
|
-
* // Use the dialect in a code node:
|
|
183
|
-
* <Code dialect="js" code="const a = 7;" />
|
|
184
|
-
* ```
|
|
185
|
-
* When no dialect is provided, the highlighter will use the default
|
|
186
|
-
* parser:
|
|
187
|
-
* ```tsx
|
|
188
|
-
* // Register the default parser by omitting the dialect:
|
|
189
|
-
* LezerHighlighter.registerParser(parser);
|
|
190
|
-
*
|
|
191
|
-
* // Code nodes with no dialect will now use the default parser:
|
|
192
|
-
* <Code code="const a = 7;" />
|
|
193
|
-
* ```
|
|
194
|
-
*/
|
|
195
|
-
@initial('')
|
|
196
|
-
@signal()
|
|
197
|
-
public declare readonly dialect: SimpleSignal<string, this>;
|
|
198
|
-
|
|
152
|
+
public static defaultHighlighter: CodeHighlighter | null = null;
|
|
199
153
|
/**
|
|
200
154
|
* The code highlighter to use for this code node.
|
|
201
155
|
*
|
|
@@ -204,7 +158,10 @@ export class Code extends Shape {
|
|
|
204
158
|
*/
|
|
205
159
|
@initial(() => Code.defaultHighlighter)
|
|
206
160
|
@signal()
|
|
207
|
-
public declare readonly highlighter: SimpleSignal<
|
|
161
|
+
public declare readonly highlighter: SimpleSignal<
|
|
162
|
+
CodeHighlighter | null,
|
|
163
|
+
this
|
|
164
|
+
>;
|
|
208
165
|
|
|
209
166
|
/**
|
|
210
167
|
* The code to display.
|
|
@@ -246,6 +203,20 @@ export class Code extends Shape {
|
|
|
246
203
|
@signal()
|
|
247
204
|
public declare readonly drawHooks: SimpleSignal<DrawHooks, this>;
|
|
248
205
|
|
|
206
|
+
protected setDrawHooks(value: DrawHooks) {
|
|
207
|
+
if (
|
|
208
|
+
!useScene().experimentalFeatures &&
|
|
209
|
+
value !== this.drawHooks.context.getInitial()
|
|
210
|
+
) {
|
|
211
|
+
useLogger().log({
|
|
212
|
+
...experimentalLog(`Code uses experimental draw hooks.`),
|
|
213
|
+
inspect: this.key,
|
|
214
|
+
});
|
|
215
|
+
} else {
|
|
216
|
+
this.drawHooks.context.setter(value);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
249
220
|
/**
|
|
250
221
|
* The currently selected code range.
|
|
251
222
|
*
|
|
@@ -309,11 +280,10 @@ export class Code extends Shape {
|
|
|
309
280
|
const code = this.code();
|
|
310
281
|
const before = resolveScope(code, false);
|
|
311
282
|
const after = resolveScope(code, true);
|
|
312
|
-
const dialect = this.dialect();
|
|
313
283
|
|
|
314
284
|
return {
|
|
315
|
-
before: highlighter.prepare(before
|
|
316
|
-
after: highlighter.prepare(after
|
|
285
|
+
before: highlighter.prepare(before),
|
|
286
|
+
after: highlighter.prepare(after),
|
|
317
287
|
};
|
|
318
288
|
}
|
|
319
289
|
|
|
@@ -328,9 +298,6 @@ export class Code extends Shape {
|
|
|
328
298
|
fontFamily: 'monospace',
|
|
329
299
|
...props,
|
|
330
300
|
});
|
|
331
|
-
if (!useScene2D().experimentalFeatures) {
|
|
332
|
-
throw new ExperimentalError('The Code node is an experimental feature');
|
|
333
|
-
}
|
|
334
301
|
}
|
|
335
302
|
|
|
336
303
|
/**
|
|
@@ -343,7 +310,6 @@ export class Code extends Shape {
|
|
|
343
310
|
initial,
|
|
344
311
|
this,
|
|
345
312
|
this.highlighter,
|
|
346
|
-
this.dialect,
|
|
347
313
|
).toSignal();
|
|
348
314
|
}
|
|
349
315
|
|