mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-21 21:25:11 +00:00
chore: add back stylistic rules and lint project
This commit is contained in:
parent
3782ac0a2c
commit
7252b56d52
56
.eslintrc
56
.eslintrc
@ -12,11 +12,67 @@
|
||||
},
|
||||
"plugins": ["jsdoc", "import", "unicorn", "no-only-tests"],
|
||||
"extends": [
|
||||
"standard",
|
||||
"plugin:jsdoc/recommended",
|
||||
"@nuxt/eslint-config",
|
||||
"plugin:import/typescript"
|
||||
],
|
||||
"rules": {
|
||||
// Imports should come first
|
||||
"import/first": "error",
|
||||
// Other import rules
|
||||
"import/no-mutable-exports": "error",
|
||||
// Allow unresolved imports
|
||||
"import/no-unresolved": "off",
|
||||
// Allow paren-less arrow functions only when there's no braces
|
||||
"arrow-parens": ["error", "as-needed", { "requireForBlockBody": true }],
|
||||
// Allow async-await
|
||||
"generator-star-spacing": "off",
|
||||
// Prefer const over let
|
||||
"prefer-const": ["error", { "destructuring": "any", "ignoreReadBeforeAssign": false }],
|
||||
// No single if in an "else" block
|
||||
"no-lonely-if": "error",
|
||||
// Force curly braces for control flow,
|
||||
// including if blocks with a single statement
|
||||
"curly": ["error", "all"
|
||||
],
|
||||
// No async function without await
|
||||
"require-await": "error",
|
||||
// Force dot notation when possible
|
||||
"dot-notation": "error",
|
||||
|
||||
"no-var": "error",
|
||||
// Force object shorthand where possible
|
||||
"object-shorthand": "error",
|
||||
// No useless destructuring/importing/exporting renames
|
||||
"no-useless-rename": "error",
|
||||
/**********************/
|
||||
/* Unicorn Rules */
|
||||
/**********************/
|
||||
// Pass error message when throwing errors
|
||||
"unicorn/error-message": "error",
|
||||
// Uppercase regex escapes
|
||||
"unicorn/escape-case": "error",
|
||||
// Array.isArray instead of instanceof
|
||||
"unicorn/no-array-instanceof": "error",
|
||||
// Prevent deprecated `new Buffer()`
|
||||
"unicorn/no-new-buffer": "error",
|
||||
// Keep regex literals safe!
|
||||
"unicorn/no-unsafe-regex": "off",
|
||||
// Lowercase number formatting for octal, hex, binary (0x12 instead of 0X12)
|
||||
"unicorn/number-literal-case": "error",
|
||||
// ** instead of Math.pow()
|
||||
"unicorn/prefer-exponentiation-operator": "error",
|
||||
// includes over indexOf when checking for existence
|
||||
"unicorn/prefer-includes": "error",
|
||||
// String methods startsWith/endsWith instead of more complicated stuff
|
||||
"unicorn/prefer-starts-ends-with": "error",
|
||||
// textContent instead of innerText
|
||||
"unicorn/prefer-text-content": "error",
|
||||
// Enforce throwing type error when throwing error while checking typeof
|
||||
"unicorn/prefer-type-error": "error",
|
||||
// Use new when throwing error
|
||||
"unicorn/throw-new-error": "error",
|
||||
"sort-imports": [
|
||||
"error",
|
||||
{
|
||||
|
@ -9,8 +9,8 @@ export default defineNuxtConfig({
|
||||
function () {
|
||||
addPluginTemplate({
|
||||
filename: 'plugins/my-plugin.mjs',
|
||||
getContents: () => `export default defineNuxtPlugin({ name: 'my-plugin' })`
|
||||
getContents: () => 'export default defineNuxtPlugin({ name: \'my-plugin\' })'
|
||||
})
|
||||
}
|
||||
],
|
||||
]
|
||||
})
|
||||
|
@ -60,6 +60,7 @@
|
||||
"consola": "3.2.3",
|
||||
"devalue": "4.3.2",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-config-standard": "^17.1.0",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-jsdoc": "48.2.1",
|
||||
"eslint-plugin-no-only-tests": "3.1.0",
|
||||
|
@ -3,13 +3,13 @@ import { describe, expect, it, vi } from 'vitest'
|
||||
import { consola } from 'consola'
|
||||
import { logger, useLogger } from './logger'
|
||||
|
||||
vi.mock("consola", () => {
|
||||
const logger = {} as any;
|
||||
vi.mock('consola', () => {
|
||||
const logger = {} as any
|
||||
|
||||
logger.create = vi.fn(() => ({...logger}));
|
||||
logger.withTag = vi.fn(() => ({...logger}));
|
||||
logger.create = vi.fn(() => ({ ...logger }))
|
||||
logger.withTag = vi.fn(() => ({ ...logger }))
|
||||
|
||||
return { consola: logger };
|
||||
return { consola: logger }
|
||||
})
|
||||
|
||||
describe('logger', () => {
|
||||
@ -20,29 +20,28 @@ describe('logger', () => {
|
||||
|
||||
describe('useLogger', () => {
|
||||
it('should expose consola when not passing a tag', () => {
|
||||
expect(useLogger()).toBe(consola);
|
||||
});
|
||||
expect(useLogger()).toBe(consola)
|
||||
})
|
||||
|
||||
it('should create a new instance when passing a tag', () => {
|
||||
const logger = vi.mocked(consola);
|
||||
const logger = vi.mocked(consola)
|
||||
|
||||
const instance = useLogger("tag");
|
||||
const instance = useLogger('tag')
|
||||
|
||||
expect(instance).toEqual(logger);
|
||||
expect(instance).not.toBe(logger);
|
||||
expect(logger.create).toBeCalledWith({});
|
||||
expect(logger.withTag).toBeCalledWith("tag");
|
||||
});
|
||||
expect(instance).toEqual(logger)
|
||||
expect(instance).not.toBe(logger)
|
||||
expect(logger.create).toBeCalledWith({})
|
||||
expect(logger.withTag).toBeCalledWith('tag')
|
||||
})
|
||||
|
||||
it('should create a new instance when passing a tag and options', () => {
|
||||
const logger = vi.mocked(consola);
|
||||
const logger = vi.mocked(consola)
|
||||
|
||||
const instance = useLogger("tag", { level: 0 });
|
||||
|
||||
expect(instance).toEqual(logger);
|
||||
expect(instance).not.toBe(logger);
|
||||
expect(logger.create).toBeCalledWith({ level: 0 });
|
||||
expect(logger.withTag).toBeCalledWith("tag");
|
||||
});
|
||||
const instance = useLogger('tag', { level: 0 })
|
||||
|
||||
expect(instance).toEqual(logger)
|
||||
expect(instance).not.toBe(logger)
|
||||
expect(logger.create).toBeCalledWith({ level: 0 })
|
||||
expect(logger.withTag).toBeCalledWith('tag')
|
||||
})
|
||||
})
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { consola } from 'consola'
|
||||
import type { ConsolaOptions } from 'consola';
|
||||
import type { ConsolaOptions } from 'consola'
|
||||
|
||||
export const logger = consola
|
||||
|
||||
|
@ -22,9 +22,9 @@ const mockNuxt = {
|
||||
modules: [],
|
||||
_layers: [{ config: { srcDir: '/my-app' } }],
|
||||
_installedModules: [],
|
||||
_modules: [],
|
||||
_modules: []
|
||||
},
|
||||
callHook: () => {},
|
||||
callHook: () => {}
|
||||
} satisfies DeepPartial<Nuxt> as unknown as Nuxt
|
||||
|
||||
const mockNuxtWithOptions = (options: NuxtConfig) => defu({ options }, mockNuxt) as Nuxt
|
||||
|
@ -9,7 +9,7 @@ const fixtures = {
|
||||
'basic test fixture': 'test/fixtures/basic',
|
||||
'basic test fixture (types)': 'test/fixtures/basic-types',
|
||||
'minimal test fixture': 'test/fixtures/minimal',
|
||||
'minimal test fixture (types)': 'test/fixtures/minimal-types',
|
||||
'minimal test fixture (types)': 'test/fixtures/minimal-types'
|
||||
}
|
||||
|
||||
describe('loadNuxtConfig', () => {
|
||||
|
@ -2,7 +2,9 @@ import { createError } from '../composables/error'
|
||||
|
||||
const intervalError = '[nuxt] `setInterval` should not be used on the server. Consider wrapping it with an `onNuxtReady`, `onBeforeMount` or `onMounted` lifecycle hook, or ensure you only call it in the browser by checking `import.meta.client`.'
|
||||
|
||||
export const setInterval = import.meta.client ? window.setInterval : () => {
|
||||
export const setInterval = import.meta.client
|
||||
? window.setInterval
|
||||
: () => {
|
||||
if (import.meta.dev) {
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
|
@ -213,7 +213,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
expose({
|
||||
refresh: () => fetchComponent(true),
|
||||
refresh: () => fetchComponent(true)
|
||||
})
|
||||
|
||||
if (import.meta.hot) {
|
||||
@ -264,7 +264,7 @@ export default defineComponent({
|
||||
const { html, slots } = info
|
||||
let replaced = html.replaceAll('data-island-uid', `data-island-uid="${uid.value}"`)
|
||||
for (const slot in slots) {
|
||||
replaced = replaced.replaceAll(`data-island-slot="${slot}">`, (full) => full + slots[slot])
|
||||
replaced = replaced.replaceAll(`data-island-slot="${slot}">`, full => full + slots[slot])
|
||||
}
|
||||
teleports.push(createVNode(Teleport, { to: `uid=${uid.value};client=${id}` }, {
|
||||
default: () => [createStaticVNode(replaced, 1)]
|
||||
|
@ -22,29 +22,6 @@ const firstNonUndefined = <T> (...args: (T | undefined)[]) => args.find(arg => a
|
||||
|
||||
const NuxtLinkDevKeySymbol: InjectionKey<boolean> = Symbol('nuxt-link-dev-key')
|
||||
|
||||
/**
|
||||
* Create a NuxtLink component with given options as defaults.
|
||||
* @see https://nuxt.com/docs/api/components/nuxt-link
|
||||
*/
|
||||
export interface NuxtLinkOptions extends
|
||||
Pick<RouterLinkProps, 'activeClass' | 'exactActiveClass'>,
|
||||
Pick<NuxtLinkProps, 'prefetchedClass'> {
|
||||
/**
|
||||
* The name of the component.
|
||||
* @default "NuxtLink"
|
||||
*/
|
||||
componentName?: string
|
||||
/**
|
||||
* A default `rel` attribute value applied on external links. Defaults to `"noopener noreferrer"`. Set it to `""` to disable.
|
||||
*/
|
||||
externalRelAttribute?: string | null
|
||||
/**
|
||||
* An option to either add or remove trailing slashes in the `href`.
|
||||
* If unset or not matching the valid values `append` or `remove`, it will be ignored.
|
||||
*/
|
||||
trailingSlash?: 'append' | 'remove'
|
||||
}
|
||||
|
||||
/**
|
||||
* <NuxtLink> is a drop-in replacement for both Vue Router's <RouterLink> component and HTML's <a> tag.
|
||||
* @see https://nuxt.com/docs/api/components/nuxt-link
|
||||
@ -88,6 +65,29 @@ export interface NuxtLinkProps extends Omit<RouterLinkProps, 'to'> {
|
||||
noPrefetch?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a NuxtLink component with given options as defaults.
|
||||
* @see https://nuxt.com/docs/api/components/nuxt-link
|
||||
*/
|
||||
export interface NuxtLinkOptions extends
|
||||
Pick<RouterLinkProps, 'activeClass' | 'exactActiveClass'>,
|
||||
Pick<NuxtLinkProps, 'prefetchedClass'> {
|
||||
/**
|
||||
* The name of the component.
|
||||
* @default "NuxtLink"
|
||||
*/
|
||||
componentName?: string
|
||||
/**
|
||||
* A default `rel` attribute value applied on external links. Defaults to `"noopener noreferrer"`. Set it to `""` to disable.
|
||||
*/
|
||||
externalRelAttribute?: string | null
|
||||
/**
|
||||
* An option to either add or remove trailing slashes in the `href`.
|
||||
* If unset or not matching the valid values `append` or `remove`, it will be ignored.
|
||||
*/
|
||||
trailingSlash?: 'append' | 'remove'
|
||||
}
|
||||
|
||||
/* @__NO_SIDE_EFFECTS__ */
|
||||
export function defineNuxtLink (options: NuxtLinkOptions) {
|
||||
const componentName = options.componentName || 'NuxtLink'
|
||||
|
@ -23,13 +23,13 @@ export default defineComponent({
|
||||
estimatedProgress: {
|
||||
type: Function as unknown as () => (duration: number, elapsed: number) => number,
|
||||
required: false
|
||||
},
|
||||
}
|
||||
},
|
||||
setup (props, { slots, expose }) {
|
||||
const { progress, isLoading, start, finish, clear } = useLoadingIndicator({
|
||||
duration: props.duration,
|
||||
throttle: props.throttle,
|
||||
estimatedProgress: props.estimatedProgress,
|
||||
estimatedProgress: props.estimatedProgress
|
||||
})
|
||||
|
||||
expose({
|
||||
|
@ -40,7 +40,7 @@ export default defineComponent({
|
||||
vnodes.push(h('div', {
|
||||
style: 'display: contents;',
|
||||
'data-island-uid': '',
|
||||
'data-island-slot': props.name,
|
||||
'data-island-slot': props.name
|
||||
}, {
|
||||
// Teleport in slot to not be hydrated client-side with the staticVNode
|
||||
default: () => [createVNode(Teleport, { to: `island-slot=${componentName};${props.name}` }, slots.default?.())]
|
||||
@ -49,7 +49,7 @@ export default defineComponent({
|
||||
vnodes.push(h('div', {
|
||||
style: 'display: contents;',
|
||||
'data-island-uid': '',
|
||||
'data-island-slot': props.name,
|
||||
'data-island-slot': props.name
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,9 @@ export function useAsyncData<
|
||||
const nuxtApp = useNuxtApp()
|
||||
|
||||
// When prerendering, share payload data automatically between requests
|
||||
const handler = import.meta.client || !import.meta.prerender || !nuxtApp.ssrContext?._sharedPrerenderCache ? _handler : () => {
|
||||
const handler = import.meta.client || !import.meta.prerender || !nuxtApp.ssrContext?._sharedPrerenderCache
|
||||
? _handler
|
||||
: () => {
|
||||
const value = nuxtApp.ssrContext!._sharedPrerenderCache!.get(key)
|
||||
if (value) { return value as Promise<ResT> }
|
||||
|
||||
|
@ -92,7 +92,7 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
|
||||
if (store) {
|
||||
store.onchange = (event) => {
|
||||
const cookie = event.changed.find((c: any) => c.name === name)
|
||||
if (cookie) handleChange({ value: cookie.value })
|
||||
if (cookie) { handleChange({ value: cookie.value }) }
|
||||
}
|
||||
} else if (channel) {
|
||||
channel.onmessage = ({ data }) => handleChange(data)
|
||||
@ -124,7 +124,7 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
|
||||
}
|
||||
/** @since 3.10.0 */
|
||||
export function refreshCookie (name: string) {
|
||||
if (store || typeof BroadcastChannel === 'undefined') return
|
||||
if (store || typeof BroadcastChannel === 'undefined') { return }
|
||||
|
||||
new BroadcastChannel(`nuxt:cookies:${name}`)?.postMessage({ refresh: true })
|
||||
}
|
||||
|
@ -53,9 +53,7 @@ export const clearError = async (options: { redirect?: string } = {}) => {
|
||||
/** @since 3.0.0 */
|
||||
export const isNuxtError = <DataT = unknown>(
|
||||
error?: string | object
|
||||
): error is NuxtError<DataT> => (
|
||||
!!error && typeof error === 'object' && NUXT_ERROR_SIGNATURE in error
|
||||
)
|
||||
): error is NuxtError<DataT> => !!error && typeof error === 'object' && NUXT_ERROR_SIGNATURE in error
|
||||
|
||||
/** @since 3.0.0 */
|
||||
export const createError = <DataT = unknown>(
|
||||
|
@ -246,7 +246,7 @@ export function useLazyFetch<
|
||||
function generateOptionSegments <_ResT, DataT, DefaultT> (opts: UseFetchOptions<_ResT, DataT, any, DefaultT, any, any>) {
|
||||
const segments: Array<string | undefined | Record<string, string>> = [
|
||||
toValue(opts.method as MaybeRef<string | undefined> | undefined)?.toUpperCase() || 'GET',
|
||||
toValue(opts.baseURL),
|
||||
toValue(opts.baseURL)
|
||||
]
|
||||
for (const _obj of [opts.params || opts.query]) {
|
||||
const obj = toValue(_obj)
|
||||
|
@ -29,7 +29,7 @@ export function usePreviewMode<S extends EnteredState> (options: PreviewModeOpti
|
||||
if (preview.value._initialized) {
|
||||
return {
|
||||
enabled: toRef(preview.value, 'enabled'),
|
||||
state: preview.value.state as S extends void ? Preview['state'] : (NonNullable<S> & Preview['state']),
|
||||
state: preview.value.state as S extends void ? Preview['state'] : (NonNullable<S> & Preview['state'])
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ export function usePreviewMode<S extends EnteredState> (options: PreviewModeOpti
|
||||
if (import.meta.client && !unregisterRefreshHook) {
|
||||
refreshNuxtData()
|
||||
|
||||
unregisterRefreshHook = useRouter().afterEach((() => refreshNuxtData()))
|
||||
unregisterRefreshHook = useRouter().afterEach(() => refreshNuxtData())
|
||||
}
|
||||
} else if (unregisterRefreshHook) {
|
||||
unregisterRefreshHook()
|
||||
@ -67,7 +67,7 @@ export function usePreviewMode<S extends EnteredState> (options: PreviewModeOpti
|
||||
|
||||
return {
|
||||
enabled: toRef(preview.value, 'enabled'),
|
||||
state: preview.value.state as S extends void ? Preview['state'] : (NonNullable<S> & Preview['state']),
|
||||
state: preview.value.state as S extends void ? Preview['state'] : (NonNullable<S> & Preview['state'])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,8 +85,7 @@ if (import.meta.client) {
|
||||
}
|
||||
|
||||
// If the errorHandler is not overridden by the user, we unset it
|
||||
if (vueApp.config.errorHandler === handleVueError)
|
||||
vueApp.config.errorHandler = undefined
|
||||
if (vueApp.config.errorHandler === handleVueError) { vueApp.config.errorHandler = undefined }
|
||||
|
||||
return vueApp
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ export const islandsTransform = createUnplugin((options: ServerOnlyComponentTran
|
||||
if (children.length) {
|
||||
const attrString = Object.entries(attributes).map(([name, value]) => name ? `${name}="${value}" ` : value).join(' ')
|
||||
const slice = code.slice(startingIndex + loc[0].end, startingIndex + loc[1].start).replaceAll(/:?key="[^"]"/g, '')
|
||||
s.overwrite(startingIndex + loc[0].start, startingIndex + loc[1].end, `<slot ${attrString} /><template #fallback>${attributes["v-for"] ? wrapWithVForDiv(slice, attributes['v-for']) : slice}</template>`)
|
||||
s.overwrite(startingIndex + loc[0].start, startingIndex + loc[1].end, `<slot ${attrString} /><template #fallback>${attributes['v-for'] ? wrapWithVForDiv(slice, attributes['v-for']) : slice}</template>`)
|
||||
}
|
||||
|
||||
const slotName = attributes.name ?? 'default'
|
||||
|
@ -239,7 +239,7 @@ export default defineNuxtModule<ComponentsOptions>({
|
||||
} else {
|
||||
fs.writeFileSync(join(nuxt.options.buildDir, 'components-chunk.mjs'), `export const paths = ${JSON.stringify(
|
||||
getComponents().filter(c => c.mode === 'client' || c.mode === 'all').reduce((acc, c) => {
|
||||
if(c.filePath.endsWith('.vue') || c.filePath.endsWith('.js') || c.filePath.endsWith('.ts')) return Object.assign(acc, {[c.pascalName]: `/@fs/${c.filePath}`})
|
||||
if (c.filePath.endsWith('.vue') || c.filePath.endsWith('.js') || c.filePath.endsWith('.ts')) { return Object.assign(acc, { [c.pascalName]: `/@fs/${c.filePath}` }) }
|
||||
const filePath = fs.existsSync(`${c.filePath}.vue`) ? `${c.filePath}.vue` : fs.existsSync(`${c.filePath}.js`) ? `${c.filePath}.js` : `${c.filePath}.ts`
|
||||
return Object.assign(acc, { [c.pascalName]: `/@fs/${filePath}` })
|
||||
}, {} as Record<string, string>)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { defineAsyncComponent, defineComponent, h } from 'vue'
|
||||
import type { AsyncComponentLoader } from 'vue'
|
||||
import { default as ClientOnly } from '#app/components/client-only'
|
||||
import ClientOnly from '#app/components/client-only'
|
||||
|
||||
/* @__NO_SIDE_EFFECTS__ */
|
||||
export const createClientPage = (loader: AsyncComponentLoader) => {
|
||||
|
@ -227,7 +227,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
||||
output: {},
|
||||
plugins: []
|
||||
},
|
||||
logLevel: logLevelMapReverse[nuxt.options.logLevel],
|
||||
logLevel: logLevelMapReverse[nuxt.options.logLevel]
|
||||
} satisfies NitroConfig)
|
||||
|
||||
// Resolve user-provided paths
|
||||
|
@ -64,11 +64,11 @@ async function initNuxt (nuxt: Nuxt) {
|
||||
nuxt.hook('close', () => nuxtCtx.unset())
|
||||
|
||||
const coreTypePackages = ['nitropack', 'defu', 'h3', '@unhead/vue', 'vue', 'vue-router', '@nuxt/schema']
|
||||
const paths = Object.fromEntries(await Promise.all(coreTypePackages.map(async pkg => {
|
||||
const paths = Object.fromEntries(await Promise.all(coreTypePackages.map(async (pkg) => {
|
||||
const path = await _resolvePath(pkg, { url: nuxt.options.modulesDir }).then(r => resolvePackageJSON(r)).catch(() => null)
|
||||
if (!path) { return }
|
||||
return [pkg, [dirname(path)]]
|
||||
})).then((r) => r.filter(Boolean) as [string, [string]][]))
|
||||
})).then(r => r.filter(Boolean) as [string, [string]][]))
|
||||
|
||||
// Set nitro resolutions for types that might be obscured with shamefully-hoist=false
|
||||
nuxt.options.nitro.typescript = defu(nuxt.options.nitro.typescript, {
|
||||
|
@ -21,6 +21,6 @@ export default defineDriver((opts: { base: string }) => {
|
||||
},
|
||||
async getItem (key, opts) {
|
||||
return await lru.getItem(key, opts) || await fs.getItem(normalizeFsKey(key), opts)
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -54,7 +54,9 @@ export default <NitroErrorHandler> async function errorhandler (error: H3Error,
|
||||
const isRenderingError = event.path.startsWith('/__nuxt_error') || !!reqHeaders['x-nuxt-error']
|
||||
|
||||
// HTML response (via SSR)
|
||||
const res = isRenderingError ? null : await useNitroApp().localFetch(
|
||||
const res = isRenderingError
|
||||
? null
|
||||
: await useNitroApp().localFetch(
|
||||
withQuery(joinURL(useRuntimeConfig(event).app.baseURL, '/__nuxt_error'), errorObject),
|
||||
{
|
||||
headers: { ...reqHeaders, 'x-nuxt-error': 'true' },
|
||||
|
@ -53,6 +53,18 @@ export interface NuxtRenderHTMLContext {
|
||||
bodyAppend: string[]
|
||||
}
|
||||
|
||||
export interface NuxtIslandSlotResponse {
|
||||
props: Array<unknown>
|
||||
fallback?: string
|
||||
}
|
||||
|
||||
export interface NuxtIslandClientResponse {
|
||||
html: string
|
||||
props: unknown
|
||||
chunk: string
|
||||
slots?: Record<string, string>
|
||||
}
|
||||
|
||||
export interface NuxtIslandContext {
|
||||
id?: string
|
||||
name: string
|
||||
@ -62,17 +74,6 @@ export interface NuxtIslandContext {
|
||||
components: Record<string, Omit<NuxtIslandClientResponse, 'html'>>
|
||||
}
|
||||
|
||||
export interface NuxtIslandSlotResponse {
|
||||
props: Array<unknown>
|
||||
fallback?: string
|
||||
}
|
||||
export interface NuxtIslandClientResponse {
|
||||
html: string
|
||||
props: unknown
|
||||
chunk: string
|
||||
slots?: Record<string, string>
|
||||
}
|
||||
|
||||
export interface NuxtIslandResponse {
|
||||
id?: string
|
||||
html: string
|
||||
@ -186,7 +187,8 @@ const islandCache = import.meta.prerender ? useStorage('internal:nuxt:prerender:
|
||||
const islandPropCache = import.meta.prerender ? useStorage('internal:nuxt:prerender:island-props') : null
|
||||
const sharedPrerenderPromises = import.meta.prerender && process.env.NUXT_SHARED_DATA ? new Map<string, Promise<any>>() : null
|
||||
const sharedPrerenderKeys = new Set<string>()
|
||||
const sharedPrerenderCache = import.meta.prerender && process.env.NUXT_SHARED_DATA ? {
|
||||
const sharedPrerenderCache = import.meta.prerender && process.env.NUXT_SHARED_DATA
|
||||
? {
|
||||
get<T = unknown> (key: string): Promise<T> | undefined {
|
||||
if (sharedPrerenderKeys.has(key)) {
|
||||
return sharedPrerenderPromises!.get(key) ?? useStorage('internal:nuxt:prerender:shared').getItem(key) as Promise<T>
|
||||
@ -198,8 +200,9 @@ const sharedPrerenderCache = import.meta.prerender && process.env.NUXT_SHARED_DA
|
||||
useStorage('internal:nuxt:prerender:shared').setItem(key, await value as any)
|
||||
// free up memory after the promise is resolved
|
||||
.finally(() => sharedPrerenderPromises!.delete(key))
|
||||
},
|
||||
} : null
|
||||
}
|
||||
}
|
||||
: null
|
||||
|
||||
async function getIslandContext (event: H3Event): Promise<NuxtIslandContext> {
|
||||
// TODO: Strict validation for url
|
||||
@ -221,7 +224,7 @@ async function getIslandContext (event: H3Event): Promise<NuxtIslandContext> {
|
||||
name: componentName,
|
||||
props: destr(context.props) || {},
|
||||
slots: {},
|
||||
components: {},
|
||||
components: {}
|
||||
}
|
||||
|
||||
return ctx
|
||||
@ -327,7 +330,6 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
||||
writeEarlyHints(event, link)
|
||||
}
|
||||
|
||||
|
||||
if (process.env.NUXT_INLINE_STYLES && !isRenderingIsland) {
|
||||
for (const id of await getEntryIds()) {
|
||||
ssrContext.modules!.add(id)
|
||||
@ -537,16 +539,16 @@ function joinTags (tags: string[]) {
|
||||
}
|
||||
|
||||
function joinAttrs (chunks: string[]) {
|
||||
if (chunks.length === 0) return ''
|
||||
if (chunks.length === 0) { return '' }
|
||||
return ' ' + chunks.join(' ')
|
||||
}
|
||||
|
||||
function renderHTMLDocument (html: NuxtRenderHTMLContext) {
|
||||
return '<!DOCTYPE html>'
|
||||
+ `<html${joinAttrs(html.htmlAttrs)}>`
|
||||
+ `<head>${joinTags(html.head)}</head>`
|
||||
+ `<body${joinAttrs(html.bodyAttrs)}>${joinTags(html.bodyPrepend)}${joinTags(html.body)}${joinTags(html.bodyAppend)}</body>`
|
||||
+ '</html>'
|
||||
return '<!DOCTYPE html>' +
|
||||
`<html${joinAttrs(html.htmlAttrs)}>` +
|
||||
`<head>${joinTags(html.head)}</head>` +
|
||||
`<body${joinAttrs(html.bodyAttrs)}>${joinTags(html.bodyPrepend)}${joinTags(html.body)}${joinTags(html.bodyAppend)}</body>` +
|
||||
'</html>'
|
||||
}
|
||||
|
||||
async function renderInlineStyles (usedModules: Set<string> | string[]): Promise<Style[]> {
|
||||
@ -639,7 +641,7 @@ function getSlotIslandResponse (ssrContext: NuxtSSRContext): NuxtIslandResponse[
|
||||
for (const slot in ssrContext.islandContext.slots) {
|
||||
response[slot] = {
|
||||
...ssrContext.islandContext.slots[slot],
|
||||
fallback: ssrContext.teleports?.[`island-fallback=${slot}`],
|
||||
fallback: ssrContext.teleports?.[`island-fallback=${slot}`]
|
||||
}
|
||||
}
|
||||
return response
|
||||
|
@ -48,7 +48,7 @@ export const errorComponentTemplate: NuxtTemplate = {
|
||||
// TODO: Use an alias
|
||||
export const testComponentWrapperTemplate: NuxtTemplate = {
|
||||
filename: 'test-component-wrapper.mjs',
|
||||
getContents: (ctx) => genExport(resolve(ctx.nuxt.options.appDir, 'components/test-component-wrapper'), ['default'])
|
||||
getContents: ctx => genExport(resolve(ctx.nuxt.options.appDir, 'components/test-component-wrapper'), ['default'])
|
||||
}
|
||||
|
||||
export const cssTemplate: NuxtTemplate = {
|
||||
|
@ -17,7 +17,7 @@ const removeUndefinedProps = (props: Props) => {
|
||||
for (const key in props) {
|
||||
const value = props[key]
|
||||
if (value !== undefined) {
|
||||
filteredProps[key] = value;
|
||||
filteredProps[key] = value
|
||||
}
|
||||
}
|
||||
return filteredProps
|
||||
|
@ -354,14 +354,14 @@ export default defineNuxtModule({
|
||||
if (nuxt.options.experimental.appManifest) {
|
||||
// Add all redirect paths as valid routes to router; we will handle these in a client-side middleware
|
||||
// when the app manifest is enabled.
|
||||
nuxt.hook('pages:extend', routes => {
|
||||
nuxt.hook('pages:extend', (routes) => {
|
||||
const nitro = useNitro()
|
||||
for (const path in nitro.options.routeRules) {
|
||||
const rule = nitro.options.routeRules[path]
|
||||
if (!rule.redirect) { continue }
|
||||
routes.push({
|
||||
path: path.replace(/\/[^/]*\*\*/, '/:pathMatch(.*)'),
|
||||
file: resolve(runtimeDir, 'component-stub'),
|
||||
file: resolve(runtimeDir, 'component-stub')
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -415,7 +415,7 @@ export default defineNuxtModule({
|
||||
addTemplate({
|
||||
filename: 'routes.mjs',
|
||||
getContents ({ app }) {
|
||||
if (!app.pages) return 'export default []'
|
||||
if (!app.pages) { return 'export default []' }
|
||||
const { routes, imports } = normalizeRoutes(app.pages, new Set(), nuxt.options.experimental.scanPageMeta)
|
||||
return [...imports, `export default ${routes}`].join('\n')
|
||||
}
|
||||
@ -490,7 +490,6 @@ export default defineNuxtModule({
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// add page meta types if enabled
|
||||
if (nuxt.options.experimental.viewTransition) {
|
||||
addTypeTemplate({
|
||||
@ -502,9 +501,9 @@ export default defineNuxtModule({
|
||||
'import type { ComputedRef, MaybeRef } from \'vue\'',
|
||||
`declare module ${genString(composablesFile)} {`,
|
||||
' interface PageMeta {',
|
||||
` viewTransition?: boolean | 'always'`,
|
||||
' }',
|
||||
' viewTransition?: boolean | \'always\'',
|
||||
' }',
|
||||
'}'
|
||||
].join('\n')
|
||||
}
|
||||
})
|
||||
|
@ -4,9 +4,8 @@ import { RouterView } from '#vue-router'
|
||||
import { defu } from 'defu'
|
||||
import type { RouteLocationNormalized, RouteLocationNormalizedLoaded } from '#vue-router'
|
||||
|
||||
import { toArray } from './utils'
|
||||
import { generateRouteKey, toArray, wrapInKeepAlive } from './utils'
|
||||
import type { RouterViewSlotProps } from './utils'
|
||||
import { generateRouteKey, wrapInKeepAlive } from './utils'
|
||||
import { RouteProvider } from '#app/components/route-provider'
|
||||
import { useNuxtApp } from '#app/nuxt'
|
||||
import { useRouter } from '#app/composables/router'
|
||||
|
@ -11,9 +11,9 @@ export default defineNuxtPlugin({
|
||||
function checkIfPageUnused () {
|
||||
if (!error.value && !nuxtApp._isNuxtPageUsed) {
|
||||
console.warn(
|
||||
'[nuxt] Your project has pages but the `<NuxtPage />` component has not been used.'
|
||||
+ ' You might be using the `<RouterView />` component instead, which will not work correctly in Nuxt.'
|
||||
+ ' You can set `pages: false` in `nuxt.config` if you do not wish to use the Nuxt `vue-router` integration.'
|
||||
'[nuxt] Your project has pages but the `<NuxtPage />` component has not been used.' +
|
||||
' You might be using the `<RouterView />` component instead, which will not work correctly in Nuxt.' +
|
||||
' You can set `pages: false` in `nuxt.config` if you do not wish to use the Nuxt `vue-router` integration.'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ export async function generateRoutesFromFiles (files: ScannedFile[], options: Ge
|
||||
name: '',
|
||||
path: '',
|
||||
file: file.absolutePath,
|
||||
children: [],
|
||||
children: []
|
||||
}
|
||||
|
||||
// Array where routes should be added, useful when adding child routes
|
||||
@ -399,7 +399,7 @@ function prepareRoutes (routes: NuxtPage[], parent?: NuxtPage, names = new Set<s
|
||||
}
|
||||
|
||||
function serializeRouteValue (value: any, skipSerialisation = false) {
|
||||
if (skipSerialisation || value === undefined) return undefined
|
||||
if (skipSerialisation || value === undefined) { return undefined }
|
||||
return JSON.stringify(value)
|
||||
}
|
||||
|
||||
@ -425,7 +425,7 @@ export function normalizeRoutes (routes: NuxtPage[], metaImports: Set<string> =
|
||||
name: serializeRouteValue(page.name),
|
||||
meta: serializeRouteValue(metaFiltered, skipMeta),
|
||||
alias: serializeRouteValue(toArray(page.alias), skipAlias),
|
||||
redirect: serializeRouteValue(page.redirect),
|
||||
redirect: serializeRouteValue(page.redirect)
|
||||
}
|
||||
|
||||
for (const key of ['path', 'name', 'meta', 'alias', 'redirect'] satisfies NormalizedRouteKeys) {
|
||||
@ -487,13 +487,13 @@ async function createClientPage(loader) {
|
||||
// skip and retain fallback if marked dynamic
|
||||
// set to extracted value or fallback if none extracted
|
||||
for (const key of ['name', 'path'] satisfies NormalizedRouteKeys) {
|
||||
if (markedDynamic.has(key)) continue
|
||||
if (markedDynamic.has(key)) { continue }
|
||||
metaRoute[key] = route[key] ?? metaRoute[key]
|
||||
}
|
||||
|
||||
// set to extracted value or delete if none extracted
|
||||
for (const key of ['meta', 'alias', 'redirect'] satisfies NormalizedRouteKeys) {
|
||||
if (markedDynamic.has(key)) continue
|
||||
if (markedDynamic.has(key)) { continue }
|
||||
|
||||
if (route[key] == null) {
|
||||
delete metaRoute[key]
|
||||
|
@ -87,7 +87,7 @@ describe('resolveApp', () => {
|
||||
'middleware/other.ts',
|
||||
'layouts/index.vue',
|
||||
'layouts/default/index.vue',
|
||||
'layouts/other.vue',
|
||||
'layouts/other.vue'
|
||||
])
|
||||
// Middleware are not resolved in a nested manner
|
||||
expect(app.middleware.filter(m => m.path.startsWith('<rootDir>'))).toMatchInlineSnapshot(`
|
||||
|
@ -351,7 +351,7 @@ describe('islandTransform - server and island components', () => {
|
||||
|
||||
"
|
||||
`)
|
||||
expect(result).toContain(`import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'`)
|
||||
expect(result).toContain('import NuxtTeleportIslandComponent from \'#app/components/nuxt-teleport-island-component\'')
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -11,10 +11,10 @@ describe('pages:generateRoutesFromFiles', () => {
|
||||
vi.mock('knitwork', async (original) => {
|
||||
return {
|
||||
...(await original<typeof import('knitwork')>()),
|
||||
'genArrayFromRaw': (val: any) => val,
|
||||
'genSafeVariableName': (..._args: string[]) => {
|
||||
genArrayFromRaw: (val: any) => val,
|
||||
genSafeVariableName: (..._args: string[]) => {
|
||||
return 'mock'
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -471,7 +471,7 @@ describe('pages:generateRoutesFromFiles', () => {
|
||||
name: 'index',
|
||||
path: '/'
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
{
|
||||
description: 'should use fallbacks when normalized with `overrideMeta: true`',
|
||||
@ -527,7 +527,7 @@ describe('pages:generateRoutesFromFiles', () => {
|
||||
alias: ['sweet-home'],
|
||||
redirect: '/',
|
||||
children: [],
|
||||
meta: { [DYNAMIC_META_KEY]: new Set(['meta']) },
|
||||
meta: { [DYNAMIC_META_KEY]: new Set(['meta']) }
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -538,7 +538,7 @@ describe('pages:generateRoutesFromFiles', () => {
|
||||
name: 'home',
|
||||
path: '/',
|
||||
alias: ['sweet-home'],
|
||||
meta: { hello: 'world' },
|
||||
meta: { hello: 'world' }
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -550,10 +550,10 @@ describe('pages:generateRoutesFromFiles', () => {
|
||||
path: '/',
|
||||
alias: ['pushed-route-alias'],
|
||||
meta: { someMetaData: true },
|
||||
file: `${pagesDir}/route-file.vue`,
|
||||
file: `${pagesDir}/route-file.vue`
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
const normalizedResults: Record<string, any> = {}
|
||||
@ -561,7 +561,6 @@ describe('pages:generateRoutesFromFiles', () => {
|
||||
|
||||
for (const test of tests) {
|
||||
it(test.description, async () => {
|
||||
|
||||
let result
|
||||
if (test.files) {
|
||||
const vfs = Object.fromEntries(
|
||||
|
4
packages/nuxt/types.d.ts
vendored
4
packages/nuxt/types.d.ts
vendored
@ -1,11 +1,11 @@
|
||||
/// <reference types="nitropack" />
|
||||
export * from './dist/index'
|
||||
|
||||
import type { DefineNuxtConfig } from 'nuxt/config'
|
||||
import type { RuntimeConfig, SchemaDefinition } from 'nuxt/schema'
|
||||
import type { H3Event } from 'h3'
|
||||
import type { NuxtIslandContext, NuxtIslandResponse, NuxtRenderHTMLContext } from './dist/app/types'
|
||||
|
||||
export * from './dist/index'
|
||||
|
||||
declare global {
|
||||
const defineNuxtConfig: DefineNuxtConfig
|
||||
const defineNuxtSchema: (schema: SchemaDefinition) => SchemaDefinition
|
||||
|
@ -27,7 +27,7 @@ export default defineUntypedSchema({
|
||||
* @see [Vue RFC#502](https://github.com/vuejs/rfcs/discussions/502)
|
||||
* @type {boolean}
|
||||
*/
|
||||
propsDestructure: false,
|
||||
propsDestructure: false
|
||||
},
|
||||
|
||||
/**
|
||||
@ -157,7 +157,7 @@ export default defineUntypedSchema({
|
||||
*/
|
||||
viewTransition: {
|
||||
$resolve: async (val, get) => val ?? await (get('experimental') as Promise<Record<string, any>>).then(
|
||||
(e) => e?.viewTransition
|
||||
e => e?.viewTransition
|
||||
) ?? false
|
||||
},
|
||||
|
||||
|
@ -27,7 +27,7 @@ export default defineUntypedSchema({
|
||||
}
|
||||
return true
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Some features of Nuxt are available on an opt-in basis, or can be disabled based on your needs.
|
||||
@ -61,7 +61,7 @@ export default defineUntypedSchema({
|
||||
// TODO: remove in v3.10
|
||||
return val ?? await (get('experimental') as Promise<Record<string, any>>).then((e: Record<string, any>) => e?.noScripts) ?? false
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
experimental: {
|
||||
/**
|
||||
@ -335,6 +335,6 @@ export default defineUntypedSchema({
|
||||
* ```
|
||||
* @type {boolean}
|
||||
*/
|
||||
clientNodeCompat: false,
|
||||
clientNodeCompat: false
|
||||
}
|
||||
})
|
||||
|
@ -70,7 +70,7 @@ export default defineUntypedSchema({
|
||||
exclude: {
|
||||
$resolve: async (val: string[] | undefined, get) => [
|
||||
...val || [],
|
||||
...(await get('build.transpile') as Array<string | RegExp | ((ctx: { isClient?: boolean; isServer?: boolean; isDev: boolean }) => string | RegExp | false)>).filter((i) => typeof i === 'string'),
|
||||
...(await get('build.transpile') as Array<string | RegExp | ((ctx: { isClient?: boolean; isServer?: boolean; isDev: boolean }) => string | RegExp | false)>).filter(i => typeof i === 'string'),
|
||||
'vue-demi'
|
||||
]
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ export default defineUntypedSchema({
|
||||
embed: 'src'
|
||||
},
|
||||
compilerOptions: { $resolve: async (val, get) => val ?? (await get('vue.compilerOptions')) },
|
||||
propsDestructure: { $resolve: async (val, get) => val ?? Boolean(await get('vue.propsDestructure')) },
|
||||
propsDestructure: { $resolve: async (val, get) => val ?? Boolean(await get('vue.propsDestructure')) }
|
||||
},
|
||||
|
||||
css: {
|
||||
|
@ -36,6 +36,7 @@ export interface NuxtTemplate<Options = TemplateDefaultOptions> {
|
||||
/** The resolved path to the source file to be template */
|
||||
src?: string
|
||||
/** Provided compile option instead of src */
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
getContents?: (data: { nuxt: Nuxt, app: NuxtApp, options: Options }) => string | Promise<string>
|
||||
/** Write to filesystem */
|
||||
write?: boolean
|
||||
|
@ -20,12 +20,14 @@ import { viteNodePlugin } from './vite-node'
|
||||
import { createViteLogger } from './utils/logger'
|
||||
|
||||
export async function buildClient (ctx: ViteBuildContext) {
|
||||
const nodeCompat = ctx.nuxt.options.experimental.clientNodeCompat ? {
|
||||
const nodeCompat = ctx.nuxt.options.experimental.clientNodeCompat
|
||||
? {
|
||||
alias: env(nodeless).alias,
|
||||
define: {
|
||||
global: 'globalThis',
|
||||
global: 'globalThis'
|
||||
}
|
||||
} : { alias: {}, define: {} }
|
||||
}
|
||||
: { alias: {}, define: {} }
|
||||
|
||||
const clientConfig: ViteConfig = vite.mergeConfig(ctx.config, vite.mergeConfig({
|
||||
configFile: false,
|
||||
@ -67,7 +69,7 @@ export async function buildClient (ctx: ViteBuildContext) {
|
||||
...nodeCompat.alias,
|
||||
...ctx.config.resolve?.alias,
|
||||
'#build/plugins': resolve(ctx.nuxt.options.buildDir, 'plugins/client'),
|
||||
'#internal/nitro': resolve(ctx.nuxt.options.buildDir, 'nitro.client.mjs'),
|
||||
'#internal/nitro': resolve(ctx.nuxt.options.buildDir, 'nitro.client.mjs')
|
||||
},
|
||||
dedupe: [
|
||||
'vue'
|
||||
|
@ -44,11 +44,11 @@ export async function buildServer (ctx: ViteBuildContext) {
|
||||
'import.meta.server': true,
|
||||
'import.meta.client': false,
|
||||
'import.meta.browser': false,
|
||||
'window': 'undefined',
|
||||
'document': 'undefined',
|
||||
'navigator': 'undefined',
|
||||
'location': 'undefined',
|
||||
'XMLHttpRequest': 'undefined'
|
||||
window: 'undefined',
|
||||
document: 'undefined',
|
||||
navigator: 'undefined',
|
||||
location: 'undefined',
|
||||
XMLHttpRequest: 'undefined'
|
||||
},
|
||||
optimizeDeps: {
|
||||
entries: ctx.nuxt.options.ssr ? [ctx.entry] : []
|
||||
@ -99,7 +99,7 @@ export async function buildServer (ctx: ViteBuildContext) {
|
||||
// https://github.com/vitest-dev/vitest/issues/229#issuecomment-1002685027
|
||||
preTransformRequests: false,
|
||||
hmr: false
|
||||
},
|
||||
}
|
||||
} satisfies vite.InlineConfig, ctx.nuxt.options.vite.$server || {}))
|
||||
|
||||
if (!ctx.nuxt.options.dev) {
|
||||
|
@ -158,7 +158,7 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
|
||||
// Trigger vite to optimize dependencies imported within a layer, just as if they were imported in final project
|
||||
await this.resolve(source, join(nuxt.options.srcDir, 'index.html'), { skipSelf: true }).catch(() => null)
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ export function client (ctx: WebpackConfigContext) {
|
||||
clientDevtool,
|
||||
clientPerformance,
|
||||
clientHMR,
|
||||
clientNodeCompat,
|
||||
clientNodeCompat
|
||||
])
|
||||
}
|
||||
|
||||
@ -54,17 +54,17 @@ function clientNodeCompat(ctx: WebpackConfigContext) {
|
||||
if (!ctx.nuxt.options.experimental.clientNodeCompat) {
|
||||
return
|
||||
}
|
||||
ctx.config.plugins!.push(new webpack.DefinePlugin({ global: 'globalThis', }))
|
||||
ctx.config.plugins!.push(new webpack.DefinePlugin({ global: 'globalThis' }))
|
||||
|
||||
ctx.config.resolve = ctx.config.resolve || {}
|
||||
ctx.config.resolve.fallback = {
|
||||
...env(nodeless).alias,
|
||||
...ctx.config.resolve.fallback,
|
||||
...ctx.config.resolve.fallback
|
||||
}
|
||||
|
||||
// https://github.com/webpack/webpack/issues/13290#issuecomment-1188760779
|
||||
ctx.config.plugins!.unshift(new webpack.NormalModuleReplacementPlugin(/node:/, (resource) => {
|
||||
resource.request = resource.request.replace(/^node:/, '');
|
||||
resource.request = resource.request.replace(/^node:/, '')
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,9 @@ importers:
|
||||
eslint:
|
||||
specifier: 8.57.0
|
||||
version: 8.57.0
|
||||
eslint-config-standard:
|
||||
specifier: ^17.1.0
|
||||
version: 17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.6.2)(eslint-plugin-promise@6.1.1)(eslint@8.57.0)
|
||||
eslint-plugin-import:
|
||||
specifier: 2.29.1
|
||||
version: 2.29.1(@typescript-eslint/parser@6.8.0)(eslint@8.57.0)
|
||||
@ -4201,7 +4204,6 @@ packages:
|
||||
resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==}
|
||||
dependencies:
|
||||
semver: 7.6.0
|
||||
dev: false
|
||||
|
||||
/bundle-name@3.0.0:
|
||||
resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==}
|
||||
@ -5427,6 +5429,30 @@ packages:
|
||||
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
/eslint-compat-utils@0.1.2(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==}
|
||||
engines: {node: '>=12'}
|
||||
peerDependencies:
|
||||
eslint: '>=6.0.0'
|
||||
dependencies:
|
||||
eslint: 8.57.0
|
||||
dev: true
|
||||
|
||||
/eslint-config-standard@17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.6.2)(eslint-plugin-promise@6.1.1)(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
eslint: ^8.0.1
|
||||
eslint-plugin-import: ^2.25.2
|
||||
eslint-plugin-n: '^15.0.0 || ^16.0.0 '
|
||||
eslint-plugin-promise: ^6.0.0
|
||||
dependencies:
|
||||
eslint: 8.57.0
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.8.0)(eslint@8.57.0)
|
||||
eslint-plugin-n: 16.6.2(eslint@8.57.0)
|
||||
eslint-plugin-promise: 6.1.1(eslint@8.57.0)
|
||||
dev: true
|
||||
|
||||
/eslint-import-resolver-node@0.3.9:
|
||||
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
|
||||
dependencies:
|
||||
@ -5466,6 +5492,18 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-es-x@7.5.0(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: '>=8'
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
|
||||
'@eslint-community/regexpp': 4.9.1
|
||||
eslint: 8.57.0
|
||||
eslint-compat-utils: 0.1.2(eslint@8.57.0)
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.8.0)(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
|
||||
engines: {node: '>=4'}
|
||||
@ -5521,11 +5559,40 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-n@16.6.2(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
peerDependencies:
|
||||
eslint: '>=7.0.0'
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
|
||||
builtins: 5.0.1
|
||||
eslint: 8.57.0
|
||||
eslint-plugin-es-x: 7.5.0(eslint@8.57.0)
|
||||
get-tsconfig: 4.7.2
|
||||
globals: 13.24.0
|
||||
ignore: 5.3.1
|
||||
is-builtin-module: 3.2.1
|
||||
is-core-module: 2.13.1
|
||||
minimatch: 3.1.2
|
||||
resolve: 1.22.8
|
||||
semver: 7.6.0
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-no-only-tests@3.1.0:
|
||||
resolution: {integrity: sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==}
|
||||
engines: {node: '>=5.0.0'}
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-promise@6.1.1(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
dependencies:
|
||||
eslint: 8.57.0
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-unicorn@51.0.1(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-MuR/+9VuB0fydoI0nIn2RDA5WISRn4AsJyNSaNKLVwie9/ONvQhxOBbkfSICBPnzKrB77Fh6CZZXjgTt/4Latw==}
|
||||
engines: {node: '>=16'}
|
||||
@ -6168,6 +6235,13 @@ packages:
|
||||
dependencies:
|
||||
type-fest: 0.20.2
|
||||
|
||||
/globals@13.24.0:
|
||||
resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
type-fest: 0.20.2
|
||||
dev: true
|
||||
|
||||
/globalthis@1.0.3:
|
||||
resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
@ -45,7 +45,7 @@ async function main () {
|
||||
.replace(/^## v.*?\n/, '')
|
||||
.replace(`...${releaseBranch}`, `...v${newVersion}`)
|
||||
.replace(/### ❤️ Contributors[\s\S]*$/, ''),
|
||||
`### ❤️ Contributors`,
|
||||
'### ❤️ Contributors',
|
||||
contributors.map(c => `- ${c.name} (@${c.username})`).join('\n')
|
||||
].join('\n')
|
||||
|
||||
|
@ -363,7 +363,7 @@ describe('pages', () => {
|
||||
// don't expect any errors or warning on client-side navigation
|
||||
const { page: page2, consoleLogs: consoleLogs2 } = await renderPage('/')
|
||||
await page2.locator('#to-client-only-components').click()
|
||||
await page2.waitForFunction(path => window.useNuxtApp?.()._route.fullPath === path, `/client-only-components`)
|
||||
await page2.waitForFunction(path => window.useNuxtApp?.()._route.fullPath === path, '/client-only-components')
|
||||
expect(consoleLogs2.some(log => log.type === 'error' || log.type === 'warning')).toBeFalsy()
|
||||
await page2.close()
|
||||
})
|
||||
@ -485,14 +485,14 @@ describe('pages', () => {
|
||||
}"
|
||||
`)
|
||||
|
||||
expect(await clientInitialPage.locator('#server-rendered').textContent()).toMatchInlineSnapshot(`"false"`)
|
||||
expect(await clientInitialPage.locator('#server-rendered').textContent()).toMatchInlineSnapshot('"false"')
|
||||
|
||||
// Then go to non client only page
|
||||
await clientInitialPage.click('a')
|
||||
await new Promise((r) => setTimeout(r, 50)) // little delay to finish transition
|
||||
await new Promise(resolve => setTimeout(resolve, 50)) // little delay to finish transition
|
||||
|
||||
// that page should be client rendered
|
||||
expect(await clientInitialPage.locator('#server-rendered').textContent()).toMatchInlineSnapshot(`"false"`)
|
||||
expect(await clientInitialPage.locator('#server-rendered').textContent()).toMatchInlineSnapshot('"false"')
|
||||
// and not contain any errors or warnings
|
||||
expect(errors.length).toBe(0)
|
||||
|
||||
@ -509,7 +509,7 @@ describe('pages', () => {
|
||||
})
|
||||
|
||||
// Now non client only page should be sever rendered
|
||||
expect(await normalInitialPage.locator('#server-rendered').textContent()).toMatchInlineSnapshot(`"true"`)
|
||||
expect(await normalInitialPage.locator('#server-rendered').textContent()).toMatchInlineSnapshot('"true"')
|
||||
|
||||
// Go to client only page
|
||||
await normalInitialPage.click('a')
|
||||
@ -563,7 +563,7 @@ describe('nuxt composables', () => {
|
||||
expect(text).toContain('baz')
|
||||
await page.getByText('Change cookie').click()
|
||||
expect(await extractCookie()).toEqual({ foo: 'bar' })
|
||||
await page.evaluate(() => document.cookie = `browser-object-default=${encodeURIComponent('{"foo":"foobar"}')}`)
|
||||
await page.evaluate(() => { document.cookie = `browser-object-default=${encodeURIComponent('{"foo":"foobar"}')}` })
|
||||
await page.getByText('Refresh cookie').click()
|
||||
text = await page.innerText('pre')
|
||||
expect(text).toContain('foobar')
|
||||
@ -639,7 +639,7 @@ describe('rich payloads', () => {
|
||||
'BigInt ref:',
|
||||
'Reactive: true',
|
||||
'Ref: true',
|
||||
'Recursive objects: true',
|
||||
'Recursive objects: true'
|
||||
]) {
|
||||
expect(html).toContain(test)
|
||||
}
|
||||
@ -731,13 +731,13 @@ describe('nuxt links', () => {
|
||||
await page.locator('#big-page-2').scrollIntoViewIfNeeded()
|
||||
expect(await page.evaluate(() => window.scrollY)).toBeGreaterThan(0)
|
||||
await page.locator('#big-page-2').click()
|
||||
await page.waitForFunction(path => window.useNuxtApp?.()._route.fullPath === path, `/big-page-2`)
|
||||
await page.waitForFunction(path => window.useNuxtApp?.()._route.fullPath === path, '/big-page-2')
|
||||
expect(await page.evaluate(() => window.scrollY)).toBe(0)
|
||||
|
||||
await page.locator('#big-page-1').scrollIntoViewIfNeeded()
|
||||
expect(await page.evaluate(() => window.scrollY)).toBeGreaterThan(0)
|
||||
await page.locator('#big-page-1').click()
|
||||
await page.waitForFunction(path => window.useNuxtApp?.()._route.fullPath === path, `/big-page-1`)
|
||||
await page.waitForFunction(path => window.useNuxtApp?.()._route.fullPath === path, '/big-page-1')
|
||||
expect(await page.evaluate(() => window.scrollY)).toBe(0)
|
||||
await page.close()
|
||||
},
|
||||
@ -754,18 +754,18 @@ describe('nuxt links', () => {
|
||||
height: 1000
|
||||
}
|
||||
})
|
||||
await page.waitForFunction(path => window.useNuxtApp?.()._route.fullPath === path, `/nested/foo/test`)
|
||||
await page.waitForFunction(path => window.useNuxtApp?.()._route.fullPath === path, '/nested/foo/test')
|
||||
|
||||
await page.locator('#user-test').scrollIntoViewIfNeeded()
|
||||
expect(await page.evaluate(() => window.scrollY)).toBeGreaterThan(0)
|
||||
await page.locator('#user-test').click()
|
||||
await page.waitForFunction(path => window.useNuxtApp?.()._route.fullPath === path, `/nested/foo/user-test`)
|
||||
await page.waitForFunction(path => window.useNuxtApp?.()._route.fullPath === path, '/nested/foo/user-test')
|
||||
expect(await page.evaluate(() => window.scrollY)).toBe(0)
|
||||
|
||||
await page.locator('#test').scrollIntoViewIfNeeded()
|
||||
expect(await page.evaluate(() => window.scrollY)).toBeGreaterThan(0)
|
||||
await page.locator('#test').click()
|
||||
await page.waitForFunction(path => window.useNuxtApp?.()._route.fullPath === path, `/nested/foo/test`)
|
||||
await page.waitForFunction(path => window.useNuxtApp?.()._route.fullPath === path, '/nested/foo/test')
|
||||
expect(await page.evaluate(() => window.scrollY)).toBe(0)
|
||||
await page.close()
|
||||
},
|
||||
@ -879,7 +879,7 @@ describe('navigate', () => {
|
||||
const res = await fetch('/navigate-some-path/', { redirect: 'manual', headers: { 'trailing-slash': 'true' } })
|
||||
expect(res.headers.get('location')).toEqual('/navigate-some-path')
|
||||
expect(res.status).toEqual(307)
|
||||
expect(await res.text()).toMatchInlineSnapshot(`"<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=/navigate-some-path"></head></html>"`)
|
||||
expect(await res.text()).toMatchInlineSnapshot('"<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=/navigate-some-path"></head></html>"')
|
||||
})
|
||||
|
||||
it('should not overwrite headers', async () => {
|
||||
@ -1729,9 +1729,9 @@ describe('server components/islands', () => {
|
||||
const text = (await page.innerText('pre')).replaceAll(/ data-island-uid="([^"]*)"/g, '').replace(/data-island-component="([^"]*)"/g, (_, content) => `data-island-component="${content.split('-')[0]}"`)
|
||||
|
||||
if (isWebpack) {
|
||||
expect(text).toMatchInlineSnapshot(`" End page <pre></pre><section id="fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"><!--teleport start--><!--teleport end--></div><!--]--></div></section><section id="no-fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"><!--teleport start--><!--teleport end--></div><!--]--></div></section><div> ServerWithClient.server.vue : <p>count: 0</p> This component should not be preloaded <div><!--[--><div>a</div><div>b</div><div>c</div><!--]--></div> This is not interactive <div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><div class="interactive-component-wrapper" style="border:solid 1px red;"> The component bellow is not a slot but declared as interactive <div class="sugar-counter" nuxt-client=""> Sugar Counter 12 x 1 = 12 <button> Inc </button></div></div></div>"`)
|
||||
expect(text).toMatchInlineSnapshot('" End page <pre></pre><section id="fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"><!--teleport start--><!--teleport end--></div><!--]--></div></section><section id="no-fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"><!--teleport start--><!--teleport end--></div><!--]--></div></section><div> ServerWithClient.server.vue : <p>count: 0</p> This component should not be preloaded <div><!--[--><div>a</div><div>b</div><div>c</div><!--]--></div> This is not interactive <div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><div class="interactive-component-wrapper" style="border:solid 1px red;"> The component bellow is not a slot but declared as interactive <div class="sugar-counter" nuxt-client=""> Sugar Counter 12 x 1 = 12 <button> Inc </button></div></div></div>"')
|
||||
} else {
|
||||
expect(text).toMatchInlineSnapshot(`" End page <pre></pre><section id="fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"><!--teleport start--><!--teleport end--></div><!--]--></div></section><section id="no-fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"><!--teleport start--><!--teleport end--></div><!--]--></div></section><div> ServerWithClient.server.vue : <p>count: 0</p> This component should not be preloaded <div><!--[--><div>a</div><div>b</div><div>c</div><!--]--></div> This is not interactive <div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><div class="interactive-component-wrapper" style="border:solid 1px red;"> The component bellow is not a slot but declared as interactive <!--[--><div style="display: contents;" data-island-component="Counter"></div><!--teleport start--><!--teleport end--><!--]--></div></div>"`)
|
||||
expect(text).toMatchInlineSnapshot('" End page <pre></pre><section id="fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"><!--teleport start--><!--teleport end--></div><!--]--></div></section><section id="no-fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"><!--teleport start--><!--teleport end--></div><!--]--></div></section><div> ServerWithClient.server.vue : <p>count: 0</p> This component should not be preloaded <div><!--[--><div>a</div><div>b</div><div>c</div><!--]--></div> This is not interactive <div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><div class="interactive-component-wrapper" style="border:solid 1px red;"> The component bellow is not a slot but declared as interactive <!--[--><div style="display: contents;" data-island-component="Counter"></div><!--teleport start--><!--teleport end--><!--]--></div></div>"')
|
||||
}
|
||||
expect(text).toContain('async component that was very long')
|
||||
|
||||
@ -1847,7 +1847,7 @@ describe.skipIf(isDev())('dynamic paths', () => {
|
||||
await startServer({
|
||||
env: {
|
||||
NUXT_APP_BUILD_ASSETS_DIR: '/_other/',
|
||||
NUXT_APP_BASE_URL: '/foo/',
|
||||
NUXT_APP_BASE_URL: '/foo/'
|
||||
}
|
||||
})
|
||||
|
||||
@ -1889,7 +1889,7 @@ describe.skipIf(isDev())('dynamic paths', () => {
|
||||
await startServer({
|
||||
env: {
|
||||
NUXT_APP_BUILD_ASSETS_DIR: '/_other/',
|
||||
NUXT_APP_BASE_URL: '/foo/',
|
||||
NUXT_APP_BASE_URL: '/foo/'
|
||||
}
|
||||
})
|
||||
const { headers } = await fetch('/foo/navigate-to/', { redirect: 'manual' })
|
||||
@ -2444,7 +2444,7 @@ describe('keepalive', () => {
|
||||
'keepalive-in-nuxtpage-2',
|
||||
'keepalive-in-nuxtpage',
|
||||
'not-keepalive',
|
||||
'keepalive-in-nuxtpage-2',
|
||||
'keepalive-in-nuxtpage-2'
|
||||
]
|
||||
|
||||
for (const slug of slugs) {
|
||||
|
@ -19,7 +19,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
|
||||
for (const outputDir of ['.output', '.output-inline']) {
|
||||
it('default client bundle size', async () => {
|
||||
const clientStats = await analyzeSizes('**/*.js', join(rootDir, outputDir, 'public'))
|
||||
expect.soft(roundToKilobytes(clientStats.totalBytes)).toMatchInlineSnapshot(`"105k"`)
|
||||
expect.soft(roundToKilobytes(clientStats.totalBytes)).toMatchInlineSnapshot('"105k"')
|
||||
expect(clientStats.files.map(f => f.replace(/\..*\.js/, '.js'))).toMatchInlineSnapshot(`
|
||||
[
|
||||
"_nuxt/entry.js",
|
||||
@ -32,10 +32,10 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
|
||||
const serverDir = join(rootDir, '.output/server')
|
||||
|
||||
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
|
||||
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"205k"`)
|
||||
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"205k"')
|
||||
|
||||
const modules = await analyzeSizes('node_modules/**/*', serverDir)
|
||||
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"1335k"`)
|
||||
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"1335k"')
|
||||
|
||||
const packages = modules.files
|
||||
.filter(m => m.endsWith('package.json'))
|
||||
@ -72,10 +72,10 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
|
||||
const serverDir = join(rootDir, '.output-inline/server')
|
||||
|
||||
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
|
||||
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"524k"`)
|
||||
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"524k"')
|
||||
|
||||
const modules = await analyzeSizes('node_modules/**/*', serverDir)
|
||||
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"78.0k"`)
|
||||
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"78.0k"')
|
||||
|
||||
const packages = modules.files
|
||||
.filter(m => m.endsWith('package.json'))
|
||||
|
2
test/fixtures/basic-types/nuxt.config.ts
vendored
2
test/fixtures/basic-types/nuxt.config.ts
vendored
@ -3,7 +3,7 @@ import { addTypeTemplate } from 'nuxt/kit'
|
||||
export default defineNuxtConfig({
|
||||
experimental: {
|
||||
typedPages: true,
|
||||
appManifest: true,
|
||||
appManifest: true
|
||||
},
|
||||
future: {
|
||||
typescriptBundlerResolution: process.env.MODULE_RESOLUTION === 'bundler'
|
||||
|
2
test/fixtures/basic-types/types.ts
vendored
2
test/fixtures/basic-types/types.ts
vendored
@ -343,7 +343,7 @@ describe('head', () => {
|
||||
// @ts-expect-error wrong return type for head function
|
||||
head () {
|
||||
return {
|
||||
'test': true
|
||||
test: true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -10,40 +10,40 @@ export default defineNuxtModule({
|
||||
addComponent({
|
||||
name: 'DCompClient',
|
||||
filePath: resolve('./runtime/components'),
|
||||
mode: 'client',
|
||||
mode: 'client'
|
||||
})
|
||||
|
||||
addComponent({
|
||||
name: 'DCompServer',
|
||||
filePath: resolve('./runtime/components'),
|
||||
mode: 'server',
|
||||
mode: 'server'
|
||||
})
|
||||
|
||||
addComponent({
|
||||
name: 'DCompAll',
|
||||
filePath: resolve('./runtime/components'),
|
||||
mode: 'all',
|
||||
mode: 'all'
|
||||
})
|
||||
|
||||
addComponent({
|
||||
name: 'NCompClient',
|
||||
export: 'NComp',
|
||||
filePath: resolve('./runtime/components'),
|
||||
mode: 'client',
|
||||
mode: 'client'
|
||||
})
|
||||
|
||||
addComponent({
|
||||
name: 'NCompServer',
|
||||
export: 'NComp',
|
||||
filePath: resolve('./runtime/components'),
|
||||
mode: 'server',
|
||||
mode: 'server'
|
||||
})
|
||||
|
||||
addComponent({
|
||||
name: 'NCompAll',
|
||||
export: 'NComp',
|
||||
filePath: resolve('./runtime/components'),
|
||||
mode: 'all',
|
||||
mode: 'all'
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
|
@ -3,11 +3,11 @@ import { defineComponent, h } from 'vue'
|
||||
export default defineComponent({
|
||||
name: 'DComp',
|
||||
props: { message: String },
|
||||
render: (props: any) => h('h1', props.message),
|
||||
render: (props: any) => h('h1', props.message)
|
||||
})
|
||||
|
||||
export const NComp = defineComponent({
|
||||
name: 'NComp',
|
||||
props: { message: String },
|
||||
render: (props: any) => h('h1', props.message),
|
||||
render: (props: any) => h('h1', props.message)
|
||||
})
|
||||
|
@ -11,21 +11,21 @@ export default defineNuxtModule({
|
||||
name: 'NCompClient',
|
||||
export: 'NComp',
|
||||
filePath: resolve('./runtime/components'),
|
||||
mode: 'client',
|
||||
mode: 'client'
|
||||
})
|
||||
|
||||
addComponent({
|
||||
name: 'NCompServer',
|
||||
export: 'NComp',
|
||||
filePath: resolve('./runtime/components'),
|
||||
mode: 'server',
|
||||
mode: 'server'
|
||||
})
|
||||
|
||||
addComponent({
|
||||
name: 'NCompAll',
|
||||
export: 'NComp',
|
||||
filePath: resolve('./runtime/components'),
|
||||
mode: 'all',
|
||||
mode: 'all'
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
|
@ -3,5 +3,5 @@ import { defineComponent, h } from 'vue'
|
||||
export const NComp = defineComponent({
|
||||
name: 'NComp',
|
||||
props: { message: String },
|
||||
render: (props: any) => h('h1', props.message),
|
||||
render: (props: any) => h('h1', props.message)
|
||||
})
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { defineNuxtModule } from 'nuxt/kit'
|
||||
|
||||
export default defineNuxtModule({
|
||||
meta: { name: 'subpath' },
|
||||
meta: { name: 'subpath' }
|
||||
})
|
||||
|
6
test/fixtures/basic/nuxt.config.ts
vendored
6
test/fixtures/basic/nuxt.config.ts
vendored
@ -101,10 +101,10 @@ export default defineNuxtConfig({
|
||||
addBuildPlugin(plugin)
|
||||
},
|
||||
function (_options, nuxt) {
|
||||
nuxt.hook('pages:extend', pages => {
|
||||
nuxt.hook('pages:extend', (pages) => {
|
||||
pages.push({
|
||||
path: '/manual-redirect',
|
||||
redirect: '/',
|
||||
redirect: '/'
|
||||
})
|
||||
})
|
||||
},
|
||||
@ -201,7 +201,7 @@ export default defineNuxtConfig({
|
||||
}
|
||||
},
|
||||
features: {
|
||||
inlineStyles: id => !!id && !id.includes('assets.vue'),
|
||||
inlineStyles: id => !!id && !id.includes('assets.vue')
|
||||
},
|
||||
experimental: {
|
||||
typedPages: true,
|
||||
|
@ -3,7 +3,7 @@ const state = useState('test', () => {
|
||||
let hasAccessToWindow = null as null | boolean
|
||||
|
||||
try {
|
||||
hasAccessToWindow = Object.keys(window).at(0) ? true : false
|
||||
hasAccessToWindow = !!Object.keys(window).at(0)
|
||||
} catch {
|
||||
hasAccessToWindow = null
|
||||
}
|
||||
|
@ -5,4 +5,3 @@ import css from '~/assets/inline-only.css?inline'
|
||||
<template>
|
||||
<pre>{{ css }}</pre>
|
||||
</template>
|
||||
|
||||
|
2
test/fixtures/basic/pages/node-compat.vue
vendored
2
test/fixtures/basic/pages/node-compat.vue
vendored
@ -3,7 +3,7 @@ import { Buffer } from 'node:buffer'
|
||||
import process from 'node:process'
|
||||
|
||||
const base64 = atob(Buffer.from('Nuxt is Awesome!', 'utf8').toString('base64'))
|
||||
const cwd = typeof process.cwd == 'function' && "[available]"
|
||||
const cwd = typeof process.cwd === 'function' && '[available]'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
1
test/fixtures/basic/pages/use-id.vue
vendored
1
test/fixtures/basic/pages/use-id.vue
vendored
@ -12,4 +12,3 @@ const id = useId()
|
||||
<ComponentWithIds />
|
||||
</form>
|
||||
</template>
|
||||
|
||||
|
2
test/fixtures/basic/server/api/error.ts
vendored
2
test/fixtures/basic/server/api/error.ts
vendored
@ -1,3 +1,3 @@
|
||||
export default defineEventHandler(async () => {
|
||||
export default defineEventHandler(() => {
|
||||
throw createError({ statusCode: 400 })
|
||||
})
|
||||
|
@ -120,21 +120,21 @@ if (process.env.TEST_ENV !== 'built' && !isWindows) {
|
||||
// initial state
|
||||
await expectWithPolling(
|
||||
resolveHmrId,
|
||||
0,
|
||||
0
|
||||
)
|
||||
|
||||
// first edit
|
||||
await triggerHmr()
|
||||
await expectWithPolling(
|
||||
resolveHmrId,
|
||||
1,
|
||||
1
|
||||
)
|
||||
|
||||
// just in-case
|
||||
await triggerHmr()
|
||||
await expectWithPolling(
|
||||
resolveHmrId,
|
||||
2,
|
||||
2
|
||||
)
|
||||
|
||||
// ensure no errors
|
||||
|
@ -42,7 +42,7 @@ registerEndpoint('/_nuxt/builds/meta/override.json', defineEventHandler(() => ({
|
||||
},
|
||||
prerendered: ['/specific-prerendered']
|
||||
})))
|
||||
registerEndpoint('/api/test', defineEventHandler((event) => ({
|
||||
registerEndpoint('/api/test', defineEventHandler(event => ({
|
||||
method: event.method,
|
||||
headers: Object.fromEntries(event.headers.entries())
|
||||
})))
|
||||
@ -106,7 +106,7 @@ describe('composables', () => {
|
||||
'navigateTo',
|
||||
'abortNavigation',
|
||||
'setPageLayout',
|
||||
'defineNuxtComponent',
|
||||
'defineNuxtComponent'
|
||||
]
|
||||
const skippedComposables: string[] = [
|
||||
'addRouteMiddleware',
|
||||
@ -248,7 +248,7 @@ describe('useAsyncData', () => {
|
||||
expect(data.value).toMatchInlineSnapshot('"default"')
|
||||
})
|
||||
|
||||
it('should execute the promise function once when dedupe option is "defer" for multiple calls', async () => {
|
||||
it('should execute the promise function once when dedupe option is "defer" for multiple calls', () => {
|
||||
const promiseFn = vi.fn(() => Promise.resolve('test'))
|
||||
useAsyncData('dedupedKey', promiseFn, { dedupe: 'defer' })
|
||||
useAsyncData('dedupedKey', promiseFn, { dedupe: 'defer' })
|
||||
@ -257,7 +257,7 @@ describe('useAsyncData', () => {
|
||||
expect(promiseFn).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('should execute the promise function multiple times when dedupe option is not specified for multiple calls', async () => {
|
||||
it('should execute the promise function multiple times when dedupe option is not specified for multiple calls', () => {
|
||||
const promiseFn = vi.fn(() => Promise.resolve('test'))
|
||||
useAsyncData('dedupedKey', promiseFn)
|
||||
useAsyncData('dedupedKey', promiseFn)
|
||||
@ -266,7 +266,7 @@ describe('useAsyncData', () => {
|
||||
expect(promiseFn).toHaveBeenCalledTimes(3)
|
||||
})
|
||||
|
||||
it('should execute the promise function as per dedupe option when different dedupe options are used for multiple calls', async () => {
|
||||
it('should execute the promise function as per dedupe option when different dedupe options are used for multiple calls', () => {
|
||||
const promiseFn = vi.fn(() => Promise.resolve('test'))
|
||||
useAsyncData('dedupedKey', promiseFn, { dedupe: 'defer' })
|
||||
useAsyncData('dedupedKey', promiseFn)
|
||||
@ -556,13 +556,13 @@ describe.skipIf(process.env.TEST_MANIFEST === 'manifest-off')('app manifests', (
|
||||
|
||||
describe('routing utilities: `navigateTo`', () => {
|
||||
it('navigateTo should disallow navigation to external URLs by default', () => {
|
||||
expect(() => navigateTo('https://test.com')).toThrowErrorMatchingInlineSnapshot(`[Error: Navigating to an external URL is not allowed by default. Use \`navigateTo(url, { external: true })\`.]`)
|
||||
expect(() => navigateTo('https://test.com')).toThrowErrorMatchingInlineSnapshot('[Error: Navigating to an external URL is not allowed by default. Use `navigateTo(url, { external: true })`.]')
|
||||
expect(() => navigateTo('https://test.com', { external: true })).not.toThrow()
|
||||
})
|
||||
it('navigateTo should disallow navigation to data/script URLs', () => {
|
||||
const urls = [
|
||||
['data:alert("hi")', 'data'],
|
||||
['\0data:alert("hi")', 'data'],
|
||||
['\0data:alert("hi")', 'data']
|
||||
]
|
||||
for (const [url, protocol] of urls) {
|
||||
expect(() => navigateTo(url, { external: true })).toThrowError(`Cannot navigate to a URL with '${protocol}:' protocol.`)
|
||||
@ -571,7 +571,7 @@ describe('routing utilities: `navigateTo`', () => {
|
||||
})
|
||||
|
||||
describe('routing utilities: `useRoute`', () => {
|
||||
it('should show provide a mock route', async () => {
|
||||
it('should show provide a mock route', () => {
|
||||
expect(useRoute()).toMatchObject({
|
||||
fullPath: '/',
|
||||
hash: '',
|
||||
@ -582,7 +582,7 @@ describe('routing utilities: `useRoute`', () => {
|
||||
params: {},
|
||||
path: '/',
|
||||
query: {},
|
||||
redirectedFrom: undefined,
|
||||
redirectedFrom: undefined
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -590,7 +590,7 @@ describe('routing utilities: `useRoute`', () => {
|
||||
describe('routing utilities: `abortNavigation`', () => {
|
||||
it('should throw an error if one is provided', () => {
|
||||
const error = useError()
|
||||
expect(() => abortNavigation({ message: 'Page not found' })).toThrowErrorMatchingInlineSnapshot(`[Error: Page not found]`)
|
||||
expect(() => abortNavigation({ message: 'Page not found' })).toThrowErrorMatchingInlineSnapshot('[Error: Page not found]')
|
||||
expect(error.value).toBeFalsy()
|
||||
})
|
||||
it('should block navigation if no error is provided', () => {
|
||||
@ -607,7 +607,7 @@ describe('routing utilities: `setPageLayout`', () => {
|
||||
route.meta.layout = undefined
|
||||
})
|
||||
|
||||
it('should not set layout directly if run within middleware', async () => {
|
||||
it('should not set layout directly if run within middleware', () => {
|
||||
const route = useRoute()
|
||||
const nuxtApp = useNuxtApp()
|
||||
nuxtApp._processingMiddleware = true
|
||||
@ -632,7 +632,7 @@ describe('useCookie', () => {
|
||||
it('should watch custom cookie refs', () => {
|
||||
const user = useCookie('userInfo', {
|
||||
default: () => ({ score: -1 }),
|
||||
maxAge: 60 * 60,
|
||||
maxAge: 60 * 60
|
||||
})
|
||||
const computedVal = computed(() => user.value.score)
|
||||
expect(computedVal.value).toBe(-1)
|
||||
|
@ -135,7 +135,6 @@ describe('runtime server component', () => {
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('client components', () => {
|
||||
it('expect swapping nuxt-client should not trigger errors #25289', async () => {
|
||||
const mockPath = '/nuxt-client.js'
|
||||
@ -198,7 +197,7 @@ describe('client components', () => {
|
||||
// @ts-expect-error mock
|
||||
vi.mocked(fetch).mockImplementation(() => ({
|
||||
id: '123',
|
||||
html: `<div data-island-uid>hello<div><div>fallback</div></div></div>`,
|
||||
html: '<div data-island-uid>hello<div><div>fallback</div></div></div>',
|
||||
state: {},
|
||||
head: {
|
||||
link: [],
|
||||
@ -267,7 +266,7 @@ describe('client components', () => {
|
||||
default: {
|
||||
name: 'ClientWithSlot',
|
||||
setup (_, { slots }) {
|
||||
return () => h('div', { class: "client-component" }, slots.default())
|
||||
return () => h('div', { class: 'client-component' }, slots.default())
|
||||
}
|
||||
}
|
||||
}))
|
||||
@ -300,7 +299,7 @@ describe('client components', () => {
|
||||
vi.stubGlobal('fetch', stubFetch)
|
||||
const wrapper = await mountSuspended(NuxtIsland, {
|
||||
props: {
|
||||
name: 'NuxtClientWithSlot',
|
||||
name: 'NuxtClientWithSlot'
|
||||
},
|
||||
attachTo: 'body'
|
||||
})
|
||||
|
@ -206,7 +206,7 @@ describe('plugin dependsOn', () => {
|
||||
pluginFactory('A', ['B'], sequence),
|
||||
pluginFactory('B', ['C'], sequence),
|
||||
pluginFactory('C', ['D'], sequence),
|
||||
pluginFactory('D', [], sequence),
|
||||
pluginFactory('D', [], sequence)
|
||||
]
|
||||
|
||||
await applyPlugins(nuxtApp, plugins)
|
||||
@ -251,7 +251,7 @@ describe('plugin dependsOn', () => {
|
||||
const plugins = [
|
||||
pluginFactory('A', undefined, sequence, false),
|
||||
pluginFactory('B', ['A', 'C'], sequence, false),
|
||||
pluginFactory('C', undefined, sequence, false),
|
||||
pluginFactory('C', undefined, sequence, false)
|
||||
]
|
||||
await applyPlugins(nuxtApp, plugins)
|
||||
|
||||
@ -261,7 +261,7 @@ describe('plugin dependsOn', () => {
|
||||
'start C',
|
||||
'end C',
|
||||
'start B',
|
||||
'end B',
|
||||
'end B'
|
||||
])
|
||||
})
|
||||
|
||||
@ -269,8 +269,8 @@ describe('plugin dependsOn', () => {
|
||||
const nuxtApp = useNuxtApp()
|
||||
const sequence: string[] = []
|
||||
const plugins = [
|
||||
pluginFactory('B', undefined, sequence,),
|
||||
pluginFactory('C', ['A', 'B'], sequence,),
|
||||
pluginFactory('B', undefined, sequence),
|
||||
pluginFactory('C', ['A', 'B'], sequence)
|
||||
]
|
||||
await applyPlugins(nuxtApp, plugins)
|
||||
|
||||
@ -278,7 +278,7 @@ describe('plugin dependsOn', () => {
|
||||
'start B',
|
||||
'end B',
|
||||
'start C',
|
||||
'end C',
|
||||
'end C'
|
||||
])
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user