mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
feat!: generate vue sfcs as part of build (#67)
This commit is contained in:
parent
1428c46e96
commit
62e2f94fcd
@ -3,6 +3,7 @@ import { resolve, join, dirname, basename } from 'upath'
|
|||||||
import type { Plugin } from 'vite'
|
import type { Plugin } from 'vite'
|
||||||
import Critters from 'critters'
|
import Critters from 'critters'
|
||||||
import template from 'lodash.template'
|
import template from 'lodash.template'
|
||||||
|
import { genObjectFromRawEntries } from 'knitwork'
|
||||||
import htmlMinifier from 'html-minifier'
|
import htmlMinifier from 'html-minifier'
|
||||||
import { camelCase } from 'scule'
|
import { camelCase } from 'scule'
|
||||||
import genericMessages from '../templates/messages.json'
|
import genericMessages from '../templates/messages.json'
|
||||||
@ -72,6 +73,36 @@ export const RenderPlugin = () => {
|
|||||||
'const _template = (messages) => _render({ messages: { ..._messages, ...messages } })'
|
'const _template = (messages) => _render({ messages: { ..._messages, ...messages } })'
|
||||||
].join('\n').trim()
|
].join('\n').trim()
|
||||||
|
|
||||||
|
const templateContent = html
|
||||||
|
.match(/<body.*?>([\s\S]*)<\/body>/)?.[0]
|
||||||
|
.replace(/(?<=<|<\/)body/g, 'div')
|
||||||
|
.replace(/messages\./g, '')
|
||||||
|
.replace(/<a href="([^"]+)"([^>]*)>([\s\S]*)<\/a>/g, '<NuxtLink to="$1"$2>$3</NuxtLink>')
|
||||||
|
.replace(/>{{\s*([\s\S]+?)\s*}}<\/[\w-]*>/g, ' v-html="$1" />')
|
||||||
|
// 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
|
||||||
|
const title = html.match(/<title.*?>([\s\S]*)<\/title>/)?.[1].replace(/{{([\s\S]+?)}}/g, (r) => {
|
||||||
|
return `\${${r.slice(2, -2)}}`.replace(/messages\./g, 'props.')
|
||||||
|
})
|
||||||
|
const styleContent = Array.from(html.matchAll(/<style[^>]*>([\s\S]*?)<\/style>/g)).map(block => block[1])
|
||||||
|
const props = genObjectFromRawEntries(Object.entries({ ...genericMessages, ...messages }).map(([key, value]) => [key, {
|
||||||
|
type: typeof value === 'string' ? 'String' : typeof value === 'number' ? 'Number' : typeof value === 'boolean' ? 'Boolean' : 'undefined',
|
||||||
|
default: JSON.stringify(value)
|
||||||
|
}]))
|
||||||
|
const vueCode = [
|
||||||
|
'<script setup lang="ts">',
|
||||||
|
title && ' import { useMeta } from \'#app\'',
|
||||||
|
` const props = defineProps(${props})`,
|
||||||
|
title && ` useMeta({ title: \`${title}\` })`,
|
||||||
|
'</script>',
|
||||||
|
'<template>',
|
||||||
|
templateContent,
|
||||||
|
'</template>',
|
||||||
|
'<style scoped>',
|
||||||
|
...styleContent,
|
||||||
|
'</style>'
|
||||||
|
].filter(Boolean).join('\n').trim()
|
||||||
|
|
||||||
// Generate types
|
// Generate types
|
||||||
const types = [
|
const types = [
|
||||||
`export type DefaultMessages = Record<${Object.keys(messages).map(a => `"${a}"`).join(' | ')}, string | boolean | number >`,
|
`export type DefaultMessages = Record<${Object.keys(messages).map(a => `"${a}"`).join(' | ')}, string | boolean | number >`,
|
||||||
@ -88,6 +119,7 @@ export const RenderPlugin = () => {
|
|||||||
|
|
||||||
// Write new template
|
// Write new template
|
||||||
await fsp.writeFile(fileName.replace('/index.html', '.mjs'), `${jsCode}\nexport const template = _template`)
|
await fsp.writeFile(fileName.replace('/index.html', '.mjs'), `${jsCode}\nexport const template = _template`)
|
||||||
|
await fsp.writeFile(fileName.replace('/index.html', '.vue'), vueCode)
|
||||||
await fsp.writeFile(fileName.replace('/index.html', '.d.ts'), `${types}`)
|
await fsp.writeFile(fileName.replace('/index.html', '.d.ts'), `${types}`)
|
||||||
|
|
||||||
// Remove original html file
|
// Remove original html file
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"repository": "nuxt/ui",
|
"repository": "nuxt/ui",
|
||||||
"license": "CC-BY-ND-4.0",
|
"license": "CC-BY-ND-4.0",
|
||||||
"exports": {
|
"exports": {
|
||||||
"./templates/*": "./dist/templates/*.mjs",
|
"./templates/*": "./dist/templates/*",
|
||||||
".": "./dist/index.mjs",
|
".": "./dist/index.mjs",
|
||||||
"./*": "./dist/*"
|
"./*": "./dist/*"
|
||||||
},
|
},
|
||||||
@ -31,6 +31,7 @@
|
|||||||
"globby": "^13.1.1",
|
"globby": "^13.1.1",
|
||||||
"html-minifier": "^4.0.0",
|
"html-minifier": "^4.0.0",
|
||||||
"jiti": "^1.13.0",
|
"jiti": "^1.13.0",
|
||||||
|
"knitwork": "^0.1.1",
|
||||||
"lodash.template": "^4.5.0",
|
"lodash.template": "^4.5.0",
|
||||||
"scule": "^0.2.1",
|
"scule": "^0.2.1",
|
||||||
"upath": "^2.0.1",
|
"upath": "^2.0.1",
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"statusCode": "500",
|
"statusCode": "500",
|
||||||
"statusMessage": "Server error",
|
"statusMessage": "Server error",
|
||||||
"description": "An error occurred in the application and the page could not be served. If you are the application owner, check your server logs for details."
|
"description": "An error occurred in the application and the page could not be served. If you are the application owner, check your server logs for details.",
|
||||||
|
"stack": ""
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user