|
1 | 1 | import { Parser as HTMLParser } from 'htmlparser2' |
2 | | -import { types as t } from '@babel/core' |
3 | | -import { parse, ParserOptions, ParserPlugin } from '@babel/parser' |
| 2 | +import { parse, ParserOptions } from '@babel/parser' |
4 | 3 | import { camelize, capitalize, isHTMLTag, isSVGTag, isVoidTag } from '@vue/shared' |
5 | 4 | import traverse from '@babel/traverse' |
6 | | -import generate from '@babel/generator' |
7 | | - |
8 | | -interface TagMeta { |
9 | | - start: number |
10 | | - end: number |
11 | | - contentStart: number |
12 | | - contentEnd: number |
13 | | - content: string |
14 | | - attrs: Record<string, string> |
15 | | - found: boolean |
16 | | -} |
17 | | - |
18 | | -export interface ParseResult { |
19 | | - id?: string |
20 | | - template: { |
21 | | - components: Set<string> |
22 | | - identifiers: Set<string> |
23 | | - } |
24 | | - scriptSetup: TagMeta |
25 | | - script: TagMeta |
26 | | -} |
| 5 | +import { ParseResult, TagMeta } from './types' |
27 | 6 |
|
28 | 7 | export function parseVueSFC(code: string, id?: string): ParseResult { |
29 | 8 | const components = new Set<string>() |
@@ -145,131 +124,3 @@ export function getIdentifiersFromCode(code: string, identifiers = new Set<strin |
145 | 124 | }) |
146 | 125 | return identifiers |
147 | 126 | } |
148 | | - |
149 | | -export function transformScriptSetup(result: ParseResult) { |
150 | | - if (result.script.found && result.scriptSetup.found && result.scriptSetup.attrs.lang !== result.script.attrs.lang) |
151 | | - throw new SyntaxError('<script setup> language must be the same as <script>') |
152 | | - |
153 | | - const lang = result.scriptSetup.attrs.lang || result.script.attrs.lang |
154 | | - const plugins: ParserPlugin[] = [] |
155 | | - if (lang === 'ts') |
156 | | - plugins.push('typescript') |
157 | | - else if (lang === 'jsx') |
158 | | - plugins.push('jsx') |
159 | | - else if (lang === 'tsx') |
160 | | - plugins.push('typescript', 'jsx') |
161 | | - else if (lang !== 'js') |
162 | | - throw new SyntaxError(`Unsupported script language: ${lang}`) |
163 | | - |
164 | | - const identifiers = new Set<string>() |
165 | | - const scriptSetupAst = parse(result.scriptSetup.content, { |
166 | | - sourceType: 'module', |
167 | | - plugins, |
168 | | - }) |
169 | | - const scriptAst = parse(result.script.content || 'export default {}', { |
170 | | - sourceType: 'module', |
171 | | - plugins, |
172 | | - }) |
173 | | - |
174 | | - // get all identifiers in `<script setup>` |
175 | | - traverse(scriptSetupAst as any, { |
176 | | - Identifier(path) { |
177 | | - identifiers.add(path.node.name) |
178 | | - }, |
179 | | - }) |
180 | | - |
181 | | - const returns = Array.from(identifiers).filter(i => result.template.identifiers.has(i)) |
182 | | - const components = Array.from(identifiers).filter(i => |
183 | | - result.template.components.has(i) |
184 | | - || result.template.components.has(camelize(i)) |
185 | | - || result.template.components.has(capitalize(camelize(i))), |
186 | | - ) |
187 | | - |
188 | | - const imports = scriptSetupAst.program.body.filter(n => n.type === 'ImportDeclaration') |
189 | | - const scriptSetupBody = scriptSetupAst.program.body.filter(n => n.type !== 'ImportDeclaration') |
190 | | - // TODO: apply macros |
191 | | - |
192 | | - // append `<script setup>` imports to `<script>` |
193 | | - scriptAst.program.body.unshift(...imports) |
194 | | - |
195 | | - // replace `export default` with a temproray variable |
196 | | - // `const __sfc_main = { ... }` |
197 | | - traverse(scriptAst as any, { |
198 | | - ExportDefaultDeclaration(path) { |
199 | | - const decl = path.node.declaration |
200 | | - path.replaceWith( |
201 | | - t.variableDeclaration('const', [ |
202 | | - t.variableDeclarator( |
203 | | - t.identifier('__sfc_main'), |
204 | | - decl as any, |
205 | | - ), |
206 | | - ]), |
207 | | - ) |
208 | | - }, |
209 | | - }) |
210 | | - |
211 | | - // inject setup function |
212 | | - // `__sfc_main.setup = () => {}` |
213 | | - if (scriptSetupBody.length) { |
214 | | - const returnStatement = t.returnStatement( |
215 | | - t.objectExpression( |
216 | | - returns.map((i) => { |
217 | | - const id = t.identifier(i) |
218 | | - return t.objectProperty(id, id, false, true) |
219 | | - }), |
220 | | - ), |
221 | | - ) |
222 | | - |
223 | | - scriptAst.program.body.push( |
224 | | - t.expressionStatement( |
225 | | - t.assignmentExpression('=', |
226 | | - t.memberExpression(t.identifier('__sfc_main'), t.identifier('setup')), |
227 | | - t.arrowFunctionExpression([], t.blockStatement([ |
228 | | - ...scriptSetupBody, |
229 | | - returnStatement as any, |
230 | | - ])), |
231 | | - ), |
232 | | - ) as any, |
233 | | - ) |
234 | | - } |
235 | | - |
236 | | - // inject components |
237 | | - // `__sfc_main.components = Object.assign({ ... }, __sfc_main.components)` |
238 | | - if (components.length) { |
239 | | - const componentsObject = t.objectExpression( |
240 | | - components.map((i) => { |
241 | | - const id = t.identifier(i) |
242 | | - return t.objectProperty(id, id, false, true) |
243 | | - }), |
244 | | - ) |
245 | | - |
246 | | - scriptAst.program.body.push( |
247 | | - t.expressionStatement( |
248 | | - t.assignmentExpression('=', |
249 | | - t.memberExpression(t.identifier('__sfc_main'), t.identifier('components')), |
250 | | - t.callExpression( |
251 | | - t.memberExpression(t.identifier('Object'), t.identifier('assign')), |
252 | | - [ |
253 | | - componentsObject, |
254 | | - t.memberExpression( |
255 | | - t.identifier('__sfc_main'), |
256 | | - t.identifier('components'), |
257 | | - ), |
258 | | - ], |
259 | | - ), |
260 | | - ), |
261 | | - ) as any, |
262 | | - ) |
263 | | - } |
264 | | - |
265 | | - // re-export |
266 | | - // `export default __sfc_main` |
267 | | - scriptAst.program.body.push( |
268 | | - t.exportDefaultDeclaration(t.identifier('__sfc_main')) as any, |
269 | | - ) |
270 | | - |
271 | | - return { |
272 | | - ast: scriptAst, |
273 | | - code: generate(scriptAst as any).code, |
274 | | - } |
275 | | -} |
0 commit comments