Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/common/composable/generateCode/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { generateApp, type IAppSchema } from '@opentiny/tiny-engine-dsl-vue'
import * as dslVue from '@opentiny/tiny-engine-dsl-vue'
import { getMergeMeta } from '@opentiny/tiny-engine-meta-register'
import { formatString } from '../../js/ast'
import defaultPrettierConfig from '../../js/config-files/prettierrc'

// 应用出码默认配置
Expand Down Expand Up @@ -42,7 +43,7 @@ const generateAppCode = async (appSchema: IAppSchema, options = {}) => {
const { parseRequiredBlocks, genSFCWithDefaultPlugin } = dslVue as any

const generatePageCode = (...args: any[]) => {
return genSFCWithDefaultPlugin(...args)
return formatString(genSFCWithDefaultPlugin(...args), 'vue')
}

/**
Expand Down
95 changes: 71 additions & 24 deletions packages/common/js/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,23 @@ export const string2Ast = (string = ''): BabelAst =>
export const ast2String = (ast: GeneratorInput): string => generate(ast, { retainLines: true }).code // 将 AST 再转回字符串

type FormatterFn = (input: string) => string
type SupportedLanguage = 'json' | 'typescript' | 'javascript' | 'html' | 'css'
type SupportedLanguage = 'json' | 'typescript' | 'javascript' | 'html' | 'css' | 'vue' | 'less'
type SupportedPrettierParser = 'json' | 'babel' | 'babel-ts' | 'html' | 'css' | 'less' | 'vue'

const formatScript: FormatterFn = (string) => {
const PRETTIER_PLUGINS = [parserBabel, parseCss, parserHtml]

const formatWithParser = (string: string, parser: SupportedPrettierParser, options: PrettierOptions = {}): string =>
prettier.format(string, {
parser,
plugins: PRETTIER_PLUGINS,
...basePrettierConfig,
...options
})

const formatScript = (string: string, parser: 'babel' | 'babel-ts' = 'babel'): string => {
let newStr = string
const options: PrettierOptions = {
parser: 'babel',
parser,
plugins: [parserBabel],
...basePrettierConfig
}
Expand Down Expand Up @@ -72,34 +83,49 @@ const formatScript: FormatterFn = (string) => {
return newStr
}

const formatJson: FormatterFn = (string) =>
prettier.format(string, {
parser: 'json',
plugins: [parserBabel],
trailingComma: 'es5',
...basePrettierConfig
})
const formatJson: FormatterFn = (string) => formatWithParser(string, 'json')

const formatHtml: FormatterFn = (string) =>
prettier.format(string, {
parser: 'html',
plugins: [parserBabel, parserHtml],
...basePrettierConfig
})
const formatHtml: FormatterFn = (string) => formatWithParser(string, 'html')

const formatCss: FormatterFn = (string) =>
prettier.format(string, {
parser: 'css',
plugins: [parseCss],
...basePrettierConfig
})
const formatCss: FormatterFn = (string) => formatWithParser(string, 'css')

const formatVue: FormatterFn = (string) => formatWithParser(string, 'vue')

const formatLess: FormatterFn = (string) => formatWithParser(string, 'less')

const formatterMap: Record<SupportedLanguage, FormatterFn> = {
json: formatJson,
typescript: formatScript,
typescript: (str) => formatScript(str, 'babel-ts'),
javascript: formatScript,
html: formatHtml,
css: formatCss
css: formatCss,
vue: formatVue,
less: formatLess
}

const parserMap: Record<string, SupportedPrettierParser> = {
json: 'json',
js: 'babel',
jsx: 'babel',
mjs: 'babel',
cjs: 'babel',
ts: 'babel-ts',
tsx: 'babel-ts',
css: 'css',
less: 'less',
html: 'html',
vue: 'vue'
}

export const getPrettierParserByFileName = (fileName = ''): SupportedPrettierParser | undefined => {
const pureFileName = fileName.split('?')[0].split('#')[0].toLowerCase()
const extension = pureFileName.split('.').at(-1)

if (!extension || extension === pureFileName) {
return undefined
}

return parserMap[extension]
}

export const formatString = (str: string, language: string): string => {
Expand All @@ -115,6 +141,27 @@ export const formatString = (str: string, language: string): string => {
return result
}

export const formatStringByFileName = (str: string, fileName: string): string => {
const parser = getPrettierParserByFileName(fileName)

if (!parser) {
return str
}

try {
if (parser === 'babel' || parser === 'babel-ts') {
return formatScript(str, parser)
}

return formatWithParser(str, parser)
} catch (error) {
const printer: Console = console
printer.log(error)

return str
}
}

export { parse, parseExpression, traverse, generate }

export const includedExpression = (code: string, expression: string): boolean => {
Expand Down
34 changes: 26 additions & 8 deletions packages/design-core/src/preview/src/preview/usePreviewData.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { reactive } from 'vue'
import { formatStringByFileName } from '@opentiny/tiny-engine-common/js/ast'
import { constants } from '@opentiny/tiny-engine-utils'
import { getImportMap as getInitImportMap } from './importMap'
import { getMetaApi, getMergeMeta, META_SERVICE, useEnv } from '@opentiny/tiny-engine-meta-register'
Expand Down Expand Up @@ -342,6 +343,21 @@ interface IUsePreviewData {
setImportMap: (importMap: Record<string, string>) => void
}

const formatGeneratedFile = (fileContent: unknown, fileName: string): string => {
if (typeof fileContent !== 'string') {
return String(fileContent ?? '')
}

return formatStringByFileName(fileContent, fileName)
}

const formatGeneratedFiles = (files: Record<string, string>) =>
Object.entries(files).reduce((acc, [fileName, fileContent]) => {
acc[fileName] = formatGeneratedFile(fileContent, fileName)

return acc
}, {} as Record<string, string>)

export const usePreviewData = ({ setFiles, store, setImportMap }: IUsePreviewData) => {
const basicFiles = setFiles(srcFiles, 'src/Main.vue')

Expand Down Expand Up @@ -407,10 +423,10 @@ export const usePreviewData = ({ setFiles, store, setImportMap }: IUsePreviewDat
const enableTailwindCSS = getMergeMeta('engine.config')?.enableTailwindCSS
const appJsCode = processAppJsCode(newFiles['app.js'] || '', params.styles, enableTailwindCSS)

newFiles['app.js'] = appJsCode
newFiles['app.js'] = formatGeneratedFile(appJsCode, 'app.js')
pageCode.forEach((item) => assignFiles(item, newFiles))

const metaFiles = generateMetaFiles(metaData)
const metaFiles = formatGeneratedFiles(generateMetaFiles(metaData))
Object.assign(newFiles, metaFiles)
setFiles(newFiles, 'App.vue')
} else if (previewType === 'app') {
Expand Down Expand Up @@ -581,7 +597,7 @@ export const usePreviewData = ({ setFiles, store, setImportMap }: IUsePreviewDat
return `${importSnippet}\n ${routeSnippets} \n ${exportSnippet}`
}

const formatCode = (fileContent, fileName) => {
const formatPreviewFile = (fileContent, fileName) => {
if (fileName === 'src/router/index.js') {
fileContent = getRouterFile(appSchema)
} else {
Expand All @@ -601,23 +617,25 @@ export const usePreviewData = ({ setFiles, store, setImportMap }: IUsePreviewDat
`const route = useRoute()\nconst router = useRouter()\nconst currentRoute = ref()\n\nwatchEffect(() => {\n\tcurrentRoute.value = route.path\n})\n\nconst routeChange = () => {\n\trouter.push(currentRoute.value)\n}\nprovide(I18nInjectionKey, i18n)`
)
}
return fileContent

return formatGeneratedFile(fileContent, fileName)
}

const fileRes = await getPreGenerateInfo()
const newFileRes = fileRes.filter((item) => item.filePath.includes('src/'))
const srcFiles = newFileRes.reduce((prev, item) => {
const fileName = item.filePath
prev[fileName] = formatCode(item.fileContent, fileName)
prev[fileName] = formatPreviewFile(item.fileContent, fileName)
return prev
}, {})
srcFiles['import-map.json'] = JSON.stringify(importMapData)
}, {} as Record<string, string>)
srcFiles['import-map.json'] = formatGeneratedFile(JSON.stringify(importMapData), 'import-map.json')
const newFiles = store.getFiles()
const enableTailwindCSS = getMergeMeta('engine.config')?.enableTailwindCSS
const appJsCode = processAppJsCode(newFiles['app.js'] || '', params.styles, enableTailwindCSS)
srcFiles['app.js'] = appJsCode
srcFiles['app.js'] = formatGeneratedFile(appJsCode, 'app.js')
srcFiles['main.js'] = `import app from './app.js' \n ${srcFiles['src/main.js']}`
srcFiles['main.js'] = srcFiles['main.js'].replace("import 'element-plus/dist/index.css'", '')
srcFiles['main.js'] = formatGeneratedFile(srcFiles['main.js'], 'main.js')
setFiles(srcFiles, 'src/main.js')
}
}
Expand Down
Loading