From 186e46378b69408cca85bde2f375819a65b2243c Mon Sep 17 00:00:00 2001 From: Ahad Birang Date: Wed, 21 Sep 2022 13:11:49 +0200 Subject: [PATCH] feat(document-driven): support `navigation.redirect` from `_dir` files (#1545) --- src/runtime/plugins/documentDriven.ts | 13 ++++++++++--- src/runtime/server/api/query.ts | 15 +++++++++++++++ test/document-driven.test.ts | 7 ++++++- .../document-driven/content/redirect/_dir.yml | 1 + 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/document-driven/content/redirect/_dir.yml diff --git a/src/runtime/plugins/documentDriven.ts b/src/runtime/plugins/documentDriven.ts index ebbd70419..a77c6f7df 100644 --- a/src/runtime/plugins/documentDriven.ts +++ b/src/runtime/plugins/documentDriven.ts @@ -1,7 +1,7 @@ import type { RouteLocationNormalized, RouteLocationNormalizedLoaded } from 'vue-router' // @ts-ignore -import { useRuntimeConfig, addRouteMiddleware } from '#app' -import { withoutTrailingSlash } from 'ufo' +import { useRuntimeConfig, addRouteMiddleware, callWithNuxt, navigateTo } from '#app' +import { withoutTrailingSlash, hasProtocol } from 'ufo' import { NavItem, ParsedContent } from '../types' // @ts-ignore import { defineNuxtPlugin, queryContent, useContentHelpers, useContentState, fetchContentNavigation, useRoute } from '#imports' @@ -224,6 +224,7 @@ export default defineNuxtPlugin((nuxt) => { // Use `redirect` key to redirect to another page if (_page?.redirect) { return _page?.redirect } + if (_page?._dir?.navigation?.redirect) { return _page?._dir?.navigation?.redirect } if (_page) { // Find used layout @@ -258,7 +259,13 @@ export default defineNuxtPlugin((nuxt) => { const redirect = await refresh(to, false) - if (redirect) { return redirect } + if (redirect) { + if (hasProtocol(redirect)) { + return callWithNuxt(nuxt, navigateTo, [redirect, { external: true }]) + } else { + return redirect + } + } }) if (process.server) { diff --git a/src/runtime/server/api/query.ts b/src/runtime/server/api/query.ts index a8b9e33e5..ca80d9528 100644 --- a/src/runtime/server/api/query.ts +++ b/src/runtime/server/api/query.ts @@ -1,4 +1,5 @@ import { createError, defineEventHandler } from 'h3' +import { join } from 'pathe' import { serverQueryContent } from '../storage' import { getContentQuery } from '../../utils/query' @@ -6,6 +7,20 @@ export default defineEventHandler(async (event) => { const query = getContentQuery(event) const contents = await serverQueryContent(event, query).find() + if (query.first) { + const path = contents?._path || query.where.find(w => w._path)?._path + if (path) { + const _dir = await serverQueryContent(event).where({ _path: join(path, '_dir') }).without('_').findOne() + if (!Array.isArray(_dir)) { + return { + _path: path, + ...contents, + _dir + } + } + } + } + // If no documents matchs and using findOne() if (query.first && Array.isArray(contents) && contents.length === 0) { throw createError({ diff --git a/test/document-driven.test.ts b/test/document-driven.test.ts index c418631d1..1e0659a20 100644 --- a/test/document-driven.test.ts +++ b/test/document-driven.test.ts @@ -1,6 +1,6 @@ import { fileURLToPath } from 'url' import { test, describe, expect } from 'vitest' -import { setup, $fetch } from '@nuxt/test-utils' +import { setup, $fetch, url } from '@nuxt/test-utils' describe('fixtures:document-driven', async () => { await setup({ @@ -69,4 +69,9 @@ describe('fixtures:document-driven', async () => { expect(e.response.statusText).toBe('Not Found') } }) + + test('redirect in `_dir.yml`', async () => { + const response = await fetch(url('/redirect')) + expect(response.url).toBe('https://nuxtjs.org/') + }) }) diff --git a/test/fixtures/document-driven/content/redirect/_dir.yml b/test/fixtures/document-driven/content/redirect/_dir.yml new file mode 100644 index 000000000..b8a0c441b --- /dev/null +++ b/test/fixtures/document-driven/content/redirect/_dir.yml @@ -0,0 +1 @@ +navigation.redirect: https://nuxtjs.org \ No newline at end of file