diff --git a/packages/ui-templates/CHANGELOG.md b/packages/ui-templates/CHANGELOG.md new file mode 100644 index 0000000000..ef609a17a9 --- /dev/null +++ b/packages/ui-templates/CHANGELOG.md @@ -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 `` ([01e1920](https://github.com/nuxt/ui/commit/01e1920da25da9a4aadf386cfc715ab1ef2c9a43)) +- **templates:** don't use `v-html` on `` ([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)) diff --git a/packages/ui-templates/README.md b/packages/ui-templates/README.md new file mode 100644 index 0000000000..0eb922e19c --- /dev/null +++ b/packages/ui-templates/README.md @@ -0,0 +1,11 @@ +# `@nuxt/ui-templates` + + + +Pre-compiled html templates for internal pages. + +🏀 [Online Playground](https://templates.ui.nuxtjs.org) + +# License + +Creative Commons License
Nuxt UI by Nuxt Project is licensed under a Creative Commons Attribution-NoDerivatives 4.0 International License.
Based on a work at https://github.com/nuxt/ui. diff --git a/packages/ui-templates/index.html b/packages/ui-templates/index.html new file mode 100644 index 0000000000..60710321da --- /dev/null +++ b/packages/ui-templates/index.html @@ -0,0 +1,17 @@ + + + + + + + +
+

Nuxt Templates

+ +
+ + diff --git a/packages/ui-templates/lib/dev.ts b/packages/ui-templates/lib/dev.ts new file mode 100644 index 0000000000..df45e95b57 --- /dev/null +++ b/packages/ui-templates/lib/dev.ts @@ -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 { + 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 } + }) + } + } +} diff --git a/packages/ui-templates/lib/prerender.ts b/packages/ui-templates/lib/prerender.ts new file mode 100644 index 0000000000..8de94df8e8 --- /dev/null +++ b/packages/ui-templates/lib/prerender.ts @@ -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) diff --git a/packages/ui-templates/lib/render.ts b/packages/ui-templates/lib/render.ts new file mode 100644 index 0000000000..fab7307b7e --- /dev/null +++ b/packages/ui-templates/lib/render.ts @@ -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 { + 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('') + + if (html.includes(']*>/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(/]*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 ? `` : '') + } + + // Minify HTML + html = htmlMinifier.minify(html, { collapseWhitespace: true }) + + if (!isCompleteHTML) { + html = html.replace('', '') + html = html.replace('', '') + } + + // 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(/([\s\S]*)<\/body>/)?.[0] + .replace(/(?<=<|<\/)body/g, 'div') + .replace(/messages\./g, '') + .replace(/]*>([\s\S]*?)<\/script>/g, '') + .replace(/]*)>([\s\S]*)<\/a>/g, '\n$3\n') + // 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 ', + '', + '' + ].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) => 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') + } + } +} diff --git a/packages/ui-templates/package.json b/packages/ui-templates/package.json new file mode 100644 index 0000000000..31cb58d20c --- /dev/null +++ b/packages/ui-templates/package.json @@ -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" + } +} diff --git a/packages/ui-templates/public b/packages/ui-templates/public new file mode 120000 index 0000000000..ec2e4be2f8 --- /dev/null +++ b/packages/ui-templates/public @@ -0,0 +1 @@ +../assets \ No newline at end of file diff --git a/packages/ui-templates/styles.ts b/packages/ui-templates/styles.ts new file mode 100644 index 0000000000..7f20ae0835 --- /dev/null +++ b/packages/ui-templates/styles.ts @@ -0,0 +1,2 @@ +import '@unocss/reset/tailwind.css' +import 'uno.css' diff --git a/packages/ui-templates/templates/error-404/index.html b/packages/ui-templates/templates/error-404/index.html new file mode 100644 index 0000000000..6d734081e1 --- /dev/null +++ b/packages/ui-templates/templates/error-404/index.html @@ -0,0 +1,77 @@ + + + + {{ messages.statusCode }} - {{ messages.statusMessage }} | {{ messages.appName }} + + + + + + +
+
+ + diff --git a/packages/ui-templates/templates/error-404/messages.json b/packages/ui-templates/templates/error-404/messages.json new file mode 100644 index 0000000000..262941b2fe --- /dev/null +++ b/packages/ui-templates/templates/error-404/messages.json @@ -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" +} diff --git a/packages/ui-templates/templates/error-500/index.html b/packages/ui-templates/templates/error-500/index.html new file mode 100644 index 0000000000..0ae46738cb --- /dev/null +++ b/packages/ui-templates/templates/error-500/index.html @@ -0,0 +1,22 @@ + + + + {{ messages.statusCode }} - {{ messages.statusMessage }} | {{ messages.appName }} + + + + + + +
+
+

{{ messages.statusCode }}

+

{{ messages.description }}

+
+ + diff --git a/packages/ui-templates/templates/error-500/messages.json b/packages/ui-templates/templates/error-500/messages.json new file mode 100644 index 0000000000..69534ad900 --- /dev/null +++ b/packages/ui-templates/templates/error-500/messages.json @@ -0,0 +1,5 @@ +{ + "statusCode": 500, + "statusMessage": "Server error", + "description": "This page is temporarily unavailable." +} diff --git a/packages/ui-templates/templates/error-dev/index.html b/packages/ui-templates/templates/error-dev/index.html new file mode 100644 index 0000000000..469ac24184 --- /dev/null +++ b/packages/ui-templates/templates/error-dev/index.html @@ -0,0 +1,26 @@ + + + + {{ messages.statusCode }} - {{ messages.statusMessage }} | {{ messages.appName }} + + + + + + +
+

{{ messages.statusCode }}

+

{{ messages.description }}

+
+
{{{ messages.stack }}}
+
+ + diff --git a/packages/ui-templates/templates/error-dev/messages.json b/packages/ui-templates/templates/error-dev/messages.json new file mode 100644 index 0000000000..afd71e0257 --- /dev/null +++ b/packages/ui-templates/templates/error-dev/messages.json @@ -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": "" +} diff --git a/packages/ui-templates/templates/loading/index.html b/packages/ui-templates/templates/loading/index.html new file mode 100644 index 0000000000..bda8016b70 --- /dev/null +++ b/packages/ui-templates/templates/loading/index.html @@ -0,0 +1,188 @@ + + + + {{ messages.loading }} | {{ messages.appName }} + + + + + + +
+ + +
+ + + diff --git a/packages/ui-templates/templates/loading/messages.json b/packages/ui-templates/templates/loading/messages.json new file mode 100644 index 0000000000..53151fbbab --- /dev/null +++ b/packages/ui-templates/templates/loading/messages.json @@ -0,0 +1,3 @@ +{ + "loading": "Loading" +} diff --git a/packages/ui-templates/templates/messages.json b/packages/ui-templates/templates/messages.json new file mode 100644 index 0000000000..364de9016d --- /dev/null +++ b/packages/ui-templates/templates/messages.json @@ -0,0 +1,4 @@ +{ + "appName": "Nuxt", + "version": "" +} diff --git a/packages/ui-templates/templates/spa-loading-icon/index.html b/packages/ui-templates/templates/spa-loading-icon/index.html new file mode 100644 index 0000000000..c698cfc761 --- /dev/null +++ b/packages/ui-templates/templates/spa-loading-icon/index.html @@ -0,0 +1,29 @@ + + + + diff --git a/packages/ui-templates/templates/spa-loading-icon/messages.json b/packages/ui-templates/templates/spa-loading-icon/messages.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/packages/ui-templates/templates/spa-loading-icon/messages.json @@ -0,0 +1 @@ +{} diff --git a/packages/ui-templates/templates/welcome/index.html b/packages/ui-templates/templates/welcome/index.html new file mode 100644 index 0000000000..cce2e6ba6f --- /dev/null +++ b/packages/ui-templates/templates/welcome/index.html @@ -0,0 +1,366 @@ + + + + {{ messages.title }} + + + + + + + + + + + diff --git a/packages/ui-templates/templates/welcome/messages.json b/packages/ui-templates/templates/welcome/messages.json new file mode 100644 index 0000000000..036c4057aa --- /dev/null +++ b/packages/ui-templates/templates/welcome/messages.json @@ -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." +} diff --git a/packages/ui-templates/test/__snapshots__/snapshots.spec.ts.snap b/packages/ui-templates/test/__snapshots__/snapshots.spec.ts.snap new file mode 100644 index 0000000000..bf980b4a26 --- /dev/null +++ b/packages/ui-templates/test/__snapshots__/snapshots.spec.ts.snap @@ -0,0 +1,1919 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`template > correctly outputs style blocks for error-404.vue 1`] = ` +".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; +} +.fixed { + position: fixed; +} +.left-0 { + left: 0; +} +.right-0 { + right: 0; +} +.z-10 { + z-index: 10; +} +.z-20 { + z-index: 20; +} +.grid { + display: grid; +} +.mb-16 { + margin-bottom: 4rem; +} +.mb-8 { + margin-bottom: 2rem; +} +.max-w-520px { + max-width: 520px; +} +.min-h-screen { + min-height: 100vh; +} +.w-full { + width: 100%; +} +.flex { + display: flex; +} +.cursor-pointer { + cursor: pointer; +} +.place-content-center { + place-content: center; +} +.items-center { + align-items: center; +} +.justify-center { + justify-content: center; +} +.overflow-hidden { + overflow: hidden; +} +.bg-white { + --un-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--un-bg-opacity)); +} +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} +.px-8 { + padding-left: 2rem; + padding-right: 2rem; +} +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} +.text-center { + text-align: center; +} +.text-8xl { + font-size: 6rem; + line-height: 1; +} +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} +.text-black { + --un-text-opacity: 1; + color: rgb(0 0 0 / var(--un-text-opacity)); +} +.font-light { + font-weight: 300; +} +.font-medium { + font-weight: 500; +} +.leading-tight { + line-height: 1.25; +} +.font-sans { + font-family: + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + Segoe UI, + Roboto, + Helvetica Neue, + Arial, + Noto Sans, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + Segoe UI Symbol, + "Noto Color Emoji"; +} +.antialiased { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +@media (prefers-color-scheme: dark) { + .dark\\:bg-black { + --un-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--un-bg-opacity)); + } + .dark\\:text-white { + --un-text-opacity: 1; + color: rgb(255 255 255 / var(--un-text-opacity)); + } +} +@media (min-width: 640px) { + .sm\\:px-0 { + padding-left: 0; + padding-right: 0; + } + .sm\\:px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; + } + .sm\\:py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + } + .sm\\:text-4xl { + font-size: 2.25rem; + line-height: 2.5rem; + } + .sm\\:text-xl { + font-size: 1.25rem; + line-height: 1.75rem; + } +} +" +`; + +exports[`template > correctly outputs style blocks for error-404.vue 2`] = ` +"*, +:before, +:after { + box-sizing: border-box; + border-width: 0; + border-style: solid; + border-color: var(--un-default-border-color, #e5e7eb); +} +:before, +:after { + --un-content: ""; +} +html { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + -moz-tab-size: 4; + tab-size: 4; + font-family: + ui-sans-serif, + system-ui, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + Segoe UI Symbol, + "Noto Color Emoji"; + font-feature-settings: normal; + font-variation-settings: normal; + -webkit-tap-highlight-color: transparent; +} +body { + margin: 0; + line-height: inherit; +} +h1 { + font-size: inherit; + font-weight: inherit; +} +a { + color: inherit; + text-decoration: inherit; +} +h1, +p { + margin: 0; +} +*, +:before, +:after { + --un-rotate: 0; + --un-rotate-x: 0; + --un-rotate-y: 0; + --un-rotate-z: 0; + --un-scale-x: 1; + --un-scale-y: 1; + --un-scale-z: 1; + --un-skew-x: 0; + --un-skew-y: 0; + --un-translate-x: 0; + --un-translate-y: 0; + --un-translate-z: 0; + --un-pan-x: ; + --un-pan-y: ; + --un-pinch-zoom: ; + --un-scroll-snap-strictness: proximity; + --un-ordinal: ; + --un-slashed-zero: ; + --un-numeric-figure: ; + --un-numeric-spacing: ; + --un-numeric-fraction: ; + --un-border-spacing-x: 0; + --un-border-spacing-y: 0; + --un-ring-offset-shadow: 0 0 rgb(0 0 0 / 0); + --un-ring-shadow: 0 0 rgb(0 0 0 / 0); + --un-shadow-inset: ; + --un-shadow: 0 0 rgb(0 0 0 / 0); + --un-ring-inset: ; + --un-ring-offset-width: 0px; + --un-ring-offset-color: #fff; + --un-ring-width: 0px; + --un-ring-color: rgb(147 197 253 / 0.5); + --un-blur: ; + --un-brightness: ; + --un-contrast: ; + --un-drop-shadow: ; + --un-grayscale: ; + --un-hue-rotate: ; + --un-invert: ; + --un-saturate: ; + --un-sepia: ; + --un-backdrop-blur: ; + --un-backdrop-brightness: ; + --un-backdrop-contrast: ; + --un-backdrop-grayscale: ; + --un-backdrop-hue-rotate: ; + --un-backdrop-invert: ; + --un-backdrop-opacity: ; + --un-backdrop-saturate: ; + --un-backdrop-sepia: ; +} +" +`; + +exports[`template > correctly outputs style blocks for error-500.vue 1`] = ` +".spotlight { + background: linear-gradient(45deg, #00dc82 0%, #36e4da 50%, #0047e1 100%); + filter: blur(20vh); +} +.fixed { + position: fixed; +} +.-bottom-1\\/2 { + bottom: -50%; +} +.left-0 { + left: 0; +} +.right-0 { + right: 0; +} +.grid { + display: grid; +} +.mb-16 { + margin-bottom: 4rem; +} +.mb-8 { + margin-bottom: 2rem; +} +.h-1\\/2 { + height: 50%; +} +.max-w-520px { + max-width: 520px; +} +.min-h-screen { + min-height: 100vh; +} +.place-content-center { + place-content: center; +} +.overflow-hidden { + overflow: hidden; +} +.bg-white { + --un-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--un-bg-opacity)); +} +.px-8 { + padding-left: 2rem; + padding-right: 2rem; +} +.text-center { + text-align: center; +} +.text-8xl { + font-size: 6rem; + line-height: 1; +} +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} +.text-black { + --un-text-opacity: 1; + color: rgb(0 0 0 / var(--un-text-opacity)); +} +.font-light { + font-weight: 300; +} +.font-medium { + font-weight: 500; +} +.leading-tight { + line-height: 1.25; +} +.font-sans { + font-family: + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + Segoe UI, + Roboto, + Helvetica Neue, + Arial, + Noto Sans, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + Segoe UI Symbol, + "Noto Color Emoji"; +} +.antialiased { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +@media (prefers-color-scheme: dark) { + .dark\\:bg-black { + --un-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--un-bg-opacity)); + } + .dark\\:text-white { + --un-text-opacity: 1; + color: rgb(255 255 255 / var(--un-text-opacity)); + } +} +@media (min-width: 640px) { + .sm\\:px-0 { + padding-left: 0; + padding-right: 0; + } + .sm\\:text-4xl { + font-size: 2.25rem; + line-height: 2.5rem; + } +} +" +`; + +exports[`template > correctly outputs style blocks for error-500.vue 2`] = ` +"*, +:before, +:after { + box-sizing: border-box; + border-width: 0; + border-style: solid; + border-color: var(--un-default-border-color, #e5e7eb); +} +:before, +:after { + --un-content: ""; +} +html { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + -moz-tab-size: 4; + tab-size: 4; + font-family: + ui-sans-serif, + system-ui, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + Segoe UI Symbol, + "Noto Color Emoji"; + font-feature-settings: normal; + font-variation-settings: normal; + -webkit-tap-highlight-color: transparent; +} +body { + margin: 0; + line-height: inherit; +} +h1 { + font-size: inherit; + font-weight: inherit; +} +h1, +p { + margin: 0; +} +*, +:before, +:after { + --un-rotate: 0; + --un-rotate-x: 0; + --un-rotate-y: 0; + --un-rotate-z: 0; + --un-scale-x: 1; + --un-scale-y: 1; + --un-scale-z: 1; + --un-skew-x: 0; + --un-skew-y: 0; + --un-translate-x: 0; + --un-translate-y: 0; + --un-translate-z: 0; + --un-pan-x: ; + --un-pan-y: ; + --un-pinch-zoom: ; + --un-scroll-snap-strictness: proximity; + --un-ordinal: ; + --un-slashed-zero: ; + --un-numeric-figure: ; + --un-numeric-spacing: ; + --un-numeric-fraction: ; + --un-border-spacing-x: 0; + --un-border-spacing-y: 0; + --un-ring-offset-shadow: 0 0 rgb(0 0 0 / 0); + --un-ring-shadow: 0 0 rgb(0 0 0 / 0); + --un-shadow-inset: ; + --un-shadow: 0 0 rgb(0 0 0 / 0); + --un-ring-inset: ; + --un-ring-offset-width: 0px; + --un-ring-offset-color: #fff; + --un-ring-width: 0px; + --un-ring-color: rgb(147 197 253 / 0.5); + --un-blur: ; + --un-brightness: ; + --un-contrast: ; + --un-drop-shadow: ; + --un-grayscale: ; + --un-hue-rotate: ; + --un-invert: ; + --un-saturate: ; + --un-sepia: ; + --un-backdrop-blur: ; + --un-backdrop-brightness: ; + --un-backdrop-contrast: ; + --un-backdrop-grayscale: ; + --un-backdrop-hue-rotate: ; + --un-backdrop-invert: ; + --un-backdrop-opacity: ; + --un-backdrop-saturate: ; + --un-backdrop-sepia: ; +} +" +`; + +exports[`template > correctly outputs style blocks for error-dev.vue 1`] = ` +".spotlight { + background: linear-gradient(45deg, #00dc82 0%, #36e4da 50%, #0047e1 100%); + opacity: 0.8; + filter: blur(30vh); + height: 60vh; + bottom: -40vh; +} +.fixed { + position: fixed; +} +.left-0 { + left: 0; +} +.right-0 { + right: 0; +} +.z-10 { + z-index: 10; +} +.mb-6 { + margin-bottom: 1.5rem; +} +.mb-8 { + margin-bottom: 2rem; +} +.h-auto { + height: auto; +} +.min-h-screen { + min-height: 100vh; +} +.flex { + display: flex; +} +.flex-1 { + flex: 1 1 0%; +} +.flex-col { + flex-direction: column; +} +.overflow-y-auto { + overflow-y: auto; +} +.rounded-t-md { + border-top-left-radius: 0.375rem; + border-top-right-radius: 0.375rem; +} +.bg-black\\/5 { + background-color: #0000000d; +} +.bg-white { + --un-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--un-bg-opacity)); +} +.p-8 { + padding: 2rem; +} +.px-10 { + padding-left: 2.5rem; + padding-right: 2.5rem; +} +.pt-14 { + padding-top: 3.5rem; +} +.text-6xl { + font-size: 3.75rem; + line-height: 1; +} +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} +.text-black { + --un-text-opacity: 1; + color: rgb(0 0 0 / var(--un-text-opacity)); +} +.font-light { + font-weight: 300; +} +.font-medium { + font-weight: 500; +} +.leading-tight { + line-height: 1.25; +} +.font-sans { + font-family: + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + Segoe UI, + Roboto, + Helvetica Neue, + Arial, + Noto Sans, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + Segoe UI Symbol, + "Noto Color Emoji"; +} +.antialiased { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +@media (prefers-color-scheme: dark) { + .dark\\:bg-black { + --un-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--un-bg-opacity)); + } + .dark\\:bg-white\\/10 { + background-color: #ffffff1a; + } + .dark\\:text-white { + --un-text-opacity: 1; + color: rgb(255 255 255 / var(--un-text-opacity)); + } +} +@media (min-width: 640px) { + .sm\\:text-2xl { + font-size: 1.5rem; + line-height: 2rem; + } + .sm\\:text-8xl { + font-size: 6rem; + line-height: 1; + } +} +" +`; + +exports[`template > correctly outputs style blocks for error-dev.vue 2`] = ` +"*, +:before, +:after { + box-sizing: border-box; + border-width: 0; + border-style: solid; + border-color: var(--un-default-border-color, #e5e7eb); +} +:before, +:after { + --un-content: ""; +} +html { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + -moz-tab-size: 4; + tab-size: 4; + font-family: + ui-sans-serif, + system-ui, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + Segoe UI Symbol, + "Noto Color Emoji"; + font-feature-settings: normal; + font-variation-settings: normal; + -webkit-tap-highlight-color: transparent; +} +body { + margin: 0; + line-height: inherit; +} +h1 { + font-size: inherit; + font-weight: inherit; +} +pre { + font-family: + ui-monospace, + SFMono-Regular, + Menlo, + Monaco, + Consolas, + Liberation Mono, + Courier New, + monospace; + font-feature-settings: normal; + font-variation-settings: normal; + font-size: 1em; +} +h1, +p, +pre { + margin: 0; +} +*, +:before, +:after { + --un-rotate: 0; + --un-rotate-x: 0; + --un-rotate-y: 0; + --un-rotate-z: 0; + --un-scale-x: 1; + --un-scale-y: 1; + --un-scale-z: 1; + --un-skew-x: 0; + --un-skew-y: 0; + --un-translate-x: 0; + --un-translate-y: 0; + --un-translate-z: 0; + --un-pan-x: ; + --un-pan-y: ; + --un-pinch-zoom: ; + --un-scroll-snap-strictness: proximity; + --un-ordinal: ; + --un-slashed-zero: ; + --un-numeric-figure: ; + --un-numeric-spacing: ; + --un-numeric-fraction: ; + --un-border-spacing-x: 0; + --un-border-spacing-y: 0; + --un-ring-offset-shadow: 0 0 rgb(0 0 0 / 0); + --un-ring-shadow: 0 0 rgb(0 0 0 / 0); + --un-shadow-inset: ; + --un-shadow: 0 0 rgb(0 0 0 / 0); + --un-ring-inset: ; + --un-ring-offset-width: 0px; + --un-ring-offset-color: #fff; + --un-ring-width: 0px; + --un-ring-color: rgb(147 197 253 / 0.5); + --un-blur: ; + --un-brightness: ; + --un-contrast: ; + --un-drop-shadow: ; + --un-grayscale: ; + --un-hue-rotate: ; + --un-invert: ; + --un-saturate: ; + --un-sepia: ; + --un-backdrop-blur: ; + --un-backdrop-brightness: ; + --un-backdrop-contrast: ; + --un-backdrop-grayscale: ; + --un-backdrop-hue-rotate: ; + --un-backdrop-invert: ; + --un-backdrop-opacity: ; + --un-backdrop-saturate: ; + --un-backdrop-sepia: ; +} +" +`; + +exports[`template > correctly outputs style blocks for loading.vue 1`] = ` +".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; + } +} +@media (prefers-color-scheme: dark) { + html, + body { + color: white; + color-scheme: dark; + } + .nuxt-loader-bar { + opacity: 0.5; + } +} +*, +:before, +:after { + box-sizing: border-box; + border-width: 0; + border-style: solid; + border-color: var(--un-default-border-color, #e5e7eb); +} +:before, +:after { + --un-content: ""; +} +html { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + -moz-tab-size: 4; + tab-size: 4; + font-family: + ui-sans-serif, + system-ui, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + Segoe UI Symbol, + "Noto Color Emoji"; + font-feature-settings: normal; + font-variation-settings: normal; + -webkit-tap-highlight-color: transparent; +} +body { + margin: 0; + line-height: inherit; +} +a { + color: inherit; + text-decoration: inherit; +} +button { + font-family: inherit; + font-feature-settings: inherit; + font-variation-settings: inherit; + font-size: 100%; + font-weight: inherit; + line-height: inherit; + color: inherit; + margin: 0; + padding: 0; +} +button { + text-transform: none; +} +button { + -webkit-appearance: button; + background-color: transparent; + background-image: none; +} +button { + cursor: pointer; +} +svg { + display: block; + vertical-align: middle; +} +*, +:before, +:after { + --un-rotate: 0; + --un-rotate-x: 0; + --un-rotate-y: 0; + --un-rotate-z: 0; + --un-scale-x: 1; + --un-scale-y: 1; + --un-scale-z: 1; + --un-skew-x: 0; + --un-skew-y: 0; + --un-translate-x: 0; + --un-translate-y: 0; + --un-translate-z: 0; + --un-pan-x: ; + --un-pan-y: ; + --un-pinch-zoom: ; + --un-scroll-snap-strictness: proximity; + --un-ordinal: ; + --un-slashed-zero: ; + --un-numeric-figure: ; + --un-numeric-spacing: ; + --un-numeric-fraction: ; + --un-border-spacing-x: 0; + --un-border-spacing-y: 0; + --un-ring-offset-shadow: 0 0 rgb(0 0 0 / 0); + --un-ring-shadow: 0 0 rgb(0 0 0 / 0); + --un-shadow-inset: ; + --un-shadow: 0 0 rgb(0 0 0 / 0); + --un-ring-inset: ; + --un-ring-offset-width: 0px; + --un-ring-offset-color: #fff; + --un-ring-width: 0px; + --un-ring-color: rgb(147 197 253 / 0.5); + --un-blur: ; + --un-brightness: ; + --un-contrast: ; + --un-drop-shadow: ; + --un-grayscale: ; + --un-hue-rotate: ; + --un-invert: ; + --un-saturate: ; + --un-sepia: ; + --un-backdrop-blur: ; + --un-backdrop-brightness: ; + --un-backdrop-contrast: ; + --un-backdrop-grayscale: ; + --un-backdrop-hue-rotate: ; + --un-backdrop-invert: ; + --un-backdrop-opacity: ; + --un-backdrop-saturate: ; + --un-backdrop-sepia: ; +} +.absolute { + position: absolute; +} +.relative { + position: relative; +} +.top-0 { + top: 0; +} +.z-20 { + z-index: 20; +} +.h-\\[200px\\] { + height: 200px; +} +.min-h-screen { + min-height: 100vh; +} +.w-\\[200px\\] { + width: 200px; +} +.flex { + display: flex; +} +.flex-col { + flex-direction: column; +} +.items-center { + align-items: center; +} +.justify-center { + justify-content: center; +} +.overflow-hidden { + overflow: hidden; +} +.rounded-full { + border-radius: 9999px; +} +.bg-white { + --un-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--un-bg-opacity)); +} +.text-center { + text-align: center; +} +.transition-opacity { + transition-property: opacity; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 0.15s; +} +@media (prefers-color-scheme: dark) { + .dark\\:bg-black { + --un-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--un-bg-opacity)); + } +} +" +`; + +exports[`template > correctly outputs style blocks for loading.vue 2`] = ` +"#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; + } +} +@media (prefers-color-scheme: dark) { + html, + body { + color: white; + color-scheme: dark; + } +} +*, +:before, +:after { + box-sizing: border-box; + border-width: 0; + border-style: solid; + border-color: var(--un-default-border-color, #e5e7eb); +} +:before, +:after { + --un-content: ""; +} +html { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + -moz-tab-size: 4; + tab-size: 4; + font-family: + ui-sans-serif, + system-ui, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + Segoe UI Symbol, + "Noto Color Emoji"; + font-feature-settings: normal; + font-variation-settings: normal; + -webkit-tap-highlight-color: transparent; +} +body { + margin: 0; + line-height: inherit; +} +a { + color: inherit; + text-decoration: inherit; +} +button { + font-family: inherit; + font-feature-settings: inherit; + font-variation-settings: inherit; + font-size: 100%; + font-weight: inherit; + line-height: inherit; + color: inherit; + margin: 0; + padding: 0; +} +button { + text-transform: none; +} +button { + -webkit-appearance: button; + background-color: transparent; + background-image: none; +} +button { + cursor: pointer; +} +svg { + display: block; + vertical-align: middle; +} +*, +:before, +:after { + --un-rotate: 0; + --un-rotate-x: 0; + --un-rotate-y: 0; + --un-rotate-z: 0; + --un-scale-x: 1; + --un-scale-y: 1; + --un-scale-z: 1; + --un-skew-x: 0; + --un-skew-y: 0; + --un-translate-x: 0; + --un-translate-y: 0; + --un-translate-z: 0; + --un-pan-x: ; + --un-pan-y: ; + --un-pinch-zoom: ; + --un-scroll-snap-strictness: proximity; + --un-ordinal: ; + --un-slashed-zero: ; + --un-numeric-figure: ; + --un-numeric-spacing: ; + --un-numeric-fraction: ; + --un-border-spacing-x: 0; + --un-border-spacing-y: 0; + --un-ring-offset-shadow: 0 0 rgb(0 0 0 / 0); + --un-ring-shadow: 0 0 rgb(0 0 0 / 0); + --un-shadow-inset: ; + --un-shadow: 0 0 rgb(0 0 0 / 0); + --un-ring-inset: ; + --un-ring-offset-width: 0px; + --un-ring-offset-color: #fff; + --un-ring-width: 0px; + --un-ring-color: rgb(147 197 253 / 0.5); + --un-blur: ; + --un-brightness: ; + --un-contrast: ; + --un-drop-shadow: ; + --un-grayscale: ; + --un-hue-rotate: ; + --un-invert: ; + --un-saturate: ; + --un-sepia: ; + --un-backdrop-blur: ; + --un-backdrop-brightness: ; + --un-backdrop-contrast: ; + --un-backdrop-grayscale: ; + --un-backdrop-hue-rotate: ; + --un-backdrop-invert: ; + --un-backdrop-opacity: ; + --un-backdrop-saturate: ; + --un-backdrop-sepia: ; +} +" +`; + +exports[`template > correctly outputs style blocks for welcome.vue 1`] = ` +"@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-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 { + 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; +} +.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; +} +@media (prefers-color-scheme: light) { + .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-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-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-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-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-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; + } +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} +.absolute { + position: absolute; +} +.relative { + position: relative; +} +.inset-x-0 { + left: 0; + right: 0; +} +.inset-y-0 { + top: 0; + bottom: 0; +} +.-top-\\[58px\\] { + top: -58px; +} +.-top-3 { + top: -0.75rem; +} +.left-0 { + left: 0; +} +.right-0 { + right: 0; +} +.z-1 { + z-index: 1; +} +.z-10 { + z-index: 10; +} +.order-last { + order: 9999; +} +.grid { + display: grid; +} +.col-span-2 { + grid-column: span 2 / span 2; +} +.row-span-2 { + grid-row: span 2 / span 2; +} +.grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); +} +.mx-auto { + margin-left: auto; + margin-right: auto; +} +.mb-2 { + margin-bottom: 0.5rem; +} +.hidden { + display: none; +} +.h-\\[70px\\] { + height: 70px; +} +.h-32 { + height: 8rem; +} +.max-w-\\[960px\\] { + max-width: 960px; +} +.min-h-screen { + min-height: 100vh; +} +.w-\\[20\\%\\] { + width: 20%; +} +.w-full { + width: 100%; +} +.flex { + display: flex; +} +.flex-1 { + flex: 1 1 0%; +} +.flex-col { + flex-direction: column; +} +.flex-col-reverse { + flex-direction: column-reverse; +} +.place-content-center { + place-content: center; +} +.items-center { + align-items: center; +} +.justify-end { + justify-content: flex-end; +} +.justify-center { + justify-content: center; +} +.gap-3 { + gap: 0.75rem; +} +.gap-6 { + gap: 1.5rem; +} +.gap-x-4 { + column-gap: 1rem; +} +.gap-y-16 { + row-gap: 4rem; +} +.gap-y-2 { + row-gap: 0.5rem; +} +.gap-y-4 { + row-gap: 1rem; +} +.border { + border-width: 1px; +} +.border-t { + border-top-width: 1px; +} +.border-gray-200 { + --un-border-opacity: 1; + border-color: rgb(224 224 224 / var(--un-border-opacity)); +} +.hover\\:border-transparent:hover { + border-color: transparent; +} +.rounded { + border-radius: 0.25rem; +} +.rounded-xl { + border-radius: 0.75rem; +} +.bg-gray-100 { + --un-bg-opacity: 1; + background-color: rgb(238 238 238 / var(--un-bg-opacity)); +} +.bg-white { + --un-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--un-bg-opacity)); +} +.from-blue-400 { + --un-gradient-from-position: 0%; + --un-gradient-from: rgb(96 165 250 / var(--un-from-opacity, 1)) + var(--un-gradient-from-position); + --un-gradient-to-position: 100%; + --un-gradient-to: rgb(96 165 250 / 0) var(--un-gradient-to-position); + --un-gradient-stops: var(--un-gradient-from), var(--un-gradient-to); +} +.from-green-400 { + --un-gradient-from-position: 0%; + --un-gradient-from: rgb(55 233 144 / var(--un-from-opacity, 1)) + var(--un-gradient-from-position); + --un-gradient-to-position: 100%; + --un-gradient-to: rgb(55 233 144 / 0) var(--un-gradient-to-position); + --un-gradient-stops: var(--un-gradient-from), var(--un-gradient-to); +} +.from-yellow-400 { + --un-gradient-from-position: 0%; + --un-gradient-from: rgb(250 204 21 / var(--un-from-opacity, 1)) + var(--un-gradient-from-position); + --un-gradient-to-position: 100%; + --un-gradient-to: rgb(250 204 21 / 0) var(--un-gradient-to-position); + --un-gradient-stops: var(--un-gradient-from), var(--un-gradient-to); +} +.to-transparent { + --un-gradient-to-position: 100%; + --un-gradient-to: transparent var(--un-gradient-to-position); +} +.bg-gradient-to-l { + --un-gradient-shape: to left; + --un-gradient: var(--un-gradient-shape), var(--un-gradient-stops); + background-image: linear-gradient(var(--un-gradient)); +} +.bg-gradient-to-r { + --un-gradient-shape: to right; + --un-gradient: var(--un-gradient-shape), var(--un-gradient-stops); + background-image: linear-gradient(var(--un-gradient)); +} +.p-1 { + padding: 0.25rem; +} +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} +.px-5 { + padding-left: 1.25rem; + padding-right: 1.25rem; +} +.py-14 { + padding-top: 3.5rem; + padding-bottom: 3.5rem; +} +.py-6 { + padding-top: 1.5rem; + padding-bottom: 1.5rem; +} +.pb-6 { + padding-bottom: 1.5rem; +} +.pt-\\[58px\\] { + padding-top: 58px; +} +.text-center { + text-align: center; +} +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; +} +.text-4xl { + font-size: 2.25rem; + line-height: 2.5rem; +} +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} +.text-black { + --un-text-opacity: 1; + color: rgb(0 0 0 / var(--un-text-opacity)); +} +.text-gray-700 { + --un-text-opacity: 1; + color: rgb(66 66 66 / var(--un-text-opacity)); +} +.hover\\:text-black:hover { + --un-text-opacity: 1; + color: rgb(0 0 0 / var(--un-text-opacity)); +} +.font-bold { + font-weight: 700; +} +.font-semibold { + font-weight: 600; +} +.font-mono { + font-family: + ui-monospace, + SFMono-Regular, + Menlo, + Monaco, + Consolas, + Liberation Mono, + Courier New, + monospace; +} +.antialiased { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.focus-visible\\:ring-2:focus-visible { + --un-ring-width: 2px; + --un-ring-offset-shadow: var(--un-ring-inset) 0 0 0 + var(--un-ring-offset-width) var(--un-ring-offset-color); + --un-ring-shadow: var(--un-ring-inset) 0 0 0 + calc(var(--un-ring-width) + var(--un-ring-offset-width)) + var(--un-ring-color); + box-shadow: var(--un-ring-offset-shadow), var(--un-ring-shadow), + var(--un-shadow); +} +.transition-opacity { + transition-property: opacity; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 0.15s; +} +.duration-300 { + transition-duration: 0.3s; +} +@media (prefers-color-scheme: dark) { + .dark\\:block { + display: block; + } + .dark\\:hidden { + display: none; + } + .dark\\:border-gray-900 { + --un-border-opacity: 1; + border-color: rgb(24 24 27 / var(--un-border-opacity)); + } + .dark\\:border-transparent { + border-color: transparent; + } + .dark\\:border-none { + border-style: none; + } + .dark\\:bg-black { + --un-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--un-bg-opacity)); + } + .dark\\:bg-gray-900 { + --un-bg-opacity: 1; + background-color: rgb(24 24 27 / var(--un-bg-opacity)); + } + .dark\\:bg-white\\/10 { + background-color: #ffffff1a; + } + .dark\\:text-gray-300 { + --un-text-opacity: 1; + color: rgb(189 189 189 / var(--un-text-opacity)); + } + .dark\\:text-white, + .dark\\:hover\\:text-white:hover { + --un-text-opacity: 1; + color: rgb(255 255 255 / var(--un-text-opacity)); + } +} +@media (min-width: 640px) { + .sm\\:col-span-1 { + grid-column: span 1 / span 1; + } + .sm\\:h-34 { + height: 8.5rem; + } + .sm\\:min-h-\\[220px\\] { + min-height: 220px; + } + .sm\\:flex-row { + flex-direction: row; + } + .sm\\:justify-between { + justify-content: space-between; + } + .sm\\:px-28 { + padding-left: 7rem; + padding-right: 7rem; + } + .sm\\:px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; + } + .sm\\:text-5xl { + font-size: 3rem; + line-height: 1; + } + .sm\\:text-base { + font-size: 1rem; + line-height: 1.5rem; + } +} +@media (min-width: 768px) { + .md\\:min-h-\\[180px\\] { + min-height: 180px; + } +} +@media (min-width: 1024px) { + .lg\\:order-none { + order: 0; + } + .lg\\:col-span-10 { + grid-column: span 10 / span 10; + } + .lg\\:col-span-4 { + grid-column: span 4 / span 4; + } + .lg\\:col-span-6 { + grid-column: span 6 / span 6; + } + .lg\\:grid-cols-10 { + grid-template-columns: repeat(10, minmax(0, 1fr)); + } + .lg\\:min-h-min { + min-height: min-content; + } + .lg\\:flex-col { + flex-direction: column; + } + .lg\\:px-8 { + padding-left: 2rem; + padding-right: 2rem; + } + .lg\\:py-7 { + padding-top: 1.75rem; + padding-bottom: 1.75rem; + } +} +" +`; + +exports[`template > correctly outputs style blocks for welcome.vue 2`] = ` +"@property --gradient-angle { + syntax: ""; + inherits: false; + initial-value: 180deg; +} +@keyframes gradient-rotate { + 0% { + --gradient-angle: 0deg; + } + 100% { + --gradient-angle: 360deg; + } +} +*, +:before, +:after { + box-sizing: border-box; + border-width: 0; + border-style: solid; + border-color: var(--un-default-border-color, #e5e7eb); +} +:before, +:after { + --un-content: ""; +} +html { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + -moz-tab-size: 4; + tab-size: 4; + font-family: + ui-sans-serif, + system-ui, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + Segoe UI Symbol, + "Noto Color Emoji"; + font-feature-settings: normal; + font-variation-settings: normal; + -webkit-tap-highlight-color: transparent; +} +body { + margin: 0; + line-height: inherit; +} +h1, +h2, +h3 { + font-size: inherit; + font-weight: inherit; +} +a { + color: inherit; + text-decoration: inherit; +} +h1, +h2, +h3, +p { + margin: 0; +} +ul { + list-style: none; + margin: 0; + padding: 0; +} +img, +svg { + display: block; + vertical-align: middle; +} +img { + max-width: 100%; + height: auto; +} +*, +:before, +:after { + --un-rotate: 0; + --un-rotate-x: 0; + --un-rotate-y: 0; + --un-rotate-z: 0; + --un-scale-x: 1; + --un-scale-y: 1; + --un-scale-z: 1; + --un-skew-x: 0; + --un-skew-y: 0; + --un-translate-x: 0; + --un-translate-y: 0; + --un-translate-z: 0; + --un-pan-x: ; + --un-pan-y: ; + --un-pinch-zoom: ; + --un-scroll-snap-strictness: proximity; + --un-ordinal: ; + --un-slashed-zero: ; + --un-numeric-figure: ; + --un-numeric-spacing: ; + --un-numeric-fraction: ; + --un-border-spacing-x: 0; + --un-border-spacing-y: 0; + --un-ring-offset-shadow: 0 0 rgb(0 0 0 / 0); + --un-ring-shadow: 0 0 rgb(0 0 0 / 0); + --un-shadow-inset: ; + --un-shadow: 0 0 rgb(0 0 0 / 0); + --un-ring-inset: ; + --un-ring-offset-width: 0px; + --un-ring-offset-color: #fff; + --un-ring-width: 0px; + --un-ring-color: rgb(147 197 253 / 0.5); + --un-blur: ; + --un-brightness: ; + --un-contrast: ; + --un-drop-shadow: ; + --un-grayscale: ; + --un-hue-rotate: ; + --un-invert: ; + --un-saturate: ; + --un-sepia: ; + --un-backdrop-blur: ; + --un-backdrop-brightness: ; + --un-backdrop-contrast: ; + --un-backdrop-grayscale: ; + --un-backdrop-hue-rotate: ; + --un-backdrop-invert: ; + --un-backdrop-opacity: ; + --un-backdrop-saturate: ; + --un-backdrop-sepia: ; +} +" +`; diff --git a/packages/ui-templates/test/snapshots.spec.ts b/packages/ui-templates/test/snapshots.spec.ts new file mode 100644 index 0000000000..bb17752553 --- /dev/null +++ b/packages/ui-templates/test/snapshots.spec.ts @@ -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(/