ripple 0.2.90 → 0.2.92
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/package.json +1 -1
- package/src/compiler/index.js +14 -8
- package/src/compiler/phases/1-parse/index.js +74 -20
- package/src/compiler/phases/3-transform/client/index.js +101 -49
- package/src/compiler/phases/3-transform/segments.js +248 -34
- package/src/compiler/scope.js +478 -404
- package/src/compiler/types/index.d.ts +299 -3
- package/src/compiler/utils.js +173 -30
- package/src/runtime/date.js +73 -0
- package/src/runtime/index-client.js +24 -21
- package/src/runtime/internal/client/html.js +18 -8
- package/src/runtime/internal/client/index.js +1 -0
- package/src/runtime/internal/client/portal.js +55 -32
- package/src/runtime/internal/client/render.js +31 -1
- package/src/runtime/internal/client/runtime.js +53 -22
- package/src/utils/normalize_css_property_name.js +23 -0
- package/tests/client/basic.test.ripple +207 -1
- package/tests/client/compiler.test.ripple +95 -1
- package/tests/client/date.test.ripple +392 -0
- package/tests/client/html.test.ripple +29 -1
- package/tests/client/portal.test.ripple +167 -0
- package/types/index.d.ts +37 -28
package/package.json
CHANGED
package/src/compiler/index.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
/** @import { RawSourceMap } from 'source-map' */
|
|
2
1
|
/** @import { Program } from 'estree' */
|
|
3
|
-
/** @import { ParseError } from './phases/1-parse/index.js' */
|
|
4
2
|
|
|
5
3
|
import { parse as parse_module } from './phases/1-parse/index.js';
|
|
6
4
|
import { analyze } from './phases/2-analyze/index.js';
|
|
@@ -9,18 +7,20 @@ import { transform_server } from './phases/3-transform/server/index.js';
|
|
|
9
7
|
import { convert_source_map_to_mappings } from './phases/3-transform/segments.js';
|
|
10
8
|
|
|
11
9
|
/**
|
|
12
|
-
*
|
|
13
|
-
* @
|
|
10
|
+
* Parse Ripple source code to ESTree AST
|
|
11
|
+
* @param {string} source
|
|
12
|
+
* @returns {Program}
|
|
14
13
|
*/
|
|
15
14
|
export function parse(source) {
|
|
16
15
|
return parse_module(source);
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
/**
|
|
20
|
-
*
|
|
21
|
-
* @param {string}
|
|
22
|
-
* @param {
|
|
23
|
-
* @
|
|
19
|
+
* Compile Ripple source code to JS/CSS output
|
|
20
|
+
* @param {string} source
|
|
21
|
+
* @param {string} filename
|
|
22
|
+
* @param {{ mode?: 'client' | 'server' }} [options]
|
|
23
|
+
* @returns {object}
|
|
24
24
|
*/
|
|
25
25
|
export function compile(source, filename, options = {}) {
|
|
26
26
|
const ast = parse_module(source);
|
|
@@ -32,6 +32,12 @@ export function compile(source, filename, options = {}) {
|
|
|
32
32
|
return result;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Compile Ripple source to Volar mappings for editor integration
|
|
37
|
+
* @param {string} source
|
|
38
|
+
* @param {string} filename
|
|
39
|
+
* @returns {object} Volar mappings object
|
|
40
|
+
*/
|
|
35
41
|
export function compile_to_volar_mappings(source, filename) {
|
|
36
42
|
// Parse and transform to get the esrap sourcemap
|
|
37
43
|
const ast = parse_module(source);
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/** @import { Program } from 'estree' */
|
|
2
|
+
/** @import {
|
|
3
|
+
* CommentWithLocation,
|
|
4
|
+
* RipplePluginConfig
|
|
5
|
+
* } from '#compiler' */
|
|
6
|
+
|
|
1
7
|
import * as acorn from 'acorn';
|
|
2
8
|
import { tsPlugin } from 'acorn-typescript';
|
|
3
9
|
import { parse_style } from './style.js';
|
|
@@ -6,6 +12,11 @@ import { regex_newline_characters } from '../../../utils/patterns.js';
|
|
|
6
12
|
|
|
7
13
|
const parser = acorn.Parser.extend(tsPlugin({ allowSatisfies: true }), RipplePlugin());
|
|
8
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Convert JSX node types to regular JavaScript node types
|
|
17
|
+
* @param {any} node - The JSX node to convert
|
|
18
|
+
* @returns {any} The converted node
|
|
19
|
+
*/
|
|
9
20
|
function convert_from_jsx(node) {
|
|
10
21
|
if (node.type === 'JSXIdentifier') {
|
|
11
22
|
node.type = 'Identifier';
|
|
@@ -17,16 +28,26 @@ function convert_from_jsx(node) {
|
|
|
17
28
|
return node;
|
|
18
29
|
}
|
|
19
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Acorn parser plugin for Ripple syntax extensions
|
|
33
|
+
* @param {RipplePluginConfig} [config] - Plugin configuration
|
|
34
|
+
* @returns {function(any): any} Parser extension function
|
|
35
|
+
*/
|
|
20
36
|
function RipplePlugin(config) {
|
|
21
|
-
return (Parser) => {
|
|
37
|
+
return (/** @type {any} */ Parser) => {
|
|
22
38
|
const original = acorn.Parser.prototype;
|
|
23
39
|
const tt = Parser.tokTypes || acorn.tokTypes;
|
|
24
40
|
const tc = Parser.tokContexts || acorn.tokContexts;
|
|
25
41
|
|
|
26
42
|
class RippleParser extends Parser {
|
|
43
|
+
/** @type {any[]} */
|
|
27
44
|
#path = [];
|
|
28
45
|
|
|
29
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Helper method to get the element name from a JSX identifier or member expression
|
|
48
|
+
* @param {any} node - The node to get the name from
|
|
49
|
+
* @returns {string | null} Element name or null
|
|
50
|
+
*/
|
|
30
51
|
getElementName(node) {
|
|
31
52
|
if (!node) return null;
|
|
32
53
|
if (node.type === 'Identifier' || node.type === 'JSXIdentifier') {
|
|
@@ -38,6 +59,11 @@ function RipplePlugin(config) {
|
|
|
38
59
|
return null;
|
|
39
60
|
}
|
|
40
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Get token from character code - handles Ripple-specific tokens
|
|
64
|
+
* @param {number} code - Character code
|
|
65
|
+
* @returns {any} Token or calls super method
|
|
66
|
+
*/
|
|
41
67
|
getTokenFromCode(code) {
|
|
42
68
|
if (code === 60) {
|
|
43
69
|
// < character
|
|
@@ -135,7 +161,10 @@ function RipplePlugin(config) {
|
|
|
135
161
|
return super.getTokenFromCode(code);
|
|
136
162
|
}
|
|
137
163
|
|
|
138
|
-
|
|
164
|
+
/**
|
|
165
|
+
* Read an @ prefixed identifier
|
|
166
|
+
* @returns {any} Token with @ identifier
|
|
167
|
+
*/
|
|
139
168
|
readAtIdentifier() {
|
|
140
169
|
const start = this.pos;
|
|
141
170
|
this.pos++; // skip '@'
|
|
@@ -166,7 +195,11 @@ function RipplePlugin(config) {
|
|
|
166
195
|
return this.finishToken(tt.name, '@' + word);
|
|
167
196
|
}
|
|
168
197
|
|
|
169
|
-
|
|
198
|
+
/**
|
|
199
|
+
* Override parseIdent to mark @ identifiers as tracked
|
|
200
|
+
* @param {any} [liberal] - Whether to allow liberal parsing
|
|
201
|
+
* @returns {any} Parsed identifier node
|
|
202
|
+
*/
|
|
170
203
|
parseIdent(liberal) {
|
|
171
204
|
const node = super.parseIdent(liberal);
|
|
172
205
|
if (node.name && node.name.startsWith('@')) {
|
|
@@ -181,6 +214,13 @@ function RipplePlugin(config) {
|
|
|
181
214
|
return node;
|
|
182
215
|
}
|
|
183
216
|
|
|
217
|
+
/**
|
|
218
|
+
* Parse expression atom - handles TrackedArray and TrackedObject literals
|
|
219
|
+
* @param {any} [refDestructuringErrors]
|
|
220
|
+
* @param {any} [forNew]
|
|
221
|
+
* @param {any} [forInit]
|
|
222
|
+
* @returns {any} Parsed expression atom
|
|
223
|
+
*/
|
|
184
224
|
parseExprAtom(refDestructuringErrors, forNew, forInit) {
|
|
185
225
|
// Check if this is a tuple literal starting with #[
|
|
186
226
|
if (this.type === tt.bracketL && this.value === '#[') {
|
|
@@ -455,24 +495,30 @@ function RipplePlugin(config) {
|
|
|
455
495
|
jsx_parseExpressionContainer() {
|
|
456
496
|
let node = this.startNode();
|
|
457
497
|
this.next();
|
|
458
|
-
|
|
498
|
+
let tracked = false;
|
|
459
499
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
500
|
+
if (this.value === 'html') {
|
|
501
|
+
node.html = true;
|
|
502
|
+
this.next();
|
|
503
|
+
if (this.type === tt.braceR) {
|
|
504
|
+
this.raise(
|
|
505
|
+
this.start,
|
|
506
|
+
'"html" is a Ripple keyword and must be used in the form {html some_content}',
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
if (this.type.label === '@') {
|
|
510
|
+
this.next(); // consume @
|
|
511
|
+
tracked = true;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
468
514
|
|
|
469
515
|
node.expression =
|
|
470
516
|
this.type === tt.braceR ? this.jsx_parseEmptyExpression() : this.parseExpression();
|
|
471
517
|
this.expect(tt.braceR);
|
|
472
518
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
519
|
+
if (tracked && node.expression.type === 'Identifier') {
|
|
520
|
+
node.expression.tracked = true;
|
|
521
|
+
}
|
|
476
522
|
|
|
477
523
|
return this.finishNode(node, 'JSXExpressionContainer');
|
|
478
524
|
}
|
|
@@ -812,6 +858,7 @@ function RipplePlugin(config) {
|
|
|
812
858
|
const element = this.startNode();
|
|
813
859
|
element.start = position.index;
|
|
814
860
|
element.loc.start = position;
|
|
861
|
+
element.metadata = {};
|
|
815
862
|
element.type = 'Element';
|
|
816
863
|
this.#path.push(element);
|
|
817
864
|
element.children = [];
|
|
@@ -970,7 +1017,7 @@ function RipplePlugin(config) {
|
|
|
970
1017
|
if (this.type.label === '{') {
|
|
971
1018
|
const node = this.jsx_parseExpressionContainer();
|
|
972
1019
|
node.type = node.html ? 'Html' : 'Text';
|
|
973
|
-
|
|
1020
|
+
delete node.html;
|
|
974
1021
|
body.push(node);
|
|
975
1022
|
} else if (this.type.label === '}') {
|
|
976
1023
|
return;
|
|
@@ -1144,7 +1191,8 @@ function RipplePlugin(config) {
|
|
|
1144
1191
|
* in JS code and so that `prettier-plugin-ripple` doesn't remove all comments when formatting.
|
|
1145
1192
|
* @param {string} source
|
|
1146
1193
|
* @param {CommentWithLocation[]} comments
|
|
1147
|
-
* @param {number} index
|
|
1194
|
+
* @param {number} [index=0] - Starting index
|
|
1195
|
+
* @returns {{ onComment: Function, add_comments: Function }} Comment handler functions
|
|
1148
1196
|
*/
|
|
1149
1197
|
function get_comment_handlers(source, comments, index = 0) {
|
|
1150
1198
|
return {
|
|
@@ -1239,7 +1287,13 @@ function get_comment_handlers(source, comments, index = 0) {
|
|
|
1239
1287
|
};
|
|
1240
1288
|
}
|
|
1241
1289
|
|
|
1290
|
+
/**
|
|
1291
|
+
* Parse Ripple source code into an AST
|
|
1292
|
+
* @param {string} source
|
|
1293
|
+
* @returns {Program}
|
|
1294
|
+
*/
|
|
1242
1295
|
export function parse(source) {
|
|
1296
|
+
/** @type {CommentWithLocation[]} */
|
|
1243
1297
|
const comments = [];
|
|
1244
1298
|
const { onComment, add_comments } = get_comment_handlers(source, comments);
|
|
1245
1299
|
let ast;
|
|
@@ -1249,7 +1303,7 @@ export function parse(source) {
|
|
|
1249
1303
|
sourceType: 'module',
|
|
1250
1304
|
ecmaVersion: 13,
|
|
1251
1305
|
locations: true,
|
|
1252
|
-
onComment,
|
|
1306
|
+
onComment: /** @type {any} */ (onComment),
|
|
1253
1307
|
});
|
|
1254
1308
|
} catch (e) {
|
|
1255
1309
|
throw e;
|
|
@@ -1257,5 +1311,5 @@ export function parse(source) {
|
|
|
1257
1311
|
|
|
1258
1312
|
add_comments(ast);
|
|
1259
1313
|
|
|
1260
|
-
return ast;
|
|
1314
|
+
return /** @type {Program} */ (ast);
|
|
1261
1315
|
}
|
|
@@ -46,8 +46,7 @@ function add_ripple_internal_import(context) {
|
|
|
46
46
|
|
|
47
47
|
function visit_function(node, context) {
|
|
48
48
|
if (context.state.to_ts) {
|
|
49
|
-
context.next(context.state);
|
|
50
|
-
return;
|
|
49
|
+
return context.next(context.state);
|
|
51
50
|
}
|
|
52
51
|
const metadata = node.metadata;
|
|
53
52
|
const state = context.state;
|
|
@@ -545,6 +544,7 @@ const visitors = {
|
|
|
545
544
|
|
|
546
545
|
if (is_dom_element) {
|
|
547
546
|
let class_attribute = null;
|
|
547
|
+
let style_attribute = null;
|
|
548
548
|
const local_updates = [];
|
|
549
549
|
const is_void = is_void_element(node.id.name);
|
|
550
550
|
|
|
@@ -560,7 +560,7 @@ const visitors = {
|
|
|
560
560
|
continue;
|
|
561
561
|
}
|
|
562
562
|
|
|
563
|
-
if (attr.value.type === 'Literal' && name !== 'class') {
|
|
563
|
+
if (attr.value.type === 'Literal' && name !== 'class' && name !== 'style') {
|
|
564
564
|
handle_static_attr(name, attr.value.value);
|
|
565
565
|
continue;
|
|
566
566
|
}
|
|
@@ -571,6 +571,12 @@ const visitors = {
|
|
|
571
571
|
continue;
|
|
572
572
|
}
|
|
573
573
|
|
|
574
|
+
if (name === 'style') {
|
|
575
|
+
style_attribute = attr;
|
|
576
|
+
|
|
577
|
+
continue;
|
|
578
|
+
}
|
|
579
|
+
|
|
574
580
|
if (name === 'value') {
|
|
575
581
|
const id = state.flush_node();
|
|
576
582
|
const metadata = { tracking: false, await: false };
|
|
@@ -743,6 +749,25 @@ const visitors = {
|
|
|
743
749
|
handle_static_attr(is_spreading ? '#class' : 'class', value);
|
|
744
750
|
}
|
|
745
751
|
|
|
752
|
+
if (style_attribute !== null) {
|
|
753
|
+
if (style_attribute.value.type === 'Literal') {
|
|
754
|
+
handle_static_attr(style_attribute.name.name, style_attribute.value.value);
|
|
755
|
+
} else {
|
|
756
|
+
const id = state.flush_node();
|
|
757
|
+
const metadata = { tracking: false, await: false };
|
|
758
|
+
const expression = visit(style_attribute.value, { ...state, metadata });
|
|
759
|
+
const name = style_attribute.name.name;
|
|
760
|
+
|
|
761
|
+
const statement = b.stmt(b.call('_$_.set_attribute', id, b.literal(name), expression));
|
|
762
|
+
|
|
763
|
+
if (metadata.tracking) {
|
|
764
|
+
local_updates.push(statement);
|
|
765
|
+
} else {
|
|
766
|
+
state.init.push(statement);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
746
771
|
state.template.push('>');
|
|
747
772
|
|
|
748
773
|
if (spread_attributes !== null && spread_attributes.length > 0) {
|
|
@@ -800,13 +825,17 @@ const visitors = {
|
|
|
800
825
|
}
|
|
801
826
|
|
|
802
827
|
props.push(
|
|
803
|
-
b.prop(
|
|
828
|
+
b.prop(
|
|
829
|
+
'get',
|
|
830
|
+
b.key(attr.name.name),
|
|
831
|
+
b.function(null, [], b.block([b.return(property)])),
|
|
832
|
+
),
|
|
804
833
|
);
|
|
805
834
|
} else {
|
|
806
|
-
props.push(b.prop('init', attr.name, property));
|
|
835
|
+
props.push(b.prop('init', b.key(attr.name.name), property));
|
|
807
836
|
}
|
|
808
837
|
} else {
|
|
809
|
-
props.push(b.prop('init', attr.name, visit(attr.value, state)));
|
|
838
|
+
props.push(b.prop('init', b.key(attr.name.name), visit(attr.value, state)));
|
|
810
839
|
}
|
|
811
840
|
} else if (attr.type === 'SpreadAttribute') {
|
|
812
841
|
props.push(
|
|
@@ -896,7 +925,11 @@ const visitors = {
|
|
|
896
925
|
}),
|
|
897
926
|
];
|
|
898
927
|
|
|
899
|
-
return b.function(
|
|
928
|
+
return b.function(
|
|
929
|
+
node.id,
|
|
930
|
+
node.params.map((param) => context.visit(param, { ...context.state, metadata })),
|
|
931
|
+
b.block(body_statements),
|
|
932
|
+
);
|
|
900
933
|
}
|
|
901
934
|
|
|
902
935
|
let props = b.id('__props');
|
|
@@ -1000,8 +1033,7 @@ const visitors = {
|
|
|
1000
1033
|
|
|
1001
1034
|
UpdateExpression(node, context) {
|
|
1002
1035
|
if (context.state.to_ts) {
|
|
1003
|
-
context.next();
|
|
1004
|
-
return;
|
|
1036
|
+
return context.next();
|
|
1005
1037
|
}
|
|
1006
1038
|
const argument = node.argument;
|
|
1007
1039
|
|
|
@@ -1047,8 +1079,7 @@ const visitors = {
|
|
|
1047
1079
|
|
|
1048
1080
|
ForOfStatement(node, context) {
|
|
1049
1081
|
if (!is_inside_component(context)) {
|
|
1050
|
-
context.next();
|
|
1051
|
-
return;
|
|
1082
|
+
return context.next();
|
|
1052
1083
|
}
|
|
1053
1084
|
const is_controlled = node.is_controlled;
|
|
1054
1085
|
const index = node.index;
|
|
@@ -1090,8 +1121,7 @@ const visitors = {
|
|
|
1090
1121
|
|
|
1091
1122
|
IfStatement(node, context) {
|
|
1092
1123
|
if (!is_inside_component(context)) {
|
|
1093
|
-
context.next();
|
|
1094
|
-
return;
|
|
1124
|
+
return context.next();
|
|
1095
1125
|
}
|
|
1096
1126
|
context.state.template.push('<!>');
|
|
1097
1127
|
|
|
@@ -1174,8 +1204,7 @@ const visitors = {
|
|
|
1174
1204
|
|
|
1175
1205
|
TryStatement(node, context) {
|
|
1176
1206
|
if (!is_inside_component(context)) {
|
|
1177
|
-
context.next();
|
|
1178
|
-
return;
|
|
1207
|
+
return context.next();
|
|
1179
1208
|
}
|
|
1180
1209
|
context.state.template.push('<!>');
|
|
1181
1210
|
|
|
@@ -1310,46 +1339,54 @@ function transform_ts_child(node, context) {
|
|
|
1310
1339
|
|
|
1311
1340
|
if (node.type === 'Text') {
|
|
1312
1341
|
state.init.push(b.stmt(visit(node.expression, { ...state })));
|
|
1342
|
+
} else if (node.type === 'Html') {
|
|
1343
|
+
// Do we need to do something special here?
|
|
1344
|
+
state.init.push(b.stmt(visit(node.expression, { ...state })));
|
|
1313
1345
|
} else if (node.type === 'Element') {
|
|
1314
1346
|
const type = node.id.name;
|
|
1315
1347
|
const children = [];
|
|
1316
1348
|
let has_children_props = false;
|
|
1317
1349
|
|
|
1318
|
-
// Filter out RefAttributes and handle them separately
|
|
1319
1350
|
const ref_attributes = [];
|
|
1320
|
-
const attributes = node.attributes
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1351
|
+
const attributes = node.attributes.map((attr) => {
|
|
1352
|
+
if (attr.type === 'Attribute') {
|
|
1353
|
+
const metadata = { await: false };
|
|
1354
|
+
const name = visit(attr.name, { ...state, metadata });
|
|
1355
|
+
const value =
|
|
1356
|
+
attr.value === null ? b.literal(true) : visit(attr.value, { ...state, metadata });
|
|
1357
|
+
|
|
1358
|
+
// Handle both regular identifiers and tracked identifiers
|
|
1359
|
+
let prop_name;
|
|
1360
|
+
if (name.type === 'Identifier') {
|
|
1361
|
+
prop_name = name.name;
|
|
1362
|
+
} else if (name.type === 'MemberExpression' && name.object.type === 'Identifier') {
|
|
1363
|
+
// For tracked attributes like {@count}, use the original name
|
|
1364
|
+
prop_name = name.object.name;
|
|
1365
|
+
} else {
|
|
1366
|
+
prop_name = attr.name.name || 'unknown';
|
|
1325
1367
|
}
|
|
1326
|
-
return true;
|
|
1327
|
-
})
|
|
1328
|
-
.map((attr) => {
|
|
1329
|
-
if (attr.type === 'Attribute') {
|
|
1330
|
-
const metadata = { await: false };
|
|
1331
|
-
const name = visit(attr.name, { ...state, metadata });
|
|
1332
|
-
const value = visit(attr.value, { ...state, metadata });
|
|
1333
|
-
const jsx_name = b.jsx_id(name.name);
|
|
1334
|
-
if (name.name === 'children') {
|
|
1335
|
-
has_children_props = true;
|
|
1336
|
-
}
|
|
1337
|
-
jsx_name.loc = name.loc;
|
|
1338
1368
|
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
const argument = visit(attr.argument, { ...state, metadata });
|
|
1343
|
-
return b.jsx_spread_attribute(argument);
|
|
1369
|
+
const jsx_name = b.jsx_id(prop_name);
|
|
1370
|
+
if (prop_name === 'children') {
|
|
1371
|
+
has_children_props = true;
|
|
1344
1372
|
}
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1373
|
+
jsx_name.loc = attr.name.loc || name.loc;
|
|
1374
|
+
|
|
1375
|
+
return b.jsx_attribute(jsx_name, b.jsx_expression_container(value));
|
|
1376
|
+
} else if (attr.type === 'SpreadAttribute') {
|
|
1377
|
+
const metadata = { await: false };
|
|
1378
|
+
const argument = visit(attr.argument, { ...state, metadata });
|
|
1379
|
+
return b.jsx_spread_attribute(argument);
|
|
1380
|
+
} else if (attr.type === 'RefAttribute') {
|
|
1381
|
+
if (!context.state.imports.has(`import { createRefKey } from 'ripple'`)) {
|
|
1382
|
+
context.state.imports.add(`import { createRefKey } from 'ripple'`);
|
|
1383
|
+
}
|
|
1384
|
+
const metadata = { await: false };
|
|
1385
|
+
const argument = visit(attr.argument, { ...state, metadata });
|
|
1386
|
+
const wrapper = b.object([b.prop('init', b.call('createRefKey'), argument, true)]);
|
|
1387
|
+
return b.jsx_spread_attribute(wrapper);
|
|
1388
|
+
}
|
|
1389
|
+
});
|
|
1353
1390
|
|
|
1354
1391
|
if (!node.selfClosing && !has_children_props && node.children.length > 0) {
|
|
1355
1392
|
const is_dom_element = is_element_dom_element(node);
|
|
@@ -1468,7 +1505,7 @@ function transform_ts_child(node, context) {
|
|
|
1468
1505
|
|
|
1469
1506
|
state.init.push(b.try(try_body, catch_handler, finally_block));
|
|
1470
1507
|
} else if (node.type === 'Component') {
|
|
1471
|
-
const component = visit(node,
|
|
1508
|
+
const component = visit(node, state);
|
|
1472
1509
|
|
|
1473
1510
|
state.init.push(component);
|
|
1474
1511
|
} else {
|
|
@@ -1592,7 +1629,17 @@ function transform_children(children, context) {
|
|
|
1592
1629
|
context.state.template.push('<!>');
|
|
1593
1630
|
|
|
1594
1631
|
const id = flush_node();
|
|
1595
|
-
state.update.push(
|
|
1632
|
+
state.update.push(
|
|
1633
|
+
b.stmt(
|
|
1634
|
+
b.call(
|
|
1635
|
+
'_$_.html',
|
|
1636
|
+
id,
|
|
1637
|
+
b.thunk(expression),
|
|
1638
|
+
state.namespace === 'svg' && b.true,
|
|
1639
|
+
state.namespace === 'mathml' && b.true,
|
|
1640
|
+
),
|
|
1641
|
+
),
|
|
1642
|
+
);
|
|
1596
1643
|
} else if (node.type === 'Text') {
|
|
1597
1644
|
const metadata = { tracking: false, await: false };
|
|
1598
1645
|
const expression = visit(node.expression, { ...state, metadata });
|
|
@@ -1684,7 +1731,12 @@ function transform_body(body, { visit, state }) {
|
|
|
1684
1731
|
transform_children(body, { visit, state: body_state, root: true });
|
|
1685
1732
|
|
|
1686
1733
|
if (body_state.update.length > 0) {
|
|
1687
|
-
|
|
1734
|
+
if (state.to_ts) {
|
|
1735
|
+
// In TypeScript mode, just add the update statements directly
|
|
1736
|
+
body_state.init.push(...body_state.update);
|
|
1737
|
+
} else {
|
|
1738
|
+
body_state.init.push(b.stmt(b.call('_$_.render', b.thunk(b.block(body_state.update)))));
|
|
1739
|
+
}
|
|
1688
1740
|
}
|
|
1689
1741
|
|
|
1690
1742
|
return [...body_state.setup, ...body_state.init, ...body_state.final];
|