forked from opentiny/tiny-engine
270 lines
6.6 KiB
JavaScript
270 lines
6.6 KiB
JavaScript
import { BUILTIN_COMPONENTS_MAP } from '@/constant'
|
|
import { getImportMap } from './parseImport'
|
|
import {
|
|
genTemplateByHook,
|
|
handleComponentNameHook,
|
|
handleTinyGrid,
|
|
handleTinyIcon,
|
|
handleExpressionChildren,
|
|
validEmptyTemplateHook
|
|
} from './generateTemplate'
|
|
import { generateStyleTag } from './generateStyle'
|
|
import {
|
|
handleConditionAttrHook,
|
|
handleLoopAttrHook,
|
|
handleSlotBindAttrHook,
|
|
handleAttrKeyHook,
|
|
handlePrimitiveAttributeHook,
|
|
handleExpressionAttrHook,
|
|
handleI18nAttrHook,
|
|
handleObjBindAttrHook,
|
|
handleEventAttrHook,
|
|
handleTinyIconPropsHook
|
|
} from './generateAttribute'
|
|
import {
|
|
GEN_SCRIPT_HOOKS,
|
|
genScriptByHook,
|
|
parsePropsHook,
|
|
parseReactiveStateHook,
|
|
addDefaultVueImport,
|
|
addDefaultVueI18nImport,
|
|
handleProvideStatesContextHook,
|
|
handleContextInjectHook,
|
|
defaultGenImportHook,
|
|
defaultGenPropsHook,
|
|
defaultGenEmitsHook,
|
|
defaultGenStateHook,
|
|
defaultGenMethodHook,
|
|
defaultGenLifecycleHook
|
|
} from './generateScript'
|
|
|
|
const parseConfig = (config = {}) => {
|
|
const {
|
|
blockRelativePath = '../components/',
|
|
blockSuffix = '.vue',
|
|
scriptConfig = {},
|
|
styleConfig = {}
|
|
} = config || {}
|
|
const res = {
|
|
...config,
|
|
blockRelativePath,
|
|
blockSuffix,
|
|
scriptConfig,
|
|
styleConfig
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
const defaultScriptConfig = {
|
|
lang: '',
|
|
setup: true
|
|
}
|
|
|
|
const defaultStyleConfig = {
|
|
scoped: true,
|
|
lang: ''
|
|
}
|
|
|
|
const generateSFCFile = (schema, componentsMap, config = {}) => {
|
|
const parsedConfig = parseConfig(config)
|
|
const { blockRelativePath, blockSuffix, scriptConfig: initScriptConfig, styleConfig: initStyleConfig } = parsedConfig
|
|
// 前置动作,对 Schema 进行解析初始化相关配置与变量
|
|
if (!schema.state) {
|
|
schema.state = {}
|
|
}
|
|
|
|
// 解析 import
|
|
const { pkgMap, blockPkgMap } = getImportMap(schema, componentsMap, { blockRelativePath, blockSuffix })
|
|
|
|
// 解析 state
|
|
let stateRes = {}
|
|
|
|
// 解析 method
|
|
const methods = schema.methods || {}
|
|
|
|
// 其他表达式语句
|
|
const statements = {}
|
|
|
|
// config
|
|
let scriptConfig = {
|
|
...defaultScriptConfig,
|
|
...initScriptConfig
|
|
}
|
|
|
|
let styleConfig = {
|
|
...defaultStyleConfig,
|
|
...initStyleConfig
|
|
}
|
|
|
|
const globalHooks = {
|
|
addStatement: (newStatement) => {
|
|
if (!newStatement?.value) {
|
|
return false
|
|
}
|
|
|
|
const key = newStatement.key || newStatement.value
|
|
|
|
if (statements[key]) {
|
|
return false
|
|
}
|
|
|
|
statements[key] = newStatement
|
|
|
|
return true
|
|
},
|
|
getStatements: () => statements,
|
|
addMethods: (key, value) => {
|
|
if (methods[key]) {
|
|
return false
|
|
}
|
|
|
|
methods[key] = value
|
|
|
|
return true
|
|
},
|
|
getMethods: () => methods,
|
|
addState: (key, value) => {
|
|
if (schema.state[key] || stateRes[key]) {
|
|
return false
|
|
}
|
|
|
|
stateRes[key] = value
|
|
|
|
return true
|
|
},
|
|
getState: () => stateRes,
|
|
setState: () => {
|
|
// state = newState
|
|
},
|
|
addImport: (fromPath, config) => {
|
|
const dependenciesMap = pkgMap[fromPath] || blockPkgMap[fromPath]
|
|
|
|
if (dependenciesMap) {
|
|
// 默认导出
|
|
if (!config.destructuring && dependenciesMap.find(({ destructuring }) => !destructuring)) {
|
|
return false
|
|
}
|
|
|
|
const hasExists = dependenciesMap.find(({ destructuring, exportName, componentName }) => {
|
|
return (
|
|
destructuring === config.destructuring &&
|
|
exportName === config.exportName &&
|
|
componentName === config.componentName
|
|
)
|
|
})
|
|
|
|
if (hasExists) {
|
|
return false
|
|
}
|
|
|
|
dependenciesMap.push(config)
|
|
|
|
return true
|
|
}
|
|
|
|
pkgMap[fromPath] = [config]
|
|
|
|
return true
|
|
},
|
|
getImport: () => ({ ...pkgMap, ...blockPkgMap }),
|
|
setScriptConfig: (newConfig) => {
|
|
if (!newConfig || typeof newConfig !== 'object') {
|
|
return
|
|
}
|
|
|
|
scriptConfig = {
|
|
...scriptConfig,
|
|
...newConfig
|
|
}
|
|
},
|
|
getScriptConfig: () => scriptConfig,
|
|
setStyleConfig: (newConfig = {}) => {
|
|
if (!newConfig || typeof newConfig !== 'object') {
|
|
return
|
|
}
|
|
|
|
styleConfig = {
|
|
...styleConfig,
|
|
...newConfig
|
|
}
|
|
},
|
|
getStyleConfig: () => styleConfig,
|
|
addCss: (css) => {
|
|
schema.css = `${schema.css}\n${css}`
|
|
}
|
|
}
|
|
|
|
// 解析 template
|
|
const templateStr = genTemplateByHook(schema, globalHooks, { ...parsedConfig, componentsMap: componentsMap })
|
|
|
|
// 生成 script
|
|
const scriptStr = genScriptByHook(schema, globalHooks, { ...parsedConfig, componentsMap: componentsMap })
|
|
|
|
// 生成 style
|
|
const styleStr = generateStyleTag(schema, styleConfig)
|
|
|
|
return `${templateStr}\n${scriptStr}\n${styleStr}`
|
|
}
|
|
|
|
export const genSFCWithDefaultPlugin = (schema, componentsMap, config = {}) => {
|
|
const { templateItemValidate = [], genTemplate = [], parseScript = [], genScript = {} } = config.hooks || {}
|
|
const defaultComponentHooks = [handleComponentNameHook, handleTinyIcon]
|
|
|
|
const defaultAttributeHook = [
|
|
handleTinyGrid,
|
|
handleConditionAttrHook,
|
|
handleLoopAttrHook,
|
|
handleSlotBindAttrHook,
|
|
handleAttrKeyHook,
|
|
handlePrimitiveAttributeHook,
|
|
handleExpressionAttrHook,
|
|
handleI18nAttrHook,
|
|
handleTinyIconPropsHook,
|
|
handleObjBindAttrHook,
|
|
handleEventAttrHook
|
|
]
|
|
|
|
const defaultChildrenHook = [handleExpressionChildren]
|
|
const defaultTemplateItemValidateHook = [validEmptyTemplateHook]
|
|
|
|
const defaultParseScriptHook = [
|
|
addDefaultVueImport,
|
|
addDefaultVueI18nImport,
|
|
parsePropsHook,
|
|
parseReactiveStateHook,
|
|
handleProvideStatesContextHook,
|
|
handleContextInjectHook
|
|
]
|
|
|
|
const { GEN_IMPORT, GEN_PROPS, GEN_EMIT, GEN_STATE, GEN_METHOD, GEN_LIFECYCLE } = GEN_SCRIPT_HOOKS
|
|
const defaultGenScriptHooks = {
|
|
[GEN_IMPORT]: defaultGenImportHook,
|
|
[GEN_PROPS]: defaultGenPropsHook,
|
|
[GEN_EMIT]: defaultGenEmitsHook,
|
|
[GEN_STATE]: defaultGenStateHook,
|
|
[GEN_METHOD]: defaultGenMethodHook,
|
|
[GEN_LIFECYCLE]: defaultGenLifecycleHook
|
|
}
|
|
|
|
const newConfig = {
|
|
...config,
|
|
hooks: {
|
|
templateItemValidate: [...templateItemValidate, ...defaultTemplateItemValidateHook],
|
|
genTemplate: [...genTemplate, ...defaultComponentHooks, ...defaultAttributeHook, ...defaultChildrenHook],
|
|
parseScript: [...parseScript, ...defaultParseScriptHook],
|
|
genScript: {
|
|
...defaultGenScriptHooks,
|
|
...genScript
|
|
}
|
|
}
|
|
}
|
|
|
|
// 兼容单独调用的场景,单独调用时,这里会默认加上 builtInComponents
|
|
const compsMapWithBuiltIn = [...componentsMap, ...BUILTIN_COMPONENTS_MAP]
|
|
|
|
return generateSFCFile(schema, compsMapWithBuiltIn, newConfig)
|
|
}
|
|
|
|
export default generateSFCFile
|