mirror of
https://github.com/vuejs/vue-cli.git
synced 2026-01-25 08:38:57 -06:00
* feat(cli): Don't allow duplicate api.injectImports * feat(cli): Don't allow duplicate api.injectRootOptions * chore(cli): Added tests for duplicate injections
74 lines
2.4 KiB
JavaScript
74 lines
2.4 KiB
JavaScript
module.exports = function injectImportsAndOptions (source, imports, injections) {
|
|
imports = imports instanceof Set ? Array.from(imports) : imports
|
|
injections = injections instanceof Set ? Array.from(injections) : injections
|
|
|
|
const hasImports = imports && imports.length > 0
|
|
const hasInjections = injections && injections.length > 0
|
|
|
|
if (!hasImports && !hasInjections) {
|
|
return source
|
|
}
|
|
|
|
const recast = require('recast')
|
|
const ast = recast.parse(source)
|
|
|
|
if (hasImports) {
|
|
const toImport = i => recast.parse(`${i}\n`).program.body[0]
|
|
const importDeclarations = []
|
|
let lastImportIndex = -1
|
|
|
|
recast.types.visit(ast, {
|
|
visitImportDeclaration ({ node }) {
|
|
lastImportIndex = ast.program.body.findIndex(n => n === node)
|
|
importDeclarations.push(node)
|
|
return false
|
|
}
|
|
})
|
|
// avoid blank line after the previous import
|
|
delete ast.program.body[lastImportIndex].loc
|
|
|
|
const nonDuplicates = i => {
|
|
return !importDeclarations.some(node => {
|
|
const result = node.source.raw === i.source.raw && node.specifiers.length === i.specifiers.length
|
|
|
|
return result && node.specifiers.every((item, index) => {
|
|
return i.specifiers[index].local.name === item.local.name
|
|
})
|
|
})
|
|
}
|
|
|
|
const newImports = imports.map(toImport).filter(nonDuplicates)
|
|
ast.program.body.splice(lastImportIndex + 1, 0, ...newImports)
|
|
}
|
|
|
|
if (hasInjections) {
|
|
const toProperty = i => {
|
|
return recast.parse(`({${i}})`).program.body[0].expression.properties
|
|
}
|
|
recast.types.visit(ast, {
|
|
visitNewExpression ({ node }) {
|
|
if (node.callee.name === 'Vue') {
|
|
const options = node.arguments[0]
|
|
if (options && options.type === 'ObjectExpression') {
|
|
const nonDuplicates = i => {
|
|
return !options.properties.slice(0, -1).some(p => {
|
|
return p.key.name === i[0].key.name &&
|
|
recast.print(p.value).code === recast.print(i[0].value).code
|
|
})
|
|
}
|
|
// inject at index length - 1 as it's usually the render fn
|
|
options.properties = [
|
|
...options.properties.slice(0, -1),
|
|
...([].concat(...injections.map(toProperty).filter(nonDuplicates))),
|
|
...options.properties.slice(-1)
|
|
]
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
})
|
|
}
|
|
|
|
return recast.print(ast).code
|
|
}
|