chore(ui-templates): improve type safety in render

This commit is contained in:
Daniel Roe 2024-06-07 23:16:07 +01:00
parent 3f6d7dad1a
commit 94c84feeeb
No known key found for this signature in database
GPG Key ID: CBC814C393D93268

View File

@ -27,7 +27,11 @@ export const RenderPlugin = () => {
const critters = new Critters({ path: outputDir }) const critters = new Critters({ path: outputDir })
const htmlFiles = await globby(resolve(outputDir, 'templates/**/*.html'), { absolute: true }) const htmlFiles = await globby(resolve(outputDir, 'templates/**/*.html'), { absolute: true })
const templateExports = [] const templateExports: Array<{
exportName: string
templateName: string
types: string
}> = []
for (const fileName of htmlFiles) { for (const fileName of htmlFiles) {
// Infer template name // Infer template name
@ -48,9 +52,13 @@ export const RenderPlugin = () => {
html = html.replace(/<link[^>]*>/g, '') html = html.replace(/<link[^>]*>/g, '')
// Inline SVGs // Inline SVGs
const svgSources = Array.from(html.matchAll(/src="([^"]+)"|url([^)]+)/g)) const svgSources: string[] = []
.map(m => m[1])
.filter(src => src?.match(/\.svg$/)) for (const [src] of html.matchAll(/src="([^"]+)"|url([^)]+)/g)) {
if (src?.match(/\.svg$/)) {
svgSources.push(src)
}
}
for (const src of svgSources) { for (const src of svgSources) {
const svg = readFileSync(join(outputDir, src), 'utf-8') const svg = readFileSync(join(outputDir, src), 'utf-8')
@ -59,8 +67,13 @@ export const RenderPlugin = () => {
} }
// Inline our scripts // Inline our scripts
const scriptSources = Array.from(html.matchAll(/<script[^>]*src="([^"]*)"[^>]*>[\s\S]*?<\/script>/g)) const scriptSources: [string, string][] = []
.filter(([_block, src]) => src?.match(/^\/.*\.js$/))
for (const [block, src] of html.matchAll(/<script[^>]*src="([^"]*)"[^>]*>[\s\S]*?<\/script>/g)) {
if (src?.match(/^\/.*\.js$/)) {
scriptSources.push([block, src])
}
}
for (const [scriptBlock, src] of scriptSources) { for (const [scriptBlock, src] of scriptSources) {
let contents = readFileSync(join(outputDir, src), 'utf-8') let contents = readFileSync(join(outputDir, src), 'utf-8')
@ -83,8 +96,10 @@ export const RenderPlugin = () => {
const chunks = html.split(/\{{2,3}[^{}]+\}{2,3}/g).map(chunk => JSON.stringify(chunk)) const chunks = html.split(/\{{2,3}[^{}]+\}{2,3}/g).map(chunk => JSON.stringify(chunk))
const hasMessages = chunks.length > 1 const hasMessages = chunks.length > 1
let templateString = chunks.shift() let templateString = chunks.shift()
for (const expression of html.matchAll(/\{{2,3}([^{}]+)\}{2,3}/g)) { for (const [_, expression] of html.matchAll(/\{{2,3}([^{}]+)\}{2,3}/g)) {
templateString += ` + (${expression[1].trim()}) + ${chunks.shift()}` if (expression) {
templateString += ` + (${expression.trim()}) + ${chunks.shift()}`
}
} }
if (chunks.length > 0) { if (chunks.length > 0) {
templateString += ' + ' + chunks.join(' + ') templateString += ' + ' + chunks.join(' + ')
@ -110,7 +125,7 @@ export const RenderPlugin = () => {
.replace(/>\{\{\{\s*(\w+)\s*\}\}\}<\/[\w-]*>/g, ' v-html="$1" />') .replace(/>\{\{\{\s*(\w+)\s*\}\}\}<\/[\w-]*>/g, ' v-html="$1" />')
// We are not matching <link> <script> and <meta> tags as these aren't used yet in nuxt/ui // We are not matching <link> <script> and <meta> tags as these aren't used yet in nuxt/ui
// and should be taken care of wherever this SFC is used // and should be taken care of wherever this SFC is used
const title = html.match(/<title[^>]*>([\s\S]*)<\/title>/)?.[1].replace(/\{\{([\s\S]+?)\}\}/g, (r) => { const title = html.match(/<title[^>]*>([\s\S]*)<\/title>/)?.[1]?.replace(/\{\{([\s\S]+?)\}\}/g, (r) => {
return `\${${r.slice(2, -2)}}`.replace(/messages\./g, 'props.') return `\${${r.slice(2, -2)}}`.replace(/messages\./g, 'props.')
}) })
const styleContent = Array.from(html.matchAll(/<style[^>]*>([\s\S]*?)<\/style>/g)).map(block => block[1]).join('\n') const styleContent = Array.from(html.matchAll(/<style[^>]*>([\s\S]*?)<\/style>/g)).map(block => block[1]).join('\n')
@ -119,7 +134,7 @@ export const RenderPlugin = () => {
if (lastChar && !['}', '.', '@', '*', ':'].includes(lastChar)) { if (lastChar && !['}', '.', '@', '*', ':'].includes(lastChar)) {
return ';' + lastChar return ';' + lastChar
} }
return lastChar return lastChar || ''
}).replace(/@media[^{]*\{\}/g, '') }).replace(/@media[^{]*\{\}/g, '')
const inlineScripts = Array.from(html.matchAll(/<script>([\s\S]*?)<\/script>/g)) const inlineScripts = Array.from(html.matchAll(/<script>([\s\S]*?)<\/script>/g))
.map(block => block[1]) .map(block => block[1])