@tsrx/vue 0.1.15 → 0.1.17
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 +2 -2
- package/src/transform.js +125 -129
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Vue compiler built on @tsrx/core",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Dominic Gannaway",
|
|
6
|
-
"version": "0.1.
|
|
6
|
+
"version": "0.1.17",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"publishConfig": {
|
|
9
9
|
"access": "public"
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"esrap": "^2.2.8",
|
|
36
36
|
"is-reference": "^3.0.3",
|
|
37
37
|
"zimmerframe": "^1.1.2",
|
|
38
|
-
"@tsrx/core": "0.1.
|
|
38
|
+
"@tsrx/core": "0.1.17"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"vue": ">=3.5",
|
package/src/transform.js
CHANGED
|
@@ -8,16 +8,14 @@ import {
|
|
|
8
8
|
clone_expression_node,
|
|
9
9
|
clone_identifier,
|
|
10
10
|
contains_component_jsx,
|
|
11
|
-
CREATE_REF_PROP_INTERNAL_NAME,
|
|
12
11
|
createHookSafeHelper,
|
|
13
12
|
create_generated_identifier,
|
|
14
|
-
componentToFunctionDeclaration,
|
|
15
13
|
createJsxTransform,
|
|
16
14
|
error,
|
|
17
15
|
is_component_like_element,
|
|
18
16
|
MERGE_REFS_INTERNAL_NAME,
|
|
17
|
+
NORMALIZE_SPREAD_PROPS_FOR_REF_ATTR_INTERNAL_NAME,
|
|
19
18
|
NORMALIZE_SPREAD_PROPS_INTERNAL_NAME,
|
|
20
|
-
rewriteHostHtmlChildren as rewrite_host_html_children,
|
|
21
19
|
setLocation,
|
|
22
20
|
toJsxAttribute,
|
|
23
21
|
} from '@tsrx/core';
|
|
@@ -68,11 +66,14 @@ const vue_platform = {
|
|
|
68
66
|
ctx.needs_define_vapor_component = true;
|
|
69
67
|
return wrap_helper_component(helper_fn, helper_id, source_node);
|
|
70
68
|
},
|
|
69
|
+
wrapNativeFunctionComponent(fn, ctx, path) {
|
|
70
|
+
return wrap_native_function_component(fn, ctx, path);
|
|
71
|
+
},
|
|
71
72
|
canHoistStaticNode(node) {
|
|
72
73
|
return !contains_component_jsx(node);
|
|
73
74
|
},
|
|
74
|
-
preprocessElementAttributes(attrs, ctx
|
|
75
|
-
return preprocess_ref_attributes(attrs,
|
|
75
|
+
preprocessElementAttributes(attrs, ctx) {
|
|
76
|
+
return preprocess_ref_attributes(attrs, ctx);
|
|
76
77
|
},
|
|
77
78
|
transformElementAttributes(attrs, ctx, element) {
|
|
78
79
|
const result = attrs.map((attr) => toJsxAttribute(attr, ctx));
|
|
@@ -130,13 +131,7 @@ const vue_platform = {
|
|
|
130
131
|
return builders.arrow([], jsx_child_to_expression(try_content));
|
|
131
132
|
},
|
|
132
133
|
transformElementChildren(node, walked_children, raw_children, attributes, ctx) {
|
|
133
|
-
return
|
|
134
|
-
node,
|
|
135
|
-
walked_children,
|
|
136
|
-
raw_children,
|
|
137
|
-
attributes,
|
|
138
|
-
ctx,
|
|
139
|
-
);
|
|
134
|
+
return rewrite_host_text_children(node, walked_children, raw_children, attributes);
|
|
140
135
|
},
|
|
141
136
|
validateComponentAwait(await_expression, _component, ctx) {
|
|
142
137
|
error(
|
|
@@ -147,10 +142,6 @@ const vue_platform = {
|
|
|
147
142
|
ctx?.comments,
|
|
148
143
|
);
|
|
149
144
|
},
|
|
150
|
-
componentToFunction(component, ctx, helper_state) {
|
|
151
|
-
ctx.needs_define_vapor_component = true;
|
|
152
|
-
return component_to_vapor_component_declaration(component, ctx, helper_state);
|
|
153
|
-
},
|
|
154
145
|
injectImports(program, ctx) {
|
|
155
146
|
inject_vue_imports(program, ctx);
|
|
156
147
|
},
|
|
@@ -388,43 +379,6 @@ function mark_type_only_host_ref_attribute(attr) {
|
|
|
388
379
|
};
|
|
389
380
|
}
|
|
390
381
|
|
|
391
|
-
/**
|
|
392
|
-
* @param {any} component
|
|
393
|
-
* @param {any} transform_context
|
|
394
|
-
* @param {any} helper_state
|
|
395
|
-
* @returns {any}
|
|
396
|
-
*/
|
|
397
|
-
function component_to_vapor_component_declaration(component, transform_context, helper_state) {
|
|
398
|
-
const fn = componentToFunctionDeclaration(component, transform_context, helper_state);
|
|
399
|
-
const generated_helpers = helper_state?.helpers || [];
|
|
400
|
-
const generated_statics = helper_state?.statics || [];
|
|
401
|
-
const call = create_define_vapor_component_call(
|
|
402
|
-
function_declaration_to_expression(fn),
|
|
403
|
-
generated_helpers,
|
|
404
|
-
generated_statics,
|
|
405
|
-
);
|
|
406
|
-
|
|
407
|
-
if (component.default || !component.id) {
|
|
408
|
-
return call;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
const component_id = create_generated_identifier(component.id.name);
|
|
412
|
-
const fn_id = fn.type === 'FunctionDeclaration' ? fn.id : null;
|
|
413
|
-
component_id.metadata = {
|
|
414
|
-
...component_id.metadata,
|
|
415
|
-
...(fn_id?.metadata || {}),
|
|
416
|
-
path: component_id.metadata?.path || [],
|
|
417
|
-
};
|
|
418
|
-
/** @type {any} */ (component_id.metadata).hover = create_component_hover_replacement(fn.params);
|
|
419
|
-
|
|
420
|
-
const declaration = builders.declaration('const', [builders.declarator(component_id, call)]);
|
|
421
|
-
Object.assign(/** @type {any} */ (declaration.metadata), {
|
|
422
|
-
generated_helpers,
|
|
423
|
-
generated_statics,
|
|
424
|
-
});
|
|
425
|
-
return declaration;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
382
|
/**
|
|
429
383
|
* @param {any} helper_fn
|
|
430
384
|
* @param {any} helper_id
|
|
@@ -443,6 +397,91 @@ function wrap_helper_component(helper_fn, helper_id, source_node) {
|
|
|
443
397
|
);
|
|
444
398
|
}
|
|
445
399
|
|
|
400
|
+
/**
|
|
401
|
+
* @param {any} fn
|
|
402
|
+
* @param {any} ctx
|
|
403
|
+
* @param {any[]} path
|
|
404
|
+
* @returns {any | null}
|
|
405
|
+
*/
|
|
406
|
+
function wrap_native_function_component(fn, ctx, path) {
|
|
407
|
+
const name = get_function_component_name(fn, path);
|
|
408
|
+
if (!name || !/^[A-Z]/.test(name)) {
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
ctx.needs_define_vapor_component = true;
|
|
413
|
+
|
|
414
|
+
const call = create_define_vapor_component_call(
|
|
415
|
+
function_declaration_to_expression(fn),
|
|
416
|
+
fn.metadata?.generated_helpers || [],
|
|
417
|
+
fn.metadata?.generated_statics || [],
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
if (fn.type !== 'FunctionDeclaration') {
|
|
421
|
+
return call;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const parent = path.at(-1);
|
|
425
|
+
if (parent?.type === 'ExportDefaultDeclaration' && parent.declaration === fn) {
|
|
426
|
+
return setLocation(call, fn, true);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (!fn.id) {
|
|
430
|
+
return call;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
return setLocation(
|
|
434
|
+
builders.declaration('const', [
|
|
435
|
+
builders.declarator(create_generated_identifier(fn.id.name), setLocation(call, fn, true)),
|
|
436
|
+
]),
|
|
437
|
+
fn,
|
|
438
|
+
true,
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* @param {any} fn
|
|
444
|
+
* @param {any[]} path
|
|
445
|
+
* @returns {string | null}
|
|
446
|
+
*/
|
|
447
|
+
function get_function_component_name(fn, path) {
|
|
448
|
+
if (fn.id?.type === 'Identifier') {
|
|
449
|
+
return fn.id.name;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const parent = path.at(-1);
|
|
453
|
+
if (parent?.type === 'VariableDeclarator' && parent.init === fn) {
|
|
454
|
+
return get_static_name(parent.id);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if (parent?.type === 'Property' && parent.value === fn) {
|
|
458
|
+
return get_static_name(parent.key);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (parent?.type === 'AssignmentExpression' && parent.right === fn) {
|
|
462
|
+
return get_static_name(parent.left);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return null;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* @param {any} node
|
|
470
|
+
* @returns {string | null}
|
|
471
|
+
*/
|
|
472
|
+
function get_static_name(node) {
|
|
473
|
+
if (node?.type === 'Identifier') {
|
|
474
|
+
return node.name;
|
|
475
|
+
}
|
|
476
|
+
if (node?.type === 'Literal' && typeof node.value === 'string') {
|
|
477
|
+
return node.value;
|
|
478
|
+
}
|
|
479
|
+
if (node?.type === 'MemberExpression' && !node.computed) {
|
|
480
|
+
return get_static_name(node.property);
|
|
481
|
+
}
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
|
|
446
485
|
/**
|
|
447
486
|
* @param {any} fn_expression
|
|
448
487
|
* @param {any[]} generated_helpers
|
|
@@ -1026,29 +1065,6 @@ function function_declaration_to_expression(fn) {
|
|
|
1026
1065
|
};
|
|
1027
1066
|
}
|
|
1028
1067
|
|
|
1029
|
-
const VUE_COMPONENT_HOVER_LABEL_REGEX = /(function|\((property|method)\))/;
|
|
1030
|
-
|
|
1031
|
-
/**
|
|
1032
|
-
* @param {any[]} [params]
|
|
1033
|
-
* @returns {(content: string) => string}
|
|
1034
|
-
*/
|
|
1035
|
-
function create_component_hover_replacement(params) {
|
|
1036
|
-
const lazy_param_regexes = (params || [])
|
|
1037
|
-
.filter((param) => param.type === 'Identifier' && /^__lazy\d+$/.test(param.name))
|
|
1038
|
-
.map((param) => new RegExp(`\\b${param.name}\\s*:\\s*`, 'g'));
|
|
1039
|
-
|
|
1040
|
-
return (content) => {
|
|
1041
|
-
let next = content.replace(VUE_COMPONENT_HOVER_LABEL_REGEX, (_, fn, kind) => {
|
|
1042
|
-
if (fn === 'function') return 'component';
|
|
1043
|
-
return `(component ${kind})`;
|
|
1044
|
-
});
|
|
1045
|
-
for (const regex of lazy_param_regexes) {
|
|
1046
|
-
next = next.replace(regex, '&');
|
|
1047
|
-
}
|
|
1048
|
-
return next;
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
1068
|
const VUE_SETUP_CALLS = new Set([
|
|
1053
1069
|
'ref',
|
|
1054
1070
|
'shallowRef',
|
|
@@ -1085,32 +1101,19 @@ function is_vue_setup_call(call_expression) {
|
|
|
1085
1101
|
}
|
|
1086
1102
|
|
|
1087
1103
|
/**
|
|
1088
|
-
*
|
|
1089
|
-
*
|
|
1090
|
-
*
|
|
1091
|
-
*
|
|
1092
|
-
*
|
|
1104
|
+
* Vue's JSX transform treats some prop names ending in `ref` as template-ref
|
|
1105
|
+
* sugar on components. Keep those as ordinary runtime props by hiding the
|
|
1106
|
+
* static prop name behind an object spread before Vue sees the JSX. Type-only
|
|
1107
|
+
* virtual TSX skips that spread so Volar can offer completions on the real
|
|
1108
|
+
* component prop name.
|
|
1093
1109
|
*
|
|
1094
1110
|
* @param {any[]} attrs
|
|
1095
|
-
* @param {any} element
|
|
1096
1111
|
* @param {any} transform_context
|
|
1097
1112
|
* @returns {any[]}
|
|
1098
1113
|
*/
|
|
1099
|
-
function preprocess_ref_attributes(attrs,
|
|
1100
|
-
if (!is_component_like_element(element)) {
|
|
1101
|
-
return attrs;
|
|
1102
|
-
}
|
|
1114
|
+
function preprocess_ref_attributes(attrs, transform_context) {
|
|
1103
1115
|
const result = [];
|
|
1104
1116
|
for (const attr of attrs) {
|
|
1105
|
-
if (attr?.type === 'RefAttribute') {
|
|
1106
|
-
error(
|
|
1107
|
-
'`{ref ...}` on the Vue target is only supported on host elements. Vue component refs resolve to component instances rather than the rendered DOM node, so Ripple-style component refs are not supported here.',
|
|
1108
|
-
transform_context?.filename ?? null,
|
|
1109
|
-
attr,
|
|
1110
|
-
transform_context?.errors,
|
|
1111
|
-
transform_context?.comments,
|
|
1112
|
-
);
|
|
1113
|
-
}
|
|
1114
1117
|
if (!transform_context.typeOnly && is_vue_named_ref_attribute(attr)) {
|
|
1115
1118
|
result.push(create_vue_named_ref_spread(attr));
|
|
1116
1119
|
continue;
|
|
@@ -1121,12 +1124,6 @@ function preprocess_ref_attributes(attrs, element, transform_context) {
|
|
|
1121
1124
|
}
|
|
1122
1125
|
|
|
1123
1126
|
/**
|
|
1124
|
-
* Vue's JSX transform treats prop names ending in `ref` as template-ref
|
|
1125
|
-
* sugar on components. Keep named TSRX refs as ordinary runtime props by
|
|
1126
|
-
* hiding the static prop name behind an object spread before Vue sees the JSX.
|
|
1127
|
-
* Type-only virtual TSX skips that spread so Volar can offer completions on
|
|
1128
|
-
* the real component prop name.
|
|
1129
|
-
*
|
|
1130
1127
|
* @param {any} attr
|
|
1131
1128
|
* @returns {boolean}
|
|
1132
1129
|
*/
|
|
@@ -1137,13 +1134,19 @@ function is_vue_named_ref_attribute(attr) {
|
|
|
1137
1134
|
attr_name &&
|
|
1138
1135
|
attr_name !== 'ref' &&
|
|
1139
1136
|
(attr?.type === 'Attribute' || attr?.type === 'JSXAttribute') &&
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
value.callee?.type === 'Identifier' &&
|
|
1143
|
-
value.callee.name === CREATE_REF_PROP_INTERNAL_NAME))
|
|
1137
|
+
value &&
|
|
1138
|
+
is_vue_ref_prop_name(attr_name)
|
|
1144
1139
|
);
|
|
1145
1140
|
}
|
|
1146
1141
|
|
|
1142
|
+
/**
|
|
1143
|
+
* @param {string} name
|
|
1144
|
+
* @returns {boolean}
|
|
1145
|
+
*/
|
|
1146
|
+
function is_vue_ref_prop_name(name) {
|
|
1147
|
+
return /(?:^|[-_])ref$/i.test(name) || /Ref$/.test(name);
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1147
1150
|
/**
|
|
1148
1151
|
* @param {any} attr
|
|
1149
1152
|
* @returns {any}
|
|
@@ -1152,7 +1155,13 @@ function create_vue_named_ref_spread(attr) {
|
|
|
1152
1155
|
const attr_name = get_vue_attribute_name(attr);
|
|
1153
1156
|
const value = get_vue_attribute_expression(attr);
|
|
1154
1157
|
if (attr_name === null) return attr;
|
|
1155
|
-
const prop = builders.prop(
|
|
1158
|
+
const prop = builders.prop(
|
|
1159
|
+
'init',
|
|
1160
|
+
builders.key(attr_name),
|
|
1161
|
+
value ?? builders.literal(true),
|
|
1162
|
+
false,
|
|
1163
|
+
false,
|
|
1164
|
+
);
|
|
1156
1165
|
return builders.jsx_spread_attribute(builders.object([prop], attr), attr);
|
|
1157
1166
|
}
|
|
1158
1167
|
|
|
@@ -1184,30 +1193,12 @@ function get_vue_attribute_expression(attr) {
|
|
|
1184
1193
|
* @param {any[]} walked_children
|
|
1185
1194
|
* @param {any[]} raw_children
|
|
1186
1195
|
* @param {any[]} attributes
|
|
1187
|
-
* @param {any} [transform_context]
|
|
1188
1196
|
* @returns {{ children: any[]; selfClosing?: boolean } | null}
|
|
1189
1197
|
*/
|
|
1190
|
-
function
|
|
1191
|
-
node,
|
|
1192
|
-
walked_children,
|
|
1193
|
-
raw_children,
|
|
1194
|
-
attributes,
|
|
1195
|
-
transform_context,
|
|
1196
|
-
) {
|
|
1198
|
+
function rewrite_host_text_children(node, walked_children, raw_children, attributes) {
|
|
1197
1199
|
const source_children = raw_children || walked_children;
|
|
1198
1200
|
const is_composite = is_component_like_element(node);
|
|
1199
1201
|
|
|
1200
|
-
const html_child_transform = rewrite_host_html_children(
|
|
1201
|
-
node,
|
|
1202
|
-
walked_children,
|
|
1203
|
-
raw_children,
|
|
1204
|
-
attributes,
|
|
1205
|
-
transform_context,
|
|
1206
|
-
);
|
|
1207
|
-
if (html_child_transform) {
|
|
1208
|
-
return html_child_transform;
|
|
1209
|
-
}
|
|
1210
|
-
|
|
1211
1202
|
if (!is_composite && source_children.length === 1 && source_children[0]?.type === 'Text') {
|
|
1212
1203
|
return null;
|
|
1213
1204
|
}
|
|
@@ -1250,10 +1241,6 @@ function inject_vue_imports(program, transform_context) {
|
|
|
1250
1241
|
ensure_named_import(program, '@tsrx/vue/ref', 'mergeRefs', MERGE_REFS_INTERNAL_NAME);
|
|
1251
1242
|
}
|
|
1252
1243
|
|
|
1253
|
-
if (transform_context.needs_ref_prop) {
|
|
1254
|
-
ensure_named_import(program, '@tsrx/vue/ref', 'create_ref_prop', CREATE_REF_PROP_INTERNAL_NAME);
|
|
1255
|
-
}
|
|
1256
|
-
|
|
1257
1244
|
if (transform_context.needs_normalize_spread_props) {
|
|
1258
1245
|
ensure_named_import(
|
|
1259
1246
|
program,
|
|
@@ -1262,6 +1249,15 @@ function inject_vue_imports(program, transform_context) {
|
|
|
1262
1249
|
NORMALIZE_SPREAD_PROPS_INTERNAL_NAME,
|
|
1263
1250
|
);
|
|
1264
1251
|
}
|
|
1252
|
+
|
|
1253
|
+
if (transform_context.needs_normalize_spread_props_for_ref_attr) {
|
|
1254
|
+
ensure_named_import(
|
|
1255
|
+
program,
|
|
1256
|
+
'@tsrx/vue/ref',
|
|
1257
|
+
'normalize_spread_props_for_ref_attr',
|
|
1258
|
+
NORMALIZE_SPREAD_PROPS_FOR_REF_ATTR_INTERNAL_NAME,
|
|
1259
|
+
);
|
|
1260
|
+
}
|
|
1265
1261
|
}
|
|
1266
1262
|
|
|
1267
1263
|
/**
|