|
1 | 1 | import { compile } from '@vue-jsx-vapor/compiler'
|
2 |
| -import generate from '@babel/generator' |
3 | 2 | import { parse } from '@babel/parser'
|
4 | 3 | import { SourceMapConsumer } from 'source-map-js'
|
5 |
| -import traverse, { |
6 |
| - type NodePath, |
7 |
| - type VisitNodeFunction, |
8 |
| -} from '@babel/traverse' |
9 |
| -import type { Opts } from '.' |
| 4 | +import traverse, { type VisitNodeFunction } from '@babel/traverse' |
| 5 | +import type { Options } from '.' |
10 | 6 | import type { JSXElement, JSXFragment, Node } from '@babel/types'
|
11 | 7 |
|
12 | 8 | export const transformJSX: VisitNodeFunction<
|
13 |
| - { |
14 |
| - filename: string |
15 |
| - opts: Opts |
16 |
| - }, |
| 9 | + Options, |
17 | 10 | JSXElement | JSXFragment
|
18 | 11 | > = (path, state) => {
|
19 | 12 | const { parent, node } = path
|
20 |
| - if ( |
21 |
| - !( |
22 |
| - parent?.type !== 'JSXExpressionContainer' && |
23 |
| - !isJSXElement(parent) && |
24 |
| - !isConditionalExpression(path.parentPath) |
25 |
| - ) |
26 |
| - ) { |
| 13 | + if (!(parent?.type !== 'JSXExpressionContainer' && !isJSXElement(parent))) { |
27 | 14 | return
|
28 | 15 | }
|
29 | 16 |
|
30 | 17 | let { code, vaporHelpers, preamble, map } = compile(
|
31 |
| - ' '.repeat(node.loc?.start.column || 0) + generate(node).code, |
| 18 | + state.rootCodes.shift()!, |
32 | 19 | {
|
33 | 20 | mode: 'module',
|
34 | 21 | inline: true,
|
35 | 22 | isTS: state.filename?.endsWith('tsx'),
|
36 | 23 | filename: state.filename,
|
37 | 24 | sourceMap: true,
|
38 |
| - ...state.opts?.compile, |
| 25 | + ...state?.compile, |
39 | 26 | },
|
40 | 27 | )
|
41 |
| - vaporHelpers.forEach((helper) => state.opts.importSet.add(helper)) |
| 28 | + vaporHelpers.forEach((helper) => state.importSet.add(helper)) |
42 | 29 |
|
43 | 30 | preamble = preamble.replaceAll(
|
44 | 31 | /(?<=const )t(?=(\d))/g,
|
45 |
| - `_t${state.opts.preambleIndex}`, |
| 32 | + `_t${state.preambleIndex}`, |
46 | 33 | )
|
47 | 34 | code = code
|
48 |
| - .replaceAll(/(?<== )t(?=\d)/g, `_t${state.opts.preambleIndex}`) |
| 35 | + .replaceAll(/(?<== )t(?=\d)/g, `_t${state.preambleIndex}`) |
49 | 36 | .replaceAll('_ctx: any', '')
|
50 | 37 | .replaceAll('$event: any', '$event')
|
51 |
| - state.opts.preambleIndex++ |
| 38 | + state.preambleIndex++ |
52 | 39 |
|
53 | 40 | for (const [, key, value] of preamble.matchAll(
|
54 | 41 | /const (_t\d+) = (_template\(.*\))/g,
|
55 | 42 | )) {
|
56 |
| - const result = state.opts.preambleMap.get(value) |
| 43 | + const result = state.preambleMap.get(value) |
57 | 44 | if (result) {
|
58 | 45 | code = code.replaceAll(key, result)
|
59 | 46 | } else {
|
60 |
| - state.opts.preambleMap.set(value, key) |
| 47 | + state.preambleMap.set(value, key) |
61 | 48 | }
|
62 | 49 | }
|
63 | 50 |
|
64 | 51 | for (const [, events] of preamble.matchAll(/_delegateEvents\((.*)\)/g)) {
|
65 |
| - events |
66 |
| - .split(', ') |
67 |
| - .forEach((event: any) => state.opts.delegateEventSet.add(event)) |
| 52 | + events.split(', ').forEach((event) => state.delegateEventSet.add(event)) |
68 | 53 | }
|
69 | 54 |
|
70 | 55 | const ast = parse(code, {
|
71 | 56 | sourceFilename: state.filename,
|
| 57 | + startLine: node.loc!.start.line - 1, |
| 58 | + plugins: ['jsx'], |
72 | 59 | })
|
73 | 60 |
|
74 | 61 | if (map) {
|
75 | 62 | const consumer = new SourceMapConsumer(map)
|
76 |
| - const line = (node.loc?.start.line ?? 1) - 1 |
| 63 | + const line = node.loc!.start.line - 1 |
77 | 64 | traverse(ast, {
|
78 | 65 | Identifier({ node: id }) {
|
79 |
| - const originalLoc = consumer.originalPositionFor(id.loc!.start) |
80 |
| - if (originalLoc) { |
81 |
| - id.loc = { |
82 |
| - ...id.loc!, |
83 |
| - start: { |
84 |
| - line: line + originalLoc.line, |
85 |
| - column: originalLoc.column, |
86 |
| - index: originalLoc.column, |
87 |
| - }, |
88 |
| - end: { |
89 |
| - line: line + originalLoc.line, |
90 |
| - column: originalLoc.column + id.name.length, |
91 |
| - index: originalLoc.column + id.name.length, |
92 |
| - }, |
93 |
| - } |
| 66 | + const originalLoc = consumer.originalPositionFor({ |
| 67 | + ...id.loc!.start, |
| 68 | + line: id.loc!.start.line - line + 1, |
| 69 | + }) |
| 70 | + const column = originalLoc.line === 1 ? node.loc!.start.column : 0 |
| 71 | + if (originalLoc.column) { |
| 72 | + id.loc!.start.line = line + originalLoc.line + (path.hub ? 0 : 1) |
| 73 | + id.loc!.start.column = column + originalLoc.column |
| 74 | + id.loc!.end.line = line + originalLoc.line |
| 75 | + id.loc!.end.column = column + originalLoc.column + id.name.length |
94 | 76 | }
|
95 | 77 | },
|
96 | 78 | })
|
97 | 79 | }
|
98 |
| - // console.dir({ a }, { depth: 112 }) |
99 |
| - // path.replaceWith() |
100 | 80 | path.replaceWith(ast.program.body[0])
|
101 |
| - // path.replaceWithSourceString(code) |
102 | 81 | }
|
103 | 82 |
|
104 |
| -function isJSXElement(node?: Node | null): node is JSXElement | JSXFragment { |
| 83 | +export function isJSXElement( |
| 84 | + node?: Node | null, |
| 85 | +): node is JSXElement | JSXFragment { |
105 | 86 | return !!node && (node.type === 'JSXElement' || node.type === 'JSXFragment')
|
106 | 87 | }
|
107 |
| - |
108 |
| -function isConditionalExpression(path: NodePath<Node> | null): boolean { |
109 |
| - return !!( |
110 |
| - path && |
111 |
| - (path?.type === 'LogicalExpression' || |
112 |
| - path.type === 'ConditionalExpression') && |
113 |
| - (path.parent.type === 'JSXExpressionContainer' || |
114 |
| - (path.parent.type === 'ConditionalExpression' && |
115 |
| - isConditionalExpression(path.parentPath))) |
116 |
| - ) |
117 |
| -} |
0 commit comments