wangsongc-test
Version:
A ast parser for vue sfc
80 lines (66 loc) • 2.39 kB
text/typescript
import { parse as parseSFC } from './sfcUtils'
import type { SFCDescriptor } from './sfcUtils'
import * as templateParser from 'vue-eslint-parser'
import { ESLintProgram } from "vue-eslint-parser/ast";
// @ts-ignore
import getParser from 'jscodeshift/src/getParser'
import jscodeshift from 'jscodeshift'
import { JSCodeshift } from "jscodeshift/src/core";
type FileInfo = {
path: string
source: string
}
export default function vueSfcAstParse(
fileInfo: FileInfo
) {
const { path, source } = fileInfo
let descriptor: SFCDescriptor
const extension = (/\.([^.]*)$/.exec(path) || [])[0]
if (extension !== '.vue') {
return {}
}
// get vue sfc descriptor
descriptor = parseSFC(source, { filename: path }).descriptor
const templateAST : ESLintProgram | null = parseTemplate(descriptor)
const parseScriptResult = parseScript(descriptor)
let scriptAST
let jscodeshiftParser
if (!parseScriptResult) {
scriptAST = null
jscodeshiftParser = null
} else {
scriptAST = parseScriptResult.scriptAST
jscodeshiftParser = parseScriptResult.jscodeshiftParser
}
return {
templateAST : templateAST,
scriptAST : scriptAST,
descriptor : descriptor,
jscodeshiftParser: jscodeshiftParser
}
}
function parseTemplate(descriptor: SFCDescriptor) : ESLintProgram | null {
if (!descriptor.template) {
return null
}
const templateContent : string = descriptor.template.ast.loc.source
const options = { sourceType: 'module' }
const templateAST : ESLintProgram = templateParser.parse(templateContent, options)
return templateAST
}
function parseScript(descriptor: SFCDescriptor) : any {
if (!descriptor.script) {
return null
}
const lang : string = descriptor.script.lang || 'js'
const scriptContent : string = descriptor.script.content
let parserOption : string = 'babylon'
// force inject `parser` option for .tsx? files, unless the module specifies a custom implementation
if (lang.startsWith('ts')) {
parserOption = lang
}
const parser = !!parserOption ? getParser(parserOption) : getParser()
const jscodeshiftParser : JSCodeshift = jscodeshift.withParser(parser)
const scriptAST = jscodeshiftParser(scriptContent)
return { scriptAST, jscodeshiftParser }
}