mirror of
https://github.com/nuxt/nuxt.git
synced 2024-12-02 10:27:15 +00:00
refactor(utils, vue-app): use ufo
to parse queries and join urls (#8765)
This commit is contained in:
parent
c8a4b91ad4
commit
119091c8d1
@ -69,7 +69,6 @@ export default () => ({
|
|||||||
fetch: true,
|
fetch: true,
|
||||||
clientOnline: true,
|
clientOnline: true,
|
||||||
clientPrefetch: true,
|
clientPrefetch: true,
|
||||||
clientUseUrl: false,
|
|
||||||
componentAliases: true,
|
componentAliases: true,
|
||||||
componentClientOnly: true
|
componentClientOnly: true
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,6 @@ Object {
|
|||||||
"asyncData": true,
|
"asyncData": true,
|
||||||
"clientOnline": true,
|
"clientOnline": true,
|
||||||
"clientPrefetch": true,
|
"clientPrefetch": true,
|
||||||
"clientUseUrl": false,
|
|
||||||
"componentAliases": true,
|
"componentAliases": true,
|
||||||
"componentClientOnly": true,
|
"componentClientOnly": true,
|
||||||
"deprecations": true,
|
"deprecations": true,
|
||||||
|
@ -164,7 +164,6 @@ Object {
|
|||||||
"asyncData": true,
|
"asyncData": true,
|
||||||
"clientOnline": true,
|
"clientOnline": true,
|
||||||
"clientPrefetch": true,
|
"clientPrefetch": true,
|
||||||
"clientUseUrl": false,
|
|
||||||
"componentAliases": true,
|
"componentAliases": true,
|
||||||
"componentClientOnly": true,
|
"componentClientOnly": true,
|
||||||
"deprecations": true,
|
"deprecations": true,
|
||||||
@ -550,7 +549,6 @@ Object {
|
|||||||
"asyncData": true,
|
"asyncData": true,
|
||||||
"clientOnline": true,
|
"clientOnline": true,
|
||||||
"clientPrefetch": true,
|
"clientPrefetch": true,
|
||||||
"clientUseUrl": false,
|
|
||||||
"componentAliases": true,
|
"componentAliases": true,
|
||||||
"componentClientOnly": true,
|
"componentClientOnly": true,
|
||||||
"deprecations": true,
|
"deprecations": true,
|
||||||
|
3
packages/types/config/features.d.ts
vendored
3
packages/types/config/features.d.ts
vendored
@ -2,6 +2,9 @@ export interface NuxtOptionsFeatures {
|
|||||||
asyncData?: boolean
|
asyncData?: boolean
|
||||||
clientOnline?: boolean
|
clientOnline?: boolean
|
||||||
clientPrefetch?: boolean
|
clientPrefetch?: boolean
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
clientUseUrl?: boolean
|
clientUseUrl?: boolean
|
||||||
componentAliases?: boolean
|
componentAliases?: boolean
|
||||||
componentClientOnly?: boolean
|
componentClientOnly?: boolean
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { joinURL } from 'ufo'
|
||||||
|
|
||||||
export const encodeHtml = function encodeHtml (str) {
|
export const encodeHtml = function encodeHtml (str) {
|
||||||
return str.replace(/</g, '<').replace(/>/g, '>')
|
return str.replace(/</g, '<').replace(/>/g, '>')
|
||||||
}
|
}
|
||||||
@ -12,13 +14,7 @@ export const isUrl = function isUrl (url) {
|
|||||||
return ['http', '//'].some(str => url.startsWith(str))
|
return ['http', '//'].some(str => url.startsWith(str))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const urlJoin = function urlJoin () {
|
export const urlJoin = joinURL
|
||||||
return [].slice
|
|
||||||
.call(arguments)
|
|
||||||
.join('/')
|
|
||||||
.replace(/\/+/g, '/')
|
|
||||||
.replace(':/', '://')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps value in array if it is not already an array
|
* Wraps value in array if it is not already an array
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { stringify } from 'querystring'
|
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { normalizeURL, joinURL } from 'ufo'
|
import { joinURL, normalizeURL, withQuery } from '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 {
|
||||||
@ -58,20 +57,19 @@ const createNext = ssrContext => (opts) => {
|
|||||||
ssrContext.nuxt.serverRendered = false
|
ssrContext.nuxt.serverRendered = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
opts.query = stringify(opts.query)
|
let fullPath = withQuery(opts.path, opts.query)
|
||||||
opts.path = opts.path + (opts.query ? '?' + opts.query : '')
|
|
||||||
const $config = ssrContext.runtimeConfig || {}
|
const $config = ssrContext.runtimeConfig || {}
|
||||||
const routerBase = ($config.app && $config.app.basePath) || '<%= router.base %>'
|
const routerBase = ($config.app && $config.app.basePath) || '<%= router.base %>'
|
||||||
if (!opts.path.startsWith('http') && (routerBase !== '/' && !opts.path.startsWith(routerBase))) {
|
if (!fullPath.startsWith('http') && (routerBase !== '/' && !fullPath.startsWith(routerBase))) {
|
||||||
opts.path = joinURL(routerBase, opts.path)
|
fullPath = joinURL(routerBase, fullPath)
|
||||||
}
|
}
|
||||||
// Avoid loop redirect
|
// Avoid loop redirect
|
||||||
if (decodeURI(opts.path) === decodeURI(ssrContext.url)) {
|
if (decodeURI(fullPath) === decodeURI(ssrContext.url)) {
|
||||||
ssrContext.redirected = false
|
ssrContext.redirected = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ssrContext.res.writeHead(opts.status, {
|
ssrContext.res.writeHead(opts.status, {
|
||||||
Location: normalizeURL(opts.path)
|
Location: normalizeURL(fullPath)
|
||||||
})
|
})
|
||||||
ssrContext.res.end()
|
ssrContext.res.end()
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { normalizeURL } from 'ufo'
|
import { isSamePath as _isSamePath, joinURL, normalizeURL, withQuery, withoutTrailingSlash } from '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)
|
||||||
@ -219,7 +219,7 @@ export async function setContext (app, context) {
|
|||||||
status
|
status
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
path = formatUrl(path, query)
|
path = withQuery(path, query)
|
||||||
if (process.server) {
|
if (process.server) {
|
||||||
app.context.next({
|
app.context.next({
|
||||||
path,
|
path,
|
||||||
@ -594,86 +594,6 @@ function flags (options) {
|
|||||||
return options && options.sensitive ? '' : 'i'
|
return options && options.sensitive ? '' : 'i'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Format given url, append query to url query string
|
|
||||||
*
|
|
||||||
* @param {string} url
|
|
||||||
* @param {string} query
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
function formatUrl (url, query) {
|
|
||||||
<% if (features.clientUseUrl) { %>
|
|
||||||
url = new URL(url, top.location.href)
|
|
||||||
for (const key in query) {
|
|
||||||
const value = query[key]
|
|
||||||
if (value == null) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
for (const arrayValue of value) {
|
|
||||||
url.searchParams.append(key, arrayValue)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
url.searchParams.append(key, value)
|
|
||||||
}
|
|
||||||
url.searchParams.sort()
|
|
||||||
return url.toString()
|
|
||||||
<% } else { %>
|
|
||||||
let protocol
|
|
||||||
const index = url.indexOf('://')
|
|
||||||
if (index !== -1) {
|
|
||||||
protocol = url.substring(0, index)
|
|
||||||
url = url.substring(index + 3)
|
|
||||||
} else if (url.startsWith('//')) {
|
|
||||||
url = url.substring(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
let parts = url.split('/')
|
|
||||||
let result = (protocol ? protocol + '://' : '//') + parts.shift()
|
|
||||||
|
|
||||||
let path = parts.join('/')
|
|
||||||
if (path === '' && parts.length === 1) {
|
|
||||||
result += '/'
|
|
||||||
}
|
|
||||||
|
|
||||||
let hash
|
|
||||||
parts = path.split('#')
|
|
||||||
if (parts.length === 2) {
|
|
||||||
[path, hash] = parts
|
|
||||||
}
|
|
||||||
|
|
||||||
result += path ? '/' + path : ''
|
|
||||||
|
|
||||||
if (query && JSON.stringify(query) !== '{}') {
|
|
||||||
result += (url.split('?').length === 2 ? '&' : '?') + formatQuery(query)
|
|
||||||
}
|
|
||||||
result += hash ? '#' + hash : ''
|
|
||||||
|
|
||||||
return result
|
|
||||||
<% } %>
|
|
||||||
}
|
|
||||||
<% if (!features.clientUseUrl) { %>
|
|
||||||
/**
|
|
||||||
* Transform data object to query string
|
|
||||||
*
|
|
||||||
* @param {object} query
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
function formatQuery (query) {
|
|
||||||
return Object.keys(query).sort().map((key) => {
|
|
||||||
const val = query[key]
|
|
||||||
if (val == null) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
if (Array.isArray(val)) {
|
|
||||||
return val.slice().map(val2 => [key, '=', val2].join('')).join('&')
|
|
||||||
}
|
|
||||||
return key + '=' + val
|
|
||||||
}).filter(Boolean).join('&')
|
|
||||||
}
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
export function addLifecycleHook(vm, hook, fn) {
|
export function addLifecycleHook(vm, hook, fn) {
|
||||||
if (!vm.$options[hook]) {
|
if (!vm.$options[hook]) {
|
||||||
vm.$options[hook] = []
|
vm.$options[hook] = []
|
||||||
@ -683,21 +603,11 @@ export function addLifecycleHook(vm, hook, fn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function urlJoin () {
|
export const urlJoin = joinURL
|
||||||
return [].slice
|
|
||||||
.call(arguments)
|
|
||||||
.join('/')
|
|
||||||
.replace(/\/+/g, '/')
|
|
||||||
.replace(':/', '://')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stripTrailingSlash (path) {
|
export const stripTrailingSlash = withoutTrailingSlash
|
||||||
return path.replace(/\/+$/, '') || '/'
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isSamePath (p1, p2) {
|
export const isSamePath = _isSamePath
|
||||||
return stripTrailingSlash(p1) === stripTrailingSlash(p2)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setScrollRestoration (newVal) {
|
export function setScrollRestoration (newVal) {
|
||||||
try {
|
try {
|
||||||
|
Loading…
Reference in New Issue
Block a user