Skip to content

Commit

Permalink
feat: improve ast transformations
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterAlfredLee committed Jul 6, 2021
1 parent 3759454 commit 02cab7b
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 17 deletions.
22 changes: 14 additions & 8 deletions src/ast-parse/astParse.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { transformationMap } from './transformations/index'
import { transformationMap, TransformationType } from './transformations/index'
import { parsersMap } from './parsers/index'
import { SFCDescriptor, vueSfcAstParser } from '@originjs/vue-sfc-ast-parser'
import * as globby from 'globby'
import fs from 'fs'
import { JSCodeshift } from 'jscodeshift/src/core';
import { ParserType } from './parsers';
import { ESLintProgram } from 'vue-eslint-parser/ast';

export type FileInfo = {
path: string,
Expand All @@ -14,8 +15,7 @@ export type FileInfo = {
export type VueSFCContext = {
path: string
source: string
// templateAST: ESLintProgram,
templateAST: any,
templateAST: ESLintProgram,
scriptAST: any,
jscodeshiftParser: JSCodeshift,
descriptor: SFCDescriptor
Expand All @@ -28,6 +28,12 @@ export type ParsingResultOccurrence = {
type: ParserType
}

export type TransformationResult = {
fileInfo: FileInfo,
content: string,
type: TransformationType
}

export type ParsingResult = {
[name: string]: ParsingResultOccurrence[]
}
Expand All @@ -48,8 +54,8 @@ export function astParseRoot (rootDir: string) {
path: filePath,
source: source
}
let transformationResult: string = source
let tempTransformationResult: string | null
let transformationResultContent: string = source
let tempTransformationResult: TransformationResult | null

// iter all transformations
for (const key in transformationMap) {
Expand All @@ -66,13 +72,13 @@ export function astParseRoot (rootDir: string) {
if (tempTransformationResult == null) {
continue
}
transformationResult = tempTransformationResult
transformationResultContent = tempTransformationResult.content

if (transformation.needReparse) {
fileInfo.source = transformationResult
fileInfo.source = transformationResultContent
}
if (transformation.needWriteToOriginFile) {
fs.writeFileSync(filePath, transformationResult)
fs.writeFileSync(filePath, transformationResultContent)
}
}

Expand Down
12 changes: 10 additions & 2 deletions src/ast-parse/transformations/addJsxTransformation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ASTTransformation } from './index'
import { stringifyDescriptor } from '@originjs/vue-sfc-ast-parser'
import { FileInfo, VueSFCContext, parseVueSfc } from '../astParse';
import { FileInfo, VueSFCContext, parseVueSfc, TransformationResult } from '../astParse';
import { TransformationType } from './index';

export const astTransform:ASTTransformation = (fileInfo: FileInfo) => {
const context: VueSFCContext = parseVueSfc(fileInfo)
Expand All @@ -11,11 +12,18 @@ export const astTransform:ASTTransformation = (fileInfo: FileInfo) => {
// if jsx element is found, the lang of script should be 'jsx'
const descriptor = context.descriptor
descriptor.script.attrs.lang = 'tsx'
return stringifyDescriptor(descriptor);
const result: TransformationResult = {
fileInfo: fileInfo,
content: stringifyDescriptor(descriptor),
type: TransformationType.addJsxTransformation
}
return result;
}

export const needReparse: boolean = false

export const needWriteToOriginFile: boolean = true

export const extensions: string[] = ['.vue']

export const transformationType: TransformationType = TransformationType.addJsxTransformation
20 changes: 15 additions & 5 deletions src/ast-parse/transformations/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
// import { ESLintProgram } from 'vue-eslint-parser/ast/nodes';
import { FileInfo } from '../astParse';
import { FileInfo, TransformationResult } from '../astParse';

export type ASTTransformation<Params = void> = {
(fileInfo: FileInfo, params: Params): string | null
(fileInfo: FileInfo, params: Params): TransformationResult | null
}

export enum TransformationType {
// eslint-disable-next-line no-unused-vars
addJsxTransformation = 'addJsxTransformation',
// eslint-disable-next-line no-unused-vars
removeHtmlLangInTemplateTransformation = 'removeHtmlLangInTemplateTransformation',
// eslint-disable-next-line no-unused-vars
indexHtmlTransformation = 'indexHtmlTransformation'
}

export const transformationMap: {
[name: string]: {
astTransform: ASTTransformation,
needReparse: boolean,
needWriteToOriginFile: boolean,
extensions: string[]
extensions: string[],
transformationType: TransformationType
}
} = {
addJsxTransformation: require('./addJsxTransformation'),
removeHtmlLangInTemplateTransformation: require('./removeHtmlLangInTemplateTransformation')
removeHtmlLangInTemplateTransformation: require('./removeHtmlLangInTemplateTransformation'),
indexHtmlTransformation: require('./indexHtmlTransformation')
}
45 changes: 45 additions & 0 deletions src/ast-parse/transformations/indexHtmlTransformation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { ASTTransformation } from './index'
import { FileInfo, TransformationResult } from '../astParse'
import { ESLintProgram } from 'vue-eslint-parser/ast';
import * as parser from 'vue-eslint-parser';
import { Node } from 'vue-eslint-parser/ast/nodes'
import { TransformationType } from './index';

const INDEX_HTML_PATH: string = 'public/index.html'

export const astTransform:ASTTransformation = (fileInfo: FileInfo) => {
if (!fileInfo.path.replace('\\', '/').endsWith(INDEX_HTML_PATH)) {
return null
}

const templateStart: string = '<template>'
const templateEnd: string = '</template>'
const htmlContent = `${templateStart}${fileInfo.source}${templateEnd}`
const htmlAST : ESLintProgram = parser.parse(htmlContent, { sourceType: 'module' })
const root: Node = htmlAST.templateBody
let bodyNode
parser.AST.traverseNodes(root, {
enterNode (node: Node) {
if (node.type === 'VElement' && node.name === 'body') {
bodyNode = node
}
},
leaveNode () {}
})
const transformedHtml: string = htmlContent.slice(0, bodyNode.endTag.range[0] - 1) + 'abcd' + htmlContent.slice(bodyNode.endTag.range[0] - 1)
const result: TransformationResult = {
fileInfo: fileInfo,
content: transformedHtml,
type: TransformationType.removeHtmlLangInTemplateTransformation
}

return result
}

export const needReparse: boolean = false

export const needWriteToOriginFile: boolean = false

export const extensions: string[] = ['.html']

export const transformationType: TransformationType = TransformationType.indexHtmlTransformation
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ASTTransformation } from './index'
import { stringifyDescriptor } from '@originjs/vue-sfc-ast-parser'
import { FileInfo, parseVueSfc, VueSFCContext } from '../astParse';
import { FileInfo, parseVueSfc, TransformationResult, VueSFCContext } from '../astParse';
import { TransformationType } from './index';

export const astTransform:ASTTransformation = (fileInfo: FileInfo) => {
const context: VueSFCContext = parseVueSfc(fileInfo)
Expand All @@ -11,11 +12,19 @@ export const astTransform:ASTTransformation = (fileInfo: FileInfo) => {
if (context.descriptor.template.attrs.lang === 'html') {
delete context.descriptor.template.attrs.lang
}
return stringifyDescriptor(context.descriptor);

const result: TransformationResult = {
fileInfo: fileInfo,
content: stringifyDescriptor(context.descriptor),
type: TransformationType.removeHtmlLangInTemplateTransformation
}
return result;
}

export const needReparse : boolean = false

export const needWriteToOriginFile: boolean = true

export const extensions: string[] = ['.vue']

export const transformationType: TransformationType = TransformationType.removeHtmlLangInTemplateTransformation

0 comments on commit 02cab7b

Please sign in to comment.