Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { createParser } from './utils/content'
import { installMDCModule } from './utils/mdc'
import { findPreset } from './presets'
import type { Manifest } from './types/manifest'
import { setupPreview, shouldEnablePreview } from './utils/preview/module'
import { setupPreview, setupPreviewWithAPI, shouldEnablePreview } from './utils/preview/module'
import { parseSourceBase } from './utils/source'
import { databaseVersion, getLocalDatabase, refineDatabaseConfig, resolveDatabaseAdapter } from './utils/database'
import type { ParsedContentFile } from './types'
Expand Down Expand Up @@ -104,10 +104,10 @@ export default defineNuxtModule<ModuleOptions>({

// Helpers are designed to be enviroment agnostic
addImports([
{ name: 'queryCollection', from: resolver.resolve('./runtime/app') },
{ name: 'queryCollectionSearchSections', from: resolver.resolve('./runtime/app') },
{ name: 'queryCollectionNavigation', from: resolver.resolve('./runtime/app') },
{ name: 'queryCollectionItemSurroundings', from: resolver.resolve('./runtime/app') },
{ name: 'queryCollection', from: resolver.resolve('./runtime/client') },
{ name: 'queryCollectionSearchSections', from: resolver.resolve('./runtime/client') },
{ name: 'queryCollectionNavigation', from: resolver.resolve('./runtime/client') },
{ name: 'queryCollectionItemSurroundings', from: resolver.resolve('./runtime/client') },
])
addServerImports([
{ name: 'queryCollection', from: resolver.resolve('./runtime/nitro') },
Expand Down Expand Up @@ -202,6 +202,7 @@ export default defineNuxtModule<ModuleOptions>({
if (hasNuxtModule('nuxt-llms')) {
installModule(resolver.resolve('./features/llms'))
}

await installMDCModule(options, nuxt)

if (nuxt.options._prepare) {
Expand Down Expand Up @@ -229,9 +230,12 @@ export default defineNuxtModule<ModuleOptions>({
})

// Handle preview mode
if (shouldEnablePreview(nuxt, options)) {
if (hasNuxtModule('nuxt-studio')) {
await setupPreview(options, nuxt, resolver, manifest)
}
if (shouldEnablePreview(nuxt, options)) {
await setupPreviewWithAPI(options, nuxt, resolver, manifest)
}
})
},
})
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion src/runtime/components/ContentRenderer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const props = defineProps({
},
})

const debug = import.meta.dev
const debug = import.meta.dev || import.meta.preview

const body = computed(() => {
let body = props.value.body || props.value
Expand Down
39 changes: 39 additions & 0 deletions src/runtime/plugins/preview-with-api.client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { PublicRuntimeConfig } from '@nuxt/content'
import { defineNuxtPlugin, useCookie, useRoute, useRuntimeConfig, getAppManifest } from '#imports'

export default defineNuxtPlugin(async (nuxtApp) => {
const previewConfig: PublicRuntimeConfig['preview'] = useRuntimeConfig().public.preview || {}
const route = useRoute()
const previewToken = useCookie('previewToken', { sameSite: 'none', secure: true })

// Deprecated: will be removed in v4
if (previewConfig.api) {
// Do not enable preview if preview token is missing in query params
if (Object.prototype.hasOwnProperty.call(route.query, 'preview') && !route.query.preview) {
return
}

if (!route.query.preview && !previewToken.value) {
return
}

if (route.query.preview) {
previewToken.value = String(route.query.preview)
}

window.sessionStorage.setItem('previewToken', String(previewToken.value))
// @ts-expect-error not exposed in runtimeConfig
window.sessionStorage.setItem('previewAPI', (typeof route.query.staging !== 'undefined' && previewConfig.stagingApi) ? previewConfig.stagingApi : previewConfig.api)

// Disable prerendering for preview
const manifest = await getAppManifest()
manifest.prerendered = []

nuxtApp.hook('app:mounted', async () => {
await import('../internal/preview').then(({ mountPreviewUI, initIframeCommunication }) => {
mountPreviewUI()
initIframeCommunication()
})
})
}
})
47 changes: 11 additions & 36 deletions src/runtime/plugins/preview.client.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,13 @@
import type { PublicRuntimeConfig } from '@nuxt/content'
import { defineNuxtPlugin, useCookie, useRoute, useRuntimeConfig, getAppManifest } from '#imports'

export default defineNuxtPlugin(async (nuxtApp) => {
const previewConfig: PublicRuntimeConfig['preview'] = useRuntimeConfig().public.preview || {}
const route = useRoute()
const previewToken = useCookie('previewToken', { sameSite: 'none', secure: true })

if (previewConfig.api) {
// Do not enable preview if preview token is missing in query params
if (Object.prototype.hasOwnProperty.call(route.query, 'preview') && !route.query.preview) {
return
}

if (!route.query.preview && !previewToken.value) {
return
}

if (route.query.preview) {
previewToken.value = String(route.query.preview)
}

window.sessionStorage.setItem('previewToken', String(previewToken.value))
// @ts-expect-error not exposed in runtimeConfig
window.sessionStorage.setItem('previewAPI', (typeof route.query.staging !== 'undefined' && previewConfig.stagingApi) ? previewConfig.stagingApi : previewConfig.api)

// Disable prerendering for preview
const manifest = await getAppManifest()
manifest.prerendered = []

nuxtApp.hook('app:mounted', async () => {
await import('../internal/preview').then(({ mountPreviewUI, initIframeCommunication }) => {
mountPreviewUI()
initIframeCommunication()
})
})
import { defineNuxtPlugin } from '#imports'

export default defineNuxtPlugin(async () => {
return {
provide: {
content: {
loadLocalDatabase: () => {
return import('../internal/database.client').then(m => m.loadDatabaseAdapter)
},
},
},
}
})
Empty file.
4 changes: 4 additions & 0 deletions src/types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ interface Window {
sendNavigateMessageInPreview: (path: string, navigate: boolean) => void
}

interface ImportMeta {
readonly preview?: boolean
}

declare module '#content/manifest' {
const manifest: Record<string, unknown>
const checksums: Record<string, string>
Expand Down
1 change: 1 addition & 0 deletions src/types/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
export interface Draft07DefinitionProperty {
type?: string // missing type means any
properties?: Record<string, Draft07DefinitionProperty>
items?: Draft07DefinitionProperty
required?: string[]

Check failure on line 18 in src/types/schema.ts

View workflow job for this annotation

GitHub Actions / ubuntu

Duplicate identifier 'items'.
default?: unknown
maxLength?: number

Check failure on line 20 in src/types/schema.ts

View workflow job for this annotation

GitHub Actions / ubuntu

Duplicate identifier 'items'.
format?: string
enum?: string[]
additionalProperties?: boolean | Record<string, Draft07DefinitionProperty>
Expand Down
23 changes: 21 additions & 2 deletions src/utils/preview/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,26 @@ import type { ModuleOptions } from '../../types'
import { previewTemplate } from '../templates'
import type { Manifest } from '../../types/manifest'

export async function setupPreview(options: ModuleOptions, nuxt: Nuxt, resolver: Resolver, manifest: Manifest) {
export async function setupPreview(_options: ModuleOptions, nuxt: Nuxt, resolver: Resolver, manifest: Manifest) {
nuxt.hook('schema:resolved', (schema: Schema) => {
// Add preview templates once schema is resolved
const template = addTemplate(previewTemplate(manifest.collections, {} as GitInfo, schema)).dst
nuxt.options.nitro.alias ||= {}
nuxt.options.nitro.alias['#content/preview'] = template
nuxt.options.alias['#content/preview'] = template
})

// Add plugins
addPlugin(resolver.resolve('./runtime/plugins/preview.client'))

// // Install dependencies
await installModule('nuxt-component-meta', {
globalsOnly: true,
include: manifest.components,
})
}

export async function setupPreviewWithAPI(options: ModuleOptions, nuxt: Nuxt, resolver: Resolver, manifest: Manifest) {
const previewOptions = options.preview!

const { resolve } = resolver
Expand All @@ -41,7 +60,7 @@ export async function setupPreview(options: ModuleOptions, nuxt: Nuxt, resolver:
})

// Add plugins
addPlugin(resolver.resolve('./runtime/plugins/preview.client'))
addPlugin(resolver.resolve('./runtime/plugins/preview-with-api.client'))

// Register preview banner component
addComponent({ name: 'ContentPreviewMode', filePath: resolver.resolve('./runtime/components/ContentPreviewMode.vue') })
Expand Down
Loading