Skip to content

Commit

Permalink
feat: refactor ast transformation of index.html
Browse files Browse the repository at this point in the history
  • Loading branch information
konpeki622 committed Jul 17, 2021
1 parent eaf60a6 commit 1253695
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 34 deletions.
43 changes: 18 additions & 25 deletions src/ast-parse/transformations/indexHtmlTransformationVueCli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import { ESLintProgram } from 'vue-eslint-parser/ast'
import * as parser from 'vue-eslint-parser'
import { Node } from 'vue-eslint-parser/ast/nodes'
import { stringSplice } from '../../utils/common'
import { pathFormat } from '../../utils/file'
import { parseVueCliConfig } from '../../config/parse'
import path from 'path'
import fs from 'fs'
import ejs from 'ejs'

const templateStart: string = '<template>'
const templateEnd: string = '</template>'
Expand All @@ -24,9 +26,9 @@ export const astTransform:ASTTransformation = async (fileInfo: FileInfo, transfo
const rootDir: string = transformationParams.config.rootDir
let indexPath: string
if (fs.existsSync(path.resolve(rootDir, 'public/index.html'))) {
indexPath = path.resolve(rootDir, 'public/index.html').replace(/\\/g, '/')
indexPath = pathFormat(path.resolve(rootDir, 'public/index.html'))
} else if (fs.existsSync(path.resolve(rootDir, 'index.html'))) {
indexPath = path.resolve(rootDir, 'index.html').replace(/\\/g, '/')
indexPath = pathFormat(path.resolve(rootDir, 'index.html'))
} else {
indexPath = null
}
Expand All @@ -39,42 +41,35 @@ export const astTransform:ASTTransformation = async (fileInfo: FileInfo, transfo
const htmlAST : ESLintProgram = parser.parse(htmlContent, { sourceType: 'module' })
const root: Node = htmlAST.templateBody

const afterIndentLength: number = 1
const behindIndentLength: number = 1
let frontIndentLength: number = 0
let offset: number = 0

const vueConfigFile = path.resolve(rootDir, 'vue.config.js')
const vueConfig = await parseVueCliConfig(vueConfigFile)
const jspRegExp = /<%(=|-)?(.|\s|\r\n)*%>/g
const jspIdentifierRegExp = /(<%(=|-)?|\s|\r\n|%>)/g
const jspMap = {}
const publicPath: string = process.env.PUBLIC_URL || vueConfig.publicPath || vueConfig.baseUrl || ''
// TODO: default values exposed by plugins and client-side env variables
const jspData = {
BASE_URL: publicPath,
NODE_ENV: '',
...process.env
}

let bodyNode

parser.AST.traverseNodes(root, {
enterNode (node: Node) {
// replace jsp tags
if ((node.type === 'VLiteral' || node.type === 'VText') && jspRegExp.test(node.value)) {
node.value.match(jspRegExp).forEach(jspSection => {
const jspValue: string = jspSection.replace(jspIdentifierRegExp, '')
if (!jspMap[jspSection] && jspValue === 'BASE_URL') {
const publicPath: string =
process.env.PUBLIC_URL || vueConfig.publicPath || vueConfig.baseUrl || ''
jspMap[jspSection] = path.relative(rootDir, path.resolve(rootDir, publicPath)).replace(/\\/g, '/') + '/'
} else if (!jspMap[jspSection]) {
jspMap[jspSection] = process.env[jspValue] ? process.env[jspValue] : ''
}
})
}
if (node.type === 'VElement' && node.name === 'body') {
bodyNode = node
} else if (node.type === 'VElement' && node.name === 'script') {
const nodeAttrs = node.startTag.attributes
// remove original entry scripts with spaces
if (nodeAttrs[0]?.key.name === 'type' && nodeAttrs[0].value.type === 'VLiteral' && nodeAttrs[0].value.value === 'module' && nodeAttrs[1].key.name === 'src') {
frontIndentLength = node.loc.start.column
htmlContent = stringSplice(htmlContent, node.range[0] - frontIndentLength, node.range[1] + afterIndentLength, offset)
offset += node.range[1] - node.range[0] + frontIndentLength + afterIndentLength + 1
const nodeStart: number = node.range[0] - frontIndentLength
const nodeEnd: number = node.range[1] + behindIndentLength
htmlContent = stringSplice(htmlContent, nodeStart, nodeEnd, offset)
offset += node.range[1] - node.range[0] + frontIndentLength + behindIndentLength + 1
}
}
},
Expand All @@ -86,10 +81,8 @@ export const astTransform:ASTTransformation = async (fileInfo: FileInfo, transfo
transformedHtml = transformedHtml.slice(0, transformedHtml.length - templateEnd.length)
transformedHtml = transformedHtml.slice(templateStart.length)

Object.keys(jspMap).forEach(key => {
const keyRegExp: RegExp = new RegExp(key, 'g')
transformedHtml = transformedHtml.replace(keyRegExp, jspMap[key])
})
// replace jsp tags
transformedHtml = ejs.compile(transformedHtml, {})(jspData)

const result: TransformationResult = {
fileInfo: fileInfo,
Expand Down
11 changes: 7 additions & 4 deletions src/ast-parse/transformations/indexHtmlTransformationWebpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ESLintProgram } from 'vue-eslint-parser/ast'
import * as parser from 'vue-eslint-parser'
import { Node } from 'vue-eslint-parser/ast/nodes'
import { stringSplice } from '../../utils/common'
import { pathFormat } from '../../utils/file'
import path from 'path'
import fs from 'fs'

Expand All @@ -23,7 +24,7 @@ export const astTransform:ASTTransformation = async (fileInfo: FileInfo, transfo
const rootDir: string = transformationParams.config.rootDir
let indexPath: string
if (fs.existsSync(path.resolve(rootDir, 'index.html'))) {
indexPath = path.resolve(rootDir, 'index.html').replace(/\\/g, '/')
indexPath = pathFormat(path.resolve(rootDir, 'index.html'))
} else {
indexPath = null
}
Expand All @@ -37,7 +38,7 @@ export const astTransform:ASTTransformation = async (fileInfo: FileInfo, transfo
const htmlAST : ESLintProgram = parser.parse(htmlContent, { sourceType: 'module' })
const root: Node = htmlAST.templateBody

const afterIndentLength: number = 1
const behindIndentLength: number = 1
let frontIndentLength: number = 0
let offset: number = 0

Expand All @@ -52,8 +53,10 @@ export const astTransform:ASTTransformation = async (fileInfo: FileInfo, transfo
// remove original entry scripts with spaces
if (nodeAttrs[0]?.key.name === 'type' && nodeAttrs[0].value.type === 'VLiteral' && nodeAttrs[0].value.value === 'module' && nodeAttrs[1].key.name === 'src') {
frontIndentLength = node.loc.start.column
htmlContent = stringSplice(htmlContent, node.range[0] - frontIndentLength, node.range[1] + afterIndentLength, offset)
offset += node.range[1] - node.range[0] + frontIndentLength + afterIndentLength + 1
const nodeStart: number = node.range[0] - frontIndentLength
const nodeEnd: number = node.range[1] + behindIndentLength
htmlContent = stringSplice(htmlContent, nodeStart, nodeEnd, offset)
offset += node.range[1] - node.range[0] + frontIndentLength + behindIndentLength + 1
}
}
},
Expand Down
10 changes: 5 additions & 5 deletions src/generate/geneIndexHtml.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from 'fs'
import path from 'path'
import { readSync, writeSync } from '../utils/file'
import { readSync, writeSync, relativePathFormat } from '../utils/file'
import { isObject, stringFormat } from '../utils/common'
import { Config } from '../config/config'
import { AstParsingResult } from '../ast-parse/astParse'
Expand All @@ -13,7 +13,7 @@ export function geneIndexHtml (rootDir: string, config: Config, astParsingResult

let entries : string[] = []
if (config.entry !== undefined && config.entry !== '' && config.entry.length !== 0 && JSON.stringify(config.entry) !== '{}') {
entries = getEntries(config.entry)
entries = getEntries(rootDir, config.entry)
} else {
entries = getDefaultEntries(rootDir)
}
Expand Down Expand Up @@ -69,21 +69,21 @@ function getDefaultEntries (rootDir: string): string[] {
return entries
}

function getEntries (entry: any) : string[] {
function getEntries (rootDir: string, entry: any) : string[] {
const entries: string[] = []
if (entry === undefined) {
return entries
}
if (isObject(entry)) {
Object.keys(entry).forEach(function (name) {
entries.push(entry[name])
entries.push(relativePathFormat(rootDir, entry[name]))
})
}
if (typeof entry === 'function') {
entries.push(entry())
}
if (typeof entry === 'string') {
entries.push(entry)
entries.push(relativePathFormat(rootDir, entry))
}

// vite support hmr by default, so do not need to import webpack-hot-middleware
Expand Down
8 changes: 8 additions & 0 deletions src/utils/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,11 @@ export function readSync (filePath: string): string {

return ''
}

export function pathFormat (filePath: string): string {
return filePath.replace(/\\/g, '/')
}

export function relativePathFormat (rootDir: string, filePath: string): string {
return path.relative(rootDir, path.resolve(rootDir, filePath)).replace(/\\/g, '/')
}

0 comments on commit 1253695

Please sign in to comment.