v2.14.10 [hotfix]

This commit is contained in:
Pooya Parsa 2020-12-07 11:37:14 +01:00
commit 85bb97906c
32 changed files with 256 additions and 189 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "nuxt-start", "name": "nuxt-start",
"version": "2.14.9", "version": "2.14.10",
"description": "Starts Nuxt Application in production mode", "description": "Starts Nuxt Application in production mode",
"keywords": [ "keywords": [
"nuxt", "nuxt",
@ -55,9 +55,9 @@
"dist" "dist"
], ],
"dependencies": { "dependencies": {
"@nuxt/cli": "2.14.9", "@nuxt/cli": "2.14.10",
"@nuxt/core": "2.14.9", "@nuxt/core": "2.14.10",
"@nuxt/telemetry": "^1.2.3", "@nuxt/telemetry": "^1.3.0",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"vue": "^2.6.12", "vue": "^2.6.12",
"vue-client-only": "^2.0.0", "vue-client-only": "^2.0.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "nuxt", "name": "nuxt",
"version": "2.14.9", "version": "2.14.10",
"description": "A minimalistic framework for server-rendered Vue.js applications (inspired by Next.js)", "description": "A minimalistic framework for server-rendered Vue.js applications (inspired by Next.js)",
"keywords": [ "keywords": [
"nuxt", "nuxt",
@ -58,15 +58,15 @@
"postinstall": "opencollective || exit 0" "postinstall": "opencollective || exit 0"
}, },
"dependencies": { "dependencies": {
"@nuxt/builder": "2.14.9", "@nuxt/builder": "2.14.10",
"@nuxt/cli": "2.14.9", "@nuxt/cli": "2.14.10",
"@nuxt/components": "^1.2.1", "@nuxt/components": "^1.2.1",
"@nuxt/core": "2.14.9", "@nuxt/core": "2.14.10",
"@nuxt/generator": "2.14.9", "@nuxt/generator": "2.14.10",
"@nuxt/loading-screen": "^2.0.3", "@nuxt/loading-screen": "^2.0.3",
"@nuxt/opencollective": "^0.3.2", "@nuxt/opencollective": "^0.3.2",
"@nuxt/telemetry": "^1.2.3", "@nuxt/telemetry": "^1.3.0",
"@nuxt/webpack": "2.14.9" "@nuxt/webpack": "2.14.10"
}, },
"engines": { "engines": {
"node": ">=10.13.0", "node": ">=10.13.0",

View File

@ -1,5 +1,5 @@
{ {
"version": "2.14.9", "version": "2.14.10",
"npmClient": "yarn", "npmClient": "yarn",
"useWorkspaces": true, "useWorkspaces": true,
"conventionalCommits": true, "conventionalCommits": true,

View File

@ -1,6 +1,6 @@
{ {
"name": "@nuxt/babel-preset-app", "name": "@nuxt/babel-preset-app",
"version": "2.14.9", "version": "2.14.10",
"description": "babel-preset-app for nuxt", "description": "babel-preset-app for nuxt",
"repository": "nuxt/nuxt.js", "repository": "nuxt/nuxt.js",
"license": "MIT", "license": "MIT",

View File

@ -1,6 +1,6 @@
{ {
"name": "@nuxt/builder", "name": "@nuxt/builder",
"version": "2.14.9", "version": "2.14.10",
"repository": "nuxt/nuxt.js", "repository": "nuxt/nuxt.js",
"license": "MIT", "license": "MIT",
"main": "dist/builder.js", "main": "dist/builder.js",
@ -9,9 +9,9 @@
], ],
"dependencies": { "dependencies": {
"@nuxt/devalue": "^1.2.4", "@nuxt/devalue": "^1.2.4",
"@nuxt/utils": "2.14.9", "@nuxt/utils": "2.14.10",
"@nuxt/vue-app": "2.14.9", "@nuxt/vue-app": "2.14.10",
"@nuxt/webpack": "2.14.9", "@nuxt/webpack": "2.14.10",
"chalk": "^4.1.0", "chalk": "^4.1.0",
"chokidar": "^3.4.3", "chokidar": "^3.4.3",
"consola": "^2.15.0", "consola": "^2.15.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "@nuxt/cli", "name": "@nuxt/cli",
"version": "2.14.9", "version": "2.14.10",
"repository": "nuxt/nuxt.js", "repository": "nuxt/nuxt.js",
"license": "MIT", "license": "MIT",
"main": "dist/cli.js", "main": "dist/cli.js",
@ -12,8 +12,8 @@
"dist" "dist"
], ],
"dependencies": { "dependencies": {
"@nuxt/config": "2.14.9", "@nuxt/config": "2.14.10",
"@nuxt/utils": "2.14.9", "@nuxt/utils": "2.14.10",
"boxen": "^4.2.0", "boxen": "^4.2.0",
"chalk": "^4.1.0", "chalk": "^4.1.0",
"compression": "^1.7.4", "compression": "^1.7.4",

View File

@ -1,6 +1,6 @@
{ {
"name": "@nuxt/config", "name": "@nuxt/config",
"version": "2.14.9", "version": "2.14.10",
"repository": "nuxt/nuxt.js", "repository": "nuxt/nuxt.js",
"license": "MIT", "license": "MIT",
"main": "dist/config.js", "main": "dist/config.js",
@ -10,7 +10,8 @@
"index.d.ts" "index.d.ts"
], ],
"dependencies": { "dependencies": {
"@nuxt/utils": "2.14.9", "@nuxt/ufo": "^0.0.3",
"@nuxt/utils": "2.14.10",
"consola": "^2.15.0", "consola": "^2.15.0",
"create-require": "^1.1.1", "create-require": "^1.1.1",
"defu": "^3.2.2", "defu": "^3.2.2",

View File

@ -7,6 +7,7 @@ import uniq from 'lodash/uniq'
import consola from 'consola' import consola from 'consola'
import destr from 'destr' import destr from 'destr'
import { TARGETS, MODES, guardDir, isNonEmptyString, isPureObject, isUrl, getMainModule, urlJoin, getPKG } from '@nuxt/utils' import { TARGETS, MODES, guardDir, isNonEmptyString, isPureObject, isUrl, getMainModule, urlJoin, getPKG } from '@nuxt/utils'
import { normalizeURL } from '@nuxt/ufo'
import { defaultNuxtConfigFile, getDefaultNuxtConfig } from './config' import { defaultNuxtConfigFile, getDefaultNuxtConfig } from './config'
export function getNuxtConfig (_options) { export function getNuxtConfig (_options) {
@ -126,7 +127,7 @@ export function getNuxtConfig (_options) {
if (!/\/$/.test(options.router.base)) { if (!/\/$/.test(options.router.base)) {
options.router.base += '/' options.router.base += '/'
} }
options.router.base = encodeURI(decodeURI(options.router.base)) options.router.base = normalizeURL(options.router.base)
// Legacy support for export // Legacy support for export
if (options.export) { if (options.export) {

View File

@ -1,6 +1,6 @@
{ {
"name": "@nuxt/core", "name": "@nuxt/core",
"version": "2.14.9", "version": "2.14.10",
"repository": "nuxt/nuxt.js", "repository": "nuxt/nuxt.js",
"license": "MIT", "license": "MIT",
"main": "dist/core.js", "main": "dist/core.js",
@ -8,11 +8,11 @@
"dist" "dist"
], ],
"dependencies": { "dependencies": {
"@nuxt/config": "2.14.9", "@nuxt/config": "2.14.10",
"@nuxt/devalue": "^1.2.4", "@nuxt/devalue": "^1.2.4",
"@nuxt/server": "2.14.9", "@nuxt/server": "2.14.10",
"@nuxt/utils": "2.14.9", "@nuxt/utils": "2.14.10",
"@nuxt/vue-renderer": "2.14.9", "@nuxt/vue-renderer": "2.14.10",
"consola": "^2.15.0", "consola": "^2.15.0",
"debug": "^4.2.0", "debug": "^4.2.0",
"esm": "^3.2.25", "esm": "^3.2.25",

View File

@ -1,6 +1,6 @@
{ {
"name": "@nuxt/generator", "name": "@nuxt/generator",
"version": "2.14.9", "version": "2.14.10",
"repository": "nuxt/nuxt.js", "repository": "nuxt/nuxt.js",
"license": "MIT", "license": "MIT",
"main": "dist/generator.js", "main": "dist/generator.js",
@ -8,7 +8,7 @@
"dist" "dist"
], ],
"dependencies": { "dependencies": {
"@nuxt/utils": "2.14.9", "@nuxt/utils": "2.14.10",
"chalk": "^4.1.0", "chalk": "^4.1.0",
"consola": "^2.15.0", "consola": "^2.15.0",
"devalue": "^2.0.1", "devalue": "^2.0.1",

View File

@ -1,6 +1,6 @@
{ {
"name": "@nuxt/server", "name": "@nuxt/server",
"version": "2.14.9", "version": "2.14.10",
"repository": "nuxt/nuxt.js", "repository": "nuxt/nuxt.js",
"license": "MIT", "license": "MIT",
"main": "dist/server.js", "main": "dist/server.js",
@ -8,9 +8,9 @@
"dist" "dist"
], ],
"dependencies": { "dependencies": {
"@nuxt/config": "2.14.9", "@nuxt/config": "2.14.10",
"@nuxt/utils": "2.14.9", "@nuxt/utils": "2.14.10",
"@nuxt/vue-renderer": "2.14.9", "@nuxt/vue-renderer": "2.14.10",
"@nuxtjs/youch": "^4.2.3", "@nuxtjs/youch": "^4.2.3",
"chalk": "^4.1.0", "chalk": "^4.1.0",
"compression": "^1.7.4", "compression": "^1.7.4",

View File

@ -162,12 +162,16 @@ export default class Server {
})) }))
// DX: redirect if router.base in development // DX: redirect if router.base in development
if (this.options.dev && this.nuxt.options.router.base !== '/') { const routerBase = this.nuxt.options.router.base
if (this.options.dev && routerBase !== '/') {
this.useMiddleware({ this.useMiddleware({
prefix: false, prefix: false,
handler: (req, res) => { handler: (req, res, next) => {
const to = urlJoin(this.nuxt.options.router.base, req.url) if (decodeURI(req.url).startsWith(decodeURI(routerBase))) {
consola.info(`[Development] Redirecting from \`${decodeURI(req.url)}\` to \`${decodeURI(to)}\` (router.base specified).`) return next()
}
const to = urlJoin(routerBase, req.url)
consola.info(`[Development] Redirecting from \`${decodeURI(req.url)}\` to \`${decodeURI(to)}\` (router.base specified)`)
res.writeHead(302, { res.writeHead(302, {
Location: to Location: to
}) })

View File

@ -1,6 +1,6 @@
{ {
"name": "@nuxt/types", "name": "@nuxt/types",
"version": "2.14.9", "version": "2.14.10",
"description": "Nuxt types", "description": "Nuxt types",
"repository": "nuxt/nuxt.js", "repository": "nuxt/nuxt.js",
"license": "MIT", "license": "MIT",

View File

@ -1,6 +1,6 @@
{ {
"name": "@nuxt/utils", "name": "@nuxt/utils",
"version": "2.14.9", "version": "2.14.10",
"repository": "nuxt/nuxt.js", "repository": "nuxt/nuxt.js",
"license": "MIT", "license": "MIT",
"main": "dist/utils.js", "main": "dist/utils.js",
@ -8,6 +8,7 @@
"dist" "dist"
], ],
"dependencies": { "dependencies": {
"@nuxt/ufo": "^0.0.3",
"consola": "^2.15.0", "consola": "^2.15.0",
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"hash-sum": "^2.0.0", "hash-sum": "^2.0.0",

View File

@ -1,7 +1,7 @@
import path from 'path' import path from 'path'
import get from 'lodash/get' import get from 'lodash/get'
import consola from 'consola' import consola from 'consola'
import { normalizeURL } from '@nuxt/ufo'
import { r } from './resolve' import { r } from './resolve'
const routeChildren = function (route) { const routeChildren = function (route) {
@ -201,10 +201,8 @@ export const createRoutes = function createRoutes ({
} else if (key === 'index' && i + 1 === keys.length) { } else if (key === 'index' && i + 1 === keys.length) {
route.path += i > 0 ? '' : '/' route.path += i > 0 ? '' : '/'
} else { } else {
const isDynamic = key.startsWith('_') route.path += normalizeURL(getRoutePathExtension(key))
route.path += '/' + getRoutePathExtension(isDynamic ? key : encodeURIComponent(decodeURIComponent(key))) if (key.startsWith('_') && key.length > 1) {
if (isDynamic && key.length > 1) {
route.path += '?' route.path += '?'
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@nuxt/vue-app", "name": "@nuxt/vue-app",
"version": "2.14.9", "version": "2.14.10",
"repository": "nuxt/nuxt.js", "repository": "nuxt/nuxt.js",
"license": "MIT", "license": "MIT",
"main": "dist/vue-app.js", "main": "dist/vue-app.js",
@ -13,6 +13,7 @@
"index.d.ts" "index.d.ts"
], ],
"dependencies": { "dependencies": {
"@nuxt/ufo": "^0.0.3",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"unfetch": "^4.2.0", "unfetch": "^4.2.0",
"vue": "^2.6.12", "vue": "^2.6.12",

View File

@ -1,5 +1,6 @@
import Vue from 'vue' import Vue from 'vue'
import Router from 'vue-router' import Router from 'vue-router'
import { normalizeURL } from '@nuxt/ufo'
import { interopDefault } from './utils'<%= isTest ? '// eslint-disable-line no-unused-vars' : '' %> import { interopDefault } from './utils'<%= isTest ? '// eslint-disable-line no-unused-vars' : '' %>
import scrollBehavior from './router.scrollBehavior.js' import scrollBehavior from './router.scrollBehavior.js'
@ -105,16 +106,27 @@ export const routerOptions = {
fallback: <%= router.fallback %> fallback: <%= router.fallback %>
} }
function decodeObj(obj) {
for (const key in obj) {
if (typeof obj[key] === 'string') {
obj[key] = decodeURIComponent(obj[key])
}
}
}
export function createRouter () { export function createRouter () {
const router = new Router(routerOptions) const router = new Router(routerOptions)
const resolve = router.resolve.bind(router)
// encodeURI(decodeURI()) ~> support both encoded and non-encoded urls const resolve = router.resolve.bind(router)
router.resolve = (to, current, append) => { router.resolve = (to, current, append) => {
if (typeof to === 'string') { if (typeof to === 'string') {
to = encodeURI(decodeURI(to)) to = normalizeURL(to)
} }
return resolve(to, current, append) const r = resolve(to, current, append)
if (r && r.resolved && r.resolved.query) {
decodeObj(r.resolved.query)
}
return r
} }
return router return router

View File

@ -1,5 +1,6 @@
import { stringify } from 'querystring' import { stringify } from 'querystring'
import Vue from 'vue' import Vue from 'vue'
import { normalizeURL } from '@nuxt/ufo'
<% if (fetch.server) { %>import fetch from 'node-fetch'<% } %> <% if (fetch.server) { %>import fetch from 'node-fetch'<% } %>
<% if (features.middleware) { %>import middleware from './middleware.js'<% } %> <% if (features.middleware) { %>import middleware from './middleware.js'<% } %>
import { import {
@ -50,12 +51,12 @@ const createNext = ssrContext => (opts) => {
opts.path = urlJoin(routerBase, opts.path) opts.path = urlJoin(routerBase, opts.path)
} }
// Avoid loop redirect // Avoid loop redirect
if (encodeURI(decodeURI(opts.path)) === ssrContext.url) { if (decodeURI(opts.path) === decodeURI(ssrContext.url)) {
ssrContext.redirected = false ssrContext.redirected = false
return return
} }
ssrContext.res.writeHead(opts.status, { ssrContext.res.writeHead(opts.status, {
Location: opts.path Location: normalizeURL(opts.path)
}) })
ssrContext.res.end() ssrContext.res.end()
} }

View File

@ -1,4 +1,5 @@
import Vue from 'vue' import Vue from 'vue'
import { normalizeURL } from '@nuxt/ufo'
// window.{{globals.loadedCallback}} hook // window.{{globals.loadedCallback}} hook
// Useful for jsdom testing or plugins (https://github.com/tmpvar/jsdom#dealing-with-asynchronous-script-loading) // Useful for jsdom testing or plugins (https://github.com/tmpvar/jsdom#dealing-with-asynchronous-script-loading)
@ -309,7 +310,7 @@ export function getLocation (base, mode) {
const fullPath = (path || '/') + window.location.search + window.location.hash const fullPath = (path || '/') + window.location.search + window.location.hash
return encodeURI(fullPath) return normalizeURL(fullPath)
} }
// Imported from path-to-regexp // Imported from path-to-regexp
@ -692,3 +693,4 @@ export function setScrollRestoration (newVal) {
window.history.scrollRestoration = newVal; window.history.scrollRestoration = newVal;
} catch(e) {} } catch(e) {}
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@nuxt/vue-renderer", "name": "@nuxt/vue-renderer",
"version": "2.14.9", "version": "2.14.10",
"repository": "nuxt/nuxt.js", "repository": "nuxt/nuxt.js",
"license": "MIT", "license": "MIT",
"main": "dist/vue-renderer.js", "main": "dist/vue-renderer.js",
@ -9,7 +9,7 @@
], ],
"dependencies": { "dependencies": {
"@nuxt/devalue": "^1.2.4", "@nuxt/devalue": "^1.2.4",
"@nuxt/utils": "2.14.9", "@nuxt/utils": "2.14.10",
"consola": "^2.15.0", "consola": "^2.15.0",
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"lru-cache": "^5.1.1", "lru-cache": "^5.1.1",

View File

@ -3,6 +3,7 @@ import fs from 'fs-extra'
import consola from 'consola' import consola from 'consola'
import template from 'lodash/template' import template from 'lodash/template'
import { TARGETS, isModernRequest, waitFor } from '@nuxt/utils' import { TARGETS, isModernRequest, waitFor } from '@nuxt/utils'
import { normalizeURL } from '@nuxt/ufo'
import SPARenderer from './renderers/spa' import SPARenderer from './renderers/spa'
import SSRRenderer from './renderers/ssr' import SSRRenderer from './renderers/ssr'
@ -274,7 +275,7 @@ export default class VueRenderer {
consola.debug(`Rendering url ${url}`) consola.debug(`Rendering url ${url}`)
// Add url to the renderContext // Add url to the renderContext
renderContext.url = encodeURI(decodeURI(url)) renderContext.url = normalizeURL(url)
// Add target to the renderContext // Add target to the renderContext
renderContext.target = this.options.target renderContext.target = this.options.target

View File

@ -1,6 +1,6 @@
{ {
"name": "@nuxt/webpack", "name": "@nuxt/webpack",
"version": "2.14.9", "version": "2.14.10",
"repository": "nuxt/nuxt.js", "repository": "nuxt/nuxt.js",
"license": "MIT", "license": "MIT",
"main": "dist/webpack.js", "main": "dist/webpack.js",
@ -9,9 +9,9 @@
], ],
"dependencies": { "dependencies": {
"@babel/core": "^7.12.9", "@babel/core": "^7.12.9",
"@nuxt/babel-preset-app": "2.14.9", "@nuxt/babel-preset-app": "2.14.10",
"@nuxt/friendly-errors-webpack-plugin": "^2.5.0", "@nuxt/friendly-errors-webpack-plugin": "^2.5.0",
"@nuxt/utils": "2.14.9", "@nuxt/utils": "2.14.10",
"babel-loader": "^8.2.2", "babel-loader": "^8.2.2",
"cache-loader": "^4.1.0", "cache-loader": "^4.1.0",
"caniuse-lite": "^1.0.30001165", "caniuse-lite": "^1.0.30001165",

View File

@ -73,6 +73,7 @@ export default class WebpackBaseConfig {
return [ return [
/\.vue\.js/i, // include SFCs in node_modules /\.vue\.js/i, // include SFCs in node_modules
/consola\/src/, /consola\/src/,
/@nuxt[/\\]ufo/, // exports modern syntax for browser field
...this.normalizeTranspile({ pathNormalize: true }) ...this.normalizeTranspile({ pathNormalize: true })
] ]
} }

View File

@ -20,7 +20,7 @@ describe('nuxt basic resources size limit', () => {
it('should stay within the size limit range in legacy mode', async () => { it('should stay within the size limit range in legacy mode', async () => {
const legacyResourcesSize = await getResourcesSize(distDir, 'client', { gzip: true, brotli: true }) const legacyResourcesSize = await getResourcesSize(distDir, 'client', { gzip: true, brotli: true })
const LEGACY_JS_RESOURCES_KB_SIZE = 200 const LEGACY_JS_RESOURCES_KB_SIZE = 201
expect(legacyResourcesSize.uncompressed).toBeWithinSize(LEGACY_JS_RESOURCES_KB_SIZE) expect(legacyResourcesSize.uncompressed).toBeWithinSize(LEGACY_JS_RESOURCES_KB_SIZE)
const LEGACY_JS_RESOURCES_GZIP_KB_SIZE = 70 const LEGACY_JS_RESOURCES_GZIP_KB_SIZE = 70

View File

@ -5,98 +5,86 @@ import { promisify } from 'util'
const readFile = promisify(fs.readFile) const readFile = promisify(fs.readFile)
describe('dynamic routes', () => { describe('dynamic routes', () => {
test('Check .nuxt/router.js', () => { test('Check .nuxt/routes.json', async () => {
return readFile( const routesFile = await readFile(resolve(__dirname, '..', 'fixtures/dynamic-routes/.nuxt/routes.json'), 'utf-8')
resolve(__dirname, '..', 'fixtures/dynamic-routes/.nuxt/router.js'), const routes = JSON.parse(routesFile)
'utf-8' // pages/test/index.vue
).then((routerFile) => { expect(routes[0].path).toBe('/parent')
routerFile = routerFile expect(routes[0].name).toBeFalsy() // parent route has no name
.slice(routerFile.indexOf('routes: [')) // pages/parent/*.vue
.replace('routes: [', '[') expect(routes[0].children.length).toBe(3) // parent has 3 children
.replace(/ _[0-9A-Za-z]+,/g, ' "",') expect(routes[0].children.map(r => r.path)).toEqual(['', 'child', 'teub'])
routerFile = routerFile.substr( expect(routes[0].children.map(r => r.name)).toEqual([
routerFile.indexOf('['), 'parent',
routerFile.lastIndexOf(']') + 1 'parent-child',
) 'parent-teub'
const routes = eval('( ' + routerFile + ')') // eslint-disable-line no-eval ])
// pages/test/index.vue // pages/posts.vue
expect(routes[0].path).toBe('/parent') expect(routes[1].path).toBe('/posts')
expect(routes[0].name).toBeFalsy() // parent route has no name expect(routes[1].name).toBe('posts')
// pages/parent/*.vue expect(routes[1].children.length).toBe(1)
expect(routes[0].children.length).toBe(3) // parent has 3 children // pages/posts/_id.vue
expect(routes[0].children.map(r => r.path)).toEqual(['', 'child', 'teub']) expect(routes[1].children[0].path).toBe(':id?')
expect(routes[0].children.map(r => r.name)).toEqual([ expect(routes[1].children[0].name).toBe('posts-id')
'parent', // pages/parent.vue
'parent-child', expect(routes[2].path).toBe('/test')
'parent-teub' expect(routes[2].name).toBe('test')
]) // pages/test/projects/index.vue
// pages/posts.vue expect(routes[3].path).toBe('/test/projects')
expect(routes[1].path).toBe('/posts') expect(routes[3].name).toBe('test-projects')
expect(routes[1].name).toBe('posts') // pages/test/users.vue
expect(routes[1].children.length).toBe(1) expect(routes[4].path).toBe('/test/users')
// pages/posts/_id.vue expect(routes[4].name).toBeFalsy() // parent route has no name
expect(routes[1].children[0].path).toBe(':id?') // pages/test/users/*.vue
expect(routes[1].children[0].name).toBe('posts-id') expect(routes[4].children.length).toBe(5) // parent has 5 children
// pages/parent.vue expect(routes[4].children.map(r => r.path)).toEqual([
expect(routes[2].path).toBe('/test') '',
expect(routes[2].name).toBe('test') 'projects',
// pages/test/projects/index.vue 'projects/:category',
expect(routes[3].path).toBe('/test/projects') ':id',
expect(routes[3].name).toBe('test-projects') ':index/teub'
// pages/test/users.vue ])
expect(routes[4].path).toBe('/test/users') expect(routes[4].children.map(r => r.name)).toEqual([
expect(routes[4].name).toBeFalsy() // parent route has no name 'test-users',
// pages/test/users/*.vue 'test-users-projects',
expect(routes[4].children.length).toBe(5) // parent has 5 children 'test-users-projects-category',
expect(routes[4].children.map(r => r.path)).toEqual([ 'test-users-id',
'', 'test-users-index-teub'
'projects', ])
'projects/:category', // pages/test/songs/toto.vue
':id', expect(routes[5].path).toBe('/test/songs/toto')
':index/teub' expect(routes[5].name).toBe('test-songs-toto')
]) // pages/test/projects/_category.vue
expect(routes[4].children.map(r => r.name)).toEqual([ expect(routes[6].path).toBe('/test/projects/:category')
'test-users', expect(routes[6].name).toBe('test-projects-category')
'test-users-projects', // pages/test/songs/_id.vue
'test-users-projects-category', expect(routes[7].path).toBe('/test/songs/:id?')
'test-users-id', expect(routes[7].name).toBe('test-songs-id')
'test-users-index-teub' // pages/users/_id.vue
]) expect(routes[8].path).toBe('/users/:id?')
// pages/test/songs/toto.vue expect(routes[8].name).toBe('users-id')
expect(routes[5].path).toBe('/test/songs/toto') // pages/test/_.vue
expect(routes[5].name).toBe('test-songs-toto') expect(routes[9].path).toBe('/test/*')
// pages/test/projects/_category.vue expect(routes[9].name).toBe('test-all')
expect(routes[6].path).toBe('/test/projects/:category')
expect(routes[6].name).toBe('test-projects-category')
// pages/test/songs/_id.vue
expect(routes[7].path).toBe('/test/songs/:id?')
expect(routes[7].name).toBe('test-songs-id')
// pages/users/_id.vue
expect(routes[8].path).toBe('/users/:id?')
expect(routes[8].name).toBe('users-id')
// pages/test/_.vue
expect(routes[9].path).toBe('/test/*')
expect(routes[9].name).toBe('test-all')
// pages/index.vue // pages/index.vue
expect(routes[10].path).toBe('/') expect(routes[10].path).toBe('/')
expect(routes[10].name).toBe('index') expect(routes[10].name).toBe('index')
// pages/_slug.vue // pages/_slug.vue
expect(routes[11].path).toBe('/:slug') expect(routes[11].path).toBe('/:slug')
expect(routes[11].name).toBe('slug') expect(routes[11].name).toBe('slug')
// pages/_key/_id.vue // pages/_key/_id.vue
expect(routes[12].path).toBe('/:key/:id?') expect(routes[12].path).toBe('/:key/:id?')
expect(routes[12].name).toBe('key-id') expect(routes[12].name).toBe('key-id')
// pages/_.vue // pages/_.vue
expect(routes[13].path).toBe('/*/p/*') expect(routes[13].path).toBe('/*/p/*')
expect(routes[13].name).toBe('all-p-all') expect(routes[13].name).toBe('all-p-all')
// pages/_/_.vue // pages/_/_.vue
expect(routes[14].path).toBe('/*/*') expect(routes[14].path).toBe('/*/*')
expect(routes[14].name).toBe('all-all') expect(routes[14].name).toBe('all-all')
// pages/_.vue // pages/_.vue
expect(routes[15].path).toBe('/*') expect(routes[15].path).toBe('/*')
expect(routes[15].name).toBe('all') expect(routes[15].name).toBe('all')
})
}) })
}) })

View File

@ -21,6 +21,18 @@ describe('encoding', () => {
expect(response).toContain('Unicode base works!') expect(response).toContain('Unicode base works!')
}) })
test('/ö/dynamic?q=food,coffee (encodeURIComponent)', async () => {
const { body: response } = await rp(url('/ö/dynamic?q=food%252Ccoffee'))
expect(response).toContain('food,coffee')
})
test('/ö/@about', async () => {
const { body: response } = await rp(url('/ö/@about'))
expect(response).toContain('About')
})
// Close server and ask nuxt to stop listening to file changes // Close server and ask nuxt to stop listening to file changes
afterAll(async () => { afterAll(async () => {
await nuxt.close() await nuxt.close()

View File

@ -5,29 +5,16 @@ import { promisify } from 'util'
const readFile = promisify(fs.readFile) const readFile = promisify(fs.readFile)
describe('route-name-splitter', () => { describe('route-name-splitter', () => {
test('Check routes names', () => { test('Check routes names', async () => {
return readFile( const routesFile = await readFile(resolve(__dirname, '..', 'fixtures/route-name-splitter/.nuxt/routes.json'), 'utf-8')
resolve(__dirname, '..', 'fixtures/route-name-splitter/.nuxt/router.js'), const routes = JSON.parse(routesFile)
'utf-8' expect(routes[0].name).toBe('parent')
).then((routerFile) => { expect(routes[1].name).toBe('posts')
routerFile = routerFile expect(routes[1].children[0].name).toBe('posts/id')
.slice(routerFile.indexOf('routes: [')) expect(routes[2].name).toBe('parent/child')
.replace('routes: [', '[') expect(routes[3].name).toBe('index')
.replace(/ _[0-9A-Za-z]+,/g, ' "",') expect(routes[4].name).toBe('all/p/all')
routerFile = routerFile.substr( expect(routes[5].name).toBe('all/all')
routerFile.indexOf('['), expect(routes[6].name).toBe('all')
routerFile.lastIndexOf(']') + 1
)
const routes = eval('( ' + routerFile + ')') // eslint-disable-line no-eval
expect(routes[0].name).toBe('parent')
expect(routes[1].name).toBe('posts')
expect(routes[1].children[0].name).toBe('posts/id')
expect(routes[2].name).toBe('parent/child')
expect(routes[3].name).toBe('index')
expect(routes[4].name).toBe('all/p/all')
expect(routes[5].name).toBe('all/all')
expect(routes[6].name).toBe('all')
})
}) })
}) })

View File

@ -1,24 +1,41 @@
<template> <template>
<div> <div>
<div> <div>
<NLink to="/тест"> <ul>
/тест <li v-for="link in links" :key="link">
</NLink> <NLink :to="link">
<NLink :to="encodeURI('/тест')"> {{ link }}
/тест (encoded) </NLink>
</NLink> <NLink :to="link.includes('?') ? link.replace('?', '?spa&') : (link + '?spa')">
<br> (spa)
<NLink to="/тест?spa"> </NLink>
/тест (SPA) <a :href="encodeURI('/ö') + link">(direct)</a>
</NLink> </li>
<NLink :to="encodeURI('/тест?spa')"> </ul>
/тест (SPA encoded)
</NLink>
</div> </div>
<Nuxt /> <Nuxt />
</div> </div>
</template> </template>
<script>
export default {
computed: {
links () {
return [
'/redirect',
'/@about',
'/тест',
encodeURI('/тест'),
'/dynamic/سلام چطوری?q=cofee,food,دسر',
encodeURI('/dynamic/سلام چطوری?q=cofee,food,دسر'),
// Using encodeURIComponent on each segment
'/dynamic/%D8%B3%D9%84%D8%A7%D9%85%20%DA%86%D8%B7%D9%88%D8%B1%DB%8C?q=cofee%2Cfood%2C%D8%AF%D8%B3%D8%B1'
]
}
}
}
</script>
<style scoped> <style scoped>
a { a {
color: grey; color: grey;

View File

@ -0,0 +1,5 @@
<template>
<div>
About
</div>
</template>

View File

@ -0,0 +1,17 @@
<template>
<div>
<div>Query (SSR): <pre v-text="q" /> </div>
<div>Params (SSR): <pre v-text="p" /> </div>
</div>
</template>
<script>
export default {
asyncData ({ route }) {
return {
q: JSON.stringify(route.query),
p: JSON.stringify(route.params)
}
}
}
</script>

View File

@ -0,0 +1,13 @@
<template>
<div>
Redirecting...
</div>
</template>
<script>
export default {
asyncData ({ redirect }) {
return redirect('/dynamic/重新导向?foo bar')
}
}
</script>

View File

@ -1938,7 +1938,7 @@
consola "^2.15.0" consola "^2.15.0"
node-fetch "^2.6.1" node-fetch "^2.6.1"
"@nuxt/telemetry@^1.2.3": "@nuxt/telemetry@^1.3.0":
version "1.3.0" version "1.3.0"
resolved "https://registry.npmjs.org/@nuxt/telemetry/-/telemetry-1.3.0.tgz#0c6595c786c4fcb060ea8508aaf6285dce8201e0" resolved "https://registry.npmjs.org/@nuxt/telemetry/-/telemetry-1.3.0.tgz#0c6595c786c4fcb060ea8508aaf6285dce8201e0"
integrity sha512-anAhyccoVyy/RetkqVsIxpJKdAu/GHyLl79ZtH0oOCbYcC85k8d+LC1S10WcqXyeqyUKifLxGR6yPqSPmQCCtg== integrity sha512-anAhyccoVyy/RetkqVsIxpJKdAu/GHyLl79ZtH0oOCbYcC85k8d+LC1S10WcqXyeqyUKifLxGR6yPqSPmQCCtg==
@ -1962,6 +1962,11 @@
rc9 "^1.2.0" rc9 "^1.2.0"
std-env "^2.2.1" std-env "^2.2.1"
"@nuxt/ufo@^0.0.3":
version "0.0.3"
resolved "https://registry.npmjs.org/@nuxt/ufo/-/ufo-0.0.3.tgz#7673a54b81c020e7aea3a9e01e09a58c494a1eca"
integrity sha512-LQkuVafVNB9+ggRF7443AX1V1rEWRs32Frk7F2qnRLf8j/SzRzxEZ99jiZqxVho72zU7NcWQ6Jy62m4fkZC6Wg==
"@nuxtjs/eslint-config@^5.0.0": "@nuxtjs/eslint-config@^5.0.0":
version "5.0.0" version "5.0.0"
resolved "https://registry.npmjs.org/@nuxtjs/eslint-config/-/eslint-config-5.0.0.tgz#d66143ee4ada9d944de0bfbe2d7e4693a2e20d60" resolved "https://registry.npmjs.org/@nuxtjs/eslint-config/-/eslint-config-5.0.0.tgz#d66143ee4ada9d944de0bfbe2d7e4693a2e20d60"