UNPKG

nuxt

Version:

[![Nuxt banner](./.github/assets/banner.png)](https://nuxt.com)

162 lines (161 loc) 5.74 kB
import { getCurrentInstance, hasInjectionContext, inject, onUnmounted } from "vue"; import { sanitizeStatusCode } from "h3"; import { hasProtocol, joinURL, parseURL, withQuery } from "ufo"; import { useNuxtApp, useRuntimeConfig } from "../nuxt.js"; import { createError, showError } from "./error.js"; import { useState } from "./state.js"; export const useRouter = () => { return useNuxtApp()?.$router; }; export const useRoute = () => { if (process.dev && isProcessingMiddleware()) { console.warn("[nuxt] Calling `useRoute` within middleware may lead to misleading results. Instead, use the (to, from) arguments passed to the middleware to access the new and old routes."); } if (hasInjectionContext()) { return inject("_route", useNuxtApp()._route); } return useNuxtApp()._route; }; export const onBeforeRouteLeave = (guard) => { const unsubscribe = useRouter().beforeEach((to, from, next) => { if (to === from) { return; } return guard(to, from, next); }); onUnmounted(unsubscribe); }; export const onBeforeRouteUpdate = (guard) => { const unsubscribe = useRouter().beforeEach(guard); onUnmounted(unsubscribe); }; /*! @__NO_SIDE_EFFECTS__ */ export function defineNuxtRouteMiddleware(middleware) { return middleware; } export const addRouteMiddleware = (name, middleware, options = {}) => { const nuxtApp = useNuxtApp(); const global = options.global || typeof name !== "string"; const mw = typeof name !== "string" ? name : middleware; if (!mw) { console.warn("[nuxt] No route middleware passed to `addRouteMiddleware`.", name); return; } if (global) { nuxtApp._middleware.global.push(mw); } else { nuxtApp._middleware.named[name] = mw; } }; const isProcessingMiddleware = () => { try { if (useNuxtApp()._processingMiddleware) { return true; } } catch { return true; } return false; }; export const navigateTo = (to, options) => { if (!to) { to = "/"; } const toPath = typeof to === "string" ? to : withQuery(to.path || "/", to.query || {}) + (to.hash || ""); if (options?.open) { if (process.client) { const { target = "_blank", windowFeatures = {} } = options.open; const features = Object.entries(windowFeatures).filter(([_, value]) => value !== void 0).map(([feature, value]) => `${feature.toLowerCase()}=${value}`).join(", "); open(toPath, target, features); } return Promise.resolve(); } const isExternal = options?.external || hasProtocol(toPath, { acceptRelative: true }); if (isExternal && !options?.external) { throw new Error("Navigating to external URL is not allowed by default. Use `navigateTo (url, { external: true })`."); } if (isExternal && parseURL(toPath).protocol === "script:") { throw new Error("Cannot navigate to an URL with script protocol."); } const inMiddleware = isProcessingMiddleware(); if (process.client && !isExternal && inMiddleware) { return to; } const router = useRouter(); const nuxtApp = useNuxtApp(); if (process.server) { if (nuxtApp.ssrContext) { const fullPath = typeof to === "string" || isExternal ? toPath : router.resolve(to).fullPath || "/"; const location2 = isExternal ? toPath : joinURL(useRuntimeConfig().app.baseURL, fullPath); async function redirect(response) { await nuxtApp.callHook("app:redirected"); const encodedLoc = location2.replace(/"/g, "%22"); nuxtApp.ssrContext._renderResponse = { statusCode: sanitizeStatusCode(options?.redirectCode || 302, 302), body: `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${encodedLoc}"></head></html>`, headers: { location: location2 } }; return response; } if (!isExternal && inMiddleware) { router.afterEach((final) => final.fullPath === fullPath ? redirect(false) : void 0); return to; } return redirect(!inMiddleware ? void 0 : ( /* abort route navigation */ false )); } } if (isExternal) { if (options?.replace) { location.replace(toPath); } else { location.href = toPath; } if (inMiddleware) { if (!nuxtApp.isHydrating) { return false; } return new Promise(() => { }); } return Promise.resolve(); } return options?.replace ? router.replace(to) : router.push(to); }; export const abortNavigation = (err) => { if (process.dev && !isProcessingMiddleware()) { throw new Error("abortNavigation() is only usable inside a route middleware handler."); } if (!err) { return false; } err = createError(err); if (err.fatal) { useNuxtApp().runWithContext(() => showError(err)); } throw err; }; export const setPageLayout = (layout) => { if (process.server) { if (process.dev && getCurrentInstance() && useState("_layout").value !== layout) { console.warn("[warn] [nuxt] `setPageLayout` should not be called to change the layout on the server within a component as this will cause hydration errors."); } useState("_layout").value = layout; } const nuxtApp = useNuxtApp(); if (process.dev && nuxtApp.isHydrating && nuxtApp.payload.serverRendered && useState("_layout").value !== layout) { console.warn("[warn] [nuxt] `setPageLayout` should not be called to change the layout during hydration as this will cause hydration errors."); } const inMiddleware = isProcessingMiddleware(); if (inMiddleware || process.server || nuxtApp.isHydrating) { const unsubscribe = useRouter().beforeResolve((to) => { to.meta.layout = layout; unsubscribe(); }); } if (!inMiddleware) { useRoute().meta.layout = layout; } };