@tsrx/core 0.1.46 → 0.1.47

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.
@@ -1,5 +1,5 @@
1
1
  /** @import * as AST from 'estree' */
2
- /** @import { Visitors } from 'zimmerframe' */
2
+ /** @import * as ESRap from 'esrap' */
3
3
 
4
4
  import tsx from 'esrap/languages/tsx';
5
5
  import { should_preserve_comment, format_comment } from '../../comment-utils.js';
@@ -12,7 +12,7 @@ import { should_preserve_comment, format_comment } from '../../comment-utils.js'
12
12
  * transform built around render children — either way a bare expression in a
13
13
  * child slot would print as JSX text.
14
14
  *
15
- * @param {any[]} path
15
+ * @param {AST.Node[]} path
16
16
  * @returns {boolean}
17
17
  */
18
18
  export function in_jsx_child_context(path) {
@@ -21,15 +21,14 @@ export function in_jsx_child_context(path) {
21
21
  }
22
22
 
23
23
  /**
24
- * @param {any} node
24
+ * @param {AST.Node | null | undefined} node
25
25
  * @returns {boolean}
26
26
  */
27
27
  export function is_empty_jsx_fragment(node) {
28
28
  return (
29
29
  node?.type === 'JSXFragment' &&
30
30
  !(node.children || []).some(
31
- (/** @type {any} */ child) =>
32
- child && (child.type !== 'JSXText' || child.value.trim() !== ''),
31
+ (child) => child && (child.type !== 'JSXText' || child.value.trim() !== ''),
33
32
  )
34
33
  );
35
34
  }
@@ -39,8 +38,8 @@ export function is_empty_jsx_fragment(node) {
39
38
  * carries its current ancestor path for downstream CSS pruning and mapping
40
39
  * helpers.
41
40
  *
42
- * @param {any} node
43
- * @param {any[]} path
41
+ * @param {AST.Node} node
42
+ * @param {AST.Node[]} path
44
43
  * @returns {void}
45
44
  */
46
45
  export function set_node_path_metadata(node, path) {
@@ -62,7 +61,7 @@ export function set_node_path_metadata(node, path) {
62
61
  *
63
62
  * Shared across all JSX-producing targets (React, Preact, Solid).
64
63
  *
65
- * @returns {any}
64
+ * @returns {ESRap.Visitors<AST.Node>}
66
65
  */
67
66
  /**
68
67
  * @param {boolean} [boundary_tokens] Enable esrap's `boundaryTokens` anchors
@@ -76,16 +75,17 @@ export function set_node_path_metadata(node, path) {
76
75
  * TS input — dropping a leading pragma changes how the whole file checks.
77
76
  */
78
77
  export function tsx_with_ts_locations(boundary_tokens = false, comments = undefined) {
79
- const base = /** @type {any} */ (tsx({ boundaryTokens: boundary_tokens }));
78
+ const base = tsx({ boundaryTokens: boundary_tokens });
79
+ const { _: base_visitor, ...base_visitors } = base;
80
80
 
81
- const leading_preserved = (/** @type {any} */ program) => {
81
+ const leading_preserved = (/** @type {AST.Program} */ program) => {
82
82
  if (!comments?.length) return [];
83
83
  // Injected statements (dynamic-import/try-import prepends) carry no
84
84
  // loc; anchor "leading" on the first statement that maps to source,
85
85
  // else every preserved comment in the file would hoist to the top.
86
- const first = program.body?.find((/** @type {any} */ node) => node.loc);
86
+ const first = program.body.find((node) => node.loc);
87
87
  return comments.filter(
88
- (/** @type {any} */ comment) =>
88
+ (comment) =>
89
89
  should_preserve_comment(comment) &&
90
90
  (first?.loc == null ||
91
91
  (comment.loc &&
@@ -95,22 +95,7 @@ export function tsx_with_ts_locations(boundary_tokens = false, comments = undefi
95
95
  );
96
96
  };
97
97
 
98
- /**
99
- * @param {any} node
100
- * @param {any} context
101
- * @param {any} visitor
102
- */
103
- const wrap_with_locations = (node, context, visitor) => {
104
- if (!node.loc) {
105
- visitor(node, context);
106
- return;
107
- }
108
- context.location(node.loc.start.line, node.loc.start.column);
109
- visitor(node, context);
110
- context.location(node.loc.end.line, node.loc.end.column);
111
- };
112
-
113
- /** @type {Record<string, (node: any, context: any) => void>} */
98
+ /** @type {ESRap.Visitors<AST.Node>} */
114
99
  const wrappers = {
115
100
  Program: (node, context) => {
116
101
  for (const comment of leading_preserved(node)) {
@@ -119,10 +104,10 @@ export function tsx_with_ts_locations(boundary_tokens = false, comments = undefi
119
104
  if (comment.loc) context.location(comment.loc.end.line, comment.loc.end.column);
120
105
  context.newline();
121
106
  }
122
- base.Program(node, context);
107
+ /** @type {NonNullable<typeof base.Program>} */ (base.Program)(node, context);
123
108
  },
124
109
  ArrayPattern: (node, context) => {
125
- base.ArrayPattern(node, context);
110
+ /** @type {NonNullable<typeof base.ArrayPattern>} */ (base.ArrayPattern)(node, context);
126
111
  if (node.typeAnnotation) {
127
112
  context.visit(node.typeAnnotation);
128
113
  }
@@ -143,7 +128,7 @@ export function tsx_with_ts_locations(boundary_tokens = false, comments = undefi
143
128
  // must fall through to base.Property to preserve their printed form.
144
129
  Property: (node, context) => {
145
130
  if (!node.method || node.value.type !== 'FunctionExpression') {
146
- base.Property(node, context);
131
+ /** @type {NonNullable<typeof base.Property>} */ (base.Property)(node, context);
147
132
  return;
148
133
  }
149
134
  const value = node.value;
@@ -204,58 +189,68 @@ export function tsx_with_ts_locations(boundary_tokens = false, comments = undefi
204
189
  context.visit(node.id);
205
190
  context.visit(node.body);
206
191
  },
192
+ _(node, context, visit) {
193
+ const visit_with_locations = () => {
194
+ if (!LOCATION_WRAPPED_NODE_TYPES.has(node.type) || !node.loc) {
195
+ visit(node);
196
+ return;
197
+ }
198
+ context.location(node.loc.start.line, node.loc.start.column);
199
+ visit(node);
200
+ context.location(node.loc.end.line, node.loc.end.column);
201
+ };
202
+ if (base_visitor) {
203
+ base_visitor(node, context, visit_with_locations);
204
+ } else {
205
+ visit_with_locations();
206
+ }
207
+ },
207
208
  };
208
209
 
209
- // Be careful when duplicating visitors that are already defined
210
- // above in the `wrappers`
211
- // if there is already a visitor but you still need a mapping
212
- // on the whole node, only then duplicate it here
213
- // e.g. JSXOpeningElement is such a case
214
- for (const type of [
215
- // JS nodes with boundary positions esrap still cannot map. Keyword
216
- // writes (if/new/return/for/switch/await) and `boundaryTokens`
217
- // anchors (brackets, braces, parens, computed/call closers) cover
218
- // many STARTS, but statement ENDS land on unanchored characters
219
- // (`;`, a block's `}`), `class` is not a keyword-write, template
220
- // literals' backticks carry no location, and an arrow's span can
221
- // start at a bare `(` — so these node-level markers remain the
222
- // source of both boundaries until esrap can anchor them.
223
- 'ClassDeclaration',
224
- 'ClassExpression',
225
- 'IfStatement',
226
- 'NewExpression',
227
- 'MemberExpression',
228
- 'ObjectExpression',
229
- 'ReturnStatement',
230
- 'ForStatement',
231
- 'ForInStatement',
232
- 'ForOfStatement',
233
- 'TemplateLiteral',
234
- 'AwaitExpression',
235
- 'SwitchStatement',
236
- 'TaggedTemplateExpression',
237
- 'ArrowFunctionExpression',
238
- // JSX wrapper nodes: esrap writes `<`, `>`, `</`, `{`, `}` without
239
- // locations, so the opening/closing element's and expression
240
- // container's start and end don't resolve.
241
- 'JSXOpeningElement',
242
- 'JSXClosingElement',
243
- 'JSXExpressionContainer',
244
- // TS wrapper nodes with the same issue.
245
- 'TSTypeParameterInstantiation',
246
- 'TSTypeParameterDeclaration',
247
- 'TSTypeParameter',
248
- ]) {
249
- const visitor = wrappers[type];
250
-
251
- wrappers[type] = (node, context) => wrap_with_locations(node, context, visitor ?? base[type]);
252
- }
253
-
254
- return { ...base, ...wrappers };
210
+ return { ...base_visitors, ...wrappers };
255
211
  }
256
212
 
213
+ // Be careful when adding visitors that are already defined in `wrappers`.
214
+ // JSXOpeningElement is intentionally in both places: its custom printer still
215
+ // needs a location marker around the whole node.
216
+ const LOCATION_WRAPPED_NODE_TYPES = new Set([
217
+ // JS nodes with boundary positions esrap still cannot map. Keyword
218
+ // writes (if/new/return/for/switch/await) and `boundaryTokens`
219
+ // anchors (brackets, braces, parens, computed/call closers) cover
220
+ // many STARTS, but statement ENDS land on unanchored characters
221
+ // (`;`, a block's `}`), `class` is not a keyword-write, template
222
+ // literals' backticks carry no location, and an arrow's span can
223
+ // start at a bare `(` — so these node-level markers remain the
224
+ // source of both boundaries until esrap can anchor them.
225
+ 'ClassDeclaration',
226
+ 'ClassExpression',
227
+ 'IfStatement',
228
+ 'NewExpression',
229
+ 'MemberExpression',
230
+ 'ObjectExpression',
231
+ 'ReturnStatement',
232
+ 'ForStatement',
233
+ 'ForInStatement',
234
+ 'ForOfStatement',
235
+ 'TemplateLiteral',
236
+ 'AwaitExpression',
237
+ 'SwitchStatement',
238
+ 'TaggedTemplateExpression',
239
+ 'ArrowFunctionExpression',
240
+ // JSX wrapper nodes: esrap writes `<`, `>`, `</`, `{`, `}` without
241
+ // locations, so the opening/closing element's and expression
242
+ // container's start and end don't resolve.
243
+ 'JSXOpeningElement',
244
+ 'JSXClosingElement',
245
+ 'JSXExpressionContainer',
246
+ // TS wrapper nodes with the same issue.
247
+ 'TSTypeParameterInstantiation',
248
+ 'TSTypeParameterDeclaration',
249
+ 'TSTypeParameter',
250
+ ]);
251
+
257
252
  /**
258
- * @param {any} node
253
+ * @param {AST.Node | null | undefined} node
259
254
  * @returns {boolean}
260
255
  */
261
256
  export function is_template_if_node(node) {
@@ -266,7 +261,7 @@ export function is_template_if_node(node) {
266
261
  }
267
262
 
268
263
  /**
269
- * @param {any} node
264
+ * @param {AST.Node | null | undefined} node
270
265
  * @returns {boolean}
271
266
  */
272
267
  export function is_template_for_of_node(node) {
@@ -277,7 +272,7 @@ export function is_template_for_of_node(node) {
277
272
  }
278
273
 
279
274
  /**
280
- * @param {any} node
275
+ * @param {AST.Node | null | undefined} node
281
276
  * @returns {boolean}
282
277
  */
283
278
  export function is_template_switch_node(node) {
@@ -288,7 +283,7 @@ export function is_template_switch_node(node) {
288
283
  }
289
284
 
290
285
  /**
291
- * @param {any} node
286
+ * @param {AST.Node | null | undefined} node
292
287
  * @returns {boolean}
293
288
  */
294
289
  export function is_template_try_node(node) {