forked from opentiny/tiny-vue
144 lines
4.4 KiB
JavaScript
144 lines
4.4 KiB
JavaScript
import { createRequire } from 'node:module'
|
|
import { readFileSync, existsSync } from 'node:fs'
|
|
import { transformVueTemplateToSolid } from './src/plugin.js'
|
|
import { dirname } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import path from 'node:path'
|
|
|
|
const __filename = fileURLToPath(import.meta.url)
|
|
const __dirname = dirname(__filename)
|
|
|
|
const require = createRequire(import.meta.url)
|
|
|
|
const indexTemplatePath = path.resolve(__dirname, './template/src/index.tss')
|
|
const pcTemplatePath = path.resolve(__dirname, './template/src/pc.jsxs')
|
|
|
|
// 多模板入口模板
|
|
const indexTemplate = readFileSync(indexTemplatePath, { encoding: 'utf-8' })
|
|
|
|
// PC模板入口
|
|
const pcTemplate = readFileSync(pcTemplatePath, { encoding: 'utf-8' })
|
|
|
|
const matchComponentRegx = /vue\/src\/([a-z]+)\/src/
|
|
|
|
const fundProps = (code, findStr) => {
|
|
let findIndex = code.indexOf(findStr)
|
|
let props = ''
|
|
|
|
if (~findIndex) {
|
|
const endStr = 'export '
|
|
let constantsPart = code.substring(findIndex + findStr.length, code.length)
|
|
props = constantsPart.substring(0, constantsPart.indexOf(endStr))
|
|
}
|
|
|
|
return props
|
|
}
|
|
|
|
const getSvgContent = (svg) => {
|
|
return svg.substring(svg.indexOf('>') + 1, svg.length)
|
|
}
|
|
|
|
const getDefaultValueFromEntry = (id) => {
|
|
const componentMatchs = id.match(matchComponentRegx)
|
|
const entryPath = id.replace('pc.vue', 'index.ts')
|
|
if (existsSync(entryPath)) {
|
|
if (componentMatchs?.[1]) {
|
|
const code = readFileSync(entryPath, { encoding: 'utf-8' })
|
|
let constants = fundProps(code, '$constants =') || '{}'
|
|
let propsContent = fundProps(code, 'Props =') || fundProps(code, 'props :')
|
|
let props = {}
|
|
|
|
if (propsContent) {
|
|
const propsContentParts = propsContent.split(/\n/)
|
|
propsContentParts.forEach((item, index) => {
|
|
if (item.indexOf('type:') && ['Boolean', 'String', 'Number'].some((type) => item.includes(type))) {
|
|
const name = propsContentParts[index - 1].replace(/\W/g, '')
|
|
let value = propsContentParts[index + 1]
|
|
|
|
if (name && value.includes('default:')) {
|
|
const type = /['"]/.test(value) ? 'Char' : 'Other'
|
|
value = value.replace('default:', '').replace(/["|'|\s,]/g, '')
|
|
props[name] = { type, value }
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
return {
|
|
$constants: constants,
|
|
$props: props
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
$constants: '{}',
|
|
$props: {}
|
|
}
|
|
}
|
|
|
|
export default function vueTemplate2Jsx() {
|
|
return {
|
|
name: '@opentiny/vue-vite-template2jsx',
|
|
enforce: 'pre',
|
|
transform(code, id) {
|
|
if (id.includes('vue-icon/src')) {
|
|
const svgName = code.match(/([a-z1-9-]+)\.svg/)
|
|
|
|
if (svgName && svgName[0]) {
|
|
let svgPath
|
|
|
|
try {
|
|
svgPath = require.resolve(`@opentiny/vue-theme/svgs/${svgName[0]}`)
|
|
} catch (e) {
|
|
svgPath = path.resolve(__dirname, `../../packages/theme/src/svgs/${svgName[0]}`)
|
|
}
|
|
|
|
if (existsSync(svgPath)) {
|
|
let svgContent = readFileSync(svgPath, { encoding: 'utf-8' })
|
|
|
|
if (svgContent.includes('<!--')) {
|
|
svgContent = svgContent.replace(/<!--[\s\S]+-->/, '')
|
|
}
|
|
|
|
if (svgContent.includes('<?xml')) {
|
|
svgContent = getSvgContent(svgContent)
|
|
}
|
|
|
|
if (svgContent.includes('<!DOCTYPE')) {
|
|
svgContent = getSvgContent(svgContent)
|
|
}
|
|
|
|
if (svgContent.includes('<style')) {
|
|
svgContent = svgContent.replace(/<style[\s\S]+<\/style>/, '')
|
|
}
|
|
|
|
const viewBox = svgContent.match(/viewBox="[\d|\s]+"/)?.[0] || `viewBox="0 0 24 24"`
|
|
|
|
return `export default function(props) {
|
|
return (<svg style={props.style} xmlns="http://www.w3.org/2000/svg" onClick={props.onClick} ${viewBox} xml:space="preserve" class={'tiny-svg svgs-icon ' + props.class}>
|
|
${getSvgContent(svgContent)}
|
|
)
|
|
}`
|
|
}
|
|
}
|
|
|
|
return code
|
|
}
|
|
|
|
if (id.includes(`src/index.ts`) && !id.includes(`common/src/index.ts`)) {
|
|
return indexTemplate
|
|
}
|
|
|
|
if (id.includes('pc.vue')) {
|
|
const componentMatchs = id.match(matchComponentRegx)
|
|
if (componentMatchs?.[1]) {
|
|
const mapData = getDefaultValueFromEntry(id)
|
|
const pcComponent = transformVueTemplateToSolid(pcTemplate, code, componentMatchs[1], mapData)
|
|
return pcComponent
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|