From b15c47f9b065bdeb89e88017a0ccdf112c4a1191 Mon Sep 17 00:00:00 2001 From: Ahad Birang Date: Tue, 13 Dec 2022 12:43:07 +0100 Subject: [PATCH 1/4] fix(query): keep track of all contents in the Index Contents with same `_path` and different locales should exist in the Index --- src/runtime/server/content-index.ts | 16 +++++++--------- src/runtime/transformers/markdown.ts | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/runtime/server/content-index.ts b/src/runtime/server/content-index.ts index 0faa7f534..3c7cf9fbe 100644 --- a/src/runtime/server/content-index.ts +++ b/src/runtime/server/content-index.ts @@ -4,19 +4,16 @@ import { isPreview } from './preview' import { cacheStorage, getContent, getContentsList, serverQueryContent } from './storage' export async function getContentIndex (event: H3Event) { - let contentIndex = await cacheStorage.getItem('content-index.json') as Record + let contentIndex = await cacheStorage.getItem('content-index.json') as Record if (!contentIndex) { - // Fetch all content + // Fetch all contents const data = await serverQueryContent(event).find() contentIndex = data.reduce((acc, item) => { - if (!acc[item._path!]) { - acc[item._path!] = item._id - } else if (item._id.startsWith('content:')) { - acc[item._path!] = item._id - } + acc[item._path!] = acc[item._path!] || [] + acc[item._path!].push(item._id) return acc - }, {} as Record) + }, {} as Record) await cacheStorage.setItem('content-index.json', contentIndex) } @@ -33,9 +30,10 @@ export async function getIndexedContentsList (event: H3Event, const index = await getContentIndex(event) const keys = Object.keys(index) .filter(key => (path as any).test ? (path as any).test(key) : key === String(path)) - .map(key => index[key]) + .flatMap(key => index[key]) const contents = await Promise.all(keys.map(key => getContent(event, key))) + return contents as unknown as Promise } diff --git a/src/runtime/transformers/markdown.ts b/src/runtime/transformers/markdown.ts index d032db83f..31304f241 100644 --- a/src/runtime/transformers/markdown.ts +++ b/src/runtime/transformers/markdown.ts @@ -23,7 +23,7 @@ export default defineTransformer({ }) async function importPlugins (plugins: Record = {}) { - const resolvedPlugins = {} + const resolvedPlugins: Record = {} for (const [name, plugin] of Object.entries(plugins)) { if (plugin) { resolvedPlugins[name] = { From 4e13325a579eda2f6725c7b01af259cc6b4a6649 Mon Sep 17 00:00:00 2001 From: Ahad Birang Date: Tue, 13 Dec 2022 13:41:36 +0100 Subject: [PATCH 2/4] test: add tests --- src/module.ts | 3 +++ src/runtime/server/content-index.ts | 12 +++++++++--- test/basic.test.ts | 3 +++ test/features/locales.ts | 15 +++++++++++++++ test/fixtures/basic/content-fa/translated.md | 1 + test/fixtures/basic/content/translated.md | 1 + test/fixtures/basic/nuxt.config.ts | 3 ++- 7 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 test/features/locales.ts create mode 100644 test/fixtures/basic/content-fa/translated.md create mode 100644 test/fixtures/basic/content/translated.md diff --git a/src/module.ts b/src/module.ts index 951c0c4b4..abcf7c210 100644 --- a/src/module.ts +++ b/src/module.ts @@ -281,6 +281,9 @@ export default defineNuxtModule({ const { resolve } = createResolver(import.meta.url) const resolveRuntimeModule = (path: string) => resolveModule(path, { paths: resolve('./runtime') }) + // Ensure default locale alway is the first item of locales + options.locales = Array.from(new Set([options.defaultLocale, ...options.locales].filter(Boolean))) as string[] + // Disable cache in dev mode const buildIntegrity = nuxt.options.dev ? undefined : Date.now() diff --git a/src/runtime/server/content-index.ts b/src/runtime/server/content-index.ts index 3c7cf9fbe..5cd0d32c4 100644 --- a/src/runtime/server/content-index.ts +++ b/src/runtime/server/content-index.ts @@ -1,17 +1,23 @@ import type { H3Event } from 'h3' import type { ParsedContent, QueryBuilder } from '../types' import { isPreview } from './preview' -import { cacheStorage, getContent, getContentsList, serverQueryContent } from './storage' +import { cacheStorage, getContent, getContentsList } from './storage' +import { useRuntimeConfig } from '#imports' export async function getContentIndex (event: H3Event) { + const defaultLocale = useRuntimeConfig().content.defaultLocale let contentIndex = await cacheStorage.getItem('content-index.json') as Record if (!contentIndex) { // Fetch all contents - const data = await serverQueryContent(event).find() + const data = await getContentsList(event) contentIndex = data.reduce((acc, item) => { acc[item._path!] = acc[item._path!] || [] - acc[item._path!].push(item._id) + if (item._locale === defaultLocale) { + acc[item._path!].unshift(item._id) + } else { + acc[item._path!].push(item._id) + } return acc }, {} as Record) diff --git a/test/basic.test.ts b/test/basic.test.ts index 01146952e..4b4fe0a70 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -18,6 +18,7 @@ import { testHighlighter } from './features/highlighter' import { testMarkdownRenderer } from './features/renderer-markdown' import { testParserOptions } from './features/parser-options' import { testComponents } from './features/components' +import { testLocales } from './features/locales' const spyConsoleWarn = vi.spyOn(global.console, 'warn') @@ -131,6 +132,8 @@ describe('Basic usage', async () => { expect(spyConsoleWarn).toHaveBeenCalledWith('Ignoring [content:with-\'invalid\'-char.md]. File name should not contain any of the following characters: \', ", ?, #, /') }) + testLocales() + testComponents() testContentQuery() diff --git a/test/features/locales.ts b/test/features/locales.ts new file mode 100644 index 000000000..a0792e100 --- /dev/null +++ b/test/features/locales.ts @@ -0,0 +1,15 @@ +import { describe, expect, test } from 'vitest' +import { $fetch, useTestContext } from '@nuxt/test-utils' + +export const testLocales = () => { + // @ts-ignore + const apiBaseUrl = useTestContext().options.nuxtConfig.content?.api?.baseURL || '/api/_content' + + describe('Locales', () => { + test('Path with multiple locales', async () => { + const params = { where: [{ _path: '/translated' }] } + const content = await $fetch(`${apiBaseUrl}/query`, { params: { _params: JSON.stringify(params) } }) + expect(content.length === 2) + }) + }) +} diff --git a/test/fixtures/basic/content-fa/translated.md b/test/fixtures/basic/content-fa/translated.md new file mode 100644 index 000000000..58c102ba9 --- /dev/null +++ b/test/fixtures/basic/content-fa/translated.md @@ -0,0 +1 @@ +# Translated to Farsi \ No newline at end of file diff --git a/test/fixtures/basic/content/translated.md b/test/fixtures/basic/content/translated.md new file mode 100644 index 000000000..012d8f298 --- /dev/null +++ b/test/fixtures/basic/content/translated.md @@ -0,0 +1 @@ +# Translate Me \ No newline at end of file diff --git a/test/fixtures/basic/nuxt.config.ts b/test/fixtures/basic/nuxt.config.ts index 821f656d8..4b2da0c79 100644 --- a/test/fixtures/basic/nuxt.config.ts +++ b/test/fixtures/basic/nuxt.config.ts @@ -23,7 +23,8 @@ export default defineNuxtConfig({ }, modules: [contentModule], content: { - locales: ['en', 'fa'], + locales: ['fa', 'en'], + defaultLocale: 'en', sources: [ { name: 'fa-ir', From 5f9d5b50dcb17ffff2b07dde5c50bd54594b15e9 Mon Sep 17 00:00:00 2001 From: Ahad Birang Date: Wed, 14 Dec 2022 13:07:23 +0100 Subject: [PATCH 3/4] fix: filter locales --- src/module.ts | 6 ++ src/runtime/composables/navigation.ts | 10 +++ src/runtime/composables/query.ts | 9 ++ src/runtime/server/storage.ts | 9 ++ test/__snapshots__/basic.test.ts.snap | 38 ++++++++ .../custom-api-base.test.ts.snap | 38 ++++++++ test/basic.test.ts | 86 +----------------- test/custom-api-base.test.ts | 89 +------------------ test/features/content-query.ts | 48 +++++++++- test/features/locales.ts | 29 +++++- test/features/renderer-markdown.ts | 21 +++++ 11 files changed, 209 insertions(+), 174 deletions(-) diff --git a/src/module.ts b/src/module.ts index abcf7c210..97ab428c0 100644 --- a/src/module.ts +++ b/src/module.ts @@ -567,6 +567,8 @@ export default defineNuxtModule({ contentContext.markdown = processMarkdownOptions(contentContext.markdown) nuxt.options.runtimeConfig.public.content = defu(nuxt.options.runtimeConfig.public.content, { + locales: options.locales, + defaultLocale: contentContext.defaultLocale, integrity: buildIntegrity, clientDB: { isSPA: options.experimental.clientDB && nuxt.options.ssr === false @@ -682,6 +684,10 @@ interface ModulePublicRuntimeConfig { integrity: number } + defaultLocale: ModuleOptions['defaultLocale'] + + locales: ModuleOptions['locales'] + tags: Record base: string; diff --git a/src/runtime/composables/navigation.ts b/src/runtime/composables/navigation.ts index 735c3a16b..fce33a92f 100644 --- a/src/runtime/composables/navigation.ts +++ b/src/runtime/composables/navigation.ts @@ -10,6 +10,16 @@ export const fetchContentNavigation = async (queryBuilder?: QueryBuilder | Query // When params is an instance of QueryBuilder then we need to pick the params explicitly const params: QueryBuilderParams = typeof queryBuilder?.params === 'function' ? queryBuilder.params() : queryBuilder + // Filter by locale if: + // - locales are defined + // - query doesn't already have a locale filter + if (content.locales.length) { + const queryLocale = params.where?.find(w => w._locale)?._locale + const locale = queryLocale || content.defaultLocale + params.where = params.where || [] + params.where.push({ _locale: locale }) + } + const _apiPath = params ? `/navigation/${hash(params)}` : '/navigation/' const apiPath = withContentBase(process.dev ? _apiPath : `${_apiPath}.${content.integrity}.json`) diff --git a/src/runtime/composables/query.ts b/src/runtime/composables/query.ts index 386f1a1fa..86676b89b 100644 --- a/src/runtime/composables/query.ts +++ b/src/runtime/composables/query.ts @@ -25,6 +25,15 @@ export const createQueryFetch = (path?: string) => async (que query.sort({ _file: 1, $numeric: true }) } + // Filter by locale if: + // - locales are defined + // - query doesn't already have a locale filter + if (content.locales.length) { + const queryLocale = query.params().where?.find(w => w._locale)?._locale + const locale = queryLocale || content.defaultLocale + query.locale(locale) + } + const params = query.params() const apiPath = withContentBase(process.dev ? '/query' : `/query/${hash(params)}.${content.integrity}.json`) diff --git a/src/runtime/server/storage.ts b/src/runtime/server/storage.ts index 60e6cffd2..d3b3d6d0e 100644 --- a/src/runtime/server/storage.ts +++ b/src/runtime/server/storage.ts @@ -199,6 +199,15 @@ export const createServerQueryFetch = (event: H3Event, path?: query.sort({ _file: 1, $numeric: true }) } + // Filter by locale if: + // - locales are defined + // - query doesn't already have a locale filter + if (contentConfig.locales.length) { + const queryLocale = query.params().where?.find(w => w._locale)?._locale + const locale = queryLocale || contentConfig.defaultLocale + query.locale(locale) + } + return createPipelineFetcher(() => getIndexedContentsList(event, query))(query) } diff --git a/test/__snapshots__/basic.test.ts.snap b/test/__snapshots__/basic.test.ts.snap index e5e530c2d..3bf23beaa 100644 --- a/test/__snapshots__/basic.test.ts.snap +++ b/test/__snapshots__/basic.test.ts.snap @@ -1,5 +1,43 @@ // Vitest Snapshot v1 +exports[`Basic usage > Content Queries > Get contents index > basic-index-body 1`] = ` +{ + "children": [ + { + "children": [ + { + "type": "text", + "value": "Index", + }, + ], + "props": { + "id": "index", + }, + "tag": "h1", + "type": "element", + }, + { + "children": [ + { + "type": "text", + "value": "Hello World", + }, + ], + "props": {}, + "tag": "p", + "type": "element", + }, + ], + "toc": { + "depth": 2, + "links": [], + "searchDepth": 2, + "title": "", + }, + "type": "root", +} +`; + exports[`Basic usage > Get contents index > basic-index-body 1`] = ` { "children": [ diff --git a/test/__snapshots__/custom-api-base.test.ts.snap b/test/__snapshots__/custom-api-base.test.ts.snap index 0888e41b6..28aa70e76 100644 --- a/test/__snapshots__/custom-api-base.test.ts.snap +++ b/test/__snapshots__/custom-api-base.test.ts.snap @@ -1,5 +1,43 @@ // Vitest Snapshot v1 +exports[`Custom api baseURL > Content Queries > Get contents index > basic-index-body 1`] = ` +{ + "children": [ + { + "children": [ + { + "type": "text", + "value": "Index", + }, + ], + "props": { + "id": "index", + }, + "tag": "h1", + "type": "element", + }, + { + "children": [ + { + "type": "text", + "value": "Hello World", + }, + ], + "props": {}, + "tag": "p", + "type": "element", + }, + ], + "toc": { + "depth": 2, + "links": [], + "searchDepth": 2, + "title": "", + }, + "type": "root", +} +`; + exports[`Custom api baseURL > Get contents index > basic-index-body 1`] = ` { "children": [ diff --git a/test/basic.test.ts b/test/basic.test.ts index 4b4fe0a70..e0814101f 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -1,7 +1,6 @@ import { fileURLToPath } from 'url' -import { assert, test, describe, expect, vi } from 'vitest' +import { test, describe, expect, vi } from 'vitest' import { setup, $fetch } from '@nuxt/test-utils' -import { hash } from 'ohash' import { testMarkdownParser } from './features/parser-markdown' import { testPathMetaTransformer } from './features/transformer-path-meta' import { testYamlParser } from './features/parser-yaml' @@ -28,94 +27,11 @@ describe('Basic usage', async () => { server: true }) - const QUERY_ENDPOINT = '/api/_content/query' - const fetchDocument = (_id: string) => { - const params = { first: true, where: { _id } } - const qid = hash(params) - return $fetch(`${QUERY_ENDPOINT}/${qid}`, { - params: { _params: JSON.stringify(params) } - }) - } - - test('List contents', async () => { - const params = { only: '_id' } - const qid = hash(params) - const docs = await $fetch(`${QUERY_ENDPOINT}/${qid}`, { - params: { _params: JSON.stringify(params) } - }) - - const ids = docs.map(doc => doc._id) - - assert(ids.length > 0) - assert(ids.includes('content:index.md')) - - // Ignored files should be listed - assert(ids.includes('content:.dot-ignored.md') === false, 'Ignored files with `.` should not be listed') - assert(ids.includes('content:-dash-ignored.md') === false, 'Ignored files with `-` should not be listed') - - assert(ids.includes('fa-ir:fa:hello.md') === true, 'Files with `fa-ir` prefix should be listed') - }) - - test('Get contents index', async () => { - const index = await fetchDocument('content:index.md') - - expect(index).toHaveProperty('body') - - expect(index.body).toMatchSnapshot('basic-index-body') - }) - - test('Get ignored contents', async () => { - const ignored = await fetchDocument('content:.dot-ignored.md').catch(_err => null) - - expect(ignored).toBeNull() - }) - - test('Search contents using `locale` helper', async () => { - const fa = await $fetch('/locale-fa') - - expect(fa).toContain('fa-ir:fa:hello.md') - expect(fa).not.toContain('content:index.md') - - const en = await $fetch('/locale-en') - - expect(en).not.toContain('fa-ir:fa:hello.md') - expect(en).toContain('content:index.md') - }) - - test('Use default locale for unscoped contents', async () => { - const index = await fetchDocument('content:index.md') - - expect(index).toMatchObject({ - _locale: 'en' - }) - }) - test('Multi part path', async () => { const html = await $fetch('/features/multi-part-path') expect(html).contains('Persian') }) - test('Empty slot', async () => { - const html = await $fetch('/features/empty-slot') - expect(html).contains('Nullish Document!!!') - expect(html).contains('Empty Child!!!') - }) - - test(' head management (if same path)', async () => { - const html = await $fetch('/head') - expect(html).contains('Head overwritten') - expect(html).contains('') - expect(html).contains('') - expect(html).contains('') - }) - - test(' head management (not same path)', async () => { - const html = await $fetch('/bypass-head') - expect(html).not.contains('Head overwritten') - expect(html).not.contains('') - expect(html).not.contains('') - }) - test('Partials specials chars', async () => { const html = await $fetch('/_partial/content-(v2)') expect(html).contains('Content (v2)') diff --git a/test/custom-api-base.test.ts b/test/custom-api-base.test.ts index c07b6a4f6..289d640b9 100644 --- a/test/custom-api-base.test.ts +++ b/test/custom-api-base.test.ts @@ -1,7 +1,6 @@ import { fileURLToPath } from 'url' -import { assert, test, describe, expect, vi } from 'vitest' +import { test, describe, expect, vi } from 'vitest' import { setup, $fetch } from '@nuxt/test-utils' -import { hash } from 'ohash' import { testMarkdownParser } from './features/parser-markdown' import { testPathMetaTransformer } from './features/transformer-path-meta' import { testYamlParser } from './features/parser-yaml' @@ -18,6 +17,7 @@ import { testHighlighter } from './features/highlighter' import { testMarkdownRenderer } from './features/renderer-markdown' import { testParserOptions } from './features/parser-options' import { testComponents } from './features/components' +import { testLocales } from './features/locales' const spyConsoleWarn = vi.spyOn(global.console, 'warn') const apiBaseURL = '/my-content-api' @@ -36,94 +36,11 @@ describe('Custom api baseURL', async () => { } }) - const QUERY_ENDPOINT = `${apiBaseURL}/query` - const fetchDocument = (_id: string) => { - const params = { first: true, where: { _id } } - const qid = hash(params) - return $fetch(`${QUERY_ENDPOINT}/${qid}`, { - params: { _params: JSON.stringify(params) } - }) - } - - test('List contents', async () => { - const params = { only: '_id' } - const qid = hash(params) - const docs = await $fetch(`${QUERY_ENDPOINT}/${qid}`, { - params: { _params: JSON.stringify(params) } - }) - - const ids = docs.map(doc => doc._id) - - assert(ids.length > 0) - assert(ids.includes('content:index.md')) - - // Ignored files should be listed - assert(ids.includes('content:.dot-ignored.md') === false, 'Ignored files with `.` should not be listed') - assert(ids.includes('content:-dash-ignored.md') === false, 'Ignored files with `-` should not be listed') - - assert(ids.includes('fa-ir:fa:hello.md') === true, 'Files with `fa-ir` prefix should be listed') - }) - - test('Get contents index', async () => { - const index = await fetchDocument('content:index.md') - - expect(index).toHaveProperty('body') - - expect(index.body).toMatchSnapshot('basic-index-body') - }) - - test('Get ignored contents', async () => { - const ignored = await fetchDocument('content:.dot-ignored.md').catch(_err => null) - - expect(ignored).toBeNull() - }) - - test('Search contents using `locale` helper', async () => { - const fa = await $fetch('/locale-fa') - - expect(fa).toContain('fa-ir:fa:hello.md') - expect(fa).not.toContain('content:index.md') - - const en = await $fetch('/locale-en') - - expect(en).not.toContain('fa-ir:fa:hello.md') - expect(en).toContain('content:index.md') - }) - - test('Use default locale for unscoped contents', async () => { - const index = await fetchDocument('content:index.md') - - expect(index).toMatchObject({ - _locale: 'en' - }) - }) - test('Multi part path', async () => { const html = await $fetch('/features/multi-part-path') expect(html).contains('Persian') }) - test('Empty slot', async () => { - const html = await $fetch('/features/empty-slot') - expect(html).contains('Nullish Document!!!') - expect(html).contains('Empty Child!!!') - }) - - test(' head management (if same path)', async () => { - const html = await $fetch('/head') - expect(html).contains('Head overwritten') - expect(html).contains('') - expect(html).contains('') - expect(html).contains('') - }) - - test(' head management (not same path)', async () => { - const html = await $fetch('/bypass-head') - expect(html).not.contains('Head overwritten') - expect(html).not.contains('') - expect(html).not.contains('') - }) - test('Partials specials chars', async () => { const html = await $fetch('/_partial/content-(v2)') expect(html).contains('Content (v2)') @@ -140,6 +57,8 @@ describe('Custom api baseURL', async () => { expect(spyConsoleWarn).toHaveBeenCalledWith('Ignoring [content:with-\'invalid\'-char.md]. File name should not contain any of the following characters: \', ", ?, #, /') }) + testLocales() + testComponents() testContentQuery() diff --git a/test/features/content-query.ts b/test/features/content-query.ts index d81383ed5..782c7e34e 100644 --- a/test/features/content-query.ts +++ b/test/features/content-query.ts @@ -1,8 +1,52 @@ -import { describe, expect, test } from 'vitest' -import { $fetch } from '@nuxt/test-utils' +import { describe, expect, test, assert } from 'vitest' +import { $fetch, useTestContext } from '@nuxt/test-utils' +import { hash } from 'ohash' export const testContentQuery = () => { + // @ts-ignore + const apiBaseUrl = useTestContext().options.nuxtConfig.content?.api?.baseURL || '/api/_content' + describe('Content Queries', () => { + const fetchDocument = (_id: string) => { + const params = { first: true, where: { _id } } + const qid = hash(params) + return $fetch(`${apiBaseUrl}/query/${qid}`, { + params: { _params: JSON.stringify(params) } + }) + } + test('List contents', async () => { + const params = { only: '_id' } + const qid = hash(params) + const docs = await $fetch(`${apiBaseUrl}/query/${qid}`, { + params: { _params: JSON.stringify(params) } + }) + + const ids = docs.map(doc => doc._id) + + assert(ids.length > 0) + assert(ids.includes('content:index.md')) + + // Ignored files should be listed + assert(ids.includes('content:.dot-ignored.md') === false, 'Ignored files with `.` should not be listed') + assert(ids.includes('content:-dash-ignored.md') === false, 'Ignored files with `-` should not be listed') + + assert(ids.includes('fa-ir:fa:hello.md') === false, 'Files with `fa-ir` prefix should be listed') + }) + + test('Get contents index', async () => { + const index = await fetchDocument('content:index.md') + + expect(index).toHaveProperty('body') + + expect(index.body).toMatchSnapshot('basic-index-body') + }) + + test('Get ignored contents', async () => { + const ignored = await fetchDocument('content:.dot-ignored.md').catch(_err => null) + + expect(ignored).toBeNull() + }) + test('Find index', async () => { const content = await $fetch('/') diff --git a/test/features/locales.ts b/test/features/locales.ts index a0792e100..b8102f1ef 100644 --- a/test/features/locales.ts +++ b/test/features/locales.ts @@ -1,4 +1,4 @@ -import { describe, expect, test } from 'vitest' +import { describe, expect, test, assert } from 'vitest' import { $fetch, useTestContext } from '@nuxt/test-utils' export const testLocales = () => { @@ -9,7 +9,32 @@ export const testLocales = () => { test('Path with multiple locales', async () => { const params = { where: [{ _path: '/translated' }] } const content = await $fetch(`${apiBaseUrl}/query`, { params: { _params: JSON.stringify(params) } }) - expect(content.length === 2) + assert(content.length === 1) + assert(content[0]._locale === 'en') + }) + + test('Search contents using `locale` helper', async () => { + const fa = await $fetch('/locale-fa') + + expect(fa).toContain('fa-ir:fa:hello.md') + expect(fa).not.toContain('content:index.md') + + const en = await $fetch('/locale-en') + + expect(en).not.toContain('fa-ir:fa:hello.md') + expect(en).toContain('content:index.md') + }) + + test('Use default locale for unscoped contents', async () => { + const index = await $fetch(`${apiBaseUrl}/query`, { + params: { + _params: JSON.stringify({ first: true, where: { _id: 'content:index.md' } }) + } + }) + + expect(index).toMatchObject({ + _locale: 'en' + }) }) }) } diff --git a/test/features/renderer-markdown.ts b/test/features/renderer-markdown.ts index ea711bbc0..cde24fdd2 100644 --- a/test/features/renderer-markdown.ts +++ b/test/features/renderer-markdown.ts @@ -67,5 +67,26 @@ export const testMarkdownRenderer = () => { const html = await $fetch('/features/slotted-content-renderer') expect(html).contains('The default slot is overridden') }) + + test('Empty slot', async () => { + const html = await $fetch('/features/empty-slot') + expect(html).contains('Nullish Document!!!') + expect(html).contains('Empty Child!!!') + }) + + test(' head management (if same path)', async () => { + const html = await $fetch('/head') + expect(html).contains('Head overwritten') + expect(html).contains('') + expect(html).contains('') + expect(html).contains('') + }) + + test(' head management (not same path)', async () => { + const html = await $fetch('/bypass-head') + expect(html).not.contains('Head overwritten') + expect(html).not.contains('') + expect(html).not.contains('') + }) }) } From 0a7b13a01ad61370e4890105b36e679711eaf306 Mon Sep 17 00:00:00 2001 From: Ahad Birang Date: Wed, 14 Dec 2022 13:11:00 +0100 Subject: [PATCH 4/4] fix: better default fallback --- src/runtime/composables/navigation.ts | 7 ++++--- src/runtime/composables/query.ts | 5 +++-- src/runtime/server/storage.ts | 5 +++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/runtime/composables/navigation.ts b/src/runtime/composables/navigation.ts index fce33a92f..62fc94bb4 100644 --- a/src/runtime/composables/navigation.ts +++ b/src/runtime/composables/navigation.ts @@ -15,9 +15,10 @@ export const fetchContentNavigation = async (queryBuilder?: QueryBuilder | Query // - query doesn't already have a locale filter if (content.locales.length) { const queryLocale = params.where?.find(w => w._locale)?._locale - const locale = queryLocale || content.defaultLocale - params.where = params.where || [] - params.where.push({ _locale: locale }) + if (!queryLocale) { + params.where = params.where || [] + params.where.push({ _locale: content.defaultLocale }) + } } const _apiPath = params ? `/navigation/${hash(params)}` : '/navigation/' diff --git a/src/runtime/composables/query.ts b/src/runtime/composables/query.ts index 86676b89b..cc98bf883 100644 --- a/src/runtime/composables/query.ts +++ b/src/runtime/composables/query.ts @@ -30,8 +30,9 @@ export const createQueryFetch = (path?: string) => async (que // - query doesn't already have a locale filter if (content.locales.length) { const queryLocale = query.params().where?.find(w => w._locale)?._locale - const locale = queryLocale || content.defaultLocale - query.locale(locale) + if (!queryLocale) { + query.locale(content.defaultLocale) + } } const params = query.params() diff --git a/src/runtime/server/storage.ts b/src/runtime/server/storage.ts index d3b3d6d0e..fad785bbb 100644 --- a/src/runtime/server/storage.ts +++ b/src/runtime/server/storage.ts @@ -204,8 +204,9 @@ export const createServerQueryFetch = (event: H3Event, path?: // - query doesn't already have a locale filter if (contentConfig.locales.length) { const queryLocale = query.params().where?.find(w => w._locale)?._locale - const locale = queryLocale || contentConfig.defaultLocale - query.locale(locale) + if (!queryLocale) { + query.locale(contentConfig.defaultLocale) + } } return createPipelineFetcher(() => getIndexedContentsList(event, query))(query)