Skip to content

Commit

Permalink
fix(document-driven): rendering flash (#1336)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel Roe <daniel@roe.dev>
Co-authored-by: Sébastien Chopin <seb@nuxtjs.com>
Co-authored-by: Yaël Guilloux <yael.guilloux@gmail.com>
  • Loading branch information
4 people committed Jul 7, 2022
1 parent d5d23c9 commit 230bbad
Show file tree
Hide file tree
Showing 14 changed files with 156 additions and 50 deletions.
6 changes: 6 additions & 0 deletions playground/document-driven/app.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<template>
<div>
<NuxtLoadingBar />
<NuxtPage />
</div>
</template>
17 changes: 17 additions & 0 deletions playground/document-driven/components/content/Alert.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<template>
<div>
<div style="display: flex; align-items: center">
<div style="font-size: 64px;">
</div>
<div>
<h3 style="margin: 0">
<Markdown :use="$slots.title" unwrap="p" />
</h3>
<div>
<Markdown :use="$slots.default" unwrap="p" />
</div>
</div>
</div>
</div>
</template>
14 changes: 14 additions & 0 deletions playground/document-driven/components/content/List.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script setup lang="ts">
// Utils from Nuxt Content
const { flatUnwrap } = useUnwrap()
</script>

<template>
<ul>
<li v-for="(item, index) of flatUnwrap($slots.default(), ['ul'])" :key="index">
☑︎
<span><Markdown :use="() => item" unwrap="li" /></span>
</li>
</ul>
</template>
10 changes: 10 additions & 0 deletions playground/document-driven/content/10.alert.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
layout: blog
---

::alert{icon="ph:circle-wavy-warning-duotone"}
#title
This is an alert
#default
This is the default content of my alert!
::
8 changes: 8 additions & 0 deletions playground/document-driven/content/9.list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
::list
- Item 1
::list{icon="ph:check-circle-light"}
- Item 1.1
- Item 1.2
::
- Item 2
::
5 changes: 1 addition & 4 deletions playground/document-driven/layouts/reversed.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
<template>
<div>
<NuxtLoadingBar />

<NuxtPage />

<slot />
<PageNav />
</div>
</template>
Expand Down
8 changes: 6 additions & 2 deletions playground/document-driven/pages/vue-file.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
<script setup>
definePageMeta({
layout: 'reversed'
documentDriven: {
surround: false
}
})
const { page } = useContent()
useContentHead(page)
</script>

<template>
<ContentRenderer :value="page" />
<NuxtLayout name="reversed">
<ContentRenderer :value="page" />
</NuxtLayout>
</template>
18 changes: 18 additions & 0 deletions playground/shared/layouts/blog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template>
<div style="max-width: 680px; margin: 0 auto">
<NuxtLoadingBar />

<PageNav />

<slot />
</div>
</template>

<style>
body, html {
margin: 0;
padding: 0;
min-height: 100vh;
min-width: 100vw;
}
</style>
5 changes: 1 addition & 4 deletions playground/shared/layouts/default.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<template>
<div>
<NuxtLoadingBar />

<PageNav />

<NuxtPage />
<slot />
</div>
</template>

Expand Down
28 changes: 22 additions & 6 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -448,12 +448,28 @@ export default defineNuxtModule<ModuleOptions>({
nuxt.options.pages = true

nuxt.hook('pages:extend', (pages) => {
pages.unshift({
name: 'slug',
path: '/:slug(.*)*',
file: resolveRuntimeModule('./pages/document-driven.vue'),
children: []
})
// Respect user's custom catch-all page
if (!pages.find(page => page.path === '/:slug(.*)*')) {
pages.unshift({
name: 'slug',
path: '/:slug(.*)*',
file: resolveRuntimeModule('./pages/document-driven.vue'),
children: []
})
}
})
nuxt.hook('app:resolve', async (app) => {
if (app.mainComponent?.includes('@nuxt/ui-templates')) {
app.mainComponent = resolveRuntimeModule('./app.vue')
} else {
const appContent = await fs.promises.readFile(app.mainComponent!, { encoding: 'utf-8' })
if (appContent.includes('<NuxtLayout') || appContent.includes('<nuxt-layout')) {
logger.warn([
'Using `<NuxtLayout>` inside `app.vue` will cause unwanted layout shifting in your application.',
'Consider removing `<NuxtLayout>` from `app.vue` and using it in your pages.'
].join(''))
}
}
})
}
} else {
Expand Down
3 changes: 3 additions & 0 deletions src/runtime/app.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<NuxtPage />
</template>
43 changes: 32 additions & 11 deletions src/runtime/composables/content.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { withoutTrailingSlash } from 'ufo'
import type { NavItem, ParsedContent } from '../types'
import { computed, useState } from '#imports'
import { computed, useState, useRoute } from '#imports'

export const useContentState = () => {
/**
* Current page complete data.
* Map of loaded pages.
*/
const page = useState<ParsedContent>('dd-page')
const pages = useState<Record<string, ParsedContent>>('dd-pages', () => ({}))

/**
* Navigation tree from root of app.
* Previous and next page data.
* Format: [prev, next]
*/
const navigation = useState<NavItem[]>('dd-navigation')
const surrounds = useState<Record<string, Omit<ParsedContent, 'body'>>>('dd-surrounds', () => ({}))

/**
* Previous and next page data.
* Format: [prev, next]
* Navigation tree from root of app.
*/
const surround = useState<Omit<ParsedContent, 'body'>[]>('dd-surround')
const navigation = useState<NavItem[]>('dd-navigation')

/**
* Globally loaded content files.
Expand All @@ -25,15 +26,35 @@ export const useContentState = () => {
const globals = useState<Record<string, ParsedContent>>('dd-globals', () => ({}))

return {
page,
pages,
surrounds,
navigation,
surround,
globals
}
}

export const useContent = () => {
const { navigation, page, surround, globals } = useContentState()
const { navigation, pages, surrounds, globals } = useContentState()

const _path = computed(() => withoutTrailingSlash(useRoute().path))

/**
* Current `page` key, computed from path and content state.
*/
const page = computed(
() => {
return pages.value[_path.value]
}
)

/**
* Current `surround` key, computed from path and content state.
*/
const surround = computed(
() => {
return surrounds.value[_path.value]
}
)

/**
* Table of contents from `page`.
Expand Down
12 changes: 7 additions & 5 deletions src/runtime/pages/document-driven.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ useContentHead(page)

<template>
<div class="document-driven-page">
<ContentRenderer v-if="page" :key="page._id" :value="page">
<template #empty="{ value }">
<DocumentDrivenEmpty :value="value" />
</template>
</ContentRenderer>
<NuxtLayout v-if="page" :name="page.layout || 'default'">
<ContentRenderer :key="page._id" :value="page">
<template #empty="{ value }">
<DocumentDrivenEmpty :value="value" />
</template>
</ContentRenderer>
</NuxtLayout>
<DocumentDrivenNotFound v-else />
</div>
</template>
29 changes: 11 additions & 18 deletions src/runtime/plugins/documentDriven.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import layouts from '#build/layouts'

export default defineNuxtPlugin((nuxt) => {
const { documentDriven: moduleOptions } = useRuntimeConfig()?.public?.content
const pagesCache = new Map<string, ParsedContent>()
const surroundCache = new Map<string, ParsedContent>()

/**
* Finds a layout value from a cascade of objects.
Expand Down Expand Up @@ -52,11 +50,12 @@ export default defineNuxtPlugin((nuxt) => {
return
}

const { navigation, page, globals, surround } = useContentState()
const { navigation, pages, globals, surrounds } = useContentState()

// Normalize route path
const _path = withoutTrailingSlash(to.path)

// Promises array to be executed all at once
const promises: (() => Promise<any> | any)[] = []

/**
Expand Down Expand Up @@ -136,14 +135,11 @@ export default defineNuxtPlugin((nuxt) => {
*/
if (moduleOptions.page && routeConfig.page !== false) {
const pageQuery = () => {
const { page } = useContentState()
const { pages } = useContentState()

// Return same page as page is already loaded
if (!force && page.value && page.value._path === _path) {
return page.value
}
if (!force && process.client && pagesCache.has(_path)) {
return pagesCache.get(_path)
if (!force && pages.value[_path] && pages.value[_path]._path === _path) {
return pages.value[_path]
}

return queryContent()
Expand All @@ -163,12 +159,11 @@ export default defineNuxtPlugin((nuxt) => {
*/
if (moduleOptions.surround && routeConfig.surround !== false) {
const surroundQuery = () => {
const { surrounds } = useContentState()

// Return same surround as page is already loaded
if (!force && page.value && page.value._path === _path) {
return surround.value
}
if (!force && process.client && surroundCache.has(_path)) {
return surroundCache.get(_path)
if (!force && surrounds.value[_path]) {
return surrounds.value[_path]
}

return queryContent()
Expand Down Expand Up @@ -219,13 +214,11 @@ export default defineNuxtPlugin((nuxt) => {
to.meta.layout = layoutName

// Update values
page.value = _page
process.client && pagesCache.set(_path, _page)
pages.value[_path] = _page
}

if (_surround) {
surround.value = _surround
process.client && surroundCache.set(_path, _surround)
surrounds.value[_path] = _surround
}
})
}
Expand Down

0 comments on commit 230bbad

Please sign in to comment.