feat(nuxt): configurable app.rootAttrs and teleportAttrs (#27014)

This commit is contained in:
Harlan Wilton 2024-05-02 01:27:30 +10:00 committed by GitHub
parent c538a35711
commit 8b67a19af6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 8 deletions

View File

@ -16,7 +16,7 @@ import destr from 'destr'
import { getQuery as getURLQuery, joinURL, withoutTrailingSlash } from 'ufo'
import { renderToString as _renderToString } from 'vue/server-renderer'
import { hash } from 'ohash'
import { renderSSRHead } from '@unhead/ssr'
import { propsToString, renderSSRHead } from '@unhead/ssr'
import type { HeadEntryOptions } from '@unhead/schema'
import type { Link, Script, Style } from '@unhead/vue'
import { createServerHead } from '@unhead/vue'
@ -29,7 +29,7 @@ import unheadPlugins from '#internal/unhead-plugins.mjs'
import type { NuxtPayload, NuxtSSRContext } from '#app'
// @ts-expect-error virtual file
import { appHead, appRootId, appRootTag, appTeleportId, appTeleportTag, componentIslands } from '#internal/nuxt.config.mjs'
import { appHead, appRootAttrs, appRootTag, appTeleportAttrs, appTeleportTag, componentIslands } from '#internal/nuxt.config.mjs'
// @ts-expect-error virtual file
import { buildAssetsURL, publicAssetsURL } from '#internal/nuxt/paths'
@ -232,15 +232,15 @@ async function getIslandContext (event: H3Event): Promise<NuxtIslandContext> {
return ctx
}
const HAS_APP_TELEPORTS = !!(appTeleportTag && appTeleportId)
const APP_TELEPORT_OPEN_TAG = HAS_APP_TELEPORTS ? `<${appTeleportTag} id="${appTeleportId}">` : ''
const HAS_APP_TELEPORTS = !!(appTeleportTag && appTeleportAttrs.id)
const APP_TELEPORT_OPEN_TAG = HAS_APP_TELEPORTS ? `<${appTeleportTag}${propsToString(appTeleportAttrs)}>` : ''
const APP_TELEPORT_CLOSE_TAG = HAS_APP_TELEPORTS ? `</${appTeleportTag}>` : ''
const APP_ROOT_OPEN_TAG = `<${appRootTag}${appRootId ? ` id="${appRootId}"` : ''}>`
const APP_ROOT_OPEN_TAG = `<${appRootTag}${propsToString(appRootAttrs)}>`
const APP_ROOT_CLOSE_TAG = `</${appRootTag}>`
const PAYLOAD_URL_RE = process.env.NUXT_JSON_PAYLOADS ? /\/_payload.json(\?.*)?$/ : /\/_payload.js(\?.*)?$/
const ROOT_NODE_REGEX = new RegExp(`^${APP_ROOT_OPEN_TAG}([\\s\\S]*)${APP_ROOT_CLOSE_TAG}$`)
const ROOT_NODE_REGEX = new RegExp(`^<${appRootTag}[^>]*>([\\s\\S]*)<\\/${appRootTag}>$`)
const PRERENDER_NO_SSR_ROUTES = new Set(['/index.html', '/200.html', '/404.html'])
@ -470,7 +470,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
bodyPrepend: normalizeChunks([bodyTagsOpen, ssrContext.teleports?.body]),
body: [
componentIslands ? replaceIslandTeleports(ssrContext, _rendered.html) : _rendered.html,
APP_TELEPORT_OPEN_TAG + (HAS_APP_TELEPORTS ? joinTags([ssrContext.teleports?.[`#${appTeleportId}`]]) : '') + APP_TELEPORT_CLOSE_TAG,
APP_TELEPORT_OPEN_TAG + (HAS_APP_TELEPORTS ? joinTags([ssrContext.teleports?.[`#${appTeleportAttrs.id}`]]) : '') + APP_TELEPORT_CLOSE_TAG,
],
bodyAppend: [bodyTags],
}

View File

@ -182,9 +182,10 @@ export default defineUntypedSchema({
/**
* Customize Nuxt root element id.
* @type {string | false}
* @deprecated Prefer `rootAttrs.id` instead
*/
rootId: {
$resolve: val => val === false ? false : val || '__nuxt',
$resolve: val => val === false ? false : (val || '__nuxt'),
},
/**
@ -194,6 +195,19 @@ export default defineUntypedSchema({
$resolve: val => val || 'div',
},
/**
* Customize Nuxt root element id.
* @type {typeof import('@unhead/schema').HtmlAttributes}
*/
rootAttrs: {
$resolve: async (val: undefined | null | Record<string, unknown>, get) => {
const rootId = await get('app.rootId')
return defu(val, {
id: rootId === false ? undefined : (rootId || '__nuxt'),
})
},
},
/**
* Customize Nuxt root element tag.
*/
@ -204,10 +218,24 @@ export default defineUntypedSchema({
/**
* Customize Nuxt Teleport element id.
* @type {string | false}
* @deprecated Prefer `teleportAttrs.id` instead
*/
teleportId: {
$resolve: val => val === false ? false : (val || 'teleports'),
},
/**
* Customize Nuxt Teleport element attributes.
* @type {typeof import('@unhead/schema').HtmlAttributes}
*/
teleportAttrs: {
$resolve: async (val: undefined | null | Record<string, unknown>, get) => {
const teleportId = await get('app.teleportId')
return defu(val, {
id: teleportId === false ? undefined : (teleportId || 'teleports'),
})
},
},
},
/**