chore: add @nuxt/ui-templates to core monorepo

This commit is contained in:
Daniel Roe 2024-05-01 11:05:03 +01:00
commit fe6bdcc017
No known key found for this signature in database
GPG Key ID: CBC814C393D93268
26 changed files with 3318 additions and 0 deletions

View File

@ -0,0 +1,212 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.3.3](https://github.com/nuxt/assets/compare/@nuxt/ui-templates@1.3.2...@nuxt/ui-templates@1.3.3) (2024-04-05)
### Bug Fixes
* **templates:** include `.d.mts` declarations ([a40c36b](https://github.com/nuxt/assets/commit/a40c36b973ebc960460fd28db53e1efdc31f552e))
## [1.3.2](https://github.com/nuxt/assets/compare/@nuxt/ui-templates@1.3.1...@nuxt/ui-templates@1.3.2) (2024-04-02)
### Bug Fixes
- add labels to footer links for accessibility ([#221](https://github.com/nuxt/assets/issues/221)) ([6e6764b](https://github.com/nuxt/assets/commit/6e6764b636e3c77dca88d712b026def4b88e0473))
- **ui-templates:** give alternative of creating `app.vue` ([#233](https://github.com/nuxt/assets/issues/233)) ([bc8c845](https://github.com/nuxt/assets/commit/bc8c8451d4bd3fff0c5c0b427a087a5a9bca58af))
## [1.3.1](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@1.3.0...@nuxt/ui-templates@1.3.1) (2023-07-29)
### Bug Fixes
- **deps:** revert critters upgrade ([0341634](https://github.com/nuxt/ui/commit/03416341f7664f232da121deebb2fb53ab3dd864))
# [1.3.0](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@1.2.1...@nuxt/ui-templates@1.3.0) (2023-07-28)
### Features
- update nuxt logo ([#213](https://github.com/nuxt/ui/issues/213)) ([a8ee040](https://github.com/nuxt/ui/commit/a8ee0408521e5a9b1a2b387a57bece0750a43b03))
## [1.2.1](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@1.2.0...@nuxt/ui-templates@1.2.1) (2023-07-26)
### Bug Fixes
- handle empty message object when generating declaration ([5f229ef](https://github.com/nuxt/ui/commit/5f229ef1a3849ee042fe46e228ecf0094ef564fc))
# [1.2.0](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@1.1.1...@nuxt/ui-templates@1.2.0) (2023-06-20)
### Bug Fixes
- **templates:** update the docs link for `app.vue` ([#207](https://github.com/nuxt/ui/issues/207)) ([65b027e](https://github.com/nuxt/ui/commit/65b027ec5a7bec116ff0d694d2491b205c7895cf))
### Features
- **templates:** add spa-loading-icon ([b3ceabe](https://github.com/nuxt/ui/commit/b3ceabeea80f9e7239d18f331dfe457c65681b3d))
## [1.1.1](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@1.1.0...@nuxt/ui-templates@1.1.1) (2023-01-31)
**Note:** Version bump only for package @nuxt/ui-templates
# [1.1.0](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@0.4.0...@nuxt/ui-templates@1.1.0) (2023-01-06)
### Bug Fixes
- **templates:** avoid using blur in no-animation mode, disable animation in Safari ([#175](https://github.com/nuxt/ui/issues/175)) ([e552ec5](https://github.com/nuxt/ui/commit/e552ec53478d1b310f2aac6aac552777d00c16f7))
- use dynamic copyright year ([#193](https://github.com/nuxt/ui/issues/193)) ([816f361](https://github.com/nuxt/ui/commit/816f3616015cf6cad1568dbdb830f0664bdc5ca5))
### Features
- new design welcome template ([#178](https://github.com/nuxt/ui/issues/178)) ([85ceb30](https://github.com/nuxt/ui/commit/85ceb30301a58094e9ae4a6556e086dec245a3fb))
# [0.4.0](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@0.3.3...@nuxt/ui-templates@0.4.0) (2022-09-20)
### Bug Fixes
- upgrade headers to h1/h2 from h4/h5 ([#165](https://github.com/nuxt/ui/issues/165)) ([a44b945](https://github.com/nuxt/ui/commit/a44b9459e95b0ab2dfcf6b5b0b4493e00f968b3f))
### Features
- **templates:** ability to disable animation effect in loading page ([#161](https://github.com/nuxt/ui/issues/161)) ([8771e98](https://github.com/nuxt/ui/commit/8771e98fc160e4040e64c7b3982c4ef6f0fcb0d9))
## [0.3.3](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@0.3.2...@nuxt/ui-templates@0.3.3) (2022-09-05)
### Bug Fixes
- **templates:** interpolate props within attrs in rendering vue component ([#157](https://github.com/nuxt/ui/issues/157)) ([c0ea878](https://github.com/nuxt/ui/commit/c0ea87866c026bba4aef12ef108c7fb5992239b4))
## [0.3.2](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@0.3.1...@nuxt/ui-templates@0.3.2) (2022-08-12)
### Features
- **templates:** improve welcome screen luminance effect ([#142](https://github.com/nuxt/ui/issues/142)) ([7f8e554](https://github.com/nuxt/ui/commit/7f8e554c6682be8e11ad4965787dcb5ca92849e0))
## [0.3.1](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@0.3.0...@nuxt/ui-templates@0.3.1) (2022-08-11)
### Bug Fixes
- **templates:** adjust style extraction regexp ([#153](https://github.com/nuxt/ui/issues/153)) ([f19b73c](https://github.com/nuxt/ui/commit/f19b73cfb96fe4a641d441971cd92073287f9892))
# [0.3.0](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@0.2.2...@nuxt/ui-templates@0.3.0) (2022-07-21)
**Note:** Version bump only for package @nuxt/ui-templates
## [0.2.2](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@0.2.1...@nuxt/ui-templates@0.2.2) (2022-07-21)
### Bug Fixes
- inline global css that's not at beginning of line ([#141](https://github.com/nuxt/ui/issues/141)) ([adb0eb6](https://github.com/nuxt/ui/commit/adb0eb65ac33c2429e1122a4e24b39e1f83cb849))
- **templates:** prevent scrollbars from appearing on loading screen ([#144](https://github.com/nuxt/ui/issues/144)) ([fbab1cb](https://github.com/nuxt/ui/commit/fbab1cb5b31dd9658d47f3c91c0fc45861b782fd))
## [0.2.1](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@0.2.0...@nuxt/ui-templates@0.2.1) (2022-07-12)
**Note:** Version bump only for package @nuxt/ui-templates
# [0.2.0](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@0.1.1...@nuxt/ui-templates@0.2.0) (2022-07-12)
### Bug Fixes
- **templates:** align twitter text in welcome template ([#120](https://github.com/nuxt/ui/issues/120)) ([52eaf32](https://github.com/nuxt/ui/commit/52eaf322b996f318a52a05d1f58ce5a879bf7187))
### Features
- **loading-template:** mouse blurred light effect ([#138](https://github.com/nuxt/ui/issues/138)) ([4c28b3f](https://github.com/nuxt/ui/commit/4c28b3f27903969416d4292051e18eef70897f0c))
## [0.1.1](https://github.com/nuxt/ui/compare/@nuxt/ui-templates@0.1.0...@nuxt/ui-templates@0.1.1) (2022-05-07)
### Bug Fixes
- use `v-text` rather than `v-html` ([#100](https://github.com/nuxt/ui/issues/100)) ([9902421](https://github.com/nuxt/ui/commit/99024218aab20a1b326b59d986d632da546df6b4))
# 0.1.0 (2022-04-19)
### Bug Fixes
- better gradients ([bc8d393](https://github.com/nuxt/ui/commit/bc8d393129ae80a48372645edeceb377f7dfcc9f))
- extract inline scripts from template ([042029d](https://github.com/nuxt/ui/commit/042029db138acb7db6796eaf6be13942bbe6cd9f))
- improve design of error pages ([#68](https://github.com/nuxt/ui/issues/68)) ([9a81dd7](https://github.com/nuxt/ui/commit/9a81dd79ea2ebeb2bd0a29d3828a440a0f5fe741))
- make style global ([a9d6416](https://github.com/nuxt/ui/commit/a9d641619450822884fd01a7c610ef5e0bd687a8))
- only convert app links to `<NuxtLink>` ([01e1920](https://github.com/nuxt/ui/commit/01e1920da25da9a4aadf386cfc715ab1ef2c9a43))
- **templates:** don't use `v-html` on `<NuxtLink>` ([f07bad4](https://github.com/nuxt/ui/commit/f07bad487f02b0b63e307daec3280a2a65c5f281))
- **templates:** fix title and don't use css variables ([c31c699](https://github.com/nuxt/ui/commit/c31c6996ab17b09cecdb91ab9c725146a2d9d0b7))
- **templates:** generate js templates ([0cb54cc](https://github.com/nuxt/ui/commit/0cb54ccc7ac8d2d97db259c2eab41ac5adf66147))
- **templates:** hybrid global + scoped styles ([835c29f](https://github.com/nuxt/ui/commit/835c29f4139a2209e720a826e1d35621099f23cd))
- **templates:** reduce size and fix z-index ([6f72fd1](https://github.com/nuxt/ui/commit/6f72fd1281044b302f4b0c3542afb3672f8fd000))
- **ui-templates:** switch to `useHead` import ([#89](https://github.com/nuxt/ui/issues/89)) ([0352482](https://github.com/nuxt/ui/commit/0352482727bbb87f190f1d3791f19a58dfce0b36))
- use vh for height ([790de8f](https://github.com/nuxt/ui/commit/790de8f7f84ee8e63f76db58fcffb73ff0c59ee2))
- use vh instead and fixed position ([9f119b8](https://github.com/nuxt/ui/commit/9f119b89a529b306cac654999ca00cd5718830f1))
### Features
- new templates design ([#81](https://github.com/nuxt/ui/issues/81)) ([830f557](https://github.com/nuxt/ui/commit/830f55741d8ab0099afe1172c8e8e4e4040e3e4a))
- **ui:** enable transformers for unocss ([631d265](https://github.com/nuxt/ui/commit/631d2655f0469286fd17b6ea39dbb0650571b156))
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.1.5](https://github.com/nuxt/ui/compare/v0.1.4...v0.1.5) (2021-11-10)
### Bug Fixes
- don't include `const` declaration in `.d.ts` ([#40](https://github.com/nuxt/ui/issues/40)) ([75a5eae](https://github.com/nuxt/ui/commit/75a5eae76b797a9f49e30ec5469056d093a3a302))
### [0.1.4](https://github.com/nuxt/ui/compare/v0.1.3...v0.1.4) (2021-10-20)
### Bug Fixes
- add button background on dark media ([#36](https://github.com/nuxt/ui/issues/36)) ([de0a759](https://github.com/nuxt/ui/commit/de0a75959d06e90239b5a203eeb9e9be6031f0c2))
- add missing `rel="noopener` on some links([#34](https://github.com/nuxt/ui/issues/34)) ([8f18183](https://github.com/nuxt/ui/commit/8f18183f1d6cca49753e3b0a6a1da0aa8e0c9c83))
### [0.1.3](https://github.com/nuxt/ui/compare/v0.1.2...v0.1.3) (2021-10-12)
### Bug Fixes
- updates colors and templates ([e5691b0](https://github.com/nuxt/ui/commit/e5691b049b684ae98a04c5a324679d0b1f34053b))
### [0.1.2](https://github.com/nuxt/ui/compare/v0.1.0...v0.1.2) (2021-10-12)
### Features
- add welcome page template ([d7f95db](https://github.com/nuxt/ui/commit/d7f95db8c3344a2a05f91fb332f0f5ab1908b780))
### Bug Fixes
- add rootdir to vite fs.allow ([02da788](https://github.com/nuxt/ui/commit/02da78871564c5128b435694daa62c02b3acbef0))
### [0.1.1](https://github.com/nuxt/ui/compare/v0.1.0...v0.1.1) (2021-10-07)
## [0.1.0](https://github.com/nuxt/ui/compare/v0.0.6...v0.1.0) (2021-09-23)
### [0.0.6](https://github.com/nuxt/ui/compare/v0.0.5...v0.0.6) (2021-09-23)
### [0.0.5](https://github.com/nuxt/ui/compare/v0.0.3...v0.0.5) (2021-07-20)
### Bug Fixes
- correct color for the logo in dark mode ([408e6aa](https://github.com/nuxt/ui/commit/408e6aa22c0ba4920dadfa4f2eae9391d2862111))
### [0.0.4](https://github.com/nuxt/ui/compare/v0.0.3...v0.0.4) (2021-07-14)
### [0.0.3](https://github.com/nuxt/ui/compare/v0.0.2...v0.0.3) (2021-07-14)
### Bug Fixes
- use statusCode not message for 500 dev ([#19](https://github.com/nuxt/ui/issues/19)) ([a910883](https://github.com/nuxt/ui/commit/a910883024b2280770cbe985092153666eb17790))
### 0.0.2 (2021-07-14)
### Features
- add prerender script to preview ([4721560](https://github.com/nuxt/ui/commit/4721560e969ce52d29107546aae2fef9a6e6224f))
- loading page ([#18](https://github.com/nuxt/ui/issues/18)) ([78799fb](https://github.com/nuxt/ui/commit/78799fb695a896f6a992f28225b99283a38503ff))
- update new structure (closes [#14](https://github.com/nuxt/ui/issues/14)) ([631c740](https://github.com/nuxt/ui/commit/631c740396736e124c3cea288c0bcc22545d4269))
### Bug Fixes
- fix prerender and strict context ([ae26e1f](https://github.com/nuxt/ui/commit/ae26e1f21e85155595cfd861d20cddeff858ad5f))

View File

@ -0,0 +1,11 @@
# `@nuxt/ui-templates`
<a href="https://www.npmjs.com/package/@nuxt/ui-templates-edge"><img src="https://flat.badgen.net/npm/v/@nuxt/ui-templates-edge"></a>
Pre-compiled html templates for internal pages.
🏀 [Online Playground](https://templates.ui.nuxtjs.org)
# License
<a rel="license" href="http://creativecommons.org/licenses/by-nd/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nd/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Nuxt UI</span> by <span xmlns:cc="http://creativecommons.org/ns#" property="cc:attributionName">Nuxt Project</span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nd/4.0/">Creative Commons Attribution-NoDerivatives 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://github.com/nuxt/ui" rel="dct:source">https://github.com/nuxt/ui</a>.

View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/petite-vue" defer init></script>
<script type="module" src="/styles.ts"></script>
</head>
<body v-scope='{{ data }}'>
<div class="container mx-auto pt-10">
<h1 class="text-4xl mb-8">Nuxt Templates</h1>
<ul>
<li v-for="name in templateNames.filter(name => !name.includes('.json'))">
<a :href="`/templates/${name}`" class="block border p-4 mb-2 hover:border-black">{{ name }}</a>
</li>
</ul>
</div>
</body>
</html>

View File

@ -0,0 +1,32 @@
import { resolve, join } from 'path'
import { promises as fsp } from 'fs'
import type { Plugin } from 'vite'
import template from 'lodash.template'
import genericMessages from '../templates/messages.json'
const r = (...path: string[]) => resolve(join(__dirname, '..', ...path))
export const DevRenderingPlugin = () => {
return <Plugin>{
name: 'dev-rendering',
async transformIndexHtml (html: string, context) {
const page = context.originalUrl || '/'
if (page === '/') {
const templateNames = await fsp.readdir(r('templates'))
const serializedData = JSON.stringify({ templateNames })
return html.replace('{{ data }}', serializedData)
}
const contents = await fsp.readFile(r(page, 'index.html'), 'utf-8')
const messages = JSON.parse(await fsp.readFile(r(page, 'messages.json'), 'utf-8'))
return template(contents, {
interpolate: /{{{?([\s\S]+?)}?}}/g
})({
messages: { ...genericMessages, ...messages }
})
}
}
}

View File

@ -0,0 +1,21 @@
import { resolve, join } from 'path'
import { promises as fsp } from 'fs'
import { globby } from 'globby'
const r = (...path: string[]) => resolve(join(__dirname, '..', ...path))
async function main () {
const templates = await globby(r('dist/templates/*.mjs'))
for (const file of templates) {
const { template } = await import(file)
const updated = template({
// messages: {},
name: '{{ name }}' // TODO
})
await fsp.mkdir(file.replace('.mjs', ''))
await fsp.writeFile(file.replace('.mjs', '/index.html'), updated)
}
}
// eslint-disable-next-line no-console
main().catch(console.error)

View File

@ -0,0 +1,165 @@
import { promises as fsp } from 'fs'
import { resolve, join, dirname, basename } from 'upath'
import type { Plugin } from 'vite'
import Critters from 'critters'
import template from 'lodash.template'
import { genObjectFromRawEntries } from 'knitwork'
import htmlMinifier from 'html-minifier'
import { camelCase } from 'scule'
import genericMessages from '../templates/messages.json'
const r = (...path: string[]) => resolve(join(__dirname, '..', ...path))
const replaceAll = (input, search, replace) => input.split(search).join(replace)
export const RenderPlugin = () => {
return <Plugin> {
name: 'render',
enforce: 'post',
async writeBundle () {
const distDir = r('dist')
const critters = new Critters({ path: distDir })
const globby = await import('globby').then(r => r.globby)
const htmlFiles = await globby(r('dist/templates/**/*.html'))
const templateExports = []
for (const fileName of htmlFiles) {
// Infer template name
const templateName = basename(dirname(fileName))
// eslint-disable-next-line no-console
console.log('Processing', templateName)
// Read source template
let html = await fsp.readFile(fileName, 'utf-8')
const isCompleteHTML = html.includes('<!DOCTYPE html>')
if (html.includes('<html')) {
// Apply critters to inline styles
html = await critters.process(html)
}
// We no longer need references to external CSS
html = html.replace(/<link[^>]*>/g, '')
// Inline SVGs
const svgSources = Array.from(html.matchAll(/src="([^"]+)"|url([^)]+)/g))
.map(m => m[1])
.filter(src => src?.match(/\.svg$/))
for (const src of svgSources) {
const svg = await fsp.readFile(r('dist', src), 'utf-8')
const base64Source = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`
html = replaceAll(html, src, base64Source)
}
// Inline our scripts
const scriptSources = Array.from(html.matchAll(/<script[^>]*src="(.*)"[^>]*>[\s\S]*?<\/script>/g))
.filter(([_block, src]) => src?.match(/^\/.*\.js$/))
for (const [scriptBlock, src] of scriptSources) {
let contents = await fsp.readFile(r('dist', src), 'utf-8')
contents = replaceAll(contents, '/* empty css */', '').trim()
html = html.replace(scriptBlock, contents.length ? `<script>${contents}</script>` : '')
}
// Minify HTML
html = htmlMinifier.minify(html, { collapseWhitespace: true })
if (!isCompleteHTML) {
html = html.replace('<html><head></head><body>', '')
html = html.replace('</body></html>', '')
}
// Load messages
const messages = JSON.parse(await fsp.readFile(r(`templates/${templateName}/messages.json`), 'utf-8'))
// Serialize into a js function
const jsCode = [
`const _messages = ${JSON.stringify({ ...genericMessages, ...messages })}`,
`const _render = ${template(html, { variable: '__var__', interpolate: /{{{?([\s\S]+?)}?}}/g }).toString().replace('__var__', '{ messages }')}`,
'const _template = (messages) => _render({ messages: { ..._messages, ...messages } })'
].join('\n').trim()
const templateContent = html
.match(/<body.*?>([\s\S]*)<\/body>/)?.[0]
.replace(/(?<=<|<\/)body/g, 'div')
.replace(/messages\./g, '')
.replace(/<script[^>]*>([\s\S]*?)<\/script>/g, '')
.replace(/<a href="(\/[^"]*)"([^>]*)>([\s\S]*)<\/a>/g, '<NuxtLink to="$1"$2>\n$3\n</NuxtLink>')
// eslint-disable-next-line no-template-curly-in-string
.replace(/<([^>]+) ([a-z]+)="([^"]*)({{\s*(\w+?)\s*}})([^"]*)"([^>]*)>/g, '<$1 :$2="`$3${$5}$6`"$7>')
.replace(/>{{\s*(\w+?)\s*}}<\/[\w-]*>/g, ' v-text="$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
// 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]).join('\n')
const globalStyles = styleContent.replace(/(\.[^{\d][^{]*?\{[^}]*?\})+.?/g, (r) => {
const lastChar = r[r.length - 1]
if (lastChar && !['}', '.', '@', '*', ':'].includes(lastChar)) {
return ';' + lastChar
}
return lastChar
}).replace(/@media[^{]*?\{\}/g, '')
const inlineScripts = Array.from(html.matchAll(/<script>([\s\S]*?)<\/script>/g))
.map(block => block[1])
.filter(i => !i.includes('const t=document.createElement("link")'))
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>',
title && 'import { useHead } from \'#imports\'',
`const props = defineProps(${props})`,
title && 'useHead(' + genObjectFromRawEntries([
['title', `\`${title}\``],
['script', inlineScripts.map(s => ({ children: `\`${s}\`` }))],
['style', [{ children: `\`${globalStyles}\`` }]]
]) + ')',
'</script>',
'<template>',
templateContent,
'</template>',
'<style scoped>',
styleContent.replace(globalStyles, ''),
'</style>'
].filter(Boolean).join('\n').trim()
// Generate types
const types = [
`export type DefaultMessages = Record<${Object.keys(messages).map(a => `"${a}"`).join(' | ') || 'string'}, string | boolean | number >`,
'declare const template: (data: Partial<DefaultMessages>) => string',
'export { template }'
].join('\n')
// Register exports
templateExports.push({
exportName: camelCase(templateName),
templateName,
types
})
// Write new 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.mts'), `${types}`)
await fsp.writeFile(fileName.replace('/index.html', '.d.ts'), `${types}`)
// Remove original html file
await fsp.unlink(fileName)
await fsp.rmdir(dirname(fileName))
}
// Write an index file with named exports for each template
const contents = templateExports.map(exp => `export { template as ${exp.exportName} } from './templates/${exp.templateName}.mjs'`).join('\n')
await fsp.writeFile(r('dist/index.mjs'), contents, 'utf8')
await fsp.writeFile(r('dist/index.d.ts'), replaceAll(contents, /\.mjs/g, ''), 'utf8')
await fsp.writeFile(r('dist/index.d.mts'), replaceAll(contents, /\.mjs/g, ''), 'utf8')
}
}
}

View File

@ -0,0 +1,46 @@
{
"name": "@nuxt/ui-templates",
"version": "1.3.3",
"repository": "nuxt/assets",
"license": "CC-BY-ND-4.0",
"exports": {
"./templates/*": "./dist/templates/*",
".": "./dist/index.mjs",
"./*": "./dist/*"
},
"main": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist/templates/*",
"dist/index.*"
],
"scripts": {
"build": "vite build",
"dev": "vite",
"lint": "eslint --ext .ts,.js .",
"optimize-assets": "npx svgo public/assets/**/*.svg",
"prepack": "pnpm build",
"prerender": "pnpm build && jiti ./lib/prerender",
"test": "pnpm lint && pnpm build"
},
"devDependencies": {
"@nuxt/ui-assets": "^0.2.1",
"@types/html-minifier": "^4.0.5",
"@types/lodash.template": "^4.5.3",
"@unocss/reset": "^0.58.9",
"critters": "0.0.22",
"execa": "^8.0.1",
"globby": "^14.0.1",
"html-minifier": "^4.0.0",
"jiti": "^1.21.0",
"knitwork": "^1.1.0",
"lodash.template": "^4.5.0",
"scule": "^1.3.0",
"unocss": "^0.58.9",
"upath": "^2.0.1",
"vite": "^5.2.8"
},
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1 @@
../assets

View File

@ -0,0 +1,2 @@
import '@unocss/reset/tailwind.css'
import 'uno.css'

View File

@ -0,0 +1,77 @@
<!DOCTYPE html>
<html>
<head>
<title>{{ messages.statusCode }} - {{ messages.statusMessage }} | {{ messages.appName }}</title>
<meta charset="utf-8"/>
<meta content="width=device-width,initial-scale=1.0,minimum-scale=1.0" name="viewport"/>
<script type="module" src="/styles.ts"></script>
<style>
.spotlight {
background: linear-gradient(45deg, #00DC82 0%, #36E4DA 50%, #0047E1 100%);
filter: blur(20vh);
height: 40vh;
bottom: -30vh;
}
.gradient-border {
position: relative;
border-radius: 0.5rem;
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
}
@media (prefers-color-scheme: light) {
.gradient-border {
background-color: rgba(255, 255, 255, 0.3);
}
.gradient-border::before {
background: linear-gradient(90deg, #e2e2e2 0%, #e2e2e2 25%, #00DC82 50%, #36E4DA 75%, #0047E1 100%);
}
}
@media (prefers-color-scheme: dark) {
.gradient-border {
background-color: rgba(20, 20, 20, 0.3);
}
.gradient-border::before {
background: linear-gradient(90deg, #303030 0%, #303030 25%, #00DC82 50%, #36E4DA 75%, #0047E1 100%);
}
}
.gradient-border::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 0.5rem;
padding: 2px;
width: 100%;
background-size: 400% auto;
opacity: 0.5;
transition: background-position 0.3s ease-in-out, opacity 0.2s ease-in-out;
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
.gradient-border:hover::before {
background-position: -50% 0;
opacity: 1;
}
</style>
</head>
<body class="font-sans antialiased bg-white dark:bg-black text-black dark:text-white grid min-h-screen place-content-center overflow-hidden ">
<div class="fixed left-0 right-0 spotlight z-10"></div>
<div class="max-w-520px text-center z-20">
<h1 class="text-8xl sm:text-10xl font-medium mb-8">{{ messages.statusCode }}</h1>
<p class="text-xl px-8 sm:px-0 sm:text-4xl font-light mb-16 leading-tight">{{ messages.description }}</p>
<div class="w-full flex items-center justify-center">
<a href="/" class="gradient-border text-md sm:text-xl py-2 px-4 sm:py-3 sm:px-6 cursor-pointer">
{{ messages.backHome }}
</a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,6 @@
{
"statusCode": 404,
"statusMessage": "Not Found",
"description": "Sorry, the page you are looking for could not be found.",
"backHome": "Go back home"
}

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<title>{{ messages.statusCode }} - {{ messages.statusMessage }} | {{ messages.appName }}</title>
<meta charset="utf-8"/>
<meta content="width=device-width,initial-scale=1.0,minimum-scale=1.0" name="viewport"/>
<script type="module" src="/styles.ts"></script>
<style>
.spotlight {
background: linear-gradient(45deg, #00DC82 0%, #36E4DA 50%, #0047E1 100%);
filter: blur(20vh);
}
</style>
</head>
<body class="font-sans antialiased bg-white dark:bg-black text-black dark:text-white grid min-h-screen place-content-center overflow-hidden ">
<div class="fixed -bottom-1/2 left-0 right-0 h-1/2 spotlight"></div>
<div class="max-w-520px text-center">
<h1 class="text-8xl sm:text-10xl font-medium mb-8">{{ messages.statusCode }}</h1>
<p class="text-xl px-8 sm:px-0 sm:text-4xl font-light mb-16 leading-tight">{{ messages.description }}</p>
</div>
</body>
</html>

View File

@ -0,0 +1,5 @@
{
"statusCode": 500,
"statusMessage": "Server error",
"description": "This page is temporarily unavailable."
}

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>{{ messages.statusCode }} - {{ messages.statusMessage }} | {{ messages.appName }}</title>
<meta charset="utf-8"/>
<meta content="width=device-width,initial-scale=1.0,minimum-scale=1.0" name="viewport"/>
<script type="module" src="/styles.ts"></script>
<style>
.spotlight {
background: linear-gradient(45deg, #00DC82 0%, #36E4DA 50%, #0047E1 100%);
opacity: 0.8;
filter: blur(30vh);
height: 60vh;
bottom: -40vh;
}
</style>
</head>
<body class="font-sans antialiased bg-white px-10 pt-14 dark:bg-black text-black dark:text-white min-h-screen flex flex-col">
<div class="fixed left-0 right-0 spotlight"></div>
<h1 class="text-6xl sm:text-8xl font-medium mb-6">{{ messages.statusCode }}</h1>
<p class="text-xl sm:text-2xl font-light mb-8 leading-tight">{{ messages.description }}</p>
<div class="bg-white rounded-t-md bg-black/5 dark:bg-white/10 flex-1 overflow-y-auto h-auto">
<pre class="text-xl font-light leading-tight z-10 p-8">{{{ messages.stack }}}</pre>
</div>
</body>
</html>

View File

@ -0,0 +1,6 @@
{
"statusCode": 500,
"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.",
"stack": ""
}

View File

@ -0,0 +1,188 @@
<!DOCTYPE html>
<html>
<head>
<title>{{ messages.loading }} | {{ messages.appName }}</title>
<meta charset="utf-8" />
<meta content="width=device-width,initial-scale=1.0,minimum-scale=1.0" name="viewport" />
<script type="module" src="/styles.ts"></script>
<style>
.nuxt-loader-bar {
background: repeating-linear-gradient(to right, #36E4DA 0%, #1DE0B1 25%, #00DC82 50%, #1DE0B1 75%, #36E4DA 100%);
height: 100px;
background-size: 200% auto;
background-position: 0 0;
animation: gradient 2s infinite;
animation-fill-mode: forwards;
animation-timing-function: linear;
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 5px;
}
.visual-effects .nuxt-loader-bar {
height: 100px;
bottom: -50px;
left: -50px;
right: -50px;
filter: blur(100px);
}
.visual-effects .mouse-gradient {
background: repeating-linear-gradient(to right, #00DC82 0%, #1DE0B1 50%, #36E4DA 100%);
filter: blur(100px);
opacity: 0.5;
}
#animation-toggle {
position: fixed;
padding: 10px;
top: 0;
right: 0;
transition: opacity 0.4s ease-in;
opacity: 0;
}
#animation-toggle:hover {
opacity: 0.8;
}
@keyframes gradient {
0% {
background-position: 0 0;
}
100% {
background-position: -200% 0;
}
}
@keyframes width {
0% {
width: 100%;
}
50% {
width: 0;
}
100% {
width: 100%;
}
}
@media (prefers-color-scheme: dark) {
html, body {
color: white;
color-scheme: dark;
}
.nuxt-loader-bar {
opacity: 0.5;
}
}
</style>
</head>
<body class="visual-effects relative overflow-hidden min-h-screen bg-white dark:bg-black flex flex-col justify-center items-center text-center">
<div id="mouseLight" class="absolute top-0 rounded-full mouse-gradient transition-opacity h-[200px] w-[200px]"></div>
<a href="https://nuxt.com" target="_blank" rel="noopener" class="nuxt-logo z-20">
<svg id="nuxtImg" xmlns="http://www.w3.org/2000/svg" width="214" height="53" fill="none" viewBox="0 0 800 200">
<path fill="#00DC82" d="M168.303 200h111.522c3.543 0 7.022-.924 10.09-2.679A20.086 20.086 0 0 0 297.3 190a19.855 19.855 0 0 0 2.7-10.001 19.858 19.858 0 0 0-2.709-9.998L222.396 41.429a20.09 20.09 0 0 0-7.384-7.32 20.313 20.313 0 0 0-10.088-2.679c-3.541 0-7.02.925-10.087 2.68a20.082 20.082 0 0 0-7.384 7.32l-19.15 32.896L130.86 9.998a20.086 20.086 0 0 0-7.387-7.32A20.322 20.322 0 0 0 113.384 0c-3.542 0-7.022.924-10.09 2.679a20.091 20.091 0 0 0-7.387 7.319L2.709 170A19.853 19.853 0 0 0 0 179.999c-.002 3.511.93 6.96 2.7 10.001a20.091 20.091 0 0 0 7.385 7.321A20.322 20.322 0 0 0 20.175 200h70.004c27.737 0 48.192-12.075 62.266-35.633l34.171-58.652 18.303-31.389 54.93 94.285h-73.233L168.303 200Zm-79.265-31.421-48.854-.011 73.232-125.706 36.541 62.853-24.466 42.01c-9.347 15.285-19.965 20.854-36.453 20.854Z" />
<path fill="currentColor" d="M377 200a4 4 0 0 0 4-4v-93s5.244 8.286 15 25l38.707 66.961c1.789 3.119 5.084 5.039 8.649 5.039H470V50h-27a4 4 0 0 0-4 4v94l-17-30-36.588-62.98c-1.792-3.108-5.081-5.02-8.639-5.02H350v150h27ZM676.203 143.857 710.551 92h-25.73a9.972 9.972 0 0 0-8.333 4.522L660.757 120.5l-15.731-23.978A9.972 9.972 0 0 0 636.693 92h-25.527l34.348 51.643L608.524 200h24.966a9.969 9.969 0 0 0 8.29-4.458l19.18-28.756 18.981 28.72a9.968 9.968 0 0 0 8.313 4.494h24.736l-36.787-56.143ZM724.598 92h19.714V60.071h28.251V92H800v24.857h-27.437V159.5c0 10.5 5.284 15.429 14.43 15.429H800V200h-16.869c-23.576 0-38.819-14.143-38.819-39.214v-43.929h-19.714V92ZM590 92h-15c-3.489 0-6.218.145-8.5 2.523-2.282 2.246-2.5 3.63-2.5 7.066v52.486c0 8.058-.376 12.962-4 16.925-3.624 3.831-8.619 5-16 5-7.247 0-12.376-1.169-16-5-3.624-3.963-4-8.867-4-16.925v-52.486c0-3.435-.218-4.82-2.5-7.066C519.218 92.145 516.489 92 513 92h-15v62.422c0 14.004 3.892 25.101 11.676 33.292C517.594 195.905 529.103 200 544 200c14.897 0 26.204-4.095 34.123-12.286 7.918-8.191 11.877-19.288 11.877-33.292V92Z" />
</svg>
</a>
<button id="animation-toggle">Animation Enabled</button>
<div class="nuxt-loader-bar"></div>
<script>
const ANIMATION_KEY = 'nuxt-loading-enable-animation'
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
let isLowPerformance = checkIsLowPerformance()
let enableAnimation = localStorage.getItem(ANIMATION_KEY) === 'false'
? false
: localStorage.getItem(ANIMATION_KEY) === 'true'
? true
: !isLowPerformance
const mouseLight = window.document.getElementById('mouseLight')
const nuxtImg = window.document.getElementById('nuxtImg')
const animationToggle = window.document.getElementById('animation-toggle')
const body = window.document.body
let bodyRect
function checkIsLowPerformance() {
return window.matchMedia('(prefers-reduced-motion: reduce)').matches
|| navigator.hardwareConcurrency < 2
|| navigator.deviceMemory < 1
// Safari has some performance issue on the blur filter. Remove this when it's fixed.
|| isSafari
}
function calculateDistance(elem, mouseX, mouseY) {
return Math.floor(Math.sqrt(Math.pow(mouseX - (elem.x + (elem.width / 2)), 2) + Math.pow(mouseY - (elem.top + (elem.height / 2)), 2)));
}
function onFocusOut() {
if (!enableAnimation) {
return
}
mouseLight.style.opacity = 0
nuxtImg.style.opacity = 0.7
}
function onMouseMove(e) {
if (!enableAnimation) {
return
}
const pointerRect = nuxtImg.getBoundingClientRect()
if (!bodyRect) {
bodyRect = body.getBoundingClientRect()
}
const distance = calculateDistance(pointerRect, e.pageX, e.pageY)
const size = Math.max((1000 - distance) / 2 / 100, 1)
mouseLight.style.top = `${e.clientY - bodyRect.y - mouseLight.clientHeight / 2}px`
mouseLight.style.left = `${e.clientX - mouseLight.clientWidth / 2}px`
mouseLight.style.width = mouseLight.style.height = `${Math.max(Math.round(size * 100), 300)}px`
mouseLight.style.filter = `blur(${Math.min(Math.max(size * 50, 100), 160)}px)`
mouseLight.style.opacity = Math.min(Math.max(size / 4, 0.6), 1)
const dx = e.pageX - pointerRect.left
const dy = e.pageY - pointerRect.top
const logoGradient = `radial-gradient(circle at ${dx}px ${dy}px, black 75%, transparent 100%)`
nuxtImg.style['-webkit-mask-image'] = logoGradient
nuxtImg.style['mask-image'] = logoGradient
nuxtImg.style.opacity = Math.min(Math.max(size / 4, 0.7), 1)
}
function toggleAnimation(value = !enableAnimation) {
enableAnimation = value
document.body.classList.toggle('visual-effects', enableAnimation)
if (value) {
onFocusOut()
animationToggle.innerText = 'Animation Enabled'
}
else {
mouseLight.style.opacity = 0
nuxtImg.style.opacity = 1
nuxtImg.style['mask-image'] = ''
nuxtImg.style['-webkit-mask-image'] = ''
animationToggle.innerText = 'Animation Disabled'
}
localStorage.setItem(ANIMATION_KEY, enableAnimation ? 'true' : 'false')
}
animationToggle.addEventListener('click', () => toggleAnimation(), { passive: true})
body.addEventListener('mousemove', onMouseMove, { passive: true })
body.addEventListener('mouseleave', onFocusOut, { passive: true })
toggleAnimation(enableAnimation)
if (typeof window.fetch === 'undefined') {
setTimeout(() => window.location.reload(), 1000)
} else {
const check = async () => {
try {
const body = await window
.fetch(window.location.href)
.then(r => r.text())
if (!body.includes('__NUXT_LOADING__')) {
return window
.location
.reload()
}
} catch {}
setTimeout(check, 1000)
}
check()
}
</script>
</body>
</html>

View File

@ -0,0 +1,3 @@
{
"loading": "Loading"
}

View File

@ -0,0 +1,4 @@
{
"appName": "Nuxt",
"version": ""
}

View File

@ -0,0 +1,29 @@
<svg class="nuxt-spa-loading" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 37 25" fill="none" width="80">
<path d="M24.236 22.006h10.742L25.563 5.822l-8.979 14.31a4 4 0 0 1-3.388 1.874H2.978l11.631-20 5.897 10.567" />
</svg>
<style>
.nuxt-spa-loading {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.nuxt-spa-loading>path {
fill: none;
stroke: #00DC82;
stroke-width: 4px;
stroke-linecap: round;
stroke-linejoin: round;
/* Stroke-dasharray property */
stroke-dasharray: 128;
stroke-dashoffset: 128;
animation: nuxt-spa-loading-move 3s linear infinite;
}
@keyframes nuxt-spa-loading-move {
100% {
stroke-dashoffset: -128;
}
}
</style>

After

Width:  |  Height:  |  Size: 746 B

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,366 @@
<!DOCTYPE html>
<html>
<head>
<title>{{ messages.title }}</title>
<meta charset="utf-8" />
<meta content="width=device-width,initial-scale=1.0,minimum-scale=1.0" name="viewport" />
<link rel="icon" type="image/png" href="/icon.png" />
<script type="module" src="/styles.ts"></script>
<style lang="postcss">
/*linear gradients */
@media (prefers-color-scheme: light) {
.get-started-gradient-border {
background: linear-gradient(to right, #ffffff, #ffffff), linear-gradient(to right, #00DC82, #1DE0B1, #36E4DA);
}
.gradient-border-modules {
background: linear-gradient(var(--gradient-angle), rgba(247, 209, 76), rgba(247, 209, 76, 0.6), rgba(255, 255, 255, 0.8), rgba(247, 209, 76));
}
.gradient-border-examples {
background: linear-gradient(var(--gradient-angle), rgba(141, 234, 255), rgba(141, 234, 255, 0.6), rgba(255, 255, 255, 0.8), rgba(141, 234, 255));
}
.gradient-border-documentation {
background: linear-gradient(var(--gradient-angle), rgba(0, 220, 130), rgba(0, 220, 130, 0.6), rgba(255, 255, 255, 0.8), rgba(0, 220, 130));
}
}
@media (prefers-color-scheme: dark) {
.get-started-gradient-border {
background: linear-gradient(to right, #18181B, #18181B), linear-gradient(to right, #00DC82, #1DE0B1, #36E4DA);
}
.gradient-border-modules {
background: linear-gradient(var(--gradient-angle), rgba(247, 209, 76), rgba(163, 129, 8), rgba(255, 255, 255, 0.3), rgba(163, 129, 8));
}
.gradient-border-examples {
background: linear-gradient(var(--gradient-angle), rgba(141, 234, 255), rgba(0, 138, 169), rgba(255, 255, 255, 0.3), rgba(0, 138, 169));
}
.gradient-border-documentation {
background: linear-gradient(var(--gradient-angle), rgba(0, 220, 130), rgba(0, 63, 37), rgba(255, 255, 255, 0.2), rgba(0, 63, 37));
}
}
/* get started */
.get-started-gradient-border {
background-clip: padding-box, border-box;
background-origin: padding-box, border-box;
border-color: transparent;
border-radius: 12px;
border-width: 1px;
}
.get-started-gradient-border:hover > :is(.get-started-gradient-left, .get-started-gradient-right) {
opacity: 0.2;
}
.get-started-gradient-left, .get-started-gradient-right {
opacity: 0;
}
/* gradient border */
.gradient-border {
opacity: 0;
position: absolute;
top: 0;
left: 0;
width: calc(100% + 2px);
border-radius: 12px;
z-index: -1;
transform: translate(-1px, -1px);
}
.gradient-border-rect {
height: calc(100% + 2px);
}
@media (min-width: 1024px) {
.gradient-border-rect {
height: calc(100% + 1px);
}
}
.gradient-border-square {
height: calc(100% + 2px);
}
.modules-gradient-right {
opacity: 0;
}
.modules-container:hover > .gradient-border, .examples-container:hover > .gradient-border, .documentation-container:hover > .gradient-border {
opacity: 1;
animation: gradient-rotate 5s cubic-bezier(0,0,1,1) 0s infinite reverse;
transition: all 0.3s linear;
}
.modules-container:hover > .modules-gradient-right {
opacity: 0.2;
}
.examples-container:hover > .examples-gradient-right {
opacity: 0.2;
}
.examples-gradient-right {
opacity: 0;
}
/* images */
.documentation-image-color-light, .documentation-image-color-dark {
display: none;
}
.modules-image-color-light, .modules-image-color-dark {
display: none;
}
.examples-image-color-light, .examples-image-color-dark {
display: none;
}
/* image */
@media (prefers-color-scheme: light) {
/*modules*/
.modules-image-light {
display: block;
}
.modules-image-dark {
display: none;
}
.modules-container:hover > a > .modules-image-light {
display: none;
}
.modules-container:hover > a > .modules-image-color-light {
display: block;
}
/* examples */
.examples-image-light {
display: block;
}
.examples-image-dark {
display: none;
}
.examples-container:hover > a > .examples-image-light {
display: none;
}
.examples-container:hover > a > .examples-image-color-light {
display: block;
}
/* documentation */
.documentation-image-light {
display: block;
}
.documentation-image-dark {
display: none;
}
.documentation-container:hover > a > div > .documentation-image-light {
display: none;
}
.documentation-container:hover > a > div > .documentation-image-color-light {
display: block;
}
}
@media (prefers-color-scheme: dark) {
/*modules*/
.modules-image-dark {
display: block;
}
.modules-image-light {
display: none;
}
.modules-container:hover > a > .modules-image-color-dark {
display: block;
}
.modules-container:hover > a > .modules-image-dark {
display: none;
}
/* examples */
.examples-image-dark {
display: block;
}
.examples-image-light {
display: none;
}
.examples-container:hover > a > .examples-image-color-dark {
display: block;
}
.examples-container:hover > a > .examples-image-dark {
display: none;
}
/* documentation */
.documentation-image-dark {
display: block;
}
.documentation-image-light {
display: none;
}
.documentation-container:hover > a > div >.documentation-image-color-dark {
display: block;
}
.documentation-container:hover > a > div > .documentation-image-dark {
display: none;
}
}
@property --gradient-angle {
syntax: '<angle>';
inherits: false;
initial-value: 180deg;
}
@keyframes gradient-rotate {
0% {
--gradient-angle: 0deg;
}
100% {
--gradient-angle: 360deg;
}
}
</style>
</head>
<body class="antialiased bg-white dark:bg-black text-black dark:text-white min-h-screen place-content-center flex flex-col items-center justify-center text-sm sm:text-base">
<div class="flex-1 flex flex-col gap-y-16 py-14">
<div class="flex flex-col gap-y-4 items-center justify-center">
<a href="https://nuxt.com" target="_blank">
<svg width="61" height="42" viewBox="0 0 61 42" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M33.9869 41.2211H56.412C57.1243 41.2212 57.824 41.0336 58.4408 40.6772C59.0576 40.3209 59.5698 39.8083 59.9258 39.191C60.2818 38.5737 60.469 37.8736 60.4687 37.1609C60.4684 36.4482 60.2805 35.7482 59.924 35.1313L44.864 9.03129C44.508 8.41416 43.996 7.90168 43.3793 7.54537C42.7626 7.18906 42.063 7.00147 41.3509 7.00147C40.6387 7.00147 39.9391 7.18906 39.3225 7.54537C38.7058 7.90168 38.1937 8.41416 37.8377 9.03129L33.9869 15.7093L26.458 2.65061C26.1018 2.03354 25.5895 1.52113 24.9726 1.16489C24.3557 0.808639 23.656 0.621094 22.9438 0.621094C22.2316 0.621094 21.5318 0.808639 20.915 1.16489C20.2981 1.52113 19.7858 2.03354 19.4296 2.65061L0.689224 35.1313C0.332704 35.7482 0.144842 36.4482 0.144532 37.1609C0.144222 37.8736 0.331476 38.5737 0.687459 39.191C1.04344 39.8083 1.5556 40.3209 2.17243 40.6772C2.78925 41.0336 3.48899 41.2212 4.20126 41.2211H18.2778C23.8551 41.2211 27.9682 38.7699 30.7984 33.9876L37.6694 22.0813L41.3498 15.7093L52.3951 34.8492H37.6694L33.9869 41.2211ZM18.0484 34.8426L8.2247 34.8404L22.9504 9.32211L30.2979 22.0813L25.3784 30.6092C23.4989 33.7121 21.3637 34.8426 18.0484 34.8426Z" fill="#00DC82" />
</svg>
</a>
<h1 class="text-black dark:text-white text-4xl sm:text-5xl font-semibold text-center">
Welcome to Nuxt!
</h1>
</div>
<div class="grid grid-cols-2 lg:grid-cols-10 gap-6 max-w-[960px] px-4">
<div class="col-span-2 lg:col-span-10 relative get-started-gradient-border">
<div class="get-started-gradient-left absolute left-0 inset-y-0 w-[20%] bg-gradient-to-r to-transparent from-green-400 rounded-xl z-1 transition-opacity duration-300"></div>
<div class="get-started-gradient-right absolute right-0 inset-y-0 w-[20%] bg-gradient-to-l to-transparent from-blue-400 rounded-xl z-1 transition-opacity duration-300"></div>
<div class="w-full absolute inset-x-0 flex justify-center -top-[58px]">
<img src="/icons/get-started.svg" class="hidden dark:block">
<img src="/icons/get-started-light.svg" class="dark:hidden">
</div>
<div class="flex flex-col rounded-xl items-center gap-y-4 pt-[58px] px-4 sm:px-28 pb-6 z-10">
<h2 class="font-semibold text-2xl text-black dark:text-white">
Get started
</h2>
<p class="mb-2 text-center">Remove this welcome page by
replacing <a class="bg-gray-100 dark:bg-white/10 rounded font-mono p-1 font-bold">&lt;NuxtWelcome /&gt;</a> in <a href="https://nuxt.com/docs/guide/directory-structure/app" target="_blank" rel="noopener" class="bg-gray-100 dark:bg-white/10 rounded font-mono p-1 font-bold">app.vue</a> with your own code, or creating your own <span class="bg-gray-100 dark:bg-white/10 rounded font-mono p-1 font-bold">app.vue</span> if it doesn't exist.</p>
</div>
</div>
<div class="lg:min-h-min sm:min-h-[220px] md:min-h-[180px] col-span-2 sm:col-span-1 lg:col-span-6 text-black dark:text-white rounded-xl modules-container relative items-center justify-center border border-gray-200 dark:border-transparent hover:border-transparent">
<div class="gradient-border gradient-border-modules gradient-border-rect"></div>
<div class="modules-gradient-right absolute right-0 inset-y-0 w-[20%] bg-gradient-to-l to-transparent from-yellow-400 rounded-xl z-1 transition-opacity duration-300"></div>
<a href="https://nuxt.com/modules" target="_blank" class="py-6 px-5 rounded-xl flex items-center justify-center gap-x-4 dark:border-none bg-white dark:bg-gray-900 sm:min-h-[220px] md:min-h-[180px] lg:min-h-min">
<img src="/icons/modules-color-light.svg" alt="modules icon" class="modules-image-color-light">
<img src="/icons/modules-color.svg" alt="modules icon" class="modules-image-color-dark">
<img src="/icons/modules-light.svg" alt="modules icon" class="modules-image-light">
<img src="/icons/modules.svg" alt="modules icon" class="modules-image-dark">
<div class="flex flex-col space-y text-black dark:text-white">
<h3 class="font-semibold text-xl">
Modules
</h3>
<p class="text-gray-700 dark:text-gray-300">
Discover our list of modules to supercharge your Nuxt project. Created by the Nuxt team and community.
</p>
</div>
</a>
</div>
<div class="row-span-2 col-span-2 order-last lg:order-none lg:col-span-4 text-black dark:text-white documentation-container rounded-xl relative items-center justify-center border border-gray-200 dark:border-transparent hover:border-transparent">
<div class="gradient-border gradient-border-square gradient-border-documentation"></div>
<a href="https://nuxt.com/docs" target="_blank" class="rounded-xl flex lg:flex-col items-center justify-center gap-y-4 bg-white dark:bg-gray-900">
<div class="py-6 lg:py-7 px-5 rounded-xl flex flex-col sm:flex-row lg:flex-col items-center justify-center gap-y-2 ">
<div class="flex flex-col space-y text-black dark:text-white">
<h3 class="font-semibold text-xl">
Documentation
</h3>
<p class="text-gray-700 dark:text-gray-300">
We highly recommend you take a look at the Nuxt documentation to level up.
</p>
</div>
<img src="/icons/documentation-color-light.svg" alt="documentation icon" class="documentation-image-color-light h-32 sm:h-34">
<img src="/icons/documentation-color.svg" alt="documentation icon" class="documentation-image-color-dark h-32 sm:h-34">
<img src="/icons/documentation-light.svg" alt="documentation icon" class="documentation-image-light h-32 sm:h-34">
<img src="/icons/documentation.svg" alt="documentation icon" class="documentation-image-dark h-32 sm:h-34">
</div>
</a>
</div>
<div class="lg:min-h-min sm:min-h-[220px] md:min-h-[180px] col-span-2 sm:col-span-1 lg:col-span-6 text-black dark:text-white rounded-xl examples-container relative items-center justify-center border border-gray-200 dark:border-transparent hover:border-transparent">
<div class="gradient-border gradient-border-examples gradient-border-rect"></div>
<div class="examples-gradient-right absolute right-0 inset-y-0 w-[20%] bg-gradient-to-l to-transparent from-blue-400 rounded-xl z-1 transition-opacity duration-300"></div>
<a href="https://nuxt.com/docs/examples" target="_blank" class="py-6 px-5 rounded-xl flex items-center justify-center gap-x-4 bg-white dark:bg-gray-900 sm:min-h-[220px] md:min-h-[180px] lg:min-h-min">
<img src="/icons/examples-color-light.svg" alt="examples icon" class="examples-image-color-light">
<img src="/icons/examples-color.svg" alt="examples icon" class="examples-image-color-dark">
<img src="/icons/examples-light.svg" alt="examples icon" class="examples-image-light">
<img src="/icons/examples.svg" alt="examples icon" class="examples-image-dark">
<div class="flex flex-col space-y text-black dark:text-white">
<h3 class="font-semibold text-xl">
Examples
</h3>
<p class="text-gray-700 dark:text-gray-300">
Explore different way of using Nuxt features and get inspired with our list of examples.
</p>
</div>
</a>
</div>
</div>
</div>
<footer class="relative border-t bg-white dark:bg-black border-gray-200 dark:border-gray-900 w-full h-[70px] flex items-center">
<div class="absolute inset-x-0 flex items-center justify-center -top-3">
<a href="https://nuxt.com" target="_blank">
<svg width="70" height="20" viewBox="0 0 70 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="34.6528" cy="10.4209" rx="34.5" ry="9.5" fill="white" class="dark:hidden" />
<ellipse cx="34.6528" cy="10.4209" rx="34.5" ry="9.5" fill="black" class="hidden dark:block" />
<path d="M36.0605 15.9209H42.6256C42.8341 15.9209 43.0389 15.8655 43.2195 15.7602C43.4001 15.6548 43.55 15.5033 43.6543 15.3209C43.7585 15.1384 43.8133 14.9315 43.8132 14.7208C43.8131 14.5102 43.7581 14.3033 43.6537 14.1209L39.2448 6.40667C39.1406 6.22427 38.9907 6.0728 38.8101 5.96748C38.6296 5.86217 38.4248 5.80672 38.2163 5.80672C38.0078 5.80672 37.803 5.86217 37.6225 5.96748C37.4419 6.0728 37.292 6.22427 37.1878 6.40667L36.0605 8.38048L33.8563 4.52076C33.752 4.33837 33.602 4.18692 33.4214 4.08163C33.2409 3.97633 33.036 3.9209 32.8275 3.9209C32.619 3.9209 32.4141 3.97633 32.2335 4.08163C32.053 4.18692 31.903 4.33837 31.7987 4.52076L26.3123 14.1209C26.2079 14.3033 26.1529 14.5102 26.1528 14.7208C26.1527 14.9315 26.2076 15.1384 26.3118 15.3209C26.416 15.5033 26.5659 15.6548 26.7465 15.7602C26.9271 15.8655 27.1319 15.9209 27.3405 15.9209H31.4615C33.0943 15.9209 34.2984 15.1964 35.127 13.7829L37.1385 10.2638L38.216 8.38048L41.4496 14.0376H37.1385L36.0605 15.9209ZM31.3943 14.0356L28.5184 14.035L32.8294 6.49263L34.9805 10.2638L33.5402 12.7844C32.99 13.7015 32.3649 14.0356 31.3943 14.0356Z" fill="#00DC82" />
</svg>
</a>
</div>
<div class="mx-auto sm:px-6 lg:px-8 px-4 w-full">
<div class="flex flex-col items-center gap-3 sm:flex-row sm:justify-between">
<div class="flex flex-col-reverse items-center gap-3 sm:flex-row">
<span class="text-sm text-gray-700 dark:text-gray-300">© 2016-{{ new Date().getFullYear() }} Nuxt - MIT
License</span>
</div>
<ul class="flex items-center justify-end gap-3">
<li>
<a
href="https://chat.nuxt.dev"
target="_blank"
class="focus-visible:ring-2 text-gray-700 hover:text-black dark:text-gray-300 dark:hover:text-white"
>
<span class="sr-only">Nuxt Discord Server</span>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.3705 1.07322C13.3663 1.06497 13.3594 1.05851 13.351 1.05499C12.3785 0.599487 11.3522 0.274675 10.2978 0.0886873C10.2882 0.0868693 10.2783 0.0881809 10.2695 0.0924354C10.2607 0.0966899 10.2534 0.103671 10.2487 0.112385C10.109 0.371315 9.98212 0.637279 9.86863 0.909263C8.73205 0.733138 7.57595 0.733138 6.43938 0.909263C6.32514 0.636589 6.19624 0.370559 6.05328 0.112385C6.04838 0.10386 6.04107 0.0970401 6.03232 0.0928132C6.02356 0.0885863 6.01377 0.0871486 6.0042 0.0886873C4.9497 0.274285 3.92333 0.599121 2.95092 1.05502C2.9426 1.05862 2.93558 1.06477 2.93082 1.07262C0.986197 4.03716 0.453491 6.92881 0.714819 9.78465C0.715554 9.79165 0.71766 9.79843 0.721013 9.80458C0.724365 9.81073 0.728896 9.81613 0.734334 9.82046C1.86667 10.6763 3.1332 11.3296 4.47988 11.7525C4.48937 11.7554 4.49949 11.7552 4.5089 11.7521C4.51831 11.7489 4.52655 11.7429 4.53251 11.7349C4.82175 11.3331 5.07803 10.9077 5.29876 10.4629C5.3018 10.4568 5.30353 10.4501 5.30384 10.4433C5.30416 10.4365 5.30305 10.4296 5.3006 10.4233C5.29814 10.4169 5.29439 10.4111 5.2896 10.4064C5.2848 10.4016 5.27906 10.3979 5.27277 10.3955C4.86862 10.2377 4.47736 10.0474 4.10266 9.82645C4.09586 9.82236 4.09014 9.81663 4.08602 9.80976C4.0819 9.80288 4.0795 9.79508 4.07903 9.78703C4.07856 9.77899 4.08004 9.77095 4.08334 9.76362C4.08664 9.7563 4.09166 9.74992 4.09794 9.74504C4.17657 9.68491 4.25524 9.62236 4.33032 9.55918C4.33699 9.55358 4.34506 9.54998 4.35362 9.5488C4.36218 9.54762 4.3709 9.54891 4.37879 9.55252C6.83362 10.6962 9.4913 10.6962 11.9171 9.55252C11.925 9.54868 11.9338 9.54721 11.9425 9.54829C11.9512 9.54936 11.9594 9.55293 11.9662 9.55858C12.0413 9.62176 12.1199 9.68491 12.1991 9.74504C12.2054 9.74987 12.2105 9.75621 12.2138 9.7635C12.2172 9.7708 12.2187 9.77882 12.2183 9.78687C12.2179 9.79492 12.2156 9.80274 12.2115 9.80964C12.2074 9.81654 12.2018 9.82232 12.195 9.82645C11.8211 10.0492 11.4295 10.2394 11.0243 10.3949C11.018 10.3974 11.0123 10.4012 11.0075 10.406C11.0028 10.4109 10.9991 10.4167 10.9967 10.4231C10.9943 10.4295 10.9932 10.4364 10.9936 10.4433C10.9939 10.4501 10.9957 10.4568 10.9988 10.4629C11.2232 10.9052 11.4791 11.3301 11.7645 11.7342C11.7703 11.7425 11.7785 11.7487 11.7879 11.7519C11.7974 11.7552 11.8076 11.7554 11.8171 11.7524C13.1662 11.331 14.4349 10.6776 15.5687 9.82046C15.5742 9.81635 15.5788 9.81108 15.5822 9.80501C15.5855 9.79893 15.5876 9.7922 15.5882 9.78525C15.9011 6.4836 15.0644 3.61565 13.3705 1.07322ZM5.66537 8.04574C4.92629 8.04574 4.31731 7.35337 4.31731 6.50305C4.31731 5.65274 4.91448 4.96032 5.66537 4.96032C6.42213 4.96032 7.02522 5.65875 7.01341 6.503C7.01341 7.35337 6.41622 8.04574 5.66537 8.04574ZM10.6496 8.04574C9.91051 8.04574 9.30153 7.35337 9.30153 6.50305C9.30153 5.65274 9.8987 4.96032 10.6496 4.96032C11.4064 4.96032 12.0094 5.65875 11.9976 6.503C11.9976 7.35337 11.4064 8.04574 10.6496 8.04574Z" fill="currentColor" />
</svg>
</a>
</li>
<li>
<a
href="https://twitter.nuxt.dev"
target="_blank"
class="focus-visible:ring-2 text-gray-700 hover:text-black dark:text-gray-300 dark:hover:text-white"
>
<span class="sr-only">Nuxt Twitter</span>
<svg width="18" height="14" viewBox="0 0 18 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.486 1.75441C16.8596 2.02615 16.1972 2.20579 15.5193 2.28774C16.2345 1.86051 16.7704 1.18839 17.0277 0.396073C16.3556 0.796126 15.62 1.07799 14.8527 1.22941C14.3398 0.673216 13.6568 0.302987 12.9108 0.176783C12.1649 0.0505786 11.3981 0.175539 10.7308 0.532064C10.0635 0.88859 9.53345 1.45652 9.2237 2.14677C8.91396 2.83702 8.84208 3.61056 9.01934 4.34607C7.66053 4.27734 6.33137 3.92353 5.11822 3.30762C3.90506 2.69171 2.83504 1.82748 1.97767 0.771073C1.67695 1.29621 1.51894 1.89093 1.51934 2.49607C1.51827 3.05806 1.65618 3.61159 1.9208 4.10738C2.18541 4.60317 2.56852 5.02583 3.036 5.33774C2.49265 5.32296 1.96091 5.17716 1.486 4.91274V4.95441C1.49008 5.74182 1.766 6.50365 2.2671 7.11104C2.7682 7.71844 3.46372 8.13411 4.236 8.28774C3.93872 8.37821 3.63007 8.42591 3.31934 8.42941C3.10424 8.42689 2.88969 8.40739 2.67767 8.37107C2.89759 9.04842 3.32319 9.64036 3.89523 10.0645C4.46728 10.4887 5.15732 10.724 5.86934 10.7377C4.66701 11.6838 3.18257 12.2001 1.65267 12.2044C1.37412 12.2053 1.09578 12.1886 0.819336 12.1544C2.38136 13.163 4.20168 13.6983 6.061 13.6961C7.34408 13.7094 8.61695 13.4669 9.80527 12.9828C10.9936 12.4987 12.0735 11.7826 12.982 10.8765C13.8905 9.97033 14.6093 8.89223 15.0965 7.70516C15.5836 6.51809 15.8294 5.24585 15.8193 3.96274C15.8193 3.82107 15.8193 3.67107 15.8193 3.52107C16.4732 3.03342 17.0372 2.43559 17.486 1.75441Z" fill="currentColor" />
</svg>
</a>
</li>
<li>
<a
href="https://github.nuxt.dev"
target="_blank"
class="focus-visible:ring-2 text-gray-700 hover:text-black dark:text-gray-300 dark:hover:text-white"
>
<span class="sr-only">Nuxt GitHub Repository</span>
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.15269 0.792969C7.17392 0.793051 5.25974 1.49723 3.75266 2.77951C2.24558 4.06179 1.24394 5.83849 0.92697 7.7917C0.609997 9.74492 0.998373 11.7472 2.02261 13.4403C3.04684 15.1333 4.6401 16.4067 6.51729 17.0325C6.93396 17.1055 7.09021 16.8555 7.09021 16.6367C7.09021 16.4388 7.07978 15.7825 7.07978 15.0846C4.98603 15.47 4.44436 14.5742 4.27769 14.1055C4.09276 13.6496 3.79959 13.2456 3.42353 12.9284C3.13186 12.7721 2.71519 12.3867 3.4131 12.3763C3.67959 12.4052 3.93518 12.498 4.15822 12.6467C4.38125 12.7953 4.56516 12.9956 4.69436 13.2305C4.80833 13.4352 4.96159 13.6155 5.14535 13.7609C5.32911 13.9063 5.53975 14.014 5.76522 14.0779C5.99068 14.1418 6.22653 14.1605 6.45926 14.1331C6.69198 14.1056 6.917 14.0325 7.12143 13.918C7.1575 13.4943 7.34631 13.0982 7.65269 12.8034C5.79853 12.5951 3.86103 11.8763 3.86103 8.68883C3.84931 7.86062 4.15493 7.05931 4.71519 6.44924C4.46043 5.72943 4.49024 4.93948 4.79853 4.24091C4.79853 4.24091 5.49642 4.02215 7.09019 5.09508C8.45376 4.72005 9.89328 4.72005 11.2569 5.09508C12.8506 4.01174 13.5485 4.24091 13.5485 4.24091C13.8569 4.93947 13.8867 5.72943 13.6319 6.44924C14.1938 7.05826 14.4997 7.86027 14.486 8.68883C14.486 11.8867 12.5381 12.5951 10.6839 12.8034C10.8828 13.005 11.036 13.247 11.133 13.513C11.2301 13.779 11.2688 14.0628 11.2464 14.3451C11.2464 15.4597 11.236 16.3555 11.236 16.6367C11.236 16.8555 11.3923 17.1159 11.8089 17.0326C13.6828 16.4016 15.2715 15.1253 16.2914 13.4313C17.3112 11.7374 17.6959 9.73616 17.3768 7.78483C17.0576 5.83351 16.0553 4.05911 14.5489 2.77839C13.0425 1.49768 11.1299 0.793998 9.15269 0.792969Z" fill="currentColor" /> </svg>
</svg>
</a>
</li>
</ul>
</div>
</div>
</footer>
</body>
</html>

View File

@ -0,0 +1,6 @@
{
"title": "Welcome to Nuxt!",
"readDocs": "We highly recommend you take a look at the Nuxt documentation, whether you are new or have previous experience with the framework.",
"followTwitter": "Follow the Nuxt Twitter account to get latest news about releases, new modules, tutorials and tips.",
"starGitHub": "Nuxt is open source and the code is available on GitHub, feel free to star it, participate in discussions or dive into the source."
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,31 @@
import fsp from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
import { beforeAll, describe, it, expect } from 'vitest'
import { execaCommand } from 'execa'
import { format } from 'prettier'
const distDir = fileURLToPath(new URL('../dist/templates', import.meta.url))
describe('template', () => {
beforeAll(async () => {
await execaCommand('pnpm build', {
cwd: fileURLToPath(new URL('..', import.meta.url))
})
})
function formatCss (css: string) {
return format(css, {
parser: 'css'
})
}
it.each(['error-404.vue', 'error-500.vue', 'error-dev.vue', 'loading.vue', 'welcome.vue'])('correctly outputs style blocks for %s', async (file) => {
const contents = await fsp.readFile(`${distDir}/${file}`, 'utf-8')
const scopedStyle = contents.match(/<style scoped>([\s\S]*)<\/style>/)
const globalStyle = contents.match(/style: \[[\s\S]*children: `([\s\S]*)`/)
expect(await formatCss(scopedStyle?.[1] || '')).toMatchSnapshot()
expect(await formatCss(globalStyle?.[1] || '')).toMatchSnapshot()
})
})

View File

@ -0,0 +1,86 @@
import { defineConfig, presetUno } from 'unocss'
export default defineConfig({
presets: [
presetUno({
dark: 'media'
})
],
content: {
filesystem: [
'./templates/**/*.html'
]
},
theme: {
colors: {
primary: {
50: '#F2FDF9',
100: '#E6FCF3',
200: '#BFF6E0',
300: '#99F1CD',
400: '#4DE7A8',
DEFAULT: '#00DC82',
600: '#00C675',
700: '#00844E',
800: '#00633B',
900: '#004227'
},
'secondary-surface': '#E5F9FF',
'secondary-lightest': '#B7E1ED',
'secondary-lighter': '#95CDDE',
'secondary-light': '#71A2B0',
secondary: '#497A87',
'secondary-dark': '#255461',
'secondary-darker': '#003543',
'secondary-darkest': '#012A35',
'secondary-black': '#001E26',
tertiary: '#B2CCCC', // cloud
'cloud-surface': '#E6F0F0',
'cloud-lightest': '#D1E2E2',
'cloud-lighter': '#B2CCCC',
'cloud-light': '#92ADAD',
cloud: '#688282',
'cloud-dark': '#566B6B',
'cloud-darker': '#334040',
'cloud-darkest': '#273131',
'cloud-black': '#1A2121',
green: {
// 50: "#eefdf2",
50: '#d0fcde',
100: '#b0fccb',
200: '#8cfab7',
300: '#64f4a3',
400: '#37e990',
500: '#00d77d',
600: '#00bb6a',
700: '#009956',
800: '#047342',
900: '#134d2e'
// 950: "#132a1c",
},
gray: {
50: '#f5f5f5',
100: '#eeeeee',
200: '#e0e0e0',
300: '#bdbdbd',
400: '#9e9e9e',
500: '#757575',
600: '#616161',
700: '#424242',
800: '#212121',
900: '#18181B'
},
sky: {
surface: '#E5F9FF',
lightest: '#B7E1ED',
lighter: '#95CDDE',
light: '#71A2B0',
DEFAULT: '#497A87',
dark: '#255461',
darker: '#003543',
darkest: '#012A35',
black: '#001E26'
}
}
}
})

View File

@ -0,0 +1,36 @@
import { resolve } from 'path'
import { readdirSync } from 'fs'
import { defineConfig } from 'vite'
import UnoCSS from 'unocss/vite'
import { DevRenderingPlugin } from './lib/dev'
import { RenderPlugin } from './lib/render'
const r = (...path: string[]) => resolve(__dirname, ...path)
export default defineConfig({
build: {
rollupOptions: {
input: {
...Object.fromEntries(
readdirSync(r('templates')).filter(dir => dir !== 'messages.json').map(dir => [
dir,
r('templates', dir, 'index.html')
])
),
index: r('index.html')
}
}
},
plugins: [
UnoCSS(),
DevRenderingPlugin(),
RenderPlugin()
],
server: {
fs: {
allow: ['./templates', __dirname]
}
}
})